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