Branch Coverage

intern.h
Criterion Covered Total %
branch 120 332 36.1


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