| 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
|
14 |
0 |
for (uint32_t i = 0; i < SI_READER_SLOTS; i++) { |
|
222
|
13 |
1 |
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) { |
|
329
|
0 |
0 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
|
0 |
0 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
330
|
0 |
0 |
if (__atomic_compare_exchange_n(&hdr->rwlock, &cur, 0, |
|
332
|
0 |
0 |
if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0) |
|
336
|
0 |
0 |
for (uint32_t i = 0; i < SI_READER_SLOTS; i++) { |
|
338
|
0 |
0 |
if (pid == 0 || si_pid_alive(pid)) continue; |
|
|
0 |
0 |
if (pid == 0 || si_pid_alive(pid)) continue; |
|
351
|
0 |
0 |
if (val >= SI_RWLOCK_WRITER_BIT) { |
|
353
|
0 |
0 |
if (!si_pid_alive(pid)) |
|
365
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
371
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
375
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) { |
|
385
|
0 |
0 |
if (h->my_slot_idx != UINT32_MAX) { |
|
403
|
109660 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
410
|
0 |
109660 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
|
0 |
0 |
if (cur > 0 && cur < SI_RWLOCK_WRITER_BIT) { |
|
411
|
0 |
0 |
if (__atomic_compare_exchange_n(lock, &cur, cur + 1, |
|
414
|
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)) { |
|
415
|
109660 |
0 |
if (__atomic_compare_exchange_n(lock, &cur, 1, |
|
419
|
0 |
0 |
if (__builtin_expect(spin < SI_RWLOCK_SPIN_LIMIT, 1)) { |
|
426
|
0 |
0 |
if (cur >= SI_RWLOCK_WRITER_BIT || cur == 0) { |
|
|
0 |
0 |
if (cur >= SI_RWLOCK_WRITER_BIT || cur == 0) { |
|
429
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
449
|
109660 |
0 |
if (h->my_slot_idx != UINT32_MAX) |
|
451
|
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) |
|
464
|
41541 |
0 |
if (__atomic_compare_exchange_n(lock, &expected, mypid, |
|
467
|
0 |
0 |
if (__builtin_expect(spin < SI_RWLOCK_SPIN_LIMIT, 1)) { |
|
473
|
0 |
0 |
if (cur != 0) { |
|
476
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
491
|
0 |
41541 |
if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0) |
|
546
|
0 |
19 |
if (!h) { |
|
548
|
0 |
0 |
if (backing_fd >= 0) close(backing_fd); |
|
557
|
6 |
13 |
h->path = path ? strdup(path) : NULL; |
|
565
|
0 |
3 |
if (hdr->magic != SI_MAGIC) return 0; |
|
566
|
0 |
3 |
if (hdr->version != SI_VERSION) return 0; |
|
567
|
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; |
|
568
|
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 */ |
|
569
|
0 |
3 |
if (hdr->hash_slots <= hdr->max_strings) return 0; /* probe termination: an empty slot always exists */ |
|
570
|
0 |
3 |
if (hdr->arena_bytes == 0) return 0; |
|
571
|
0 |
3 |
if (hdr->total_size != file_size) return 0; |
|
572
|
0 |
3 |
if (hdr->total_size != si_total_size(hdr->hash_slots, hdr->max_strings, hdr->arena_bytes)) return 0; |
|
574
|
0 |
3 |
if (hdr->reader_slots_off != L.reader_slots) return 0; |
|
575
|
0 |
3 |
if (hdr->hash_off != L.hash) return 0; |
|
576
|
0 |
3 |
if (hdr->reverse_off != L.reverse) return 0; |
|
577
|
0 |
3 |
if (hdr->arena_off != L.arena) return 0; |
|
578
|
0 |
3 |
if (hdr->count > hdr->max_strings) return 0; |
|
579
|
0 |
3 |
if (hdr->arena_used > hdr->arena_bytes) return 0; |
|
586
|
20 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
587
|
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; } |
|
588
|
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; } |
|
594
|
7 |
12 |
if (*arena_bytes_io == 0) { /* default arena: 32 bytes/string */ |
|
596
|
0 |
7 |
if (a > SI_MAX_ARENA) a = SI_MAX_ARENA; |
|
597
|
0 |
7 |
if (a < 64) a = 64; |
|
605
|
1 |
17 |
if (!si_validate_create_args(max_strings, &arena_bytes, &hash_slots, errbuf)) return NULL; |
|
613
|
10 |
7 |
if (anonymous) { |
|
616
|
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; } |
|
619
|
0 |
7 |
if (fd < 0) { SI_ERR("open: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { SI_ERR("open: %s", strerror(errno)); return NULL; } |
|
620
|
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; } |
|
622
|
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; } |
|
624
|
3 |
4 |
if (!is_new && (uint64_t)st.st_size < sizeof(SiHeader)) { |
|
|
1 |
2 |
if (!is_new && (uint64_t)st.st_size < sizeof(SiHeader)) { |
|
625
|
1 |
0 |
SI_ERR("%s: file too small (%lld)", path, (long long)st.st_size); |
|
628
|
4 |
2 |
if (is_new && ftruncate(fd, (off_t)total) < 0) { |
|
|
0 |
4 |
if (is_new && ftruncate(fd, (off_t)total) < 0) { |
|
629
|
0 |
0 |
SI_ERR("ftruncate: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; |
|
631
|
2 |
4 |
map_size = is_new ? (size_t)total : (size_t)st.st_size; |
|
633
|
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; } |
|
634
|
2 |
4 |
if (!is_new) { |
|
635
|
0 |
2 |
if (!si_validate_header((SiHeader *)base, (uint64_t)st.st_size)) { |
|
636
|
0 |
0 |
SI_ERR("invalid intern file"); munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL; |
|
643
|
4 |
10 |
if (fd >= 0) { flock(fd, LOCK_UN); close(fd); } |
|
649
|
0 |
2 |
if (!si_validate_create_args(max_strings, &arena_bytes, &hash_slots, errbuf)) return NULL; |
|
652
|
1 |
1 |
int fd = memfd_create(name ? name : "intern", MFD_CLOEXEC | MFD_ALLOW_SEALING); |
|
653
|
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; } |
|
654
|
0 |
2 |
if (ftruncate(fd, (off_t)total) < 0) { |
|
655
|
0 |
0 |
SI_ERR("ftruncate: %s", strerror(errno)); close(fd); return NULL; |
|
659
|
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; } |
|
665
|
1 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
667
|
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; } |
|
668
|
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; } |
|
671
|
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; } |
|
672
|
0 |
1 |
if (!si_validate_header((SiHeader *)base, (uint64_t)st.st_size)) { |
|
673
|
0 |
0 |
SI_ERR("invalid intern table"); munmap(base, ms); return NULL; |
|
676
|
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; } |
|
681
|
0 |
19 |
if (!h) return; |
|
682
|
3 |
16 |
if (h->backing_fd >= 0) close(h->backing_fd); |
|
683
|
19 |
0 |
if (h->hdr) munmap(h->hdr, h->mmap_size); |
|
689
|
4 |
0 |
if (!h || !h->hdr) return 0; |
|
|
0 |
4 |
if (!h || !h->hdr) return 0; |
|
720
|
86483 |
37146 |
while (h->slots[i].state) { |
|
721
|
85053 |
1430 |
if (h->slots[i].fp == want_fp) { |
|
724
|
77614 |
7439 |
if (l == n && memcmp(cand, s, n) == 0) { *found = 1; return i; } |
|
|
77017 |
597 |
if (l == n && memcmp(cand, s, n) == 0) { *found = 1; return i; } |
|
736
|
72621 |
3 |
if (f) { *id = h->slots[i].id; return 1; } |
|
747
|
4396 |
37143 |
if (f) return h->slots[slot].id; |
|
748
|
1 |
37142 |
if (hdr->count >= hdr->max_strings) return -1; |
|
750
|
3 |
37139 |
if ((uint64_t)hdr->arena_used + need > hdr->arena_bytes) return -1; |
|
754
|
37138 |
1 |
if (n) memcpy(h->arena + off + sizeof(uint32_t), s, n); |