| line |
true |
false |
branch |
|
127
|
0 |
19 |
if (v < 2) return 1; |
|
167
|
0 |
0 |
if (pid == 0) return 1; /* no owner recorded, assume alive */ |
|
168
|
0 |
0 |
return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH); |
|
|
0 |
0 |
return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH); |
|
178
|
0 |
0 |
if (!__atomic_compare_exchange_n(&hdr->rwlock, &observed_rwlock, |
|
184
|
0 |
0 |
if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0) |
|
208
|
151188 |
13 |
if (__builtin_expect(cur_gen == h->cached_fork_gen && h->my_slot_idx != UINT32_MAX, 1)) |
|
|
151188 |
0 |
if (__builtin_expect(cur_gen == h->cached_fork_gen && h->my_slot_idx != UINT32_MAX, 1)) |
|
219
|
13 |
0 |
for (uint32_t i = 0; i < SI_READER_SLOTS; i++) { |
|
222
|
13 |
0 |
if (__atomic_compare_exchange_n(&h->reader_slots[s].pid, |
|
242
|
0 |
0 |
if (!sub) return; |
|
245
|
0 |
0 |
uint32_t want = (cur > sub) ? cur - sub : 0; |
|
246
|
0 |
0 |
if (__atomic_compare_exchange_n(p, &cur, want, |
|
269
|
0 |
0 |
if (!__atomic_compare_exchange_n(&h->reader_slots[i].pid, &expected, 0, |
|
274
|
0 |
0 |
if (wp) si_atomic_sub_cap(&hdr->rwlock_waiters, wp); |
|
275
|
0 |
0 |
if (writp) si_atomic_sub_cap(&hdr->rwlock_writers_waiting, writp); |
|
289
|
0 |
0 |
if (!h->reader_slots) return; |
|
302
|
0 |
0 |
for (uint32_t i = 0; i < SI_READER_SLOTS; i++) { |
|
304
|
0 |
0 |
if (pid == 0) continue; |
|
306
|
0 |
0 |
if (si_pid_alive(pid)) { |
|
307
|
0 |
0 |
if (sc > 0) any_live_reader = 1; |
|
310
|
0 |
0 |
if (sc > 0) { found_dead_reader = 1; continue; } |
|
327
|
0 |
0 |
if (found_dead_reader && !any_live_reader) { |
|
|
0 |
0 |
if (found_dead_reader && !any_live_reader) { |
|
331
|
0 |
0 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
|
0 |
0 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
334
|
0 |
0 |
for (uint32_t i = 0; !live_now && i < SI_READER_SLOTS; i++) { |
|
|
0 |
0 |
for (uint32_t i = 0; !live_now && i < SI_READER_SLOTS; i++) { |
|
336
|
0 |
0 |
if (p && si_pid_alive(p) && |
|
|
0 |
0 |
if (p && si_pid_alive(p) && |
|
337
|
0 |
0 |
__atomic_load_n(&h->reader_slots[i].subcount, __ATOMIC_RELAXED) > 0) |
|
340
|
0 |
0 |
if (live_now) { |
|
342
|
0 |
0 |
} else if (__atomic_compare_exchange_n(&hdr->rwlock, &cur, 0, |
|
344
|
0 |
0 |
if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0) |
|
350
|
0 |
0 |
if (drain_ok) { |
|
351
|
0 |
0 |
for (uint32_t i = 0; i < SI_READER_SLOTS; i++) { |
|
353
|
0 |
0 |
if (p == 0 || si_pid_alive(p)) continue; |
|
|
0 |
0 |
if (p == 0 || si_pid_alive(p)) continue; |
|
367
|
0 |
0 |
if (val >= SI_RWLOCK_WRITER_BIT) { |
|
369
|
0 |
0 |
if (!si_pid_alive(pid)) |
|
381
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
387
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
391
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) { |
|
401
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) { |
|
419
|
109660 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
426
|
0 |
109660 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
|
0 |
0 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
427
|
0 |
0 |
if (__atomic_compare_exchange_n(lock, &cur, cur + 1, |
|
430
|
109660 |
0 |
} else if (cur == 0 && !__atomic_load_n(writers_waiting, __ATOMIC_RELAXED)) { |
|
|
109660 |
0 |
} else if (cur == 0 && !__atomic_load_n(writers_waiting, __ATOMIC_RELAXED)) { |
|
431
|
109660 |
0 |
if (__atomic_compare_exchange_n(lock, &cur, 1, |
|
435
|
0 |
0 |
if (__builtin_expect(spin < SI_RWLOCK_SPIN_LIMIT, 1)) { |
|
442
|
0 |
0 |
if (cur >= SI_RWLOCK_WRITER_BIT || |
|
443
|
0 |
0 |
(cur == 0 && __atomic_load_n(writers_waiting, __ATOMIC_RELAXED))) { |
|
|
0 |
0 |
(cur == 0 && __atomic_load_n(writers_waiting, __ATOMIC_RELAXED))) { |
|
448
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
468
|
109660 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
470
|
109660 |
0 |
if (after == 0 && __atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0) |
|
|
0 |
109660 |
if (after == 0 && __atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0) |
|
483
|
41541 |
0 |
if (__atomic_compare_exchange_n(lock, &expected, mypid, |
|
486
|
0 |
0 |
if (__builtin_expect(spin < SI_RWLOCK_SPIN_LIMIT, 1)) { |
|
492
|
0 |
0 |
if (cur != 0) { |
|
495
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
510
|
0 |
41541 |
if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0) |
|
565
|
0 |
19 |
if (!h) { |
|
567
|
0 |
0 |
if (backing_fd >= 0) close(backing_fd); |
|
576
|
6 |
13 |
h->path = path ? strdup(path) : NULL; |
|
584
|
0 |
3 |
if (hdr->magic != SI_MAGIC) return 0; |
|
585
|
0 |
3 |
if (hdr->version != SI_VERSION) return 0; |
|
586
|
3 |
0 |
if (hdr->max_strings == 0 || hdr->max_strings > SI_MAX_STRINGS) return 0; |
|
|
0 |
3 |
if (hdr->max_strings == 0 || hdr->max_strings > SI_MAX_STRINGS) return 0; |
|
587
|
3 |
0 |
if (hdr->hash_slots == 0 || (hdr->hash_slots & (hdr->hash_slots - 1)) != 0) return 0; /* pow2 */ |
|
|
0 |
3 |
if (hdr->hash_slots == 0 || (hdr->hash_slots & (hdr->hash_slots - 1)) != 0) return 0; /* pow2 */ |
|
588
|
0 |
3 |
if (hdr->hash_slots <= hdr->max_strings) return 0; /* probe termination: an empty slot always exists */ |
|
589
|
0 |
3 |
if (hdr->arena_bytes == 0) return 0; |
|
590
|
0 |
3 |
if (hdr->total_size != file_size) return 0; |
|
591
|
0 |
3 |
if (hdr->total_size != si_total_size(hdr->hash_slots, hdr->max_strings, hdr->arena_bytes)) return 0; |
|
593
|
0 |
3 |
if (hdr->reader_slots_off != L.reader_slots) return 0; |
|
594
|
0 |
3 |
if (hdr->hash_off != L.hash) return 0; |
|
595
|
0 |
3 |
if (hdr->reverse_off != L.reverse) return 0; |
|
596
|
0 |
3 |
if (hdr->arena_off != L.arena) return 0; |
|
597
|
0 |
3 |
if (hdr->count > hdr->max_strings) return 0; |
|
598
|
0 |
3 |
if (hdr->arena_used > hdr->arena_bytes) return 0; |
|
605
|
20 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
606
|
1 |
19 |
if (max_strings == 0) { SI_ERR("max_strings must be > 0"); return 0; } |
|
|
1 |
0 |
if (max_strings == 0) { SI_ERR("max_strings must be > 0"); return 0; } |
|
607
|
0 |
19 |
if (max_strings > SI_MAX_STRINGS) { SI_ERR("max_strings too large (max %u)", SI_MAX_STRINGS); return 0; } |
|
|
0 |
0 |
if (max_strings > SI_MAX_STRINGS) { SI_ERR("max_strings too large (max %u)", SI_MAX_STRINGS); return 0; } |
|
613
|
7 |
12 |
if (*arena_bytes_io == 0) { /* default arena: 32 bytes/string */ |
|
615
|
0 |
7 |
if (a > SI_MAX_ARENA) a = SI_MAX_ARENA; |
|
616
|
0 |
7 |
if (a < 64) a = 64; |
|
625
|
7 |
0 |
for (int attempt = 0; attempt < 100; attempt++) { |
|
627
|
4 |
3 |
if (fd >= 0) { (void)fchmod(fd, mode); return fd; } /* exact mode: umask narrowed the O_EXCL create */ |
|
628
|
0 |
3 |
if (errno != EEXIST) { SI_ERR("create %s: %s", path, strerror(errno)); return -1; } |
|
|
0 |
0 |
if (errno != EEXIST) { SI_ERR("create %s: %s", path, strerror(errno)); return -1; } |
|
630
|
3 |
0 |
if (fd >= 0) return fd; |
|
631
|
0 |
0 |
if (errno == ENOENT) continue; /* creator unlinked between our two opens; retry */ |
|
632
|
0 |
0 |
SI_ERR("open %s: %s", path, strerror(errno)); /* ELOOP => symlink rejected */ |
|
635
|
0 |
0 |
SI_ERR("open %s: create/attach kept racing", path); |
|
641
|
1 |
17 |
if (!si_validate_create_args(max_strings, &arena_bytes, &hash_slots, errbuf)) return NULL; |
|
649
|
10 |
7 |
if (anonymous) { |
|
652
|
0 |
10 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
655
|
0 |
7 |
if (fd < 0) return NULL; |
|
656
|
0 |
7 |
if (flock(fd, LOCK_EX) < 0) { SI_ERR("flock: %s", strerror(errno)); close(fd); return NULL; } |
|
|
0 |
0 |
if (flock(fd, LOCK_EX) < 0) { SI_ERR("flock: %s", strerror(errno)); close(fd); return NULL; } |
|
658
|
0 |
7 |
if (fstat(fd, &st) < 0) { SI_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
|
0 |
0 |
if (fstat(fd, &st) < 0) { SI_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
660
|
3 |
4 |
if (!is_new && (uint64_t)st.st_size < sizeof(SiHeader)) { |
|
|
1 |
2 |
if (!is_new && (uint64_t)st.st_size < sizeof(SiHeader)) { |
|
661
|
1 |
0 |
SI_ERR("%s: file too small (%lld)", path, (long long)st.st_size); |
|
664
|
4 |
2 |
if (is_new && ftruncate(fd, (off_t)total) < 0) { |
|
|
0 |
4 |
if (is_new && ftruncate(fd, (off_t)total) < 0) { |
|
665
|
0 |
0 |
SI_ERR("ftruncate: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; |
|
667
|
2 |
4 |
map_size = is_new ? (size_t)total : (size_t)st.st_size; |
|
669
|
0 |
6 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
670
|
2 |
4 |
if (!is_new) { |
|
671
|
0 |
2 |
if (!si_validate_header((SiHeader *)base, (uint64_t)st.st_size)) { |
|
672
|
0 |
0 |
SI_ERR("invalid intern file"); munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL; |
|
679
|
4 |
10 |
if (fd >= 0) { flock(fd, LOCK_UN); close(fd); } |
|
685
|
0 |
2 |
if (!si_validate_create_args(max_strings, &arena_bytes, &hash_slots, errbuf)) return NULL; |
|
688
|
1 |
1 |
int fd = memfd_create(name ? name : "intern", MFD_CLOEXEC | MFD_ALLOW_SEALING); |
|
689
|
0 |
2 |
if (fd < 0) { SI_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { SI_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
690
|
0 |
2 |
if (ftruncate(fd, (off_t)total) < 0) { |
|
691
|
0 |
0 |
SI_ERR("ftruncate: %s", strerror(errno)); close(fd); return NULL; |
|
695
|
0 |
2 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; } |
|
701
|
1 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
703
|
0 |
1 |
if (fstat(fd, &st) < 0) { SI_ERR("fstat: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fstat(fd, &st) < 0) { SI_ERR("fstat: %s", strerror(errno)); return NULL; } |
|
704
|
0 |
1 |
if ((uint64_t)st.st_size < sizeof(SiHeader)) { SI_ERR("too small"); return NULL; } |
|
|
0 |
0 |
if ((uint64_t)st.st_size < sizeof(SiHeader)) { SI_ERR("too small"); return NULL; } |
|
707
|
0 |
1 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { SI_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
708
|
0 |
1 |
if (!si_validate_header((SiHeader *)base, (uint64_t)st.st_size)) { |
|
709
|
0 |
0 |
SI_ERR("invalid intern table"); munmap(base, ms); return NULL; |
|
712
|
0 |
1 |
if (myfd < 0) { SI_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; } |
|
|
0 |
0 |
if (myfd < 0) { SI_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; } |
|
717
|
0 |
19 |
if (!h) return; |
|
720
|
19 |
0 |
if (h->reader_slots && h->my_slot_idx != UINT32_MAX && h->cached_pid && |
|
|
13 |
6 |
if (h->reader_slots && h->my_slot_idx != UINT32_MAX && h->cached_pid && |
|
|
13 |
0 |
if (h->reader_slots && h->my_slot_idx != UINT32_MAX && h->cached_pid && |
|
721
|
13 |
0 |
h->cached_fork_gen == __atomic_load_n(&si_fork_gen, __ATOMIC_RELAXED) && |
|
722
|
13 |
0 |
__atomic_load_n(&h->reader_slots[h->my_slot_idx].subcount, __ATOMIC_ACQUIRE) == 0) { |
|
727
|
3 |
16 |
if (h->backing_fd >= 0) close(h->backing_fd); |
|
728
|
19 |
0 |
if (h->hdr) munmap(h->hdr, h->mmap_size); |
|
734
|
4 |
0 |
if (!h || !h->hdr) return 0; |
|
|
0 |
4 |
if (!h || !h->hdr) return 0; |
|
769
|
86483 |
37146 |
while (h->slots[i].state) { |
|
770
|
85053 |
1430 |
if (h->slots[i].fp == want_fp) { |
|
778
|
85053 |
0 |
if (id < count) { |
|
780
|
85053 |
0 |
if (off <= used && used - off >= sizeof(uint32_t)) { |
|
|
85053 |
0 |
if (off <= used && used - off >= sizeof(uint32_t)) { |
|
783
|
85053 |
0 |
if (l <= used - off - (uint32_t)sizeof(uint32_t) |
|
784
|
77614 |
7439 |
&& l == n && memcmp(cand, s, n) == 0) { *found = 1; return i; } |
|
|
77017 |
597 |
&& l == n && memcmp(cand, s, n) == 0) { *found = 1; return i; } |
|
792
|
0 |
9466 |
if (++probes >= hslots) break; |
|
802
|
72621 |
3 |
if (f) { *id = h->slots[i].id; return 1; } |
|
813
|
4396 |
37143 |
if (f) return h->slots[slot].id; |
|
814
|
1 |
37142 |
if (hdr->count >= hdr->max_strings) return -1; |
|
816
|
3 |
37139 |
if ((uint64_t)hdr->arena_used + need > hdr->arena_bytes) return -1; |
|
820
|
37138 |
1 |
if (n) memcpy(h->arena + off + sizeof(uint32_t), s, n); |