| 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; |