uringmachine 0.3 → 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +128 -0
  5. data/TODO.md +14 -0
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_write.rb +56 -0
  8. data/examples/dns_client.rb +12 -0
  9. data/examples/echo_server.rb +18 -40
  10. data/examples/http_server.rb +42 -43
  11. data/examples/inout.rb +19 -0
  12. data/examples/nc.rb +36 -0
  13. data/examples/server_client.rb +64 -0
  14. data/examples/snooze.rb +44 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +24 -23
  17. data/ext/um/um.c +524 -278
  18. data/ext/um/um.h +146 -44
  19. data/ext/um/um_buffer.c +49 -0
  20. data/ext/um/um_class.c +217 -106
  21. data/ext/um/um_const.c +213 -0
  22. data/ext/um/um_ext.c +4 -0
  23. data/ext/um/um_mutex_class.c +47 -0
  24. data/ext/um/um_op.c +86 -114
  25. data/ext/um/um_queue_class.c +58 -0
  26. data/ext/um/um_sync.c +273 -0
  27. data/ext/um/um_utils.c +49 -4
  28. data/lib/uringmachine/dns_resolver.rb +84 -0
  29. data/lib/uringmachine/version.rb +1 -1
  30. data/lib/uringmachine.rb +28 -0
  31. data/supressions/ruby.supp +71 -0
  32. data/test/helper.rb +8 -0
  33. data/test/test_um.rb +685 -46
  34. data/vendor/liburing/.github/workflows/build.yml +29 -1
  35. data/vendor/liburing/.gitignore +6 -0
  36. data/vendor/liburing/CHANGELOG +16 -0
  37. data/vendor/liburing/CONTRIBUTING.md +165 -0
  38. data/vendor/liburing/configure +64 -0
  39. data/vendor/liburing/examples/Makefile +9 -1
  40. data/vendor/liburing/examples/kdigest.c +405 -0
  41. data/vendor/liburing/examples/proxy.c +75 -8
  42. data/vendor/liburing/examples/reg-wait.c +159 -0
  43. data/vendor/liburing/liburing.pc.in +1 -1
  44. data/vendor/liburing/liburing.spec +1 -1
  45. data/vendor/liburing/src/Makefile +16 -2
  46. data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
  47. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  48. data/vendor/liburing/src/include/liburing.h +59 -6
  49. data/vendor/liburing/src/int_flags.h +10 -3
  50. data/vendor/liburing/src/liburing-ffi.map +16 -0
  51. data/vendor/liburing/src/liburing.map +10 -0
  52. data/vendor/liburing/src/queue.c +28 -16
  53. data/vendor/liburing/src/register.c +106 -1
  54. data/vendor/liburing/src/sanitize.c +176 -0
  55. data/vendor/liburing/src/setup.c +47 -19
  56. data/vendor/liburing/src/setup.h +6 -0
  57. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  58. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  59. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  60. data/vendor/liburing/test/917257daa0fe.c +7 -0
  61. data/vendor/liburing/test/Makefile +38 -4
  62. data/vendor/liburing/test/a0908ae19763.c +7 -0
  63. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  64. data/vendor/liburing/test/accept.c +14 -4
  65. data/vendor/liburing/test/b19062a56726.c +7 -0
  66. data/vendor/liburing/test/bind-listen.c +2 -2
  67. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  68. data/vendor/liburing/test/buf-ring.c +2 -0
  69. data/vendor/liburing/test/cmd-discard.c +427 -0
  70. data/vendor/liburing/test/coredump.c +7 -0
  71. data/vendor/liburing/test/cq-overflow.c +13 -1
  72. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  73. data/vendor/liburing/test/defer-taskrun.c +2 -2
  74. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  75. data/vendor/liburing/test/defer.c +2 -2
  76. data/vendor/liburing/test/double-poll-crash.c +1 -1
  77. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  78. data/vendor/liburing/test/eventfd.c +0 -1
  79. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  80. data/vendor/liburing/test/fadvise.c +9 -26
  81. data/vendor/liburing/test/fdinfo.c +9 -1
  82. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  83. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  84. data/vendor/liburing/test/file-register.c +14 -2
  85. data/vendor/liburing/test/file-update.c +1 -1
  86. data/vendor/liburing/test/file-verify.c +27 -16
  87. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  88. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  89. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  90. data/vendor/liburing/test/fsnotify.c +1 -0
  91. data/vendor/liburing/test/futex.c +16 -4
  92. data/vendor/liburing/test/helpers.c +47 -0
  93. data/vendor/liburing/test/helpers.h +6 -0
  94. data/vendor/liburing/test/init-mem.c +5 -3
  95. data/vendor/liburing/test/io-cancel.c +0 -24
  96. data/vendor/liburing/test/io_uring_passthrough.c +4 -0
  97. data/vendor/liburing/test/io_uring_register.c +38 -8
  98. data/vendor/liburing/test/iopoll-leak.c +4 -0
  99. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  100. data/vendor/liburing/test/iopoll.c +3 -3
  101. data/vendor/liburing/test/kallsyms.c +203 -0
  102. data/vendor/liburing/test/link-timeout.c +159 -0
  103. data/vendor/liburing/test/linked-defer-close.c +224 -0
  104. data/vendor/liburing/test/madvise.c +12 -25
  105. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  106. data/vendor/liburing/test/min-timeout.c +0 -25
  107. data/vendor/liburing/test/mkdir.c +6 -0
  108. data/vendor/liburing/test/msg-ring.c +8 -2
  109. data/vendor/liburing/test/napi-test.c +16 -3
  110. data/vendor/liburing/test/no-mmap-inval.c +3 -1
  111. data/vendor/liburing/test/nop.c +44 -0
  112. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  113. data/vendor/liburing/test/open-close.c +40 -0
  114. data/vendor/liburing/test/openat2.c +37 -14
  115. data/vendor/liburing/test/poll-many.c +13 -7
  116. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  117. data/vendor/liburing/test/poll-v-poll.c +6 -3
  118. data/vendor/liburing/test/pollfree.c +148 -0
  119. data/vendor/liburing/test/read-mshot-empty.c +158 -153
  120. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  121. data/vendor/liburing/test/read-mshot.c +282 -27
  122. data/vendor/liburing/test/read-write.c +78 -13
  123. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  124. data/vendor/liburing/test/recv-msgall.c +5 -0
  125. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  126. data/vendor/liburing/test/recvsend_bundle.c +94 -31
  127. data/vendor/liburing/test/reg-fd-only.c +15 -5
  128. data/vendor/liburing/test/reg-wait.c +251 -0
  129. data/vendor/liburing/test/regbuf-clone.c +645 -0
  130. data/vendor/liburing/test/regbuf-merge.c +7 -0
  131. data/vendor/liburing/test/register-restrictions.c +86 -85
  132. data/vendor/liburing/test/rename.c +59 -1
  133. data/vendor/liburing/test/resize-rings.c +643 -0
  134. data/vendor/liburing/test/ringbuf-read.c +5 -0
  135. data/vendor/liburing/test/ringbuf-status.c +5 -1
  136. data/vendor/liburing/test/rsrc_tags.c +1 -1
  137. data/vendor/liburing/test/runtests.sh +16 -1
  138. data/vendor/liburing/test/send-zerocopy.c +59 -0
  139. data/vendor/liburing/test/short-read.c +1 -0
  140. data/vendor/liburing/test/socket.c +43 -0
  141. data/vendor/liburing/test/splice.c +3 -1
  142. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  143. data/vendor/liburing/test/sq-poll-share.c +2 -0
  144. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  145. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  146. data/vendor/liburing/test/sqpoll-sleep.c +40 -33
  147. data/vendor/liburing/test/sqwait.c +136 -0
  148. data/vendor/liburing/test/statx.c +89 -0
  149. data/vendor/liburing/test/stdout.c +2 -0
  150. data/vendor/liburing/test/submit-and-wait.c +1 -25
  151. data/vendor/liburing/test/submit-reuse.c +4 -26
  152. data/vendor/liburing/test/symlink.c +12 -1
  153. data/vendor/liburing/test/sync-cancel.c +56 -22
  154. data/vendor/liburing/test/thread-exit.c +5 -0
  155. data/vendor/liburing/test/timeout-new.c +1 -26
  156. data/vendor/liburing/test/timeout.c +25 -34
  157. data/vendor/liburing/test/unlink.c +94 -1
  158. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  159. data/vendor/liburing/test/waitid.c +62 -8
  160. data/vendor/liburing/test/wq-aff.c +35 -0
  161. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  162. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  163. metadata +37 -6
  164. data/examples/event_loop.rb +0 -69
  165. data/examples/fibers.rb +0 -105
  166. data/examples/http_server_multishot.rb +0 -57
  167. data/examples/http_server_simpler.rb +0 -34
@@ -19,6 +19,7 @@
19
19
 
20
20
  static int nr_msgs;
21
21
  static int use_tcp;
22
+ static int classic_buffers;
22
23
 
23
24
  #define RECV_BIDS 8192
24
25
  #define RECV_BID_MASK (RECV_BIDS - 1)
@@ -113,6 +114,9 @@ static int recv_prep(struct io_uring *ring, struct recv_data *rd, int *sock)
113
114
 
114
115
  pthread_barrier_wait(&rd->connect);
115
116
 
117
+ if (rd->abort)
118
+ goto err;
119
+
116
120
  socklen = sizeof(saddr);
117
121
  use_fd = accept(sockfd, (struct sockaddr *)&saddr, &socklen);
118
122
  if (use_fd < 0) {
@@ -245,13 +249,36 @@ err:
245
249
  return 1;
246
250
  }
247
251
 
252
+ static int provide_classic_buffers(struct io_uring *ring, void *buf, int nbufs, int bgid)
253
+ {
254
+ struct io_uring_sqe *sqe;
255
+ struct io_uring_cqe *cqe;
256
+ int ret;
257
+
258
+ sqe = io_uring_get_sqe(ring);
259
+ io_uring_prep_provide_buffers(sqe, buf, MSG_SIZE, nbufs, bgid, 0);
260
+ io_uring_submit(ring);
261
+
262
+ ret = io_uring_wait_cqe(ring, &cqe);
263
+ if (ret) {
264
+ fprintf(stderr, "provide buffer wait: %d\n", ret);
265
+ return 1;
266
+ }
267
+ if (cqe->res) {
268
+ fprintf(stderr, "provide buffers fail: %d\n", cqe->res);
269
+ return 1;
270
+ }
271
+ io_uring_cqe_seen(ring, cqe);
272
+ return 0;
273
+ }
274
+
248
275
  static void *recv_fn(void *data)
249
276
  {
250
277
  struct recv_data *rd = data;
251
278
  struct io_uring_params p = { };
252
279
  struct io_uring ring;
253
280
  struct io_uring_buf_ring *br;
254
- void *buf, *ptr;
281
+ void *buf = NULL, *ptr;
255
282
  int ret, sock, i;
256
283
 
257
284
  p.cq_entries = 4096;
@@ -264,22 +291,31 @@ static void *recv_fn(void *data)
264
291
  goto err;
265
292
  }
266
293
 
267
- if (posix_memalign(&buf, 4096, MSG_SIZE * RECV_BIDS))
294
+ if (posix_memalign(&buf, sysconf(_SC_PAGESIZE), MSG_SIZE * RECV_BIDS))
268
295
  goto err;
269
296
 
270
- br = io_uring_setup_buf_ring(&ring, RECV_BIDS, RECV_BGID, 0, &ret);
271
- if (!br) {
272
- fprintf(stderr, "failed setting up recv ring %d\n", ret);
273
- goto err;
274
- }
297
+ if (!classic_buffers) {
298
+ br = io_uring_setup_buf_ring(&ring, RECV_BIDS, RECV_BGID, 0, &ret);
299
+ if (!br) {
300
+ if (ret != -EINVAL)
301
+ fprintf(stderr, "failed setting up recv ring %d\n", ret);
302
+ goto err;
303
+ }
275
304
 
276
- ptr = buf;
277
- for (i = 0; i < RECV_BIDS; i++) {
278
- io_uring_buf_ring_add(br, ptr, MSG_SIZE, i, RECV_BID_MASK, i);
279
- ptr += MSG_SIZE;
305
+ ptr = buf;
306
+ for (i = 0; i < RECV_BIDS; i++) {
307
+ io_uring_buf_ring_add(br, ptr, MSG_SIZE, i, RECV_BID_MASK, i);
308
+ ptr += MSG_SIZE;
309
+ }
310
+ io_uring_buf_ring_advance(br, RECV_BIDS);
311
+ rd->recv_buf = buf;
312
+ } else {
313
+ ret = provide_classic_buffers(&ring, buf, RECV_BIDS, RECV_BGID);
314
+ if (ret) {
315
+ fprintf(stderr, "failed providing classic buffers\n");
316
+ goto err;
317
+ }
280
318
  }
281
- io_uring_buf_ring_advance(br, RECV_BIDS);
282
- rd->recv_buf = buf;
283
319
 
284
320
  ret = recv_prep(&ring, rd, &sock);
285
321
  if (ret) {
@@ -293,6 +329,7 @@ static void *recv_fn(void *data)
293
329
  close(rd->accept_fd);
294
330
  io_uring_queue_exit(&ring);
295
331
  err:
332
+ free(buf);
296
333
  return (void *)(intptr_t)ret;
297
334
  }
298
335
 
@@ -402,7 +439,7 @@ static int do_send(struct recv_data *rd)
402
439
  struct io_uring_buf_ring *br;
403
440
  int sockfd, ret, len, i;
404
441
  socklen_t optlen;
405
- void *buf, *ptr;
442
+ void *buf = NULL, *ptr;
406
443
 
407
444
  ret = io_uring_queue_init_params(16, &ring, &p);
408
445
  if (ret) {
@@ -410,29 +447,39 @@ static int do_send(struct recv_data *rd)
410
447
  return 1;
411
448
  }
412
449
  if (!(p.features & IORING_FEAT_RECVSEND_BUNDLE)) {
450
+ rd->abort = 1;
413
451
  no_send_mshot = 1;
452
+ pthread_barrier_wait(&rd->connect);
414
453
  return 0;
415
454
  }
416
455
 
417
- if (posix_memalign(&buf, 4096, MSG_SIZE * nr_msgs))
456
+ if (posix_memalign(&buf, sysconf(_SC_PAGESIZE), MSG_SIZE * nr_msgs))
418
457
  return 1;
419
458
 
420
- br = io_uring_setup_buf_ring(&ring, nr_msgs, SEND_BGID, 0, &ret);
421
- if (!br) {
422
- if (ret == -EINVAL) {
423
- fprintf(stderr, "einval on br setup\n");
424
- return 0;
459
+ if (!classic_buffers) {
460
+ br = io_uring_setup_buf_ring(&ring, nr_msgs, SEND_BGID, 0, &ret);
461
+ if (!br) {
462
+ if (ret == -EINVAL) {
463
+ fprintf(stderr, "einval on br setup\n");
464
+ return 0;
465
+ }
466
+ fprintf(stderr, "failed setting up send ring %d\n", ret);
467
+ return 1;
425
468
  }
426
- fprintf(stderr, "failed setting up send ring %d\n", ret);
427
- return 1;
428
- }
429
469
 
430
- ptr = buf;
431
- for (i = 0; i < nr_msgs; i++) {
432
- io_uring_buf_ring_add(br, ptr, MSG_SIZE, i, nr_msgs - 1, i);
433
- ptr += MSG_SIZE;
470
+ ptr = buf;
471
+ for (i = 0; i < nr_msgs; i++) {
472
+ io_uring_buf_ring_add(br, ptr, MSG_SIZE, i, nr_msgs - 1, i);
473
+ ptr += MSG_SIZE;
474
+ }
475
+ io_uring_buf_ring_advance(br, nr_msgs);
476
+ } else {
477
+ ret = provide_classic_buffers(&ring, buf, nr_msgs, SEND_BGID);
478
+ if (ret) {
479
+ fprintf(stderr, "failed providing classic buffers\n");
480
+ return ret;
481
+ }
434
482
  }
435
- io_uring_buf_ring_advance(br, nr_msgs);
436
483
 
437
484
  memset(&saddr, 0, sizeof(saddr));
438
485
  saddr.sin_family = AF_INET;
@@ -509,6 +556,7 @@ static int do_send(struct recv_data *rd)
509
556
 
510
557
  close(sockfd);
511
558
  io_uring_queue_exit(&ring);
559
+ free(buf);
512
560
  return 0;
513
561
 
514
562
  err:
@@ -516,6 +564,7 @@ err:
516
564
  err2:
517
565
  io_uring_queue_exit(&ring);
518
566
  pthread_barrier_wait(&rd->finish);
567
+ free(buf);
519
568
  return 1;
520
569
  }
521
570
 
@@ -550,8 +599,12 @@ static int test(int backlog, unsigned int max_sends, int *to_eagain,
550
599
  }
551
600
 
552
601
  ret = do_send(&rd);
553
- if (no_send_mshot)
602
+ if (no_send_mshot) {
603
+ fprintf(stderr, "no_send_mshot, aborting (ignore other errors)\n");
604
+ rd.abort = 1;
605
+ pthread_join(recv_thread, &retval);
554
606
  return 0;
607
+ }
555
608
 
556
609
  if (ret)
557
610
  return ret;
@@ -656,7 +709,7 @@ static int test_tcp(void)
656
709
  use_tcp = 1;
657
710
  ret = run_tests(false);
658
711
  if (ret == T_EXIT_FAIL)
659
- fprintf(stderr, "TCP test case failed\n");
712
+ fprintf(stderr, "TCP test case (classic=%d) failed\n", classic_buffers);
660
713
  return ret;
661
714
  }
662
715
 
@@ -668,7 +721,7 @@ static int test_udp(void)
668
721
  use_port++;
669
722
  ret = run_tests(true);
670
723
  if (ret == T_EXIT_FAIL)
671
- fprintf(stderr, "UDP test case failed\n");
724
+ fprintf(stderr, "UDP test case (classic=%d) failed\n", classic_buffers);
672
725
  return ret;
673
726
  }
674
727
 
@@ -679,6 +732,16 @@ int main(int argc, char *argv[])
679
732
  if (argc > 1)
680
733
  return T_EXIT_SKIP;
681
734
 
735
+ ret = test_tcp();
736
+ if (ret != T_EXIT_PASS)
737
+ return ret;
738
+
739
+ ret = test_udp();
740
+ if (ret != T_EXIT_PASS)
741
+ return ret;
742
+
743
+ classic_buffers = 1;
744
+
682
745
  ret = test_tcp();
683
746
  if (ret != T_EXIT_PASS)
684
747
  return ret;
@@ -49,15 +49,16 @@ static int test_nops(struct io_uring *ring, int sq_size, int nr_nops)
49
49
  return T_EXIT_PASS;
50
50
  }
51
51
 
52
- static int test(int nentries)
52
+ static int test(int nentries, int ring_flags)
53
53
  {
54
54
  struct io_uring ring;
55
55
  unsigned values[2];
56
56
  int ret;
57
57
 
58
58
  ret = io_uring_queue_init(nentries, &ring,
59
- IORING_SETUP_REGISTERED_FD_ONLY | IORING_SETUP_NO_MMAP);
60
- if (ret == -EINVAL) {
59
+ IORING_SETUP_REGISTERED_FD_ONLY | IORING_SETUP_NO_MMAP |
60
+ ring_flags);
61
+ if (ret == -EINVAL || ret == -ENOENT) {
61
62
  no_mmap = 1;
62
63
  return T_EXIT_SKIP;
63
64
  } else if (ret == -ENOMEM) {
@@ -110,7 +111,16 @@ int main(int argc, char *argv[])
110
111
  return T_EXIT_SKIP;
111
112
 
112
113
  /* test single normal page */
113
- ret = test(NORMAL_PAGE_ENTRIES);
114
+ ret = test(NORMAL_PAGE_ENTRIES, 0);
115
+ if (ret == T_EXIT_SKIP || no_mmap) {
116
+ return T_EXIT_SKIP;
117
+ } else if (ret != T_EXIT_PASS) {
118
+ fprintf(stderr, "test 8 failed\n");
119
+ return T_EXIT_FAIL;
120
+ }
121
+
122
+ /* test single normal page */
123
+ ret = test(NORMAL_PAGE_ENTRIES, IORING_SETUP_SQPOLL);
114
124
  if (ret == T_EXIT_SKIP || no_mmap) {
115
125
  return T_EXIT_SKIP;
116
126
  } else if (ret != T_EXIT_PASS) {
@@ -119,7 +129,7 @@ int main(int argc, char *argv[])
119
129
  }
120
130
 
121
131
  /* test with entries requiring a huge page */
122
- ret = test(HUGE_PAGE_ENTRIES);
132
+ ret = test(HUGE_PAGE_ENTRIES, 0);
123
133
  if (ret == T_EXIT_SKIP) {
124
134
  return T_EXIT_SKIP;
125
135
  } else if (ret != T_EXIT_PASS) {
@@ -0,0 +1,251 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: Test that registered waits work
4
+ */
5
+ #include <errno.h>
6
+ #include <stdio.h>
7
+ #include <unistd.h>
8
+ #include <stdlib.h>
9
+ #include <string.h>
10
+ #include <fcntl.h>
11
+ #include <sys/time.h>
12
+
13
+ #include "liburing.h"
14
+ #include "helpers.h"
15
+ #include "test.h"
16
+
17
+ static struct io_uring_reg_wait *reg;
18
+
19
+ static int test_invalid_reg2(void)
20
+ {
21
+ struct io_uring ring;
22
+ void *buf, *ptr;
23
+ int ret;
24
+
25
+ io_uring_queue_init(1, &ring, 0);
26
+
27
+ if (posix_memalign(&buf, 4096, 4096))
28
+ return T_EXIT_FAIL;
29
+ memset(buf, 0, 4096);
30
+ ptr = buf + 4096 - 32;
31
+
32
+ ret = io_uring_register_wait_reg(&ring, ptr, 1);
33
+ if (ret != -EINVAL) {
34
+ fprintf(stderr, "register cqwait: %d\n", ret);
35
+ return T_EXIT_FAIL;
36
+ }
37
+
38
+ ptr = buf + (sizeof(struct io_uring_reg_wait) / 2);
39
+ ret = io_uring_register_wait_reg(&ring, ptr, 1);
40
+ if (ret != -EINVAL) {
41
+ fprintf(stderr, "register cqwait: %d\n", ret);
42
+ return T_EXIT_FAIL;
43
+ }
44
+
45
+ free(buf);
46
+ buf = (void *) 0x1000;
47
+ ret = io_uring_register_wait_reg(&ring, buf, 1);
48
+ if (ret != -EFAULT) {
49
+ fprintf(stderr, "register cqwait: %d\n", ret);
50
+ return T_EXIT_FAIL;
51
+ }
52
+
53
+ buf = (void *) 0x1240;
54
+ ret = io_uring_register_wait_reg(&ring, buf, 1);
55
+ if (ret != -EFAULT) {
56
+ fprintf(stderr, "register cqwait: %d\n", ret);
57
+ return T_EXIT_FAIL;
58
+ }
59
+
60
+ buf = (void *) 0x1241;
61
+ ret = io_uring_register_wait_reg(&ring, buf, 1);
62
+ if (ret != -EINVAL) {
63
+ fprintf(stderr, "register cqwait: %d\n", ret);
64
+ return T_EXIT_FAIL;
65
+ }
66
+
67
+ io_uring_queue_exit(&ring);
68
+ return T_EXIT_PASS;
69
+ }
70
+
71
+ static int test_invalid_reg(void)
72
+ {
73
+ struct io_uring_reg_wait *ireg;
74
+ struct io_uring_cqe *cqe;
75
+ struct io_uring ring;
76
+ struct timeval tv;
77
+ void *buf, *ptr;
78
+ int ret;
79
+
80
+ io_uring_queue_init(1, &ring, 0);
81
+
82
+ if (posix_memalign(&buf, 4096, 4096))
83
+ return T_EXIT_FAIL;
84
+ memset(buf, 0, 4096);
85
+ ptr = buf + 512;
86
+ ireg = ptr;
87
+
88
+ ret = io_uring_register_wait_reg(&ring, ireg, 56);
89
+ if (ret) {
90
+ fprintf(stderr, "register cqwait: %d\n", ret);
91
+ return T_EXIT_FAIL;
92
+ }
93
+
94
+ ireg = ptr;
95
+ memset(ireg, 0, sizeof(*ireg));
96
+ ireg->ts.tv_sec = 1;
97
+ ireg->ts.tv_nsec = 0;
98
+ ireg->flags = IORING_REG_WAIT_TS;
99
+
100
+ gettimeofday(&tv, NULL);
101
+ ret = io_uring_submit_and_wait_reg(&ring, &cqe, 1, 0);
102
+ if (ret != -ETIME) {
103
+ fprintf(stderr, "wait_reg failed: %d\n", ret);
104
+ return T_EXIT_FAIL;
105
+ }
106
+
107
+ ret = mtime_since_now(&tv);
108
+ /* allow some slack, should be around 1.1s */
109
+ if (ret < 1000 || ret > 1200) {
110
+ fprintf(stderr, "wait too long or short: %d\n", ret);
111
+ goto err;
112
+ }
113
+
114
+ memset(ireg, 0, sizeof(*ireg));
115
+ ireg->ts.tv_sec = 1;
116
+ ireg->ts.tv_nsec = 0;
117
+ ireg->flags = IORING_REG_WAIT_TS;
118
+
119
+ gettimeofday(&tv, NULL);
120
+ ret = io_uring_submit_and_wait_reg(&ring, &cqe, 1, 56);
121
+ if (ret != -EFAULT) {
122
+ fprintf(stderr, "out-of-range reg_wait failed: %d\n", ret);
123
+ return T_EXIT_FAIL;
124
+ }
125
+
126
+ free(buf);
127
+ io_uring_queue_exit(&ring);
128
+ return T_EXIT_PASS;
129
+ err:
130
+ io_uring_queue_exit(&ring);
131
+ return T_EXIT_FAIL;
132
+ }
133
+
134
+ static int test_invalid_sig(struct io_uring *ring)
135
+ {
136
+ struct io_uring_cqe *cqe;
137
+ sigset_t sig;
138
+ int ret;
139
+
140
+ memset(reg, 0, sizeof(*reg));
141
+ reg->ts.tv_sec = 1;
142
+ reg->ts.tv_nsec = 0;
143
+ reg->sigmask = (unsigned long) &sig;
144
+ reg->sigmask_sz = 1;
145
+
146
+ ret = io_uring_submit_and_wait_reg(ring, &cqe, 1, 0);
147
+ if (ret != -EINVAL) {
148
+ fprintf(stderr, "sigmask_sz failed: %d\n", ret);
149
+ return T_EXIT_FAIL;
150
+ }
151
+
152
+ memset(reg, 0, sizeof(*reg));
153
+ reg->ts.tv_sec = 1;
154
+ reg->ts.tv_nsec = 0;
155
+ reg->sigmask = 100;
156
+ reg->sigmask_sz = 8;
157
+
158
+ ret = io_uring_submit_and_wait_reg(ring, &cqe, 1, 0);
159
+ if (ret != -EFAULT) {
160
+ fprintf(stderr, "sigmask invalid failed: %d\n", ret);
161
+ return T_EXIT_FAIL;
162
+ }
163
+
164
+ return T_EXIT_PASS;
165
+ }
166
+
167
+ static int test_basic(struct io_uring *ring)
168
+ {
169
+ struct io_uring_cqe *cqe;
170
+ struct timeval tv;
171
+ int ret;
172
+
173
+ memset(reg, 0, sizeof(*reg));
174
+ reg->ts.tv_sec = 1;
175
+ reg->ts.tv_nsec = 100000000ULL;
176
+ reg->flags = IORING_REG_WAIT_TS;
177
+
178
+ gettimeofday(&tv, NULL);
179
+ ret = io_uring_submit_and_wait_reg(ring, &cqe, 2, 0);
180
+ if (ret != -ETIME) {
181
+ fprintf(stderr, "submit_and_wait_reg: %d\n", ret);
182
+ goto err;
183
+ }
184
+ ret = mtime_since_now(&tv);
185
+ /* allow some slack, should be around 1.1s */
186
+ if (ret < 1000 || ret > 1200) {
187
+ fprintf(stderr, "wait too long or short: %d\n", ret);
188
+ goto err;
189
+ }
190
+ return T_EXIT_PASS;
191
+ err:
192
+ return T_EXIT_FAIL;
193
+ }
194
+
195
+ static int test_ring(void)
196
+ {
197
+ struct io_uring ring;
198
+ struct io_uring_params p = { };
199
+ int ret;
200
+
201
+ p.flags = 0;
202
+ ret = io_uring_queue_init_params(8, &ring, &p);
203
+ if (ret) {
204
+ fprintf(stderr, "ring setup failed: %d\n", ret);
205
+ return 1;
206
+ }
207
+
208
+ reg = io_uring_setup_reg_wait(&ring, 64, &ret);
209
+ if (!reg) {
210
+ if (ret == -EINVAL)
211
+ return T_EXIT_SKIP;
212
+ fprintf(stderr, "setup_reg_wait: %d\n", ret);
213
+ return T_EXIT_FAIL;
214
+ }
215
+
216
+ ret = test_basic(&ring);
217
+ if (ret == T_EXIT_FAIL) {
218
+ fprintf(stderr, "test failed\n");
219
+ goto err;
220
+ }
221
+
222
+ ret = test_invalid_sig(&ring);
223
+ if (ret == T_EXIT_FAIL) {
224
+ fprintf(stderr, "test_invalid sig failed\n");
225
+ goto err;
226
+ }
227
+
228
+ ret = test_invalid_reg();
229
+ if (ret == T_EXIT_FAIL) {
230
+ fprintf(stderr, "test_invalid_reg failed\n");
231
+ goto err;
232
+ }
233
+
234
+ ret = test_invalid_reg2();
235
+ if (ret == T_EXIT_FAIL) {
236
+ fprintf(stderr, "test_invalid_reg2 failed\n");
237
+ goto err;
238
+ }
239
+
240
+ err:
241
+ io_uring_queue_exit(&ring);
242
+ return ret;
243
+ }
244
+
245
+ int main(int argc, char *argv[])
246
+ {
247
+ if (argc > 1)
248
+ return 0;
249
+
250
+ return test_ring();
251
+ }