Branch Coverage

dsu.h
Criterion Covered Total %
branch 90 256 35.1


line true false branch
147 0 0 if (pid == 0) return 1; /* no owner recorded, assume alive */
148 0 0 return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH);
0 0 return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH);
158 0 0 if (!__atomic_compare_exchange_n(&hdr->rwlock, &observed_rwlock,
164 0 0 if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
188 14842 15 if (__builtin_expect(cur_gen == h->cached_fork_gen && h->my_slot_idx != UINT32_MAX, 1))
14842 0 if (__builtin_expect(cur_gen == h->cached_fork_gen && h->my_slot_idx != UINT32_MAX, 1))
199 17 0 for (uint32_t i = 0; i < DSU_READER_SLOTS; i++) {
202 15 2 if (__atomic_compare_exchange_n(&h->reader_slots[s].pid,
222 0 0 if (!sub) return;
225 0 0 uint32_t want = (cur > sub) ? cur - sub : 0;
226 0 0 if (__atomic_compare_exchange_n(p, &cur, want,
249 0 0 if (!__atomic_compare_exchange_n(&h->reader_slots[i].pid, &expected, 0,
254 0 0 if (wp) dsu_atomic_sub_cap(&hdr->rwlock_waiters, wp);
255 0 0 if (writp) dsu_atomic_sub_cap(&hdr->rwlock_writers_waiting, writp);
269 0 0 if (!h->reader_slots) return;
282 0 0 for (uint32_t i = 0; i < DSU_READER_SLOTS; i++) {
284 0 0 if (pid == 0) continue;
286 0 0 if (dsu_pid_alive(pid)) {
287 0 0 if (sc > 0) any_live_reader = 1;
290 0 0 if (sc > 0) { found_dead_reader = 1; continue; }
307 0 0 if (found_dead_reader && !any_live_reader) {
0 0 if (found_dead_reader && !any_live_reader) {
309 0 0 if (cur > 0 && cur < DSU_RWLOCK_WRITER_BIT) {
0 0 if (cur > 0 && cur < DSU_RWLOCK_WRITER_BIT) {
310 0 0 if (__atomic_compare_exchange_n(&hdr->rwlock, &cur, 0,
312 0 0 if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
316 0 0 for (uint32_t i = 0; i < DSU_READER_SLOTS; i++) {
318 0 0 if (pid == 0 || dsu_pid_alive(pid)) continue;
0 0 if (pid == 0 || dsu_pid_alive(pid)) continue;
331 0 0 if (val >= DSU_RWLOCK_WRITER_BIT) {
333 0 0 if (!dsu_pid_alive(pid))
345 0 0 if (h->my_slot_idx != UINT32_MAX)
351 0 0 if (h->my_slot_idx != UINT32_MAX)
355 0 0 if (h->my_slot_idx != UINT32_MAX) {
365 0 0 if (h->my_slot_idx != UINT32_MAX) {
383 2017 0 if (h->my_slot_idx != UINT32_MAX)
390 0 2017 if (cur > 0 && cur < DSU_RWLOCK_WRITER_BIT) {
0 0 if (cur > 0 && cur < DSU_RWLOCK_WRITER_BIT) {
391 0 0 if (__atomic_compare_exchange_n(lock, &cur, cur + 1,
394 2017 0 } else if (cur == 0 && !__atomic_load_n(writers_waiting, __ATOMIC_RELAXED)) {
2017 0 } else if (cur == 0 && !__atomic_load_n(writers_waiting, __ATOMIC_RELAXED)) {
395 2017 0 if (__atomic_compare_exchange_n(lock, &cur, 1,
399 0 0 if (__builtin_expect(spin < DSU_RWLOCK_SPIN_LIMIT, 1)) {
406 0 0 if (cur >= DSU_RWLOCK_WRITER_BIT || cur == 0) {
0 0 if (cur >= DSU_RWLOCK_WRITER_BIT || cur == 0) {
409 0 0 if (rc == -1 && errno == ETIMEDOUT) {
0 0 if (rc == -1 && errno == ETIMEDOUT) {
429 2017 0 if (h->my_slot_idx != UINT32_MAX)
431 2017 0 if (after == 0 && __atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
0 2017 if (after == 0 && __atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
444 12840 0 if (__atomic_compare_exchange_n(lock, &expected, mypid,
447 0 0 if (__builtin_expect(spin < DSU_RWLOCK_SPIN_LIMIT, 1)) {
453 0 0 if (cur != 0) {
456 0 0 if (rc == -1 && errno == ETIMEDOUT) {
0 0 if (rc == -1 && errno == ETIMEDOUT) {
471 0 12840 if (__atomic_load_n(&hdr->rwlock_waiters, __ATOMIC_RELAXED) > 0)
516 15239 20524 while (p[x] != x) {
529 1094 932 if (ra == rb) return 0;
532 281 651 if (sz[ra] < sz[rb]) { uint32_t t = ra; ra = rb; rb = t; }
555 32 2 for (uint32_t i = 0; i < n; i++) { p[i] = i; sz[i] = 1; }
566 22 0 if (errbuf) errbuf[0] = '\0';
567 2 20 if (n < 1) { DSU_ERR("n must be >= 1"); return 0; }
2 0 if (n < 1) { DSU_ERR("n must be >= 1"); return 0; }
568 0 20 if (n > DSU_MAX_N) { DSU_ERR("n must be <= %u", (unsigned)DSU_MAX_N); return 0; }
0 0 if (n > DSU_MAX_N) { DSU_ERR("n must be <= %u", (unsigned)DSU_MAX_N); return 0; }
589 1242 18 for (uint32_t i = 0; i < n; i++) { p[i] = i; sz[i] = 1; }
598 0 20 if (!h) {
600 0 0 if (backing_fd >= 0) close(backing_fd);
607 4 16 h->path = path ? strdup(path) : NULL;
617 0 2 if (hdr->magic != DSU_MAGIC) return 0;
618 0 2 if (hdr->version != DSU_VERSION) return 0;
619 2 0 if (hdr->n < 1 || hdr->n > DSU_MAX_N) return 0;
0 2 if (hdr->n < 1 || hdr->n > DSU_MAX_N) return 0;
620 2 0 if (hdr->num_sets < 1 || hdr->num_sets > hdr->n) return 0;
0 2 if (hdr->num_sets < 1 || hdr->num_sets > hdr->n) return 0;
621 0 2 if (hdr->total_size != file_size) return 0;
622 0 2 if (hdr->total_size != dsu_total_size(hdr->n)) return 0;
624 0 2 if (hdr->reader_slots_off != L.reader_slots) return 0;
625 0 2 if (hdr->parent_off != L.parent) return 0;
626 0 2 if (hdr->size_off != L.size) return 0;
631 1 18 if (!dsu_validate_create_args(n_in, errbuf)) return NULL;
640 13 5 if (anonymous) {
643 0 13 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); return NULL; }
0 0 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); return NULL; }
646 0 5 if (fd < 0) { DSU_ERR("open: %s", strerror(errno)); return NULL; }
0 0 if (fd < 0) { DSU_ERR("open: %s", strerror(errno)); return NULL; }
647 0 5 if (flock(fd, LOCK_EX) < 0) { DSU_ERR("flock: %s", strerror(errno)); close(fd); return NULL; }
0 0 if (flock(fd, LOCK_EX) < 0) { DSU_ERR("flock: %s", strerror(errno)); close(fd); return NULL; }
649 0 5 if (fstat(fd, &st) < 0) { DSU_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
0 0 if (fstat(fd, &st) < 0) { DSU_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
651 2 3 if (!is_new && (uint64_t)st.st_size < sizeof(DsuHeader)) {
1 1 if (!is_new && (uint64_t)st.st_size < sizeof(DsuHeader)) {
652 1 0 DSU_ERR("%s: file too small (%lld)", path, (long long)st.st_size);
655 3 1 if (is_new && ftruncate(fd, (off_t)total) < 0) {
0 3 if (is_new && ftruncate(fd, (off_t)total) < 0) {
656 0 0 DSU_ERR("ftruncate: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL;
658 1 3 map_size = is_new ? (size_t)total : (size_t)st.st_size;
660 0 4 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
0 0 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; }
661 1 3 if (!is_new) {
662 0 1 if (!dsu_validate_header((DsuHeader *)base, (uint64_t)st.st_size)) {
663 0 0 DSU_ERR("invalid disjoint-set file"); munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL;
670 3 13 if (fd >= 0) { flock(fd, LOCK_UN); close(fd); }
675 1 2 if (!dsu_validate_create_args(n_in, errbuf)) return NULL;
679 1 1 int fd = memfd_create(name ? name : "dsu", MFD_CLOEXEC | MFD_ALLOW_SEALING);
680 0 2 if (fd < 0) { DSU_ERR("memfd_create: %s", strerror(errno)); return NULL; }
0 0 if (fd < 0) { DSU_ERR("memfd_create: %s", strerror(errno)); return NULL; }
681 0 2 if (ftruncate(fd, (off_t)total) < 0) {
682 0 0 DSU_ERR("ftruncate: %s", strerror(errno)); close(fd); return NULL;
686 0 2 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; }
0 0 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; }
692 2 0 if (errbuf) errbuf[0] = '\0';
694 0 2 if (fstat(fd, &st) < 0) { DSU_ERR("fstat: %s", strerror(errno)); return NULL; }
0 0 if (fstat(fd, &st) < 0) { DSU_ERR("fstat: %s", strerror(errno)); return NULL; }
695 1 1 if ((uint64_t)st.st_size < sizeof(DsuHeader)) { DSU_ERR("too small"); return NULL; }
1 0 if ((uint64_t)st.st_size < sizeof(DsuHeader)) { DSU_ERR("too small"); return NULL; }
698 0 1 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); return NULL; }
0 0 if (base == MAP_FAILED) { DSU_ERR("mmap: %s", strerror(errno)); return NULL; }
699 0 1 if (!dsu_validate_header((DsuHeader *)base, (uint64_t)st.st_size)) {
700 0 0 DSU_ERR("invalid disjoint-set table"); munmap(base, ms); return NULL;
703 0 1 if (myfd < 0) { DSU_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; }
0 0 if (myfd < 0) { DSU_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; }
708 0 20 if (!h) return;
709 3 17 if (h->backing_fd >= 0) close(h->backing_fd);
710 20 0 if (h->base) munmap(h->base, h->mmap_size);
716 2 0 if (!h || !h->base) return 0;
0 2 if (!h || !h->base) return 0;