| line |
true |
false |
branch |
|
174
|
0 |
59 |
if (v < 2) return 2; |
|
175
|
0 |
59 |
if (v > 0x80000000U) return 0; |
|
192
|
4826 |
65 |
if (needed <= h->copy_buf_cap) return 1; |
|
193
|
0 |
65 |
uint32_t ns = h->copy_buf_cap ? h->copy_buf_cap : 64; |
|
194
|
0 |
7 |
while (ns < needed) { uint32_t n2 = ns * 2; if (n2 <= ns) { ns = needed; break; } ns = n2; } |
|
|
7 |
65 |
while (ns < needed) { uint32_t n2 = ns * 2; if (n2 <= ns) { ns = needed; break; } ns = n2; } |
|
196
|
0 |
65 |
if (!nb) return 0; |
|
215
|
0 |
4 |
if (pid == 0) return 1; |
|
216
|
0 |
4 |
return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH); |
|
|
0 |
0 |
return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH); |
|
222
|
0 |
0 |
if (!__atomic_compare_exchange_n(&hdr->mutex, &observed, 0, |
|
226
|
0 |
0 |
if (__atomic_load_n(&hdr->mutex_waiters, __ATOMIC_RELAXED) > 0) |
|
234
|
6592 |
323 |
if (__atomic_compare_exchange_n(&hdr->mutex, &expected, mypid, |
|
237
|
317 |
6 |
if (__builtin_expect(spin < REQREP_SPIN_LIMIT, 1)) { |
|
243
|
6 |
0 |
if (cur != 0) { |
|
246
|
1 |
5 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
|
0 |
1 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
249
|
0 |
0 |
if (val >= REQREP_MUTEX_WRITER_BIT) { |
|
251
|
0 |
0 |
if (!reqrep_pid_alive(pid)) |
|
265
|
8 |
6584 |
if (__atomic_load_n(&hdr->mutex_waiters, __ATOMIC_RELAXED) > 0) |
|
270
|
1852 |
1046 |
if (__atomic_load_n(&hdr->recv_waiters, __ATOMIC_RELAXED) > 0) { |
|
277
|
0 |
2277 |
if (__atomic_load_n(&hdr->send_waiters, __ATOMIC_RELAXED) > 0) { |
|
284
|
0 |
2886 |
if (__atomic_load_n(&hdr->slot_waiters, __ATOMIC_RELAXED) > 0) { |
|
296
|
2486 |
7 |
if (remaining->tv_nsec < 0) { |
|
307
|
1758 |
2563 |
if (deadline->tv_nsec >= 1000000000L) { |
|
322
|
3258 |
2 |
for (uint32_t i = 0; i < n; i++) { |
|
326
|
2902 |
356 |
if (__atomic_compare_exchange_n(&slot->state, &expected, RESP_ACQUIRED, |
|
336
|
4 |
2 |
for (uint32_t i = 0; i < n; i++) { |
|
339
|
0 |
4 |
if (state == RESP_ACQUIRED || state == RESP_READY) { |
|
|
0 |
0 |
if (state == RESP_ACQUIRED || state == RESP_READY) { |
|
341
|
4 |
0 |
if (pid && !reqrep_pid_alive(pid)) { |
|
|
0 |
4 |
if (pid && !reqrep_pid_alive(pid)) { |
|
342
|
0 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &state, RESP_FREE, |
|
346
|
0 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &expected, RESP_ACQUIRED, |
|
378
|
0 |
112 |
if (!h) return NULL; |
|
391
|
103 |
9 |
h->path = path ? strdup(path) : NULL; |
|
400
|
0 |
55 |
if (hdr->magic != REQREP_MAGIC) return 0; |
|
401
|
0 |
55 |
if (hdr->version != REQREP_VERSION) return 0; |
|
402
|
0 |
55 |
if (hdr->mode != expected_mode) return 0; |
|
403
|
55 |
0 |
if (hdr->req_cap == 0 || (hdr->req_cap & (hdr->req_cap - 1)) != 0) return 0; |
|
|
0 |
55 |
if (hdr->req_cap == 0 || (hdr->req_cap & (hdr->req_cap - 1)) != 0) return 0; |
|
404
|
0 |
55 |
if (hdr->total_size != (uint64_t)file_size) return 0; |
|
405
|
0 |
55 |
if (hdr->req_slots_off != sizeof(ReqRepHeader)) return 0; |
|
406
|
0 |
55 |
if (hdr->resp_slots == 0) return 0; |
|
407
|
0 |
55 |
if (hdr->resp_stride < sizeof(RespSlotHeader)) return 0; |
|
413
|
0 |
55 |
if (req_slots_end > hdr->total_size) return 0; |
|
414
|
45 |
10 |
if (expected_mode == REQREP_MODE_STR) { |
|
415
|
0 |
45 |
if (hdr->req_arena_off < req_slots_end) return 0; |
|
416
|
0 |
45 |
if ((uint64_t)hdr->req_arena_off + hdr->req_arena_cap > hdr->total_size) return 0; |
|
418
|
0 |
45 |
if (hdr->resp_off < (uint64_t)hdr->req_arena_off + hdr->req_arena_cap) return 0; |
|
420
|
0 |
55 |
if (hdr->resp_off < req_slots_end) return 0; |
|
421
|
0 |
55 |
if ((uint64_t)hdr->resp_off + (uint64_t)hdr->resp_slots * hdr->resp_stride > hdr->total_size) return 0; |
|
445
|
898 |
50 |
for (uint32_t i = 0; i < resp_slots_n; i++) { |
|
462
|
0 |
51 |
if (req_arena_off_64 > UINT32_MAX) return -1; |
|
465
|
0 |
51 |
if (arena_hint > UINT32_MAX) return -1; |
|
467
|
15 |
36 |
if (req_arena_cap < 4096) req_arena_cap = 4096; |
|
471
|
0 |
51 |
if (resp_off_64 > UINT32_MAX) return -1; |
|
486
|
48 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
489
|
0 |
48 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
|
0 |
0 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
490
|
0 |
48 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
|
0 |
0 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
492
|
46 |
2 |
if (arena_hint == 0) arena_hint = (uint64_t)req_cap * 256; |
|
496
|
0 |
48 |
if (reqrep_compute_layout(req_cap, resp_slots_n, resp_data_max, arena_hint, |
|
499
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap/arena_hint too large for uint32 offsets"); |
|
507
|
1 |
47 |
if (anonymous) { |
|
511
|
0 |
1 |
if (base == MAP_FAILED) { |
|
512
|
0 |
0 |
REQREP_ERR("mmap(anonymous): %s", strerror(errno)); |
|
520
|
0 |
47 |
if (fd < 0) { REQREP_ERR("open(%s): %s", path, strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { REQREP_ERR("open(%s): %s", path, strerror(errno)); return NULL; } |
|
522
|
0 |
47 |
if (flock(fd, LOCK_EX) < 0) { |
|
523
|
0 |
0 |
REQREP_ERR("flock(%s): %s", path, strerror(errno)); |
|
528
|
0 |
47 |
if (fstat(fd, &st) < 0) { |
|
529
|
0 |
0 |
REQREP_ERR("fstat(%s): %s", path, strerror(errno)); |
|
535
|
1 |
46 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
|
0 |
1 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
536
|
0 |
0 |
REQREP_ERR("%s: file too small (%lld)", path, (long long)st.st_size); |
|
540
|
46 |
1 |
if (is_new) { |
|
541
|
0 |
46 |
if (ftruncate(fd, (off_t)total_size) < 0) { |
|
542
|
0 |
0 |
REQREP_ERR("ftruncate(%s): %s", path, strerror(errno)); |
|
547
|
1 |
46 |
map_size = is_new ? (size_t)total_size : (size_t)st.st_size; |
|
549
|
0 |
47 |
if (base == MAP_FAILED) { |
|
550
|
0 |
0 |
REQREP_ERR("mmap(%s): %s", path, strerror(errno)); |
|
554
|
1 |
46 |
if (!is_new) { |
|
555
|
0 |
1 |
if (!reqrep_validate_header((ReqRepHeader *)base, (size_t)st.st_size, REQREP_MODE_STR)) { |
|
556
|
0 |
0 |
REQREP_ERR("%s: invalid or incompatible reqrep file", path); |
|
562
|
0 |
1 |
if (!h) { munmap(base, map_size); return NULL; } |
|
574
|
0 |
47 |
if (!h) { munmap(base, map_size); return NULL; } |
|
579
|
49 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
580
|
0 |
49 |
if (!path) { REQREP_ERR("path required"); return NULL; } |
|
|
0 |
0 |
if (!path) { REQREP_ERR("path required"); return NULL; } |
|
583
|
0 |
49 |
if (fd < 0) { REQREP_ERR("open(%s): %s", path, strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { REQREP_ERR("open(%s): %s", path, strerror(errno)); return NULL; } |
|
585
|
0 |
49 |
if (flock(fd, LOCK_EX) < 0) { |
|
586
|
0 |
0 |
REQREP_ERR("flock(%s): %s", path, strerror(errno)); |
|
591
|
0 |
49 |
if (fstat(fd, &st) < 0) { |
|
592
|
0 |
0 |
REQREP_ERR("fstat(%s): %s", path, strerror(errno)); |
|
596
|
0 |
49 |
if ((uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
597
|
0 |
0 |
REQREP_ERR("%s: file too small or not initialized", path); |
|
603
|
0 |
49 |
if (base == MAP_FAILED) { |
|
604
|
0 |
0 |
REQREP_ERR("mmap(%s): %s", path, strerror(errno)); |
|
608
|
0 |
49 |
if (!reqrep_validate_header((ReqRepHeader *)base, map_size, mode)) { |
|
609
|
0 |
0 |
REQREP_ERR("%s: invalid or incompatible reqrep file", path); |
|
617
|
0 |
49 |
if (!h) { munmap(base, map_size); return NULL; } |
|
624
|
3 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
627
|
0 |
3 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
|
0 |
0 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
628
|
0 |
3 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
|
0 |
0 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
630
|
3 |
0 |
if (arena_hint == 0) arena_hint = (uint64_t)req_cap * 256; |
|
634
|
0 |
3 |
if (reqrep_compute_layout(req_cap, resp_slots_n, resp_data_max, arena_hint, |
|
637
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap/arena_hint too large for uint32 offsets"); |
|
641
|
3 |
0 |
int fd = memfd_create(name ? name : "reqrep", MFD_CLOEXEC | MFD_ALLOW_SEALING); |
|
642
|
0 |
3 |
if (fd < 0) { REQREP_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { REQREP_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
644
|
0 |
3 |
if (ftruncate(fd, (off_t)total_size) < 0) { |
|
645
|
0 |
0 |
REQREP_ERR("ftruncate(memfd): %s", strerror(errno)); |
|
651
|
0 |
3 |
if (base == MAP_FAILED) { |
|
652
|
0 |
0 |
REQREP_ERR("mmap(memfd): %s", strerror(errno)); |
|
661
|
0 |
3 |
if (!h) { munmap(base, (size_t)total_size); close(fd); return NULL; } |
|
666
|
4 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
669
|
0 |
4 |
if (fstat(fd, &st) < 0) { |
|
670
|
0 |
0 |
REQREP_ERR("fstat(fd=%d): %s", fd, strerror(errno)); |
|
674
|
0 |
4 |
if ((uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
675
|
0 |
0 |
REQREP_ERR("fd %d: too small (%lld)", fd, (long long)st.st_size); |
|
681
|
0 |
4 |
if (base == MAP_FAILED) { |
|
682
|
0 |
0 |
REQREP_ERR("mmap(fd=%d): %s", fd, strerror(errno)); |
|
686
|
0 |
4 |
if (!reqrep_validate_header((ReqRepHeader *)base, map_size, mode)) { |
|
687
|
0 |
0 |
REQREP_ERR("fd %d: invalid or incompatible reqrep", fd); |
|
693
|
0 |
4 |
if (myfd < 0) { |
|
694
|
0 |
0 |
REQREP_ERR("fcntl(F_DUPFD_CLOEXEC): %s", strerror(errno)); |
|
700
|
0 |
4 |
if (!h) { munmap(base, map_size); close(myfd); return NULL; } |
|
705
|
0 |
112 |
if (!h) return; |
|
706
|
8 |
104 |
if (h->notify_fd >= 0) close(h->notify_fd); |
|
707
|
10 |
102 |
if (h->reply_fd >= 0) close(h->reply_fd); |
|
708
|
8 |
104 |
if (h->backing_fd >= 0) close(h->backing_fd); |
|
709
|
112 |
0 |
if (h->hdr) munmap(h->hdr, h->mmap_size); |
|
725
|
0 |
2863 |
if (len > REQREP_STR_LEN_MASK) return -2; |
|
727
|
4 |
2859 |
if (hdr->req_tail - hdr->req_head >= h->req_cap) { |
|
733
|
4 |
2855 |
if (alloc == 0) alloc = 8; |
|
735
|
0 |
2859 |
if (alloc > h->req_arena_cap) return -2; |
|
739
|
1 |
2858 |
if ((uint64_t)pos + alloc > h->req_arena_cap) { |
|
744
|
1 |
2858 |
if ((uint64_t)hdr->arena_used + skip > h->req_arena_cap) { |
|
745
|
0 |
1 |
if (hdr->req_tail == hdr->req_head) { |
|
761
|
4 |
2854 |
slot->packed_len = len | (utf8 ? REQREP_UTF8_FLAG : 0); |
|
779
|
1 |
2863 |
if (slot < 0) return -3; |
|
788
|
2858 |
5 |
if (r == 1) { |
|
802
|
1 |
2764 |
if (r == 1 || r == -2) return r; |
|
|
0 |
1 |
if (r == 1 || r == -2) return r; |
|
803
|
0 |
1 |
if (timeout == 0) return r; |
|
808
|
1 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
811
|
0 |
1 |
uint32_t *futex_word = (r == -3) ? &hdr->slot_futex : &hdr->send_futex; |
|
812
|
0 |
1 |
uint32_t *waiter_cnt = (r == -3) ? &hdr->slot_waiters : &hdr->send_waiters; |
|
816
|
1 |
0 |
if (r == 1 || r == -2) return r; |
|
|
0 |
1 |
if (r == 1 || r == -2) return r; |
|
820
|
1 |
0 |
if (has_deadline) { |
|
821
|
0 |
1 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
831
|
1 |
0 |
if (r == 1 || r == -2) return r; |
|
|
0 |
1 |
if (r == 1 || r == -2) return r; |
|
832
|
1 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
|
1 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
842
|
1495 |
2252 |
if (hdr->req_tail == hdr->req_head) { |
|
854
|
0 |
2252 |
if (!reqrep_ensure_copy_buf(h, len + 1)) |
|
856
|
2248 |
4 |
if (len > 0) |
|
862
|
2252 |
0 |
if (hdr->arena_used >= slot->arena_skip) |
|
866
|
1095 |
1157 |
if (hdr->arena_used == 0) |
|
880
|
2230 |
1489 |
if (r == 1) reqrep_wake_producers(h->hdr); |
|
889
|
1403 |
751 |
if (r != 0) return r; |
|
890
|
0 |
751 |
if (timeout == 0) return 0; |
|
895
|
751 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
900
|
28 |
723 |
if (r != 0) return r; |
|
904
|
723 |
0 |
if (has_deadline) { |
|
905
|
0 |
723 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
915
|
718 |
5 |
if (r != 0) return r; |
|
916
|
5 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
|
5 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
930
|
0 |
2249 |
if (slot_idx >= h->resp_slots) return -1; |
|
931
|
1 |
2248 |
if (len > h->resp_data_max) return -3; |
|
935
|
193 |
2055 |
if (state != RESP_ACQUIRED) return -2; |
|
936
|
8 |
2047 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -2; |
|
939
|
2043 |
4 |
if (len > 0) memcpy(data, str, len); |
|
945
|
0 |
2047 |
if (!__atomic_compare_exchange_n(&slot->state, &expected_state, RESP_READY, |
|
949
|
1838 |
209 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
961
|
0 |
4718 |
if (slot_idx >= h->resp_slots) return -1; |
|
965
|
5 |
4713 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -4; |
|
966
|
2074 |
2639 |
if (state != RESP_READY) return 0; |
|
971
|
0 |
2639 |
if (!reqrep_ensure_copy_buf(h, len + 1)) return -2; |
|
974
|
2635 |
4 |
if (len > 0) memcpy(h->copy_buf, data, len); |
|
988
|
481 |
2073 |
if (r != 0) return r; |
|
989
|
0 |
2073 |
if (timeout == 0) return 0; |
|
995
|
1762 |
311 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
999
|
0 |
2074 |
if (state == RESP_READY) |
|
1005
|
0 |
2074 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != REQREP_ID_GEN(id)) { |
|
1011
|
0 |
2074 |
if (state == RESP_READY) { |
|
1017
|
1763 |
311 |
if (has_deadline) { |
|
1018
|
1 |
1762 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1029
|
2072 |
1 |
if (r != 0) return r; |
|
1038
|
0 |
218 |
if (slot_idx >= h->resp_slots) return; |
|
1040
|
0 |
218 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return; |
|
1042
|
207 |
11 |
if (__atomic_compare_exchange_n(&slot->state, &expected_state, RESP_FREE, |
|
1047
|
1 |
206 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1061
|
1801 |
747 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1064
|
0 |
2548 |
if (r != 1) return r; |
|
1067
|
1801 |
747 |
if (has_deadline) { |
|
1072
|
0 |
1801 |
if (get_timeout <= 0) { |
|
1079
|
1 |
2547 |
if (r != 1) { |
|
1092
|
68 |
10 |
for (uint32_t i = 0; i < h->resp_slots; i++) { |
|
1095
|
61 |
7 |
if ((state == RESP_ACQUIRED || state == RESP_READY) && |
|
|
0 |
61 |
if ((state == RESP_ACQUIRED || state == RESP_READY) && |
|
1096
|
7 |
0 |
__atomic_load_n(&slot->owner_pid, __ATOMIC_RELAXED) == mypid) |
|
1124
|
4 |
1 |
for (uint32_t i = 0; i < h->resp_slots; i++) { |
|
1127
|
2 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
|
0 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
1128
|
2 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &state, RESP_FREE, |
|
1132
|
0 |
2 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1158
|
0 |
6 |
if (h->notify_fd >= 0) return h->notify_fd; |
|
1164
|
0 |
2 |
if (h->notify_fd >= 0 && h->notify_fd != fd) |
|
|
0 |
0 |
if (h->notify_fd >= 0 && h->notify_fd != fd) |
|
1170
|
3 |
0 |
if (h->notify_fd >= 0) { |
|
1177
|
0 |
2 |
if (h->notify_fd < 0) return -1; |
|
1179
|
0 |
2 |
if (read(h->notify_fd, &val, sizeof(val)) != sizeof(val)) return -1; |
|
1184
|
0 |
9 |
if (h->reply_fd >= 0) return h->reply_fd; |
|
1190
|
0 |
1 |
if (h->reply_fd >= 0 && h->reply_fd != fd) |
|
|
0 |
0 |
if (h->reply_fd >= 0 && h->reply_fd != fd) |
|
1196
|
4 |
0 |
if (h->reply_fd >= 0) { |
|
1203
|
0 |
2 |
if (h->reply_fd < 0) return -1; |
|
1205
|
0 |
2 |
if (read(h->reply_fd, &val, sizeof(val)) != sizeof(val)) return -1; |
|
1221
|
0 |
8 |
if (resp_off > UINT32_MAX) return -1; |
|
1247
|
202 |
7 |
for (uint32_t i = 0; i < req_cap; i++) |
|
1251
|
51 |
7 |
for (uint32_t i = 0; i < resp_slots_n; i++) { |
|
1261
|
7 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
1263
|
0 |
7 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
|
0 |
0 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
1264
|
0 |
7 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
|
0 |
0 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
1268
|
0 |
7 |
if (reqrep_int_compute_layout(req_cap, resp_slots_n, &req_slots_off, |
|
1270
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap too large for uint32 offsets"); |
|
1278
|
0 |
7 |
if (anonymous) { |
|
1282
|
0 |
0 |
if (base == MAP_FAILED) { REQREP_ERR("mmap(anonymous): %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { REQREP_ERR("mmap(anonymous): %s", strerror(errno)); return NULL; } |
|
1285
|
0 |
7 |
if (fd < 0) { REQREP_ERR("open(%s): %s", path, strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { REQREP_ERR("open(%s): %s", path, strerror(errno)); return NULL; } |
|
1286
|
0 |
7 |
if (flock(fd, LOCK_EX) < 0) { REQREP_ERR("flock: %s", strerror(errno)); close(fd); return NULL; } |
|
|
0 |
0 |
if (flock(fd, LOCK_EX) < 0) { REQREP_ERR("flock: %s", strerror(errno)); close(fd); return NULL; } |
|
1288
|
0 |
7 |
if (fstat(fd, &st) < 0) { REQREP_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
|
0 |
0 |
if (fstat(fd, &st) < 0) { REQREP_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
1290
|
1 |
6 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
|
0 |
1 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
1291
|
0 |
0 |
REQREP_ERR("%s: file too small", path); flock(fd, LOCK_UN); close(fd); return NULL; |
|
1293
|
6 |
1 |
if (is_new && ftruncate(fd, (off_t)total_size) < 0) { |
|
|
0 |
6 |
if (is_new && ftruncate(fd, (off_t)total_size) < 0) { |
|
1294
|
0 |
0 |
REQREP_ERR("ftruncate: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; |
|
1296
|
1 |
6 |
map_size = is_new ? (size_t)total_size : (size_t)st.st_size; |
|
1298
|
0 |
7 |
if (base == MAP_FAILED) { REQREP_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { REQREP_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
1299
|
1 |
6 |
if (!is_new) { |
|
1300
|
0 |
1 |
if (!reqrep_validate_header((ReqRepHeader *)base, map_size, REQREP_MODE_INT)) { |
|
1301
|
0 |
0 |
REQREP_ERR("%s: invalid or incompatible", path); munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL; |
|
1319
|
1 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
1321
|
0 |
1 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
|
0 |
0 |
if (req_cap == 0) { REQREP_ERR("invalid req_cap"); return NULL; } |
|
1322
|
0 |
1 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
|
0 |
0 |
if (resp_slots_n == 0) { REQREP_ERR("resp_slots must be > 0"); return NULL; } |
|
1326
|
0 |
1 |
if (reqrep_int_compute_layout(req_cap, resp_slots_n, &req_slots_off, |
|
1328
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap too large for uint32 offsets"); |
|
1332
|
1 |
0 |
int fd = memfd_create(name ? name : "reqrep_int", MFD_CLOEXEC | MFD_ALLOW_SEALING); |
|
1333
|
0 |
1 |
if (fd < 0) { REQREP_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { REQREP_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
1334
|
0 |
1 |
if (ftruncate(fd, (off_t)total_size) < 0) { |
|
1335
|
0 |
0 |
REQREP_ERR("ftruncate: %s", strerror(errno)); close(fd); return NULL; |
|
1339
|
0 |
1 |
if (base == MAP_FAILED) { REQREP_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { REQREP_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; } |
|
1350
|
1 |
39 |
if (rslot < 0) return -3; |
|
1364
|
38 |
1 |
if (diff == 0) { |
|
1365
|
38 |
0 |
if (__atomic_compare_exchange_n(&hdr->req_tail, &pos, pos + 1, |
|
1376
|
1 |
0 |
} else if (diff < 0) { |
|
1389
|
8 |
0 |
if (r == 1) return 1; |
|
1390
|
0 |
0 |
if (timeout == 0) return r; |
|
1394
|
0 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1397
|
0 |
0 |
uint32_t *futex_word = (r == -3) ? &hdr->slot_futex : &hdr->send_futex; |
|
1398
|
0 |
0 |
uint32_t *waiter_cnt = (r == -3) ? &hdr->slot_waiters : &hdr->send_waiters; |
|
1402
|
0 |
0 |
if (r == 1) return 1; |
|
1406
|
0 |
0 |
if (has_deadline) { |
|
1407
|
0 |
0 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1416
|
0 |
0 |
if (r == 1) return 1; |
|
1417
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
1430
|
36 |
10 |
if (diff == 0) { |
|
1431
|
36 |
0 |
if (__atomic_compare_exchange_n(&hdr->req_head, &pos, pos + 1, |
|
1439
|
10 |
0 |
} else if (diff < 0) { |
|
1450
|
3 |
4 |
if (reqrep_int_try_recv(h, out_value, out_id)) return 1; |
|
1451
|
0 |
4 |
if (timeout == 0) return 0; |
|
1455
|
4 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1458
|
0 |
4 |
if (reqrep_int_try_recv(h, out_value, out_id)) return 1; |
|
1461
|
4 |
0 |
if (has_deadline) { |
|
1462
|
0 |
4 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1470
|
4 |
0 |
if (reqrep_int_try_recv(h, out_value, out_id)) return 1; |
|
1471
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
1480
|
0 |
35 |
if (slot_idx >= h->resp_slots) return -1; |
|
1484
|
2 |
33 |
if (state != RESP_ACQUIRED) return -2; |
|
1485
|
1 |
32 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -2; |
|
1490
|
0 |
32 |
if (!__atomic_compare_exchange_n(&slot->state, &expected_state, RESP_READY, |
|
1494
|
5 |
27 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1503
|
0 |
40 |
if (slot_idx >= h->resp_slots) return -1; |
|
1507
|
1 |
39 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -4; |
|
1508
|
7 |
32 |
if (state != RESP_READY) return 0; |
|
1518
|
2 |
6 |
if (r != 0) return r; |
|
1519
|
0 |
6 |
if (timeout == 0) return 0; |
|
1524
|
1 |
5 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1527
|
0 |
7 |
if (state == RESP_READY) |
|
1530
|
0 |
7 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != REQREP_ID_GEN(id)) { |
|
1535
|
0 |
7 |
if (state == RESP_READY) { |
|
1540
|
2 |
5 |
if (has_deadline) { |
|
1541
|
1 |
1 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1550
|
5 |
1 |
if (r != 0) return r; |
|
1559
|
1 |
5 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1561
|
0 |
6 |
if (r != 1) return r; |
|
1563
|
1 |
5 |
if (has_deadline) { |
|
1568
|
0 |
1 |
if (get_timeout <= 0) { reqrep_cancel(h, id); return 0; } |
|
1571
|
1 |
5 |
if (r != 1) { |
|
1593
|
16 |
1 |
for (uint32_t i = 0; i < h->req_cap; i++) |
|
1598
|
4 |
1 |
for (uint32_t i = 0; i < h->resp_slots; i++) { |
|
1601
|
2 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
|
0 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
1602
|
2 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &state, RESP_FREE, |
|
1606
|
0 |
2 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |