| 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
|
6169 |
78 |
if (__atomic_compare_exchange_n(&hdr->mutex, &expected, mypid, |
|
237
|
78 |
0 |
if (__builtin_expect(spin < REQREP_SPIN_LIMIT, 1)) { |
|
243
|
0 |
0 |
if (cur != 0) { |
|
246
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) { |
|
249
|
0 |
0 |
if (val >= REQREP_MUTEX_WRITER_BIT) { |
|
251
|
0 |
0 |
if (!reqrep_pid_alive(pid)) |
|
265
|
0 |
6169 |
if (__atomic_load_n(&hdr->mutex_waiters, __ATOMIC_RELAXED) > 0) |
|
270
|
1365 |
1533 |
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 |
2891 |
if (__atomic_load_n(&hdr->slot_waiters, __ATOMIC_RELAXED) > 0) { |
|
296
|
2295 |
7 |
if (remaining->tv_nsec < 0) { |
|
307
|
1777 |
2350 |
if (deadline->tv_nsec >= 1000000000L) { |
|
322
|
3096 |
2 |
for (uint32_t i = 0; i < n; i++) { |
|
326
|
2902 |
194 |
if (__atomic_compare_exchange_n(&slot->state, &expected, RESP_ACQUIRED, |
|
348
|
4 |
2 |
for (uint32_t i = 0; i < n; i++) { |
|
351
|
0 |
4 |
if (state != RESP_ACQUIRED && state != RESP_READY) continue; |
|
|
0 |
0 |
if (state != RESP_ACQUIRED && state != RESP_READY) continue; |
|
353
|
4 |
0 |
if (!pid || reqrep_pid_alive(pid)) continue; |
|
|
4 |
0 |
if (!pid || reqrep_pid_alive(pid)) continue; |
|
359
|
0 |
0 |
if (!__atomic_compare_exchange_n(&slot->owner_pid, &expected_pid, 0, |
|
368
|
0 |
0 |
while (cur_state != RESP_FREE) { |
|
369
|
0 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &cur_state, RESP_FREE, |
|
377
|
0 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &expected, RESP_ACQUIRED, |
|
409
|
0 |
2677 |
if (!__atomic_compare_exchange_n(&slot->owner_pid, &expected_pid, 0, |
|
434
|
0 |
112 |
if (!h) return NULL; |
|
447
|
103 |
9 |
h->path = path ? strdup(path) : NULL; |
|
456
|
0 |
55 |
if (hdr->magic != REQREP_MAGIC) return 0; |
|
457
|
0 |
55 |
if (hdr->version != REQREP_VERSION) return 0; |
|
458
|
0 |
55 |
if (hdr->mode != expected_mode) return 0; |
|
459
|
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; |
|
460
|
0 |
55 |
if (hdr->total_size != (uint64_t)file_size) return 0; |
|
461
|
0 |
55 |
if (hdr->req_slots_off != sizeof(ReqRepHeader)) return 0; |
|
462
|
0 |
55 |
if (hdr->resp_slots == 0) return 0; |
|
463
|
0 |
55 |
if (hdr->resp_stride < sizeof(RespSlotHeader)) return 0; |
|
467
|
0 |
55 |
if ((uint64_t)hdr->resp_stride < (uint64_t)sizeof(RespSlotHeader) + hdr->resp_data_max) return 0; |
|
473
|
0 |
55 |
if (req_slots_end > hdr->total_size) return 0; |
|
474
|
45 |
10 |
if (expected_mode == REQREP_MODE_STR) { |
|
475
|
0 |
45 |
if (hdr->req_arena_off < req_slots_end) return 0; |
|
476
|
0 |
45 |
if ((uint64_t)hdr->req_arena_off + hdr->req_arena_cap > hdr->total_size) return 0; |
|
478
|
0 |
45 |
if (hdr->resp_off < (uint64_t)hdr->req_arena_off + hdr->req_arena_cap) return 0; |
|
480
|
0 |
55 |
if (hdr->resp_off < req_slots_end) return 0; |
|
481
|
0 |
55 |
if ((uint64_t)hdr->resp_off + (uint64_t)hdr->resp_slots * hdr->resp_stride > hdr->total_size) return 0; |
|
505
|
898 |
50 |
for (uint32_t i = 0; i < resp_slots_n; i++) { |
|
522
|
0 |
51 |
if (req_arena_off_64 > UINT32_MAX) return -1; |
|
525
|
0 |
51 |
if (arena_hint > UINT32_MAX) return -1; |
|
527
|
15 |
36 |
if (req_arena_cap < 4096) req_arena_cap = 4096; |
|
535
|
0 |
51 |
if (resp_stride_64 > UINT32_MAX) return -1; |
|
538
|
0 |
51 |
if (resp_off_64 > UINT32_MAX) return -1; |
|
553
|
48 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
556
|
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; } |
|
557
|
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; } |
|
559
|
46 |
2 |
if (arena_hint == 0) arena_hint = (uint64_t)req_cap * 256; |
|
563
|
0 |
48 |
if (reqrep_compute_layout(req_cap, resp_slots_n, resp_data_max, arena_hint, |
|
566
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap/arena_hint too large for uint32 offsets"); |
|
574
|
1 |
47 |
if (anonymous) { |
|
578
|
0 |
1 |
if (base == MAP_FAILED) { |
|
579
|
0 |
0 |
REQREP_ERR("mmap(anonymous): %s", strerror(errno)); |
|
587
|
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; } |
|
589
|
0 |
47 |
if (flock(fd, LOCK_EX) < 0) { |
|
590
|
0 |
0 |
REQREP_ERR("flock(%s): %s", path, strerror(errno)); |
|
595
|
0 |
47 |
if (fstat(fd, &st) < 0) { |
|
596
|
0 |
0 |
REQREP_ERR("fstat(%s): %s", path, strerror(errno)); |
|
602
|
1 |
46 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
|
0 |
1 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
603
|
0 |
0 |
REQREP_ERR("%s: file too small (%lld)", path, (long long)st.st_size); |
|
607
|
46 |
1 |
if (is_new) { |
|
608
|
0 |
46 |
if (ftruncate(fd, (off_t)total_size) < 0) { |
|
609
|
0 |
0 |
REQREP_ERR("ftruncate(%s): %s", path, strerror(errno)); |
|
614
|
1 |
46 |
map_size = is_new ? (size_t)total_size : (size_t)st.st_size; |
|
616
|
0 |
47 |
if (base == MAP_FAILED) { |
|
617
|
0 |
0 |
REQREP_ERR("mmap(%s): %s", path, strerror(errno)); |
|
621
|
1 |
46 |
if (!is_new) { |
|
622
|
0 |
1 |
if (!reqrep_validate_header((ReqRepHeader *)base, (size_t)st.st_size, REQREP_MODE_STR)) { |
|
623
|
0 |
0 |
REQREP_ERR("%s: invalid or incompatible reqrep file", path); |
|
629
|
0 |
1 |
if (!h) { munmap(base, map_size); return NULL; } |
|
641
|
0 |
47 |
if (!h) { munmap(base, map_size); return NULL; } |
|
646
|
49 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
647
|
0 |
49 |
if (!path) { REQREP_ERR("path required"); return NULL; } |
|
|
0 |
0 |
if (!path) { REQREP_ERR("path required"); return NULL; } |
|
650
|
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; } |
|
652
|
0 |
49 |
if (flock(fd, LOCK_EX) < 0) { |
|
653
|
0 |
0 |
REQREP_ERR("flock(%s): %s", path, strerror(errno)); |
|
658
|
0 |
49 |
if (fstat(fd, &st) < 0) { |
|
659
|
0 |
0 |
REQREP_ERR("fstat(%s): %s", path, strerror(errno)); |
|
663
|
0 |
49 |
if ((uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
664
|
0 |
0 |
REQREP_ERR("%s: file too small or not initialized", path); |
|
670
|
0 |
49 |
if (base == MAP_FAILED) { |
|
671
|
0 |
0 |
REQREP_ERR("mmap(%s): %s", path, strerror(errno)); |
|
675
|
0 |
49 |
if (!reqrep_validate_header((ReqRepHeader *)base, map_size, mode)) { |
|
676
|
0 |
0 |
REQREP_ERR("%s: invalid or incompatible reqrep file", path); |
|
684
|
0 |
49 |
if (!h) { munmap(base, map_size); return NULL; } |
|
691
|
3 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
694
|
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; } |
|
695
|
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; } |
|
697
|
3 |
0 |
if (arena_hint == 0) arena_hint = (uint64_t)req_cap * 256; |
|
701
|
0 |
3 |
if (reqrep_compute_layout(req_cap, resp_slots_n, resp_data_max, arena_hint, |
|
704
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap/arena_hint too large for uint32 offsets"); |
|
708
|
3 |
0 |
int fd = memfd_create(name ? name : "reqrep", MFD_CLOEXEC | MFD_ALLOW_SEALING); |
|
709
|
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; } |
|
711
|
0 |
3 |
if (ftruncate(fd, (off_t)total_size) < 0) { |
|
712
|
0 |
0 |
REQREP_ERR("ftruncate(memfd): %s", strerror(errno)); |
|
718
|
0 |
3 |
if (base == MAP_FAILED) { |
|
719
|
0 |
0 |
REQREP_ERR("mmap(memfd): %s", strerror(errno)); |
|
728
|
0 |
3 |
if (!h) { munmap(base, (size_t)total_size); close(fd); return NULL; } |
|
733
|
4 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
736
|
0 |
4 |
if (fstat(fd, &st) < 0) { |
|
737
|
0 |
0 |
REQREP_ERR("fstat(fd=%d): %s", fd, strerror(errno)); |
|
741
|
0 |
4 |
if ((uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
742
|
0 |
0 |
REQREP_ERR("fd %d: too small (%lld)", fd, (long long)st.st_size); |
|
748
|
0 |
4 |
if (base == MAP_FAILED) { |
|
749
|
0 |
0 |
REQREP_ERR("mmap(fd=%d): %s", fd, strerror(errno)); |
|
753
|
0 |
4 |
if (!reqrep_validate_header((ReqRepHeader *)base, map_size, mode)) { |
|
754
|
0 |
0 |
REQREP_ERR("fd %d: invalid or incompatible reqrep", fd); |
|
760
|
0 |
4 |
if (myfd < 0) { |
|
761
|
0 |
0 |
REQREP_ERR("fcntl(F_DUPFD_CLOEXEC): %s", strerror(errno)); |
|
767
|
0 |
4 |
if (!h) { munmap(base, map_size); close(myfd); return NULL; } |
|
772
|
0 |
112 |
if (!h) return; |
|
773
|
8 |
104 |
if (h->notify_fd >= 0) close(h->notify_fd); |
|
774
|
10 |
102 |
if (h->reply_fd >= 0) close(h->reply_fd); |
|
775
|
8 |
104 |
if (h->backing_fd >= 0) close(h->backing_fd); |
|
776
|
112 |
0 |
if (h->hdr) munmap(h->hdr, h->mmap_size); |
|
792
|
0 |
2863 |
if (len > REQREP_STR_LEN_MASK) return -2; |
|
794
|
4 |
2859 |
if (hdr->req_tail - hdr->req_head >= h->req_cap) { |
|
800
|
4 |
2855 |
if (alloc == 0) alloc = 8; |
|
802
|
0 |
2859 |
if (alloc > h->req_arena_cap) return -2; |
|
806
|
1 |
2858 |
if ((uint64_t)pos + alloc > h->req_arena_cap) { |
|
811
|
1 |
2858 |
if ((uint64_t)hdr->arena_used + skip > h->req_arena_cap) { |
|
812
|
0 |
1 |
if (hdr->req_tail == hdr->req_head) { |
|
828
|
4 |
2854 |
slot->packed_len = len | (utf8 ? REQREP_UTF8_FLAG : 0); |
|
846
|
1 |
2863 |
if (slot < 0) return -3; |
|
855
|
2858 |
5 |
if (r == 1) { |
|
869
|
1 |
2764 |
if (r == 1 || r == -2) return r; |
|
|
0 |
1 |
if (r == 1 || r == -2) return r; |
|
870
|
0 |
1 |
if (timeout == 0) return r; |
|
875
|
1 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
878
|
0 |
1 |
uint32_t *futex_word = (r == -3) ? &hdr->slot_futex : &hdr->send_futex; |
|
879
|
0 |
1 |
uint32_t *waiter_cnt = (r == -3) ? &hdr->slot_waiters : &hdr->send_waiters; |
|
883
|
1 |
0 |
if (r == 1 || r == -2) return r; |
|
|
0 |
1 |
if (r == 1 || r == -2) return r; |
|
887
|
1 |
0 |
if (has_deadline) { |
|
888
|
0 |
1 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
898
|
1 |
0 |
if (r == 1 || r == -2) return r; |
|
|
0 |
1 |
if (r == 1 || r == -2) return r; |
|
899
|
1 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
|
1 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
909
|
1072 |
2252 |
if (hdr->req_tail == hdr->req_head) { |
|
921
|
0 |
2252 |
if (!reqrep_ensure_copy_buf(h, len + 1)) |
|
923
|
2248 |
4 |
if (len > 0) |
|
929
|
2252 |
0 |
if (hdr->arena_used >= slot->arena_skip) |
|
933
|
1127 |
1125 |
if (hdr->arena_used == 0) |
|
947
|
2230 |
1066 |
if (r == 1) reqrep_wake_producers(h->hdr); |
|
956
|
1616 |
538 |
if (r != 0) return r; |
|
957
|
0 |
538 |
if (timeout == 0) return 0; |
|
962
|
538 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
967
|
25 |
513 |
if (r != 0) return r; |
|
971
|
513 |
0 |
if (has_deadline) { |
|
972
|
0 |
513 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
982
|
508 |
5 |
if (r != 0) return r; |
|
983
|
5 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
|
5 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
1011
|
0 |
2249 |
if (slot_idx >= h->resp_slots) return -1; |
|
1012
|
1 |
2248 |
if (len > h->resp_data_max) return -3; |
|
1016
|
194 |
2054 |
if (state != RESP_ACQUIRED) return -2; |
|
1017
|
11 |
2043 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -2; |
|
1020
|
2039 |
4 |
if (len > 0) memcpy(data, str, len); |
|
1026
|
1 |
2042 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) |
|
1031
|
0 |
2042 |
if (!__atomic_compare_exchange_n(&slot->state, &expected_state, RESP_READY, |
|
1039
|
0 |
2042 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) { |
|
1043
|
0 |
0 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1049
|
1921 |
121 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1061
|
0 |
5173 |
if (slot_idx >= h->resp_slots) return -1; |
|
1065
|
5 |
5168 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -4; |
|
1066
|
2529 |
2639 |
if (state != RESP_READY) return 0; |
|
1071
|
0 |
2639 |
if (!reqrep_ensure_copy_buf(h, len + 1)) return -2; |
|
1074
|
2635 |
4 |
if (len > 0) memcpy(h->copy_buf, data, len); |
|
1090
|
26 |
2528 |
if (r != 0) return r; |
|
1091
|
0 |
2528 |
if (timeout == 0) return 0; |
|
1097
|
1781 |
747 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1101
|
0 |
2529 |
if (state == RESP_READY) |
|
1107
|
0 |
2529 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != REQREP_ID_GEN(id)) { |
|
1113
|
0 |
2529 |
if (state == RESP_READY) { |
|
1119
|
1782 |
747 |
if (has_deadline) { |
|
1120
|
1 |
1781 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1131
|
2527 |
1 |
if (r != 0) return r; |
|
1140
|
0 |
218 |
if (slot_idx >= h->resp_slots) return; |
|
1142
|
0 |
218 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return; |
|
1144
|
212 |
6 |
if (__atomic_compare_exchange_n(&slot->state, &expected_state, RESP_FREE, |
|
1149
|
1 |
211 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1163
|
1801 |
747 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1166
|
0 |
2548 |
if (r != 1) return r; |
|
1169
|
1801 |
747 |
if (has_deadline) { |
|
1174
|
0 |
1801 |
if (get_timeout <= 0) { |
|
1181
|
1 |
2547 |
if (r != 1) { |
|
1196
|
68 |
10 |
for (uint32_t i = 0; i < h->resp_slots; i++) { |
|
1199
|
61 |
7 |
if ((state == RESP_ACQUIRED || state == RESP_READY) && |
|
|
0 |
61 |
if ((state == RESP_ACQUIRED || state == RESP_READY) && |
|
1200
|
7 |
0 |
__atomic_load_n(&slot->owner_pid, __ATOMIC_ACQUIRE) == mypid) |
|
1217
|
40 |
0 |
return (tail >= head) ? (tail - head) : 0; |
|
1231
|
4 |
1 |
for (uint32_t i = 0; i < h->resp_slots; i++) { |
|
1234
|
2 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
|
0 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
1235
|
2 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &state, RESP_FREE, |
|
1239
|
0 |
2 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1265
|
0 |
6 |
if (h->notify_fd >= 0) return h->notify_fd; |
|
1271
|
0 |
2 |
if (h->notify_fd >= 0 && h->notify_fd != fd) |
|
|
0 |
0 |
if (h->notify_fd >= 0 && h->notify_fd != fd) |
|
1277
|
3 |
0 |
if (h->notify_fd >= 0) { |
|
1284
|
0 |
2 |
if (h->notify_fd < 0) return -1; |
|
1286
|
0 |
2 |
if (read(h->notify_fd, &val, sizeof(val)) != sizeof(val)) return -1; |
|
1291
|
0 |
9 |
if (h->reply_fd >= 0) return h->reply_fd; |
|
1297
|
0 |
1 |
if (h->reply_fd >= 0 && h->reply_fd != fd) |
|
|
0 |
0 |
if (h->reply_fd >= 0 && h->reply_fd != fd) |
|
1303
|
4 |
0 |
if (h->reply_fd >= 0) { |
|
1310
|
0 |
2 |
if (h->reply_fd < 0) return -1; |
|
1312
|
0 |
2 |
if (read(h->reply_fd, &val, sizeof(val)) != sizeof(val)) return -1; |
|
1328
|
0 |
8 |
if (resp_off > UINT32_MAX) return -1; |
|
1354
|
202 |
7 |
for (uint32_t i = 0; i < req_cap; i++) |
|
1358
|
51 |
7 |
for (uint32_t i = 0; i < resp_slots_n; i++) { |
|
1368
|
7 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
1370
|
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; } |
|
1371
|
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; } |
|
1375
|
0 |
7 |
if (reqrep_int_compute_layout(req_cap, resp_slots_n, &req_slots_off, |
|
1377
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap too large for uint32 offsets"); |
|
1385
|
0 |
7 |
if (anonymous) { |
|
1389
|
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; } |
|
1392
|
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; } |
|
1393
|
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; } |
|
1395
|
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; } |
|
1397
|
1 |
6 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
|
0 |
1 |
if (!is_new && (uint64_t)st.st_size < sizeof(ReqRepHeader)) { |
|
1398
|
0 |
0 |
REQREP_ERR("%s: file too small", path); flock(fd, LOCK_UN); close(fd); return NULL; |
|
1400
|
6 |
1 |
if (is_new && ftruncate(fd, (off_t)total_size) < 0) { |
|
|
0 |
6 |
if (is_new && ftruncate(fd, (off_t)total_size) < 0) { |
|
1401
|
0 |
0 |
REQREP_ERR("ftruncate: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; |
|
1403
|
1 |
6 |
map_size = is_new ? (size_t)total_size : (size_t)st.st_size; |
|
1405
|
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; } |
|
1406
|
1 |
6 |
if (!is_new) { |
|
1407
|
0 |
1 |
if (!reqrep_validate_header((ReqRepHeader *)base, map_size, REQREP_MODE_INT)) { |
|
1408
|
0 |
0 |
REQREP_ERR("%s: invalid or incompatible", path); munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL; |
|
1412
|
0 |
1 |
if (!h) { munmap(base, map_size); return NULL; } |
|
1419
|
0 |
6 |
if (!h) { munmap(base, map_size); return NULL; } |
|
1426
|
0 |
0 |
if (!h) { munmap(base, map_size); return NULL; } |
|
1432
|
1 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
1434
|
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; } |
|
1435
|
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; } |
|
1439
|
0 |
1 |
if (reqrep_int_compute_layout(req_cap, resp_slots_n, &req_slots_off, |
|
1441
|
0 |
0 |
REQREP_ERR("layout overflow: req_cap too large for uint32 offsets"); |
|
1445
|
1 |
0 |
int fd = memfd_create(name ? name : "reqrep_int", MFD_CLOEXEC | MFD_ALLOW_SEALING); |
|
1446
|
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; } |
|
1447
|
0 |
1 |
if (ftruncate(fd, (off_t)total_size) < 0) { |
|
1448
|
0 |
0 |
REQREP_ERR("ftruncate: %s", strerror(errno)); close(fd); return NULL; |
|
1452
|
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; } |
|
1457
|
0 |
1 |
if (!h) { munmap(base, (size_t)total_size); close(fd); return NULL; } |
|
1465
|
1 |
39 |
if (rslot < 0) return -3; |
|
1479
|
38 |
1 |
if (diff == 0) { |
|
1480
|
38 |
0 |
if (__atomic_compare_exchange_n(&hdr->req_tail, &pos, pos + 1, |
|
1491
|
1 |
0 |
} else if (diff < 0) { |
|
1504
|
8 |
0 |
if (r == 1) return 1; |
|
1505
|
0 |
0 |
if (timeout == 0) return r; |
|
1509
|
0 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1512
|
0 |
0 |
uint32_t *futex_word = (r == -3) ? &hdr->slot_futex : &hdr->send_futex; |
|
1513
|
0 |
0 |
uint32_t *waiter_cnt = (r == -3) ? &hdr->slot_waiters : &hdr->send_waiters; |
|
1517
|
0 |
0 |
if (r == 1) return 1; |
|
1521
|
0 |
0 |
if (has_deadline) { |
|
1522
|
0 |
0 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1531
|
0 |
0 |
if (r == 1) return 1; |
|
1532
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return r; |
|
1545
|
36 |
10 |
if (diff == 0) { |
|
1546
|
36 |
0 |
if (__atomic_compare_exchange_n(&hdr->req_head, &pos, pos + 1, |
|
1554
|
10 |
0 |
} else if (diff < 0) { |
|
1565
|
3 |
4 |
if (reqrep_int_try_recv(h, out_value, out_id)) return 1; |
|
1566
|
0 |
4 |
if (timeout == 0) return 0; |
|
1570
|
4 |
0 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1573
|
0 |
4 |
if (reqrep_int_try_recv(h, out_value, out_id)) return 1; |
|
1576
|
4 |
0 |
if (has_deadline) { |
|
1577
|
0 |
4 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1585
|
4 |
0 |
if (reqrep_int_try_recv(h, out_value, out_id)) return 1; |
|
1586
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT) return 0; |
|
1597
|
0 |
35 |
if (slot_idx >= h->resp_slots) return -1; |
|
1601
|
2 |
33 |
if (state != RESP_ACQUIRED) return -2; |
|
1602
|
1 |
32 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -2; |
|
1607
|
0 |
32 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) |
|
1611
|
0 |
32 |
if (!__atomic_compare_exchange_n(&slot->state, &expected_state, RESP_READY, |
|
1616
|
0 |
32 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) { |
|
1620
|
0 |
0 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1626
|
5 |
27 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |
|
1635
|
0 |
40 |
if (slot_idx >= h->resp_slots) return -1; |
|
1639
|
1 |
39 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != expected_gen) return -4; |
|
1640
|
7 |
32 |
if (state != RESP_READY) return 0; |
|
1651
|
2 |
6 |
if (r != 0) return r; |
|
1652
|
0 |
6 |
if (timeout == 0) return 0; |
|
1657
|
1 |
5 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1660
|
0 |
7 |
if (state == RESP_READY) |
|
1663
|
0 |
7 |
if (__atomic_load_n(&slot->generation, __ATOMIC_ACQUIRE) != REQREP_ID_GEN(id)) { |
|
1668
|
0 |
7 |
if (state == RESP_READY) { |
|
1673
|
2 |
5 |
if (has_deadline) { |
|
1674
|
1 |
1 |
if (!reqrep_remaining_time(&deadline, &remaining)) { |
|
1683
|
5 |
1 |
if (r != 0) return r; |
|
1692
|
1 |
5 |
if (has_deadline) reqrep_make_deadline(timeout, &deadline); |
|
1694
|
0 |
6 |
if (r != 1) return r; |
|
1696
|
1 |
5 |
if (has_deadline) { |
|
1701
|
0 |
1 |
if (get_timeout <= 0) { reqrep_cancel(h, id); return 0; } |
|
1704
|
1 |
5 |
if (r != 1) { |
|
1717
|
6 |
0 |
return (tail >= head) ? (tail - head) : 0; |
|
1728
|
16 |
1 |
for (uint32_t i = 0; i < h->req_cap; i++) |
|
1733
|
4 |
1 |
for (uint32_t i = 0; i < h->resp_slots; i++) { |
|
1736
|
2 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
|
0 |
2 |
while (state == RESP_ACQUIRED || state == RESP_READY) { |
|
1737
|
2 |
0 |
if (__atomic_compare_exchange_n(&slot->state, &state, RESP_FREE, |
|
1741
|
0 |
2 |
if (__atomic_load_n(&slot->waiters, __ATOMIC_RELAXED) > 0) |