uringmachine 0.19.1 → 0.20.0

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -1
  3. data/TODO.md +0 -1
  4. data/examples/bm_fileno.rb +33 -0
  5. data/examples/bm_mutex.rb +85 -0
  6. data/examples/bm_mutex_single.rb +33 -0
  7. data/examples/bm_queue.rb +27 -28
  8. data/examples/bm_send.rb +2 -5
  9. data/examples/bm_snooze.rb +20 -42
  10. data/examples/fiber_scheduler_demo.rb +15 -51
  11. data/examples/fiber_scheduler_fork.rb +24 -0
  12. data/examples/nc_ssl.rb +71 -0
  13. data/ext/um/extconf.rb +5 -15
  14. data/ext/um/um.c +57 -41
  15. data/ext/um/um.h +21 -11
  16. data/ext/um/um_async_op_class.c +2 -2
  17. data/ext/um/um_buffer.c +1 -1
  18. data/ext/um/um_class.c +94 -23
  19. data/ext/um/um_const.c +51 -3
  20. data/ext/um/um_mutex_class.c +1 -1
  21. data/ext/um/um_queue_class.c +1 -1
  22. data/ext/um/um_stream.c +5 -5
  23. data/ext/um/um_stream_class.c +3 -0
  24. data/ext/um/um_sync.c +22 -27
  25. data/ext/um/um_utils.c +59 -19
  26. data/grant-2025/journal.md +229 -0
  27. data/grant-2025/tasks.md +66 -0
  28. data/lib/uringmachine/fiber_scheduler.rb +180 -48
  29. data/lib/uringmachine/version.rb +1 -1
  30. data/lib/uringmachine.rb +6 -0
  31. data/test/test_fiber_scheduler.rb +138 -0
  32. data/test/test_stream.rb +2 -2
  33. data/test/test_um.rb +427 -34
  34. data/vendor/liburing/.github/workflows/ci.yml +94 -1
  35. data/vendor/liburing/.github/workflows/test_build.c +9 -0
  36. data/vendor/liburing/configure +27 -0
  37. data/vendor/liburing/examples/Makefile +6 -0
  38. data/vendor/liburing/examples/helpers.c +8 -0
  39. data/vendor/liburing/examples/helpers.h +5 -0
  40. data/vendor/liburing/liburing.spec +1 -1
  41. data/vendor/liburing/src/Makefile +9 -3
  42. data/vendor/liburing/src/include/liburing/barrier.h +11 -5
  43. data/vendor/liburing/src/include/liburing/io_uring/query.h +41 -0
  44. data/vendor/liburing/src/include/liburing/io_uring.h +50 -0
  45. data/vendor/liburing/src/include/liburing/sanitize.h +16 -4
  46. data/vendor/liburing/src/include/liburing.h +445 -121
  47. data/vendor/liburing/src/liburing-ffi.map +15 -0
  48. data/vendor/liburing/src/liburing.map +8 -0
  49. data/vendor/liburing/src/sanitize.c +4 -1
  50. data/vendor/liburing/src/setup.c +7 -4
  51. data/vendor/liburing/test/232c93d07b74.c +4 -16
  52. data/vendor/liburing/test/Makefile +15 -1
  53. data/vendor/liburing/test/accept.c +2 -13
  54. data/vendor/liburing/test/conn-unreach.c +132 -0
  55. data/vendor/liburing/test/fd-pass.c +32 -7
  56. data/vendor/liburing/test/fdinfo.c +39 -12
  57. data/vendor/liburing/test/fifo-futex-poll.c +114 -0
  58. data/vendor/liburing/test/fifo-nonblock-read.c +1 -12
  59. data/vendor/liburing/test/futex.c +1 -1
  60. data/vendor/liburing/test/helpers.c +99 -2
  61. data/vendor/liburing/test/helpers.h +9 -0
  62. data/vendor/liburing/test/io_uring_passthrough.c +6 -12
  63. data/vendor/liburing/test/mock_file.c +379 -0
  64. data/vendor/liburing/test/mock_file.h +47 -0
  65. data/vendor/liburing/test/nop.c +2 -2
  66. data/vendor/liburing/test/nop32-overflow.c +150 -0
  67. data/vendor/liburing/test/nop32.c +126 -0
  68. data/vendor/liburing/test/pipe.c +166 -0
  69. data/vendor/liburing/test/poll-race-mshot.c +13 -1
  70. data/vendor/liburing/test/recv-mshot-fair.c +81 -34
  71. data/vendor/liburing/test/recvsend_bundle.c +1 -1
  72. data/vendor/liburing/test/resize-rings.c +2 -0
  73. data/vendor/liburing/test/ring-query.c +322 -0
  74. data/vendor/liburing/test/ringbuf-loop.c +87 -0
  75. data/vendor/liburing/test/runtests.sh +2 -2
  76. data/vendor/liburing/test/send-zerocopy.c +43 -5
  77. data/vendor/liburing/test/send_recv.c +102 -32
  78. data/vendor/liburing/test/shutdown.c +2 -12
  79. data/vendor/liburing/test/socket-nb.c +3 -14
  80. data/vendor/liburing/test/socket-rw-eagain.c +2 -12
  81. data/vendor/liburing/test/socket-rw-offset.c +2 -12
  82. data/vendor/liburing/test/socket-rw.c +2 -12
  83. data/vendor/liburing/test/sqe-mixed-bad-wrap.c +87 -0
  84. data/vendor/liburing/test/sqe-mixed-nop.c +82 -0
  85. data/vendor/liburing/test/sqe-mixed-uring_cmd.c +153 -0
  86. data/vendor/liburing/test/timestamp.c +56 -19
  87. data/vendor/liburing/test/vec-regbuf.c +2 -4
  88. data/vendor/liburing/test/wq-aff.c +7 -0
  89. metadata +24 -2
@@ -15,13 +15,15 @@
15
15
  #include "liburing.h"
16
16
  #include "helpers.h"
17
17
 
18
- static char str[] = "This is a test of send and recv over io_uring!";
18
+ #define MAX_MSG 4096
19
19
 
20
- #define MAX_MSG 128
20
+ static unsigned long str[MAX_MSG / sizeof(unsigned long)];
21
21
 
22
22
  #define PORT 10202
23
23
  #define HOST "127.0.0.1"
24
24
 
25
+ static int no_send_vec;
26
+
25
27
  static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock,
26
28
  int registerfiles, int async, int provide)
27
29
  {
@@ -86,7 +88,8 @@ err:
86
88
  static int do_recv(struct io_uring *ring, struct iovec *iov, int enobufs)
87
89
  {
88
90
  struct io_uring_cqe *cqe;
89
- int ret;
91
+ unsigned long *ptr;
92
+ int i, ret;
90
93
 
91
94
  ret = io_uring_wait_cqe(ring, &cqe);
92
95
  if (ret) {
@@ -109,14 +112,16 @@ static int do_recv(struct io_uring *ring, struct iovec *iov, int enobufs)
109
112
  goto err;
110
113
  }
111
114
 
112
- if (cqe->res -1 != strlen(str)) {
113
- fprintf(stderr, "got wrong length: %d/%d\n", cqe->res,
114
- (int) strlen(str) + 1);
115
+ if (cqe->res != MAX_MSG) {
116
+ fprintf(stderr, "got wrong length: %d/%d\n", cqe->res, MAX_MSG);
115
117
  goto err;
116
118
  }
117
119
 
118
- if (strcmp(str, iov->iov_base)) {
119
- fprintf(stderr, "string mismatch\n");
120
+ ptr = iov->iov_base;
121
+ for (i = 0; i < MAX_MSG / sizeof(unsigned long); i++) {
122
+ if (ptr[i] == str[i])
123
+ continue;
124
+ fprintf(stderr, "data mismatch at %d: %lu\n", i, ptr[i]);
120
125
  goto err;
121
126
  }
122
127
 
@@ -183,13 +188,10 @@ err:
183
188
  return (void *)(intptr_t)ret;
184
189
  }
185
190
 
186
- static int do_send(void)
191
+ static int do_send(int async, int vec, int big_vec)
187
192
  {
188
193
  struct sockaddr_in saddr;
189
- struct iovec iov = {
190
- .iov_base = str,
191
- .iov_len = sizeof(str),
192
- };
194
+ struct iovec vecs[32];
193
195
  struct io_uring ring;
194
196
  struct io_uring_cqe *cqe;
195
197
  struct io_uring_sqe *sqe;
@@ -218,8 +220,37 @@ static int do_send(void)
218
220
  goto err;
219
221
  }
220
222
 
223
+ retry:
221
224
  sqe = io_uring_get_sqe(&ring);
222
- io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0);
225
+ if (vec) {
226
+ size_t total = MAX_MSG;
227
+ unsigned long *ptr = str;
228
+ int i, nvecs;
229
+
230
+ if (!big_vec) {
231
+ vecs[0].iov_base = str;
232
+ vecs[0].iov_len = MAX_MSG / 2;
233
+ vecs[1].iov_base = &str[256];
234
+ vecs[1].iov_len = MAX_MSG / 2;
235
+ nvecs = 2;
236
+ } else {
237
+ total /= 32;
238
+
239
+ for (i = 0; i < 32; i++) {
240
+ vecs[i].iov_base = ptr;
241
+ vecs[i].iov_len = total;
242
+ ptr += total / sizeof(unsigned long);
243
+ }
244
+ nvecs = 32;
245
+ }
246
+
247
+ io_uring_prep_send(sqe, sockfd, vecs, nvecs, 0);
248
+ sqe->ioprio = (1U << 5);
249
+ } else {
250
+ io_uring_prep_send(sqe, sockfd, str, sizeof(str), 0);
251
+ }
252
+ if (async)
253
+ sqe->flags |= IOSQE_ASYNC;
223
254
  sqe->user_data = 1;
224
255
 
225
256
  ret = io_uring_submit(&ring);
@@ -230,10 +261,16 @@ static int do_send(void)
230
261
 
231
262
  ret = io_uring_wait_cqe(&ring, &cqe);
232
263
  if (cqe->res == -EINVAL) {
264
+ if (vec) {
265
+ vec = 0;
266
+ no_send_vec = 1;
267
+ io_uring_cqe_seen(&ring, cqe);
268
+ goto retry;
269
+ }
233
270
  fprintf(stdout, "send not supported, skipping\n");
234
271
  goto err;
235
272
  }
236
- if (cqe->res != iov.iov_len) {
273
+ if (cqe->res != sizeof(str)) {
237
274
  fprintf(stderr, "failed cqe: %d\n", cqe->res);
238
275
  goto err;
239
276
  }
@@ -249,7 +286,8 @@ err2:
249
286
  return 1;
250
287
  }
251
288
 
252
- static int test(int use_sqthread, int regfiles, int async, int provide)
289
+ static int test(int use_sqthread, int regfiles, int async, int provide, int vec,
290
+ int big_vec)
253
291
  {
254
292
  pthread_mutexattr_t attr;
255
293
  pthread_t recv_thread;
@@ -257,6 +295,9 @@ static int test(int use_sqthread, int regfiles, int async, int provide)
257
295
  int ret;
258
296
  void *retval;
259
297
 
298
+ if (vec && no_send_vec)
299
+ return T_EXIT_SKIP;
300
+
260
301
  pthread_mutexattr_init(&attr);
261
302
  pthread_mutexattr_setpshared(&attr, 1);
262
303
  pthread_mutex_init(&rd.mutex, &attr);
@@ -274,7 +315,7 @@ static int test(int use_sqthread, int regfiles, int async, int provide)
274
315
  }
275
316
 
276
317
  pthread_mutex_lock(&rd.mutex);
277
- do_send();
318
+ do_send(async, vec, big_vec);
278
319
  pthread_join(recv_thread, &retval);
279
320
  return (intptr_t)retval;
280
321
  }
@@ -325,10 +366,13 @@ static int test_invalid(void)
325
366
 
326
367
  int main(int argc, char *argv[])
327
368
  {
328
- int ret;
369
+ int i, ret;
329
370
 
330
371
  if (argc > 1)
331
- return 0;
372
+ return T_EXIT_SKIP;
373
+
374
+ for (i = 0; i < MAX_MSG / sizeof(unsigned long); i++)
375
+ str[i] = i + 1;
332
376
 
333
377
  ret = test_invalid();
334
378
  if (ret) {
@@ -336,77 +380,103 @@ int main(int argc, char *argv[])
336
380
  return ret;
337
381
  }
338
382
 
339
- ret = test(0, 0, 1, 1);
383
+ ret = test(0, 0, 1, 1, 0, 0);
340
384
  if (ret) {
341
385
  fprintf(stderr, "test sqthread=0 1 1 failed\n");
342
386
  return ret;
343
387
  }
344
388
 
345
- ret = test(1, 1, 1, 1);
389
+ ret = test(1, 1, 1, 1, 0, 0);
346
390
  if (ret) {
347
391
  fprintf(stderr, "test sqthread=1 reg=1 1 1 failed\n");
348
392
  return ret;
349
393
  }
350
394
 
351
- ret = test(1, 0, 1, 1);
395
+ ret = test(1, 0, 1, 1, 0, 0);
352
396
  if (ret) {
353
397
  fprintf(stderr, "test sqthread=1 reg=0 1 1 failed\n");
354
398
  return ret;
355
399
  }
356
400
 
357
- ret = test(0, 0, 0, 1);
401
+ ret = test(0, 0, 0, 1, 0, 0);
358
402
  if (ret) {
359
403
  fprintf(stderr, "test sqthread=0 0 1 failed\n");
360
404
  return ret;
361
405
  }
362
406
 
363
- ret = test(1, 1, 0, 1);
407
+ ret = test(1, 1, 0, 1, 0, 0);
364
408
  if (ret) {
365
409
  fprintf(stderr, "test sqthread=1 reg=1 0 1 failed\n");
366
410
  return ret;
367
411
  }
368
412
 
369
- ret = test(1, 0, 0, 1);
413
+ ret = test(1, 0, 0, 1, 0, 0);
370
414
  if (ret) {
371
415
  fprintf(stderr, "test sqthread=1 reg=0 0 1 failed\n");
372
416
  return ret;
373
417
  }
374
418
 
375
- ret = test(0, 0, 1, 0);
419
+ ret = test(0, 0, 1, 0, 0, 0);
376
420
  if (ret) {
377
421
  fprintf(stderr, "test sqthread=0 0 1 failed\n");
378
422
  return ret;
379
423
  }
380
424
 
381
- ret = test(1, 1, 1, 0);
425
+ ret = test(1, 1, 1, 0, 0, 0);
382
426
  if (ret) {
383
427
  fprintf(stderr, "test sqthread=1 reg=1 1 0 failed\n");
384
428
  return ret;
385
429
  }
386
430
 
387
- ret = test(1, 0, 1, 0);
431
+ ret = test(1, 0, 1, 0, 0, 0);
388
432
  if (ret) {
389
433
  fprintf(stderr, "test sqthread=1 reg=0 1 0 failed\n");
390
434
  return ret;
391
435
  }
392
436
 
393
- ret = test(0, 0, 0, 0);
437
+ ret = test(0, 0, 0, 0, 0, 0);
394
438
  if (ret) {
395
439
  fprintf(stderr, "test sqthread=0 0 0 failed\n");
396
440
  return ret;
397
441
  }
398
442
 
399
- ret = test(1, 1, 0, 0);
443
+ ret = test(1, 1, 0, 0, 0, 0);
400
444
  if (ret) {
401
445
  fprintf(stderr, "test sqthread=1 reg=1 0 0 failed\n");
402
446
  return ret;
403
447
  }
404
448
 
405
- ret = test(1, 0, 0, 0);
449
+ ret = test(1, 0, 0, 0, 0, 0);
406
450
  if (ret) {
407
451
  fprintf(stderr, "test sqthread=1 reg=0 0 0 failed\n");
408
452
  return ret;
409
453
  }
410
454
 
411
- return 0;
455
+ ret = test(0, 0, 0, 0, 1, 0);
456
+ if (ret) {
457
+ fprintf(stderr, "test small vec sync failed\n");
458
+ return ret;
459
+ }
460
+ if (no_send_vec)
461
+ return T_EXIT_PASS;
462
+
463
+ ret = test(0, 0, 1, 0, 1, 0);
464
+ if (ret) {
465
+ fprintf(stderr, "test small vec async failed\n");
466
+ return ret;
467
+ }
468
+
469
+ ret = test(0, 0, 0, 0, 1, 1);
470
+ if (ret) {
471
+ fprintf(stderr, "test big vec sync failed\n");
472
+ return ret;
473
+ }
474
+
475
+ ret = test(0, 0, 1, 0, 1, 1);
476
+ if (ret) {
477
+ fprintf(stderr, "test big vec async failed\n");
478
+ return ret;
479
+ }
480
+
481
+ return T_EXIT_PASS;
412
482
  }
@@ -58,22 +58,12 @@ int main(int argc, char *argv[])
58
58
  ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
59
59
  assert(ret != -1);
60
60
 
61
- int32_t flags = fcntl(p_fd[1], F_GETFL, 0);
62
- assert(flags != -1);
63
-
64
- flags |= O_NONBLOCK;
65
- ret = fcntl(p_fd[1], F_SETFL, flags);
66
- assert(ret != -1);
61
+ t_set_nonblock(p_fd[1]);
67
62
 
68
63
  ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr));
69
64
  assert(ret == -1);
70
65
 
71
- flags = fcntl(p_fd[1], F_GETFL, 0);
72
- assert(flags != -1);
73
-
74
- flags &= ~O_NONBLOCK;
75
- ret = fcntl(p_fd[1], F_SETFL, flags);
76
- assert(ret != -1);
66
+ t_clear_nonblock(p_fd[1]);
77
67
 
78
68
  p_fd[0] = accept(recv_s0, NULL, NULL);
79
69
  assert(p_fd[0] != -1);
@@ -51,12 +51,7 @@ static int test(int o_nonblock, int msg_dontwait)
51
51
  ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
52
52
  assert(ret != -1);
53
53
 
54
- flags = fcntl(p_fd[1], F_GETFL, 0);
55
- assert(flags != -1);
56
-
57
- flags |= O_NONBLOCK;
58
- ret = fcntl(p_fd[1], F_SETFL, flags);
59
- assert(ret != -1);
54
+ t_set_nonblock(p_fd[1]);
60
55
 
61
56
  ret = connect(p_fd[1], (struct sockaddr *) &addr, sizeof(addr));
62
57
  assert(ret == -1);
@@ -64,14 +59,8 @@ static int test(int o_nonblock, int msg_dontwait)
64
59
  p_fd[0] = accept(recv_s0, NULL, NULL);
65
60
  assert(p_fd[0] != -1);
66
61
 
67
- if (o_nonblock) {
68
- flags = fcntl(p_fd[0], F_GETFL, 0);
69
- assert(flags != -1);
70
-
71
- flags |= O_NONBLOCK;
72
- ret = fcntl(p_fd[0], F_SETFL, flags);
73
- assert(ret != -1);
74
- }
62
+ if (o_nonblock)
63
+ t_set_nonblock(p_fd[0]);
75
64
 
76
65
  while (1) {
77
66
  int32_t code;
@@ -53,12 +53,7 @@ int main(int argc, char *argv[])
53
53
  ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
54
54
  assert(ret != -1);
55
55
 
56
- int32_t flags = fcntl(p_fd[1], F_GETFL, 0);
57
- assert(flags != -1);
58
-
59
- flags |= O_NONBLOCK;
60
- ret = fcntl(p_fd[1], F_SETFL, flags);
61
- assert(ret != -1);
56
+ t_set_nonblock(p_fd[1]);
62
57
 
63
58
  ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr));
64
59
  assert(ret == -1);
@@ -66,12 +61,7 @@ int main(int argc, char *argv[])
66
61
  p_fd[0] = accept(recv_s0, NULL, NULL);
67
62
  assert(p_fd[0] != -1);
68
63
 
69
- flags = fcntl(p_fd[0], F_GETFL, 0);
70
- assert(flags != -1);
71
-
72
- flags |= O_NONBLOCK;
73
- ret = fcntl(p_fd[0], F_SETFL, flags);
74
- assert(ret != -1);
64
+ t_set_nonblock(p_fd[0]);
75
65
 
76
66
  while (1) {
77
67
  int32_t code;
@@ -56,22 +56,12 @@ int main(int argc, char *argv[])
56
56
  ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
57
57
  assert(ret != -1);
58
58
 
59
- int32_t flags = fcntl(p_fd[1], F_GETFL, 0);
60
- assert(flags != -1);
61
-
62
- flags |= O_NONBLOCK;
63
- ret = fcntl(p_fd[1], F_SETFL, flags);
64
- assert(ret != -1);
59
+ t_set_nonblock(p_fd[1]);
65
60
 
66
61
  ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr));
67
62
  assert(ret == -1);
68
63
 
69
- flags = fcntl(p_fd[1], F_GETFL, 0);
70
- assert(flags != -1);
71
-
72
- flags &= ~O_NONBLOCK;
73
- ret = fcntl(p_fd[1], F_SETFL, flags);
74
- assert(ret != -1);
64
+ t_clear_nonblock(p_fd[1]);
75
65
 
76
66
  p_fd[0] = accept(recv_s0, NULL, NULL);
77
67
  assert(p_fd[0] != -1);
@@ -56,22 +56,12 @@ int main(int argc, char *argv[])
56
56
  ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
57
57
  assert(ret != -1);
58
58
 
59
- int32_t flags = fcntl(p_fd[1], F_GETFL, 0);
60
- assert(flags != -1);
61
-
62
- flags |= O_NONBLOCK;
63
- ret = fcntl(p_fd[1], F_SETFL, flags);
64
- assert(ret != -1);
59
+ t_set_nonblock(p_fd[1]);
65
60
 
66
61
  ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr));
67
62
  assert(ret == -1);
68
63
 
69
- flags = fcntl(p_fd[1], F_GETFL, 0);
70
- assert(flags != -1);
71
-
72
- flags &= ~O_NONBLOCK;
73
- ret = fcntl(p_fd[1], F_SETFL, flags);
74
- assert(ret != -1);
64
+ t_clear_nonblock(p_fd[1]);
75
65
 
76
66
  p_fd[0] = accept(recv_s0, NULL, NULL);
77
67
  assert(p_fd[0] != -1);
@@ -0,0 +1,87 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: run various nop tests
4
+ *
5
+ */
6
+ #include <stdio.h>
7
+
8
+ #include "liburing.h"
9
+ #include "helpers.h"
10
+ #include "test.h"
11
+
12
+ static int seq;
13
+
14
+ static int test_single_nop(struct io_uring *ring, bool should_fail)
15
+ {
16
+ struct io_uring_cqe *cqe;
17
+ struct io_uring_sqe *sqe;
18
+ int ret;
19
+
20
+ sqe = io_uring_get_sqe(ring);
21
+ if (!sqe) {
22
+ fprintf(stderr, "get sqe failed\n");
23
+ return T_EXIT_FAIL;
24
+ }
25
+
26
+ if (should_fail)
27
+ io_uring_prep_nop128(sqe);
28
+ else
29
+ io_uring_prep_nop(sqe);
30
+ sqe->user_data = ++seq;
31
+
32
+ ret = io_uring_submit(ring);
33
+ if (ret <= 0) {
34
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
35
+ return T_EXIT_FAIL;
36
+ }
37
+
38
+ ret = io_uring_wait_cqe(ring, &cqe);
39
+ if (ret < 0) {
40
+ fprintf(stderr, "wait completion %d\n", ret);
41
+ } else if (should_fail && cqe->res == 0) {
42
+ fprintf(stderr, "Unexpected success\n");
43
+ } else if (!should_fail && cqe->res != 0) {
44
+ fprintf(stderr, "Completion error:%d\n", cqe->res);
45
+ } else if (cqe->res == 0 && cqe->user_data != seq) {
46
+ fprintf(stderr, "Unexpected user_data: %ld\n", (long) cqe->user_data);
47
+ } else {
48
+ io_uring_cqe_seen(ring, cqe);
49
+ return T_EXIT_PASS;
50
+ }
51
+ return T_EXIT_FAIL;
52
+ }
53
+
54
+ int main(int argc, char *argv[])
55
+ {
56
+ struct io_uring ring;
57
+ int ret, i;
58
+
59
+ if (argc > 1)
60
+ return T_EXIT_SKIP;
61
+
62
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_SQE_MIXED);
63
+ if (ret) {
64
+ if (ret == -EINVAL)
65
+ return T_EXIT_SKIP;
66
+ fprintf(stderr, "ring setup failed: %d\n", ret);
67
+ return T_EXIT_FAIL;
68
+ }
69
+
70
+ /* prime the sq to the last entry before wrapping */
71
+ for (i = 0; i < 7; i++) {
72
+ ret = test_single_nop(&ring, false);
73
+ if (ret != T_EXIT_PASS)
74
+ goto done;
75
+ }
76
+
77
+ /* inserting a 128b sqe in the last entry should fail */
78
+ ret = test_single_nop(&ring, true);
79
+ if (ret != T_EXIT_PASS)
80
+ goto done;
81
+
82
+ /* proceeding from the bad wrap should succeed */
83
+ ret = test_single_nop(&ring, false);
84
+ done:
85
+ io_uring_queue_exit(&ring);
86
+ return ret;
87
+ }
@@ -0,0 +1,82 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: run various nop tests
4
+ *
5
+ */
6
+ #include <stdio.h>
7
+
8
+ #include "liburing.h"
9
+ #include "helpers.h"
10
+ #include "test.h"
11
+
12
+ static int seq;
13
+
14
+ static int test_single_nop(struct io_uring *ring, bool sqe128)
15
+ {
16
+ struct io_uring_cqe *cqe;
17
+ struct io_uring_sqe *sqe;
18
+ int ret;
19
+
20
+ if (sqe128)
21
+ sqe = io_uring_get_sqe128(ring);
22
+ else
23
+ sqe = io_uring_get_sqe(ring);
24
+
25
+ if (!sqe) {
26
+ fprintf(stderr, "get sqe failed\n");
27
+ return T_EXIT_FAIL;
28
+ }
29
+
30
+ if (sqe128)
31
+ io_uring_prep_nop128(sqe);
32
+ else
33
+ io_uring_prep_nop(sqe);
34
+
35
+ sqe->user_data = ++seq;
36
+
37
+ ret = io_uring_submit(ring);
38
+ if (ret <= 0) {
39
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
40
+ return T_EXIT_FAIL;
41
+ }
42
+
43
+ ret = io_uring_wait_cqe(ring, &cqe);
44
+ if (ret < 0) {
45
+ fprintf(stderr, "wait completion %d\n", ret);
46
+ } else if (cqe->res != 0) {
47
+ fprintf(stderr, "Completion error:%d\n", cqe->res);
48
+ } else if (cqe->user_data != seq) {
49
+ fprintf(stderr, "Unexpected user_data: %ld\n", (long) cqe->user_data);
50
+ } else {
51
+ io_uring_cqe_seen(ring, cqe);
52
+ return T_EXIT_PASS;
53
+ }
54
+ return T_EXIT_FAIL;
55
+ }
56
+
57
+ int main(int argc, char *argv[])
58
+ {
59
+ struct io_uring ring;
60
+ int ret, i;
61
+
62
+ if (argc > 1)
63
+ return T_EXIT_SKIP;
64
+
65
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_SQE_MIXED);
66
+ if (ret) {
67
+ if (ret == -EINVAL)
68
+ return T_EXIT_SKIP;
69
+ fprintf(stderr, "ring setup failed: %d\n", ret);
70
+ return T_EXIT_FAIL;
71
+ }
72
+
73
+ /* alternate big and little sqe's */
74
+ for (i = 0; i < 32; i++) {
75
+ ret = test_single_nop(&ring, i & 1);
76
+ if (ret != T_EXIT_PASS)
77
+ break;
78
+ }
79
+
80
+ io_uring_queue_exit(&ring);
81
+ return ret;
82
+ }