uringmachine 0.1

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 (307) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +12 -0
  3. data/.github/workflows/test.yml +35 -0
  4. data/.gitignore +59 -0
  5. data/.gitmodules +3 -0
  6. data/CHANGELOG.md +7 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +21 -0
  9. data/README.md +11 -0
  10. data/Rakefile +39 -0
  11. data/TODO.md +0 -0
  12. data/examples/echo_server.rb +52 -0
  13. data/examples/event_loop.rb +69 -0
  14. data/examples/fibers.rb +105 -0
  15. data/examples/http_server.rb +56 -0
  16. data/examples/http_server_multishot.rb +57 -0
  17. data/examples/http_server_simpler.rb +34 -0
  18. data/ext/um/extconf.rb +71 -0
  19. data/ext/um/iou.h +101 -0
  20. data/ext/um/op_ctx.c +138 -0
  21. data/ext/um/ring.c +755 -0
  22. data/ext/um/um.c +267 -0
  23. data/ext/um/um.h +97 -0
  24. data/ext/um/um_class.c +175 -0
  25. data/ext/um/um_ext.c +11 -0
  26. data/ext/um/um_op.c +87 -0
  27. data/ext/um/um_utils.c +23 -0
  28. data/lib/uringmachine/version.rb +3 -0
  29. data/lib/uringmachine.rb +8 -0
  30. data/test/helper.rb +70 -0
  31. data/test/test_iou.rb +876 -0
  32. data/test/test_um.rb +168 -0
  33. data/uringmachine.gemspec +27 -0
  34. data/vendor/liburing/.github/actions/codespell/stopwords +7 -0
  35. data/vendor/liburing/.github/pull_request_template.md +86 -0
  36. data/vendor/liburing/.github/workflows/build.yml +137 -0
  37. data/vendor/liburing/.github/workflows/codespell.yml +25 -0
  38. data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
  39. data/vendor/liburing/.gitignore +41 -0
  40. data/vendor/liburing/CHANGELOG +111 -0
  41. data/vendor/liburing/CITATION.cff +11 -0
  42. data/vendor/liburing/COPYING +502 -0
  43. data/vendor/liburing/COPYING.GPL +339 -0
  44. data/vendor/liburing/LICENSE +20 -0
  45. data/vendor/liburing/Makefile +96 -0
  46. data/vendor/liburing/Makefile.common +7 -0
  47. data/vendor/liburing/Makefile.quiet +11 -0
  48. data/vendor/liburing/README +106 -0
  49. data/vendor/liburing/SECURITY.md +6 -0
  50. data/vendor/liburing/configure +624 -0
  51. data/vendor/liburing/debian/README.Debian +7 -0
  52. data/vendor/liburing/debian/changelog +38 -0
  53. data/vendor/liburing/debian/control +39 -0
  54. data/vendor/liburing/debian/copyright +49 -0
  55. data/vendor/liburing/debian/liburing-dev.install +4 -0
  56. data/vendor/liburing/debian/liburing-dev.manpages +5 -0
  57. data/vendor/liburing/debian/liburing2.install +1 -0
  58. data/vendor/liburing/debian/liburing2.symbols +56 -0
  59. data/vendor/liburing/debian/patches/series +1 -0
  60. data/vendor/liburing/debian/rules +29 -0
  61. data/vendor/liburing/debian/source/format +1 -0
  62. data/vendor/liburing/debian/source/local-options +2 -0
  63. data/vendor/liburing/debian/source/options +1 -0
  64. data/vendor/liburing/debian/watch +3 -0
  65. data/vendor/liburing/examples/Makefile +53 -0
  66. data/vendor/liburing/examples/helpers.c +62 -0
  67. data/vendor/liburing/examples/helpers.h +7 -0
  68. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  69. data/vendor/liburing/examples/io_uring-cp.c +282 -0
  70. data/vendor/liburing/examples/io_uring-test.c +112 -0
  71. data/vendor/liburing/examples/io_uring-udp.c +403 -0
  72. data/vendor/liburing/examples/link-cp.c +193 -0
  73. data/vendor/liburing/examples/napi-busy-poll-client.c +509 -0
  74. data/vendor/liburing/examples/napi-busy-poll-server.c +450 -0
  75. data/vendor/liburing/examples/poll-bench.c +101 -0
  76. data/vendor/liburing/examples/proxy.c +2461 -0
  77. data/vendor/liburing/examples/proxy.h +102 -0
  78. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  79. data/vendor/liburing/examples/send-zerocopy.c +658 -0
  80. data/vendor/liburing/examples/ucontext-cp.c +258 -0
  81. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  82. data/vendor/liburing/liburing.pc.in +12 -0
  83. data/vendor/liburing/liburing.spec +66 -0
  84. data/vendor/liburing/make-debs.sh +55 -0
  85. data/vendor/liburing/src/Makefile +129 -0
  86. data/vendor/liburing/src/arch/aarch64/lib.h +47 -0
  87. data/vendor/liburing/src/arch/aarch64/syscall.h +91 -0
  88. data/vendor/liburing/src/arch/generic/lib.h +17 -0
  89. data/vendor/liburing/src/arch/generic/syscall.h +100 -0
  90. data/vendor/liburing/src/arch/riscv64/lib.h +48 -0
  91. data/vendor/liburing/src/arch/riscv64/syscall.h +100 -0
  92. data/vendor/liburing/src/arch/syscall-defs.h +94 -0
  93. data/vendor/liburing/src/arch/x86/lib.h +11 -0
  94. data/vendor/liburing/src/arch/x86/syscall.h +296 -0
  95. data/vendor/liburing/src/ffi.c +15 -0
  96. data/vendor/liburing/src/include/liburing/barrier.h +81 -0
  97. data/vendor/liburing/src/include/liburing/io_uring.h +818 -0
  98. data/vendor/liburing/src/include/liburing.h +1602 -0
  99. data/vendor/liburing/src/int_flags.h +11 -0
  100. data/vendor/liburing/src/lib.h +52 -0
  101. data/vendor/liburing/src/liburing-ffi.map +211 -0
  102. data/vendor/liburing/src/liburing.map +104 -0
  103. data/vendor/liburing/src/nolibc.c +55 -0
  104. data/vendor/liburing/src/queue.c +468 -0
  105. data/vendor/liburing/src/register.c +374 -0
  106. data/vendor/liburing/src/setup.c +689 -0
  107. data/vendor/liburing/src/setup.h +9 -0
  108. data/vendor/liburing/src/syscall.c +29 -0
  109. data/vendor/liburing/src/syscall.h +53 -0
  110. data/vendor/liburing/src/version.c +21 -0
  111. data/vendor/liburing/test/232c93d07b74.c +305 -0
  112. data/vendor/liburing/test/35fa71a030ca.c +329 -0
  113. data/vendor/liburing/test/500f9fbadef8.c +91 -0
  114. data/vendor/liburing/test/7ad0e4b2f83c.c +94 -0
  115. data/vendor/liburing/test/8a9973408177.c +107 -0
  116. data/vendor/liburing/test/917257daa0fe.c +54 -0
  117. data/vendor/liburing/test/Makefile +297 -0
  118. data/vendor/liburing/test/a0908ae19763.c +59 -0
  119. data/vendor/liburing/test/a4c0b3decb33.c +181 -0
  120. data/vendor/liburing/test/accept-link.c +255 -0
  121. data/vendor/liburing/test/accept-non-empty.c +256 -0
  122. data/vendor/liburing/test/accept-reuse.c +163 -0
  123. data/vendor/liburing/test/accept-test.c +83 -0
  124. data/vendor/liburing/test/accept.c +919 -0
  125. data/vendor/liburing/test/across-fork.c +284 -0
  126. data/vendor/liburing/test/b19062a56726.c +54 -0
  127. data/vendor/liburing/test/b5837bd5311d.c +78 -0
  128. data/vendor/liburing/test/bind-listen.c +408 -0
  129. data/vendor/liburing/test/buf-ring-nommap.c +123 -0
  130. data/vendor/liburing/test/buf-ring-put.c +83 -0
  131. data/vendor/liburing/test/buf-ring.c +473 -0
  132. data/vendor/liburing/test/ce593a6c480a.c +139 -0
  133. data/vendor/liburing/test/close-opath.c +123 -0
  134. data/vendor/liburing/test/config +14 -0
  135. data/vendor/liburing/test/connect-rep.c +204 -0
  136. data/vendor/liburing/test/connect.c +442 -0
  137. data/vendor/liburing/test/coredump.c +60 -0
  138. data/vendor/liburing/test/cq-full.c +97 -0
  139. data/vendor/liburing/test/cq-overflow.c +530 -0
  140. data/vendor/liburing/test/cq-peek-batch.c +103 -0
  141. data/vendor/liburing/test/cq-ready.c +95 -0
  142. data/vendor/liburing/test/cq-size.c +65 -0
  143. data/vendor/liburing/test/d4ae271dfaae.c +96 -0
  144. data/vendor/liburing/test/d77a67ed5f27.c +65 -0
  145. data/vendor/liburing/test/defer-taskrun.c +391 -0
  146. data/vendor/liburing/test/defer-tw-timeout.c +173 -0
  147. data/vendor/liburing/test/defer.c +319 -0
  148. data/vendor/liburing/test/double-poll-crash.c +195 -0
  149. data/vendor/liburing/test/drop-submit.c +94 -0
  150. data/vendor/liburing/test/eeed8b54e0df.c +120 -0
  151. data/vendor/liburing/test/empty-eownerdead.c +45 -0
  152. data/vendor/liburing/test/eploop.c +74 -0
  153. data/vendor/liburing/test/eventfd-disable.c +179 -0
  154. data/vendor/liburing/test/eventfd-reg.c +77 -0
  155. data/vendor/liburing/test/eventfd-ring.c +98 -0
  156. data/vendor/liburing/test/eventfd.c +113 -0
  157. data/vendor/liburing/test/evloop.c +73 -0
  158. data/vendor/liburing/test/exec-target.c +6 -0
  159. data/vendor/liburing/test/exit-no-cleanup.c +117 -0
  160. data/vendor/liburing/test/fadvise.c +202 -0
  161. data/vendor/liburing/test/fallocate.c +265 -0
  162. data/vendor/liburing/test/fc2a85cb02ef.c +132 -0
  163. data/vendor/liburing/test/fd-install.c +500 -0
  164. data/vendor/liburing/test/fd-pass.c +237 -0
  165. data/vendor/liburing/test/fdinfo.c +419 -0
  166. data/vendor/liburing/test/file-register.c +1189 -0
  167. data/vendor/liburing/test/file-update.c +231 -0
  168. data/vendor/liburing/test/file-verify.c +654 -0
  169. data/vendor/liburing/test/files-exit-hang-poll.c +114 -0
  170. data/vendor/liburing/test/files-exit-hang-timeout.c +137 -0
  171. data/vendor/liburing/test/fixed-buf-iter.c +115 -0
  172. data/vendor/liburing/test/fixed-buf-merge.c +101 -0
  173. data/vendor/liburing/test/fixed-hugepage.c +411 -0
  174. data/vendor/liburing/test/fixed-link.c +90 -0
  175. data/vendor/liburing/test/fixed-reuse.c +160 -0
  176. data/vendor/liburing/test/fpos.c +255 -0
  177. data/vendor/liburing/test/fsnotify.c +118 -0
  178. data/vendor/liburing/test/fsync.c +224 -0
  179. data/vendor/liburing/test/futex.c +571 -0
  180. data/vendor/liburing/test/hardlink.c +170 -0
  181. data/vendor/liburing/test/helpers.c +318 -0
  182. data/vendor/liburing/test/helpers.h +108 -0
  183. data/vendor/liburing/test/ignore-single-mmap.c +48 -0
  184. data/vendor/liburing/test/init-mem.c +164 -0
  185. data/vendor/liburing/test/io-cancel.c +561 -0
  186. data/vendor/liburing/test/io_uring_enter.c +264 -0
  187. data/vendor/liburing/test/io_uring_passthrough.c +482 -0
  188. data/vendor/liburing/test/io_uring_register.c +503 -0
  189. data/vendor/liburing/test/io_uring_setup.c +110 -0
  190. data/vendor/liburing/test/iopoll-leak.c +85 -0
  191. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  192. data/vendor/liburing/test/iopoll.c +465 -0
  193. data/vendor/liburing/test/lfs-openat-write.c +119 -0
  194. data/vendor/liburing/test/lfs-openat.c +273 -0
  195. data/vendor/liburing/test/link-timeout.c +1108 -0
  196. data/vendor/liburing/test/link.c +497 -0
  197. data/vendor/liburing/test/link_drain.c +255 -0
  198. data/vendor/liburing/test/madvise.c +195 -0
  199. data/vendor/liburing/test/min-timeout-wait.c +354 -0
  200. data/vendor/liburing/test/min-timeout.c +233 -0
  201. data/vendor/liburing/test/mkdir.c +112 -0
  202. data/vendor/liburing/test/msg-ring-fd.c +331 -0
  203. data/vendor/liburing/test/msg-ring-flags.c +212 -0
  204. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  205. data/vendor/liburing/test/msg-ring.c +467 -0
  206. data/vendor/liburing/test/multicqes_drain.c +429 -0
  207. data/vendor/liburing/test/napi-test.c +215 -0
  208. data/vendor/liburing/test/napi-test.sh +48 -0
  209. data/vendor/liburing/test/no-mmap-inval.c +42 -0
  210. data/vendor/liburing/test/nolibc.c +62 -0
  211. data/vendor/liburing/test/nop-all-sizes.c +99 -0
  212. data/vendor/liburing/test/nop.c +177 -0
  213. data/vendor/liburing/test/nvme.h +169 -0
  214. data/vendor/liburing/test/ooo-file-unreg.c +82 -0
  215. data/vendor/liburing/test/open-close.c +261 -0
  216. data/vendor/liburing/test/open-direct-link.c +188 -0
  217. data/vendor/liburing/test/open-direct-pick.c +180 -0
  218. data/vendor/liburing/test/openat2.c +312 -0
  219. data/vendor/liburing/test/personality.c +204 -0
  220. data/vendor/liburing/test/pipe-bug.c +95 -0
  221. data/vendor/liburing/test/pipe-eof.c +83 -0
  222. data/vendor/liburing/test/pipe-reuse.c +105 -0
  223. data/vendor/liburing/test/poll-cancel-all.c +496 -0
  224. data/vendor/liburing/test/poll-cancel-ton.c +135 -0
  225. data/vendor/liburing/test/poll-cancel.c +228 -0
  226. data/vendor/liburing/test/poll-link.c +221 -0
  227. data/vendor/liburing/test/poll-many.c +230 -0
  228. data/vendor/liburing/test/poll-mshot-overflow.c +265 -0
  229. data/vendor/liburing/test/poll-mshot-update.c +323 -0
  230. data/vendor/liburing/test/poll-race-mshot.c +276 -0
  231. data/vendor/liburing/test/poll-race.c +105 -0
  232. data/vendor/liburing/test/poll-ring.c +48 -0
  233. data/vendor/liburing/test/poll-v-poll.c +353 -0
  234. data/vendor/liburing/test/poll.c +327 -0
  235. data/vendor/liburing/test/probe.c +135 -0
  236. data/vendor/liburing/test/read-before-exit.c +129 -0
  237. data/vendor/liburing/test/read-mshot-empty.c +153 -0
  238. data/vendor/liburing/test/read-mshot.c +404 -0
  239. data/vendor/liburing/test/read-write.c +1013 -0
  240. data/vendor/liburing/test/recv-msgall-stream.c +398 -0
  241. data/vendor/liburing/test/recv-msgall.c +263 -0
  242. data/vendor/liburing/test/recv-multishot.c +602 -0
  243. data/vendor/liburing/test/recvsend_bundle.c +691 -0
  244. data/vendor/liburing/test/reg-fd-only.c +131 -0
  245. data/vendor/liburing/test/reg-hint.c +56 -0
  246. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  247. data/vendor/liburing/test/regbuf-merge.c +91 -0
  248. data/vendor/liburing/test/register-restrictions.c +633 -0
  249. data/vendor/liburing/test/rename.c +132 -0
  250. data/vendor/liburing/test/ring-leak.c +283 -0
  251. data/vendor/liburing/test/ring-leak2.c +249 -0
  252. data/vendor/liburing/test/ringbuf-read.c +196 -0
  253. data/vendor/liburing/test/ringbuf-status.c +242 -0
  254. data/vendor/liburing/test/rsrc_tags.c +461 -0
  255. data/vendor/liburing/test/runtests-loop.sh +16 -0
  256. data/vendor/liburing/test/runtests-quiet.sh +11 -0
  257. data/vendor/liburing/test/runtests.sh +168 -0
  258. data/vendor/liburing/test/rw_merge_test.c +98 -0
  259. data/vendor/liburing/test/self.c +91 -0
  260. data/vendor/liburing/test/send-zerocopy.c +971 -0
  261. data/vendor/liburing/test/send_recv.c +412 -0
  262. data/vendor/liburing/test/send_recvmsg.c +444 -0
  263. data/vendor/liburing/test/shared-wq.c +84 -0
  264. data/vendor/liburing/test/short-read.c +75 -0
  265. data/vendor/liburing/test/shutdown.c +165 -0
  266. data/vendor/liburing/test/sigfd-deadlock.c +88 -0
  267. data/vendor/liburing/test/single-issuer.c +169 -0
  268. data/vendor/liburing/test/skip-cqe.c +428 -0
  269. data/vendor/liburing/test/socket-getsetsock-cmd.c +346 -0
  270. data/vendor/liburing/test/socket-io-cmd.c +237 -0
  271. data/vendor/liburing/test/socket-rw-eagain.c +149 -0
  272. data/vendor/liburing/test/socket-rw-offset.c +149 -0
  273. data/vendor/liburing/test/socket-rw.c +137 -0
  274. data/vendor/liburing/test/socket.c +408 -0
  275. data/vendor/liburing/test/splice.c +512 -0
  276. data/vendor/liburing/test/sq-full-cpp.cc +45 -0
  277. data/vendor/liburing/test/sq-full.c +45 -0
  278. data/vendor/liburing/test/sq-poll-dup.c +211 -0
  279. data/vendor/liburing/test/sq-poll-kthread.c +169 -0
  280. data/vendor/liburing/test/sq-poll-share.c +138 -0
  281. data/vendor/liburing/test/sq-space_left.c +159 -0
  282. data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
  283. data/vendor/liburing/test/sqpoll-exec.c +132 -0
  284. data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
  285. data/vendor/liburing/test/sqpoll-sleep.c +69 -0
  286. data/vendor/liburing/test/statx.c +172 -0
  287. data/vendor/liburing/test/stdout.c +232 -0
  288. data/vendor/liburing/test/submit-and-wait.c +108 -0
  289. data/vendor/liburing/test/submit-link-fail.c +156 -0
  290. data/vendor/liburing/test/submit-reuse.c +237 -0
  291. data/vendor/liburing/test/symlink.c +117 -0
  292. data/vendor/liburing/test/sync-cancel.c +235 -0
  293. data/vendor/liburing/test/teardowns.c +58 -0
  294. data/vendor/liburing/test/test.h +36 -0
  295. data/vendor/liburing/test/thread-exit.c +143 -0
  296. data/vendor/liburing/test/timeout-new.c +256 -0
  297. data/vendor/liburing/test/timeout.c +1798 -0
  298. data/vendor/liburing/test/truncate.c +186 -0
  299. data/vendor/liburing/test/tty-write-dpoll.c +60 -0
  300. data/vendor/liburing/test/unlink.c +112 -0
  301. data/vendor/liburing/test/version.c +25 -0
  302. data/vendor/liburing/test/wait-timeout.c +287 -0
  303. data/vendor/liburing/test/waitid.c +373 -0
  304. data/vendor/liburing/test/wakeup-hang.c +162 -0
  305. data/vendor/liburing/test/wq-aff.c +146 -0
  306. data/vendor/liburing/test/xattr.c +442 -0
  307. metadata +412 -0
@@ -0,0 +1,354 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: run various min_timeout tests
4
+ *
5
+ */
6
+ #include <errno.h>
7
+ #include <stdio.h>
8
+ #include <unistd.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+ #include <fcntl.h>
12
+ #include <sys/time.h>
13
+ #include <pthread.h>
14
+
15
+ #include "liburing.h"
16
+ #include "helpers.h"
17
+
18
+ struct data {
19
+ pthread_barrier_t startup;
20
+ unsigned long usec_sleep;
21
+ int out_fds[8];
22
+ int nr_fds;
23
+ };
24
+
25
+ static unsigned long long mtime_since(const struct timeval *s,
26
+ const struct timeval *e)
27
+ {
28
+ long long sec, usec;
29
+
30
+ sec = e->tv_sec - s->tv_sec;
31
+ usec = (e->tv_usec - s->tv_usec);
32
+ if (sec > 0 && usec < 0) {
33
+ sec--;
34
+ usec += 1000000;
35
+ }
36
+
37
+ sec *= 1000;
38
+ usec /= 1000;
39
+ return sec + usec;
40
+ }
41
+
42
+ static unsigned long long mtime_since_now(struct timeval *tv)
43
+ {
44
+ struct timeval end;
45
+
46
+ gettimeofday(&end, NULL);
47
+ return mtime_since(tv, &end);
48
+ }
49
+
50
+ static int time_pass(struct timeval *start, unsigned long min_t,
51
+ unsigned long max_t, const char *name)
52
+ {
53
+ unsigned long elapsed;
54
+
55
+ elapsed = mtime_since_now(start);
56
+ if (elapsed < min_t || elapsed > max_t) {
57
+ fprintf(stderr, "%s fails time check\n", name);
58
+ fprintf(stderr, " elapsed=%lu, min=%lu, max=%lu\n", elapsed,
59
+ min_t, max_t);
60
+ return T_EXIT_FAIL;
61
+ }
62
+ return T_EXIT_PASS;
63
+ }
64
+
65
+ static void *pipe_write(void *data)
66
+ {
67
+ struct data *d = data;
68
+ char buf[32];
69
+ int i;
70
+
71
+ memset(buf, 0x55, sizeof(buf));
72
+
73
+ pthread_barrier_wait(&d->startup);
74
+
75
+ if (d->usec_sleep)
76
+ usleep(d->usec_sleep);
77
+
78
+ for (i = 0; i < d->nr_fds; i++) {
79
+ int ret;
80
+
81
+ ret = write(d->out_fds[i], buf, sizeof(buf));
82
+ if (ret < 0) {
83
+ perror("write");
84
+ return NULL;
85
+ }
86
+ }
87
+
88
+ return NULL;
89
+ }
90
+
91
+ static int __test_writes(struct io_uring *ring, int npipes, int usec_sleep,
92
+ int usec_wait, int min_t, int max_t, const char *name)
93
+ {
94
+ struct __kernel_timespec ts;
95
+ struct io_uring_cqe *cqe;
96
+ struct io_uring_sqe *sqe;
97
+ struct timeval tv;
98
+ int ret, i, fds[4][2];
99
+ pthread_t thread;
100
+ struct data d;
101
+ char buf[32];
102
+ void *tret;
103
+
104
+ for (i = 0; i < npipes; i++) {
105
+ if (pipe(fds[i]) < 0) {
106
+ perror("pipe");
107
+ return T_EXIT_FAIL;
108
+ }
109
+ d.out_fds[i] = fds[i][1];
110
+ }
111
+ d.nr_fds = npipes;
112
+
113
+ pthread_barrier_init(&d.startup, NULL, 2);
114
+ d.usec_sleep = usec_sleep;
115
+
116
+ pthread_create(&thread, NULL, pipe_write, &d);
117
+ pthread_barrier_wait(&d.startup);
118
+
119
+ for (i = 0; i < npipes; i++) {
120
+ sqe = io_uring_get_sqe(ring);
121
+ io_uring_prep_read(sqe, fds[i][0], buf, sizeof(buf), 0);
122
+ }
123
+
124
+ io_uring_submit(ring);
125
+
126
+ ts.tv_sec = 1;
127
+ ts.tv_nsec = 0;
128
+ gettimeofday(&tv, NULL);
129
+ ret = io_uring_wait_cqes_min_timeout(ring, &cqe, 4, &ts, usec_wait, NULL);
130
+ if (ret) {
131
+ fprintf(stderr, "wait_cqes: %d\n", ret);
132
+ return T_EXIT_FAIL;
133
+ }
134
+
135
+ ret = time_pass(&tv, min_t, max_t, name);
136
+
137
+ io_uring_cq_advance(ring, npipes);
138
+
139
+ pthread_join(thread, &tret);
140
+ for (i = 0; i < npipes; i++) {
141
+ close(fds[i][0]);
142
+ close(fds[i][1]);
143
+ }
144
+ return ret;
145
+ }
146
+ /*
147
+ * Test doing min_wait for N events, where 0 events are already available
148
+ * on wait enter but N/2 are posted within the min_wait window. We'll expect to
149
+ * return when the min_wait window expires.
150
+ */
151
+ static int test_some_wait(struct io_uring *ring)
152
+ {
153
+ return __test_writes(ring, 2, 1000, 100000, 95, 120, __FUNCTION__);
154
+ }
155
+
156
+ /*
157
+ * Test doing min_wait for N events, where 0 events are already available
158
+ * on wait enter but N are posted within the min_wait window. We'll expect to
159
+ * return upon arrival of the N events, not the full min_wait window.
160
+ */
161
+ static int test_post_wait(struct io_uring *ring)
162
+ {
163
+ return __test_writes(ring, 4, 10000, 200000, 9, 12, __FUNCTION__);
164
+ }
165
+
166
+ /*
167
+ * Test doing min_wait for N events, where 0 events are already available
168
+ * on wait enter and one is posted after the min_wait timeout has expired.
169
+ * That first event should cause wait to abort, even if the task has asked
170
+ * for more to wait on.
171
+ */
172
+ static int test_late(struct io_uring *ring)
173
+ {
174
+ return __test_writes(ring, 1, 100000, 10000, 95, 120, __FUNCTION__);
175
+ }
176
+
177
+ static int __test_nop(struct io_uring *ring, int nr_nops, int min_t, int max_t,
178
+ unsigned long long_wait, const char *name)
179
+ {
180
+ struct __kernel_timespec ts;
181
+ struct io_uring_cqe *cqe;
182
+ struct timeval tv;
183
+ int i, ret;
184
+
185
+ for (i = 0; i < nr_nops; i++) {
186
+ struct io_uring_sqe *sqe;
187
+
188
+ sqe = io_uring_get_sqe(ring);
189
+ io_uring_prep_nop(sqe);
190
+ }
191
+
192
+ if (nr_nops)
193
+ io_uring_submit(ring);
194
+
195
+ ts.tv_sec = 0;
196
+ ts.tv_nsec = long_wait * 1000;
197
+ gettimeofday(&tv, NULL);
198
+ ret = io_uring_wait_cqes_min_timeout(ring, &cqe, 4, &ts, 50000, NULL);
199
+ io_uring_cq_advance(ring, nr_nops);
200
+ if (nr_nops) {
201
+ if (ret) {
202
+ fprintf(stderr, "wait_cqes: %d\n", ret);
203
+ return T_EXIT_FAIL;
204
+ }
205
+ } else {
206
+ if (ret != -ETIME) {
207
+ fprintf(stderr, "wait_cqes: %d\n", ret);
208
+ return T_EXIT_FAIL;
209
+ }
210
+ }
211
+
212
+ return time_pass(&tv, min_t, max_t, name);
213
+ }
214
+
215
+ /*
216
+ * Test doing min_wait for N events, where N/2 events are already available
217
+ * on wait enter. This should abort waiting after min_wait, not do the full
218
+ * wait.
219
+ */
220
+ static int test_some(struct io_uring *ring)
221
+ {
222
+ return __test_nop(ring, 2, 45, 55, 100000, __FUNCTION__);
223
+ }
224
+
225
+ /*
226
+ * Test doing min_wait for N events, where N events are already available
227
+ * on wait enter.
228
+ */
229
+ static int test_already(struct io_uring *ring)
230
+ {
231
+ return __test_nop(ring, 4, 0, 1, 100000, __FUNCTION__);
232
+ }
233
+
234
+ /*
235
+ * Test doing min_wait for N events, and nothing ever gets posted. We'd
236
+ * expect the time to be the normal wait time, not the min_wait time.
237
+ */
238
+ static int test_nothing(struct io_uring *ring)
239
+ {
240
+ return __test_nop(ring, 0, 95, 110, 100000, __FUNCTION__);
241
+ }
242
+
243
+ /*
244
+ * Test doing min_wait for N events, and nothing ever gets posted, and use
245
+ * a min_wait time that's bigger than the total wait. We only expect the
246
+ * min_wait to elapse.
247
+ */
248
+ static int test_min_wait_biggest(struct io_uring *ring)
249
+ {
250
+ return __test_nop(ring, 0, 45, 55, 20000, __FUNCTION__);
251
+ }
252
+
253
+ /*
254
+ * Test doing min_wait for N events, and nothing ever gets posted, and use
255
+ * a min_wait time that's roughly equal to the total wait. We only expect the
256
+ * min_wait to elapse.
257
+ */
258
+ static int test_min_wait_equal(struct io_uring *ring)
259
+ {
260
+ return __test_nop(ring, 0, 45, 55, 50001, __FUNCTION__);
261
+ }
262
+
263
+ int main(int argc, char *argv[])
264
+ {
265
+ struct io_uring ring1, ring2;
266
+ struct io_uring_params p = { };
267
+ int ret;
268
+
269
+ if (argc > 1)
270
+ return 0;
271
+
272
+ ret = t_create_ring_params(8, &ring1, &p);
273
+ if (ret == T_SETUP_SKIP)
274
+ return T_EXIT_SKIP;
275
+ else if (ret != T_SETUP_OK)
276
+ return ret;
277
+ if (!(p.features & IORING_FEAT_MIN_TIMEOUT))
278
+ return T_EXIT_SKIP;
279
+
280
+ p.flags = IORING_SETUP_SINGLE_ISSUER|IORING_SETUP_DEFER_TASKRUN;
281
+ ret = t_create_ring_params(8, &ring2, &p);
282
+ if (ret == T_SETUP_SKIP)
283
+ return T_EXIT_SKIP;
284
+ else if (ret != T_SETUP_OK)
285
+ return ret;
286
+
287
+ ret = test_already(&ring1);
288
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
289
+ return ret;
290
+
291
+ ret = test_already(&ring2);
292
+ if (ret == T_EXIT_FAIL)
293
+ return T_EXIT_FAIL;
294
+
295
+ ret = test_some(&ring1);
296
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
297
+ return ret;
298
+
299
+ ret = test_some(&ring2);
300
+ if (ret == T_EXIT_FAIL)
301
+ return T_EXIT_FAIL;
302
+
303
+ ret = test_late(&ring1);
304
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
305
+ return ret;
306
+
307
+ ret = test_late(&ring2);
308
+ if (ret == T_EXIT_FAIL)
309
+ return T_EXIT_FAIL;
310
+
311
+ ret = test_post_wait(&ring1);
312
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
313
+ return ret;
314
+
315
+ ret = test_post_wait(&ring2);
316
+ if (ret == T_EXIT_FAIL)
317
+ return T_EXIT_FAIL;
318
+
319
+ ret = test_some_wait(&ring1);
320
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
321
+ return ret;
322
+
323
+ ret = test_some_wait(&ring2);
324
+ if (ret == T_EXIT_FAIL)
325
+ return T_EXIT_FAIL;
326
+
327
+ ret = test_nothing(&ring1);
328
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
329
+ return ret;
330
+
331
+ ret = test_nothing(&ring2);
332
+ if (ret == T_EXIT_FAIL)
333
+ return T_EXIT_FAIL;
334
+
335
+ ret = test_min_wait_biggest(&ring1);
336
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
337
+ return ret;
338
+
339
+ ret = test_min_wait_biggest(&ring2);
340
+ if (ret == T_EXIT_FAIL)
341
+ return T_EXIT_FAIL;
342
+
343
+ ret = test_min_wait_equal(&ring1);
344
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
345
+ return ret;
346
+
347
+ ret = test_min_wait_equal(&ring2);
348
+ if (ret == T_EXIT_FAIL)
349
+ return T_EXIT_FAIL;
350
+
351
+ io_uring_queue_exit(&ring1);
352
+ io_uring_queue_exit(&ring2);
353
+ return T_EXIT_PASS;
354
+ }
@@ -0,0 +1,233 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test min timeout handling
4
+ *
5
+ */
6
+ #include <errno.h>
7
+ #include <stdio.h>
8
+ #include <unistd.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+ #include <fcntl.h>
12
+ #include <sys/resource.h>
13
+ #include <sys/time.h>
14
+ #include <pthread.h>
15
+
16
+ #include "liburing.h"
17
+ #include "helpers.h"
18
+
19
+ #define NPIPES 8
20
+ #define NWRITES 6
21
+
22
+ #define WAIT_USEC (250000)
23
+
24
+ static int no_min_timeout;
25
+
26
+ struct d {
27
+ int fd[NPIPES];
28
+ long delay;
29
+ };
30
+
31
+ static void *thread_fn(void *data)
32
+ {
33
+ struct d *d = data;
34
+ char buf[32];
35
+ int i;
36
+
37
+ memset(buf, 0x55, sizeof(buf));
38
+
39
+ for (i = 0; i < NWRITES; i++) {
40
+ int ret;
41
+
42
+ usleep(d->delay);
43
+ ret = write(d->fd[i], buf, sizeof(buf));
44
+ if (ret != sizeof(buf)) {
45
+ fprintf(stderr, "bad write %d\n", ret);
46
+ break;
47
+ }
48
+ }
49
+ return NULL;
50
+ }
51
+
52
+ /*
53
+ * Allow 25% tolerance
54
+ */
55
+ static int within_range(unsigned int target, unsigned int msec)
56
+ {
57
+ unsigned int high, low;
58
+
59
+ low = (target * 3) / 4;
60
+ high = (target * 5) / 4;
61
+ return (msec >= low && msec <= high);
62
+ }
63
+
64
+ static unsigned long long mtime_since(const struct timeval *s,
65
+ const struct timeval *e)
66
+ {
67
+ long long sec, usec;
68
+
69
+ sec = e->tv_sec - s->tv_sec;
70
+ usec = (e->tv_usec - s->tv_usec);
71
+ if (sec > 0 && usec < 0) {
72
+ sec--;
73
+ usec += 1000000;
74
+ }
75
+
76
+ sec *= 1000;
77
+ usec /= 1000;
78
+ return sec + usec;
79
+ }
80
+
81
+ static unsigned long long mtime_since_now(struct timeval *tv)
82
+ {
83
+ struct timeval end;
84
+
85
+ gettimeofday(&end, NULL);
86
+ return mtime_since(tv, &end);
87
+ }
88
+
89
+ static int test(int flags, int expected_ctx, int min_wait, int write_delay,
90
+ int nr_cqes, int msec_target)
91
+ {
92
+ struct io_uring_cqe *cqe;
93
+ struct io_uring_sqe *sqe;
94
+ struct io_uring ring;
95
+ struct __kernel_timespec ts;
96
+ struct rusage s, e;
97
+ pthread_t thread;
98
+ struct d d;
99
+ struct io_uring_params p = { .flags = flags, };
100
+ int ret, fds[NPIPES][2], i;
101
+ struct timeval start_time;
102
+ char buf[32];
103
+ void *tret;
104
+ long ttime;
105
+
106
+ ret = io_uring_queue_init_params(NPIPES, &ring, &p);
107
+ if (ret == -EINVAL)
108
+ return T_EXIT_SKIP;
109
+ if (!(p.features & IORING_FEAT_MIN_TIMEOUT)) {
110
+ no_min_timeout = 1;
111
+ return T_EXIT_SKIP;
112
+ }
113
+
114
+ for (i = 0; i < NPIPES; i++) {
115
+ if (pipe(fds[i]) < 0) {
116
+ perror("pipe");
117
+ return 1;
118
+ }
119
+ d.fd[i] = fds[i][1];
120
+ }
121
+
122
+ d.delay = write_delay;
123
+ pthread_create(&thread, NULL, thread_fn, &d);
124
+
125
+ for (i = 0; i < NPIPES; i++) {
126
+ sqe = io_uring_get_sqe(&ring);
127
+ io_uring_prep_read(sqe, fds[i][0], buf, sizeof(buf), 0);
128
+ }
129
+
130
+ ts.tv_sec = 0;
131
+ ts.tv_nsec = WAIT_USEC * 1000LL;
132
+
133
+ gettimeofday(&start_time, NULL);
134
+ getrusage(RUSAGE_THREAD, &s);
135
+ ret = io_uring_submit_and_wait_min_timeout(&ring, &cqe, 8, &ts, min_wait, NULL);
136
+ if (ret != NPIPES)
137
+ fprintf(stderr, "submit_and_wait=%d\n", ret);
138
+
139
+ getrusage(RUSAGE_THREAD, &e);
140
+ e.ru_nvcsw -= s.ru_nvcsw;
141
+ ttime = mtime_since_now(&start_time);
142
+ if (!within_range(msec_target, ttime)) {
143
+ fprintf(stderr, "Expected %d msec, got %ld msec\n", msec_target,
144
+ ttime);
145
+ fprintf(stderr, "flags=%x, min_wait=%d, write_delay=%d\n",
146
+ flags, min_wait, write_delay);
147
+ }
148
+ /* will usually be accurate, but allow for offset of 1 */
149
+ if (e.ru_nvcsw != expected_ctx &&
150
+ (e.ru_nvcsw - expected_ctx > 1))
151
+ fprintf(stderr, "%ld ctx switches, expected %d\n", e.ru_nvcsw,
152
+ expected_ctx);
153
+
154
+ for (i = 0; i < NPIPES; i++) {
155
+ ret = io_uring_peek_cqe(&ring, &cqe);
156
+ if (ret)
157
+ break;
158
+ io_uring_cqe_seen(&ring, cqe);
159
+ }
160
+
161
+ if (i != nr_cqes)
162
+ fprintf(stderr, "Got %d CQEs, expected %d\n", i, nr_cqes);
163
+
164
+ pthread_join(thread, &tret);
165
+
166
+ for (i = 0; i < NPIPES; i++) {
167
+ close(fds[i][0]);
168
+ close(fds[i][1]);
169
+ }
170
+
171
+ return T_EXIT_PASS;
172
+ }
173
+
174
+ int main(int argc, char *argv[])
175
+ {
176
+ int ret;
177
+
178
+ if (argc > 1)
179
+ return T_EXIT_SKIP;
180
+
181
+ ret = test(0, NWRITES + 1, 0, 2000, NWRITES, WAIT_USEC / 1000);
182
+ if (ret == T_EXIT_FAIL)
183
+ return T_EXIT_FAIL;
184
+ if (no_min_timeout)
185
+ return T_EXIT_SKIP;
186
+
187
+ ret = test(0, NWRITES + 1, 50000, 2000, NWRITES, 50);
188
+ if (ret == T_EXIT_FAIL)
189
+ return T_EXIT_FAIL;
190
+
191
+ ret = test(0, NWRITES + 1, 500000, 2000, NWRITES, 500);
192
+ if (ret == T_EXIT_FAIL)
193
+ return T_EXIT_FAIL;
194
+
195
+ /* no writes within min timeout, but it's given. expect 1 cqe */
196
+ ret = test(0, 1, 10000, 20000, 1, 20);
197
+ if (ret == T_EXIT_FAIL)
198
+ return T_EXIT_FAIL;
199
+
200
+ /* same as above, but no min timeout. should time out and we get 6 */
201
+ ret = test(0, NWRITES + 1, 0, 20000, NWRITES, WAIT_USEC / 1000);
202
+ if (ret == T_EXIT_FAIL)
203
+ return T_EXIT_FAIL;
204
+
205
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 1,
206
+ 0, 2000, NWRITES, WAIT_USEC / 1000);
207
+ if (ret == T_EXIT_FAIL)
208
+ return T_EXIT_FAIL;
209
+
210
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 1,
211
+ 50000, 2000, NWRITES, 50);
212
+ if (ret == T_EXIT_FAIL)
213
+ return T_EXIT_FAIL;
214
+
215
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 1,
216
+ 500000, 2000, NWRITES, 500);
217
+ if (ret == T_EXIT_FAIL)
218
+ return T_EXIT_FAIL;
219
+
220
+ /* no writes within min timeout, but it's given. expect 1 cqe */
221
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 1,
222
+ 10000, 20000, 1, 20);
223
+ if (ret == T_EXIT_FAIL)
224
+ return T_EXIT_FAIL;
225
+
226
+ /* same as above, but no min timeout. should time out and we get 6 */
227
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 1,
228
+ 0, 20000, NWRITES, WAIT_USEC / 1000);
229
+ if (ret == T_EXIT_FAIL)
230
+ return T_EXIT_FAIL;
231
+
232
+ return ret;
233
+ }
@@ -0,0 +1,112 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test io_uring mkdirat handling
4
+ */
5
+ #include <fcntl.h>
6
+ #include <stdio.h>
7
+ #include <string.h>
8
+ #include <sys/stat.h>
9
+ #include <sys/types.h>
10
+ #include <unistd.h>
11
+
12
+ #include "liburing.h"
13
+ #include "helpers.h"
14
+
15
+ static int do_mkdirat(struct io_uring *ring, const char *fn)
16
+ {
17
+ int ret;
18
+ struct io_uring_sqe *sqe;
19
+ struct io_uring_cqe *cqe;
20
+
21
+ sqe = io_uring_get_sqe(ring);
22
+ if (!sqe) {
23
+ fprintf(stderr, "sqe get failed\n");
24
+ goto err;
25
+ }
26
+ io_uring_prep_mkdirat(sqe, AT_FDCWD, fn, 0700);
27
+
28
+ ret = io_uring_submit(ring);
29
+ if (ret != 1) {
30
+ fprintf(stderr, "submit failed: %d\n", ret);
31
+ goto err;
32
+ }
33
+
34
+ ret = io_uring_wait_cqes(ring, &cqe, 1, 0, 0);
35
+ if (ret) {
36
+ fprintf(stderr, "wait_cqe failed: %d\n", ret);
37
+ goto err;
38
+ }
39
+ ret = cqe->res;
40
+ io_uring_cqe_seen(ring, cqe);
41
+ return ret;
42
+ err:
43
+ return 1;
44
+ }
45
+
46
+ static int stat_file(const char *fn)
47
+ {
48
+ struct stat sb;
49
+
50
+ if (!stat(fn, &sb))
51
+ return 0;
52
+
53
+ return errno;
54
+ }
55
+
56
+ int main(int argc, char *argv[])
57
+ {
58
+ static const char fn[] = "io_uring-mkdirat-test";
59
+ int ret;
60
+ struct io_uring ring;
61
+
62
+ if (argc > 1)
63
+ return T_EXIT_SKIP;
64
+
65
+ ret = io_uring_queue_init(8, &ring, 0);
66
+ if (ret) {
67
+ fprintf(stderr, "queue init failed: %d\n", ret);
68
+ return ret;
69
+ }
70
+
71
+ ret = do_mkdirat(&ring, fn);
72
+ if (ret < 0) {
73
+ if (ret == -EBADF || ret == -EINVAL) {
74
+ fprintf(stdout, "mkdirat not supported, skipping\n");
75
+ goto skip;
76
+ }
77
+ fprintf(stderr, "mkdirat: %s\n", strerror(-ret));
78
+ goto err;
79
+ } else if (ret) {
80
+ goto err;
81
+ }
82
+
83
+ if (stat_file(fn)) {
84
+ perror("stat");
85
+ goto err;
86
+ }
87
+
88
+ ret = do_mkdirat(&ring, fn);
89
+ if (ret != -EEXIST) {
90
+ fprintf(stderr, "do_mkdirat already exists failed: %d\n", ret);
91
+ goto err1;
92
+ }
93
+
94
+ ret = do_mkdirat(&ring, "surely/this/wont/exist");
95
+ if (ret != -ENOENT) {
96
+ fprintf(stderr, "do_mkdirat no parent failed: %d\n", ret);
97
+ goto err1;
98
+ }
99
+
100
+ unlinkat(AT_FDCWD, fn, AT_REMOVEDIR);
101
+ io_uring_queue_exit(&ring);
102
+ return T_EXIT_PASS;
103
+ skip:
104
+ unlinkat(AT_FDCWD, fn, AT_REMOVEDIR);
105
+ io_uring_queue_exit(&ring);
106
+ return T_EXIT_SKIP;
107
+ err1:
108
+ unlinkat(AT_FDCWD, fn, AT_REMOVEDIR);
109
+ err:
110
+ io_uring_queue_exit(&ring);
111
+ return T_EXIT_FAIL;
112
+ }