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