Branch Coverage

radix.h
Criterion Covered Total %
branch 145 320 45.3


line true false branch
162 0 0 if (pid == 0) return 1; /* no owner recorded, assume alive */
163 0 0 return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH);
0 0 return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH);
173 0 0 if (!__atomic_compare_exchange_n(&hdr->rwlock, &observed_rwlock,
179 0 0 if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
203 4860 20 if (__builtin_expect(cur_gen == h->cached_fork_gen && h->my_slot_idx != UINT32_MAX, 1))
4860 0 if (__builtin_expect(cur_gen == h->cached_fork_gen && h->my_slot_idx != UINT32_MAX, 1))
214 22 0 for (uint32_t i = 0; i < RDX_READER_SLOTS; i++) {
217 20 2 if (__atomic_compare_exchange_n(&h->reader_slots[s].pid,
237 0 0 if (!sub) return;
240 0 0 uint32_t want = (cur > sub) ? cur - sub : 0;
241 0 0 if (__atomic_compare_exchange_n(p, &cur, want,
264 0 0 if (!__atomic_compare_exchange_n(&h->reader_slots[i].pid, &expected, 0,
269 0 0 if (wp) rdx_atomic_sub_cap(&hdr->rwlock_waiters, wp);
270 0 0 if (writp) rdx_atomic_sub_cap(&hdr->rwlock_writers_waiting, writp);
284 0 0 if (!h->reader_slots) return;
297 0 0 for (uint32_t i = 0; i < RDX_READER_SLOTS; i++) {
299 0 0 if (pid == 0) continue;
301 0 0 if (rdx_pid_alive(pid)) {
302 0 0 if (sc > 0) any_live_reader = 1;
305 0 0 if (sc > 0) { found_dead_reader = 1; continue; }
322 0 0 if (found_dead_reader && !any_live_reader) {
0 0 if (found_dead_reader && !any_live_reader) {
324 0 0 if (cur > 0 && cur < RDX_RWLOCK_WRITER_BIT) {
0 0 if (cur > 0 && cur < RDX_RWLOCK_WRITER_BIT) {
325 0 0 if (__atomic_compare_exchange_n(&hdr->rwlock, &cur, 0,
327 0 0 if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
331 0 0 for (uint32_t i = 0; i < RDX_READER_SLOTS; i++) {
333 0 0 if (pid == 0 || rdx_pid_alive(pid)) continue;
0 0 if (pid == 0 || rdx_pid_alive(pid)) continue;
346 0 0 if (val >= RDX_RWLOCK_WRITER_BIT) {
348 0 0 if (!rdx_pid_alive(pid))
360 0 0 if (h->my_slot_idx != UINT32_MAX)
366 0 0 if (h->my_slot_idx != UINT32_MAX)
370 0 0 if (h->my_slot_idx != UINT32_MAX) {
380 0 0 if (h->my_slot_idx != UINT32_MAX) {
398 3264 0 if (h->my_slot_idx != UINT32_MAX)
405 0 3264 if (cur > 0 && cur < RDX_RWLOCK_WRITER_BIT) {
0 0 if (cur > 0 && cur < RDX_RWLOCK_WRITER_BIT) {
406 0 0 if (__atomic_compare_exchange_n(lock, &cur, cur + 1,
409 3264 0 } else if (cur == 0 && !__atomic_load_n(writers_waiting, __ATOMIC_RELAXED)) {
3264 0 } else if (cur == 0 && !__atomic_load_n(writers_waiting, __ATOMIC_RELAXED)) {
410 3264 0 if (__atomic_compare_exchange_n(lock, &cur, 1,
414 0 0 if (__builtin_expect(spin < RDX_RWLOCK_SPIN_LIMIT, 1)) {
421 0 0 if (cur >= RDX_RWLOCK_WRITER_BIT || cur == 0) {
0 0 if (cur >= RDX_RWLOCK_WRITER_BIT || cur == 0) {
424 0 0 if (rc == -1 && errno == ETIMEDOUT) {
0 0 if (rc == -1 && errno == ETIMEDOUT) {
444 3264 0 if (h->my_slot_idx != UINT32_MAX)
446 3264 0 if (after == 0 && __atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
0 3264 if (after == 0 && __atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
459 1616 0 if (__atomic_compare_exchange_n(lock, &expected, mypid,
462 0 0 if (__builtin_expect(spin < RDX_RWLOCK_SPIN_LIMIT, 1)) {
468 0 0 if (cur != 0) {
471 0 0 if (rc == -1 && errno == ETIMEDOUT) {
0 0 if (rc == -1 && errno == ETIMEDOUT) {
486 0 1616 if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
532 1222 0 if (hdr->node_used < hdr->node_cap) {
546 1080 0 if (len) memcpy(rdx_arena(h) + off, bytes, len);
557 2 1089 if (hdr->node_cap - hdr->node_used < 2) return 0;
558 1 1088 if (hdr->arena_cap - hdr->arena_used < klen) return 0;
573 6281 2701 while (i < max && a[i] == b[i]) i++;
6142 139 while (i < max && a[i] == b[i]) i++;
587 5 3781 if (kpos == klen) { /* key ends here -> mark this node */
591 2 3 if (isnew) hdr->keys++;
596 941 2840 if (ch == 0) { /* no child on b -> new leaf with the rest as its label */
611 2698 142 if (m == llen) { /* whole label matched -> descend */
629 3 139 if (kpos + m == klen) { /* the key ends exactly at the split point */
656 3680 14927 if (kpos == klen) return cur;
658 27 14900 if (!ch) return 0;
660 8 14892 if (klen - kpos < llen) return 0;
661 2 14890 if (memcmp(arena + nodes[ch].label_off, key + kpos, llen) != 0) return 0;
671 36 3157 if (!n) return 0;
673 2632 525 if (nodes[n].has_value) { if (out) *out = nodes[n].value; return 1; }
1589 1043 if (nodes[n].has_value) { if (out) *out = nodes[n].value; return 1; }
684 3 40 if (nodes[cur].has_value) { if (out) *out = nodes[cur].value; found = 1; } /* empty key stored */
3 0 if (nodes[cur].has_value) { if (out) *out = nodes[cur].value; found = 1; } /* empty key stored */
686 15 129 if (kpos == klen) break;
688 17 112 if (!ch) break;
690 109 3 if (klen - kpos < llen || memcmp(arena + nodes[ch].label_off, key + kpos, llen) != 0) break;
101 8 if (klen - kpos < llen || memcmp(arena + nodes[ch].label_off, key + kpos, llen) != 0) break;
693 43 58 if (nodes[cur].has_value) { if (out) *out = nodes[cur].value; found = 1; }
43 0 if (nodes[cur].has_value) { if (out) *out = nodes[cur].value; found = 1; }
703 1 523 if (!n) return 0;
705 1 522 if (!nodes[n].has_value) return 0;
730 29 0 if (errbuf) errbuf[0] = '\0';
731 2 27 if (node_cap < 2) { RDX_ERR("node_capacity must be >= 2 (NIL + root)"); return 0; }
2 0 if (node_cap < 2) { RDX_ERR("node_capacity must be >= 2 (NIL + root)"); return 0; }
732 1 26 if (node_cap > RDX_MAX_NODES) { RDX_ERR("node_capacity must be <= %u", (unsigned)RDX_MAX_NODES); return 0; }
1 0 if (node_cap > RDX_MAX_NODES) { RDX_ERR("node_capacity must be <= %u", (unsigned)RDX_MAX_NODES); return 0; }
733 1 25 if (arena_cap < 1) { RDX_ERR("arena_capacity must be >= 1"); return 0; }
1 0 if (arena_cap < 1) { RDX_ERR("arena_capacity must be >= 1"); return 0; }
734 1 24 if (arena_cap > RDX_MAX_ARENA) { RDX_ERR("arena_capacity must be <= %u", (unsigned)RDX_MAX_ARENA); return 0; }
1 0 if (arena_cap > RDX_MAX_ARENA) { RDX_ERR("arena_capacity must be <= %u", (unsigned)RDX_MAX_ARENA); return 0; }
776 0 24 if (!h) {
778 0 0 if (backing_fd >= 0) close(backing_fd);
785 4 20 h->path = path ? strdup(path) : NULL;
796 0 2 if (hdr->magic != RDX_MAGIC) return 0;
797 0 2 if (hdr->version != RDX_VERSION) return 0;
798 2 0 if (hdr->node_cap < 2 || hdr->node_cap > RDX_MAX_NODES) return 0;
0 2 if (hdr->node_cap < 2 || hdr->node_cap > RDX_MAX_NODES) return 0;
799 2 0 if (hdr->arena_cap < 1 || hdr->arena_cap > RDX_MAX_ARENA) return 0;
0 2 if (hdr->arena_cap < 1 || hdr->arena_cap > RDX_MAX_ARENA) return 0;
800 0 2 if (hdr->total_size != file_size) return 0;
801 0 2 if (hdr->total_size != rdx_total_size(hdr->node_cap, hdr->arena_cap)) return 0;
803 0 2 if (hdr->reader_slots_off != L.reader_slots) return 0;
804 0 2 if (hdr->node_pool_off != L.node_pool) return 0;
805 0 2 if (hdr->arena_off != L.arena) return 0;
806 2 0 if (hdr->root == 0 || hdr->root >= hdr->node_cap) return 0;
0 2 if (hdr->root == 0 || hdr->root >= hdr->node_cap) return 0;
807 2 0 if (hdr->node_used < 2 || hdr->node_used > hdr->node_cap) return 0;
0 2 if (hdr->node_used < 2 || hdr->node_used > hdr->node_cap) return 0;
808 0 2 if (hdr->arena_used > hdr->arena_cap) return 0;
813 4 22 if (!rdx_validate_create_args(node_cap_in, arena_cap_in, errbuf)) return NULL;
823 17 5 if (anonymous) {
826 0 17 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); return NULL; }
0 0 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); return NULL; }
829 0 5 if (fd < 0) { RDX_ERR("open: %s", strerror(errno)); return NULL; }
0 0 if (fd < 0) { RDX_ERR("open: %s", strerror(errno)); return NULL; }
830 0 5 if (flock(fd, LOCK_EX) < 0) { RDX_ERR("flock: %s", strerror(errno)); close(fd); return NULL; }
0 0 if (flock(fd, LOCK_EX) < 0) { RDX_ERR("flock: %s", strerror(errno)); close(fd); return NULL; }
832 0 5 if (fstat(fd, &st) < 0) { RDX_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
0 0 if (fstat(fd, &st) < 0) { RDX_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
834 2 3 if (!is_new && (uint64_t)st.st_size < sizeof(RdxHeader)) {
1 1 if (!is_new && (uint64_t)st.st_size < sizeof(RdxHeader)) {
835 1 0 RDX_ERR("%s: file too small (%lld)", path, (long long)st.st_size);
838 3 1 if (is_new && ftruncate(fd, (off_t)total) < 0) {
0 3 if (is_new && ftruncate(fd, (off_t)total) < 0) {
839 0 0 RDX_ERR("ftruncate: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL;
841 1 3 map_size = is_new ? (size_t)total : (size_t)st.st_size;
843 0 4 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
0 0 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
844 1 3 if (!is_new) {
845 0 1 if (!rdx_validate_header((RdxHeader *)base, (uint64_t)st.st_size)) {
846 0 0 RDX_ERR("invalid radix-tree file"); munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL;
853 3 17 if (fd >= 0) { flock(fd, LOCK_UN); close(fd); }
858 1 2 if (!rdx_validate_create_args(node_cap_in, arena_cap_in, errbuf)) return NULL;
863 1 1 int fd = memfd_create(name ? name : "radix", MFD_CLOEXEC | MFD_ALLOW_SEALING);
864 0 2 if (fd < 0) { RDX_ERR("memfd_create: %s", strerror(errno)); return NULL; }
0 0 if (fd < 0) { RDX_ERR("memfd_create: %s", strerror(errno)); return NULL; }
865 0 2 if (ftruncate(fd, (off_t)total) < 0) {
866 0 0 RDX_ERR("ftruncate: %s", strerror(errno)); close(fd); return NULL;
870 0 2 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; }
0 0 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; }
876 2 0 if (errbuf) errbuf[0] = '\0';
878 0 2 if (fstat(fd, &st) < 0) { RDX_ERR("fstat: %s", strerror(errno)); return NULL; }
0 0 if (fstat(fd, &st) < 0) { RDX_ERR("fstat: %s", strerror(errno)); return NULL; }
879 1 1 if ((uint64_t)st.st_size < sizeof(RdxHeader)) { RDX_ERR("too small"); return NULL; }
1 0 if ((uint64_t)st.st_size < sizeof(RdxHeader)) { RDX_ERR("too small"); return NULL; }
882 0 1 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); return NULL; }
0 0 if (base == MAP_FAILED) { RDX_ERR("mmap: %s", strerror(errno)); return NULL; }
883 0 1 if (!rdx_validate_header((RdxHeader *)base, (uint64_t)st.st_size)) {
884 0 0 RDX_ERR("invalid radix-tree table"); munmap(base, ms); return NULL;
887 0 1 if (myfd < 0) { RDX_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; }
0 0 if (myfd < 0) { RDX_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; }
892 0 24 if (!h) return;
893 3 21 if (h->backing_fd >= 0) close(h->backing_fd);
894 24 0 if (h->base) munmap(h->base, h->mmap_size);
900 2 0 if (!h || !h->base) return 0;
0 2 if (!h || !h->base) return 0;