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,571 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: exercise futex wait/wake/waitv
4
+ *
5
+ */
6
+ #include <stdio.h>
7
+ #include <unistd.h>
8
+ #include <stdlib.h>
9
+ #include <pthread.h>
10
+ #include <errno.h>
11
+ #include <linux/futex.h>
12
+
13
+ #include "liburing.h"
14
+ #include "helpers.h"
15
+
16
+ #define LOOPS 500
17
+ #define NFUTEX 8
18
+
19
+ #ifndef FUTEX2_SIZE_U8
20
+ #define FUTEX2_SIZE_U8 0x00
21
+ #define FUTEX2_SIZE_U16 0x01
22
+ #define FUTEX2_SIZE_U32 0x02
23
+ #define FUTEX2_SIZE_U64 0x03
24
+ #define FUTEX2_NUMA 0x04
25
+ /* 0x08 */
26
+ /* 0x10 */
27
+ /* 0x20 */
28
+ /* 0x40 */
29
+ #define FUTEX2_PRIVATE FUTEX_PRIVATE_FLAG
30
+
31
+ #define FUTEX2_SIZE_MASK 0x03
32
+ #endif
33
+
34
+ static int no_futex;
35
+
36
+ static void *fwake(void *data)
37
+ {
38
+ unsigned int *futex = data;
39
+ struct io_uring_sqe *sqe;
40
+ struct io_uring_cqe *cqe;
41
+ struct io_uring ring;
42
+ int ret;
43
+
44
+ ret = io_uring_queue_init(1, &ring, 0);
45
+ if (ret) {
46
+ fprintf(stderr, "queue init: %d\n", ret);
47
+ return NULL;
48
+ }
49
+
50
+ *futex = 1;
51
+ sqe = io_uring_get_sqe(&ring);
52
+ io_uring_prep_futex_wake(sqe, futex, 1, FUTEX_BITSET_MATCH_ANY,
53
+ FUTEX2_SIZE_U32, 0);
54
+ sqe->user_data = 3;
55
+
56
+ io_uring_submit(&ring);
57
+
58
+ ret = io_uring_wait_cqe(&ring, &cqe);
59
+ if (ret) {
60
+ fprintf(stderr, "wait: %d\n", ret);
61
+ return NULL;
62
+ }
63
+ io_uring_cqe_seen(&ring, cqe);
64
+ io_uring_queue_exit(&ring);
65
+ return NULL;
66
+ }
67
+
68
+ static int __test(struct io_uring *ring, int vectored, int async,
69
+ int async_cancel)
70
+ {
71
+ struct io_uring_sqe *sqe;
72
+ struct io_uring_cqe *cqe;
73
+ struct futex_waitv fw[NFUTEX];
74
+ unsigned int *futex;
75
+ pthread_t threads[NFUTEX];
76
+ void *tret;
77
+ int ret, i, nfutex;
78
+
79
+ nfutex = NFUTEX;
80
+ if (!vectored)
81
+ nfutex = 1;
82
+
83
+ futex = calloc(nfutex, sizeof(*futex));
84
+ for (i = 0; i < nfutex; i++) {
85
+ fw[i].val = 0;
86
+ fw[i].uaddr = (unsigned long) &futex[i];
87
+ fw[i].flags = FUTEX2_SIZE_U32;
88
+ fw[i].__reserved = 0;
89
+ }
90
+
91
+ sqe = io_uring_get_sqe(ring);
92
+ if (vectored)
93
+ io_uring_prep_futex_waitv(sqe, fw, nfutex, 0);
94
+ else
95
+ io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
96
+ FUTEX2_SIZE_U32, 0);
97
+ if (async)
98
+ sqe->flags |= IOSQE_ASYNC;
99
+ sqe->user_data = 1;
100
+
101
+ io_uring_submit(ring);
102
+
103
+ for (i = 0; i < nfutex; i++)
104
+ pthread_create(&threads[i], NULL, fwake, &futex[i]);
105
+
106
+ sqe = io_uring_get_sqe(ring);
107
+ io_uring_prep_cancel64(sqe, 1, 0);
108
+ if (async_cancel)
109
+ sqe->flags |= IOSQE_ASYNC;
110
+ sqe->user_data = 2;
111
+
112
+ io_uring_submit(ring);
113
+
114
+ for (i = 0; i < 2; i++) {
115
+ ret = io_uring_wait_cqe(ring, &cqe);
116
+ if (ret) {
117
+ fprintf(stderr, "parent wait %d\n", ret);
118
+ return 1;
119
+ }
120
+
121
+ if (cqe->res == -EINVAL || cqe->res == -EOPNOTSUPP) {
122
+ no_futex = 1;
123
+ return 0;
124
+ }
125
+ io_uring_cqe_seen(ring, cqe);
126
+ }
127
+
128
+ ret = io_uring_peek_cqe(ring, &cqe);
129
+ if (!ret) {
130
+ fprintf(stderr, "peek found cqe!\n");
131
+ return 1;
132
+ }
133
+
134
+ for (i = 0; i < nfutex; i++)
135
+ pthread_join(threads[i], &tret);
136
+
137
+ return 0;
138
+ }
139
+
140
+ static int test(int flags, int vectored)
141
+ {
142
+ struct io_uring ring;
143
+ int ret, i;
144
+
145
+ ret = io_uring_queue_init(8, &ring, flags);
146
+ if (ret)
147
+ return ret;
148
+
149
+ for (i = 0; i < LOOPS; i++) {
150
+ int async_cancel = (!i % 2);
151
+ int async_wait = !(i % 3);
152
+ ret = __test(&ring, vectored, async_wait, async_cancel);
153
+ if (ret) {
154
+ fprintf(stderr, "flags=%x, failed=%d\n", flags, i);
155
+ break;
156
+ }
157
+ if (no_futex)
158
+ break;
159
+ }
160
+
161
+ io_uring_queue_exit(&ring);
162
+ return ret;
163
+ }
164
+
165
+ static int test_order(int vectored, int async)
166
+ {
167
+ struct io_uring_sqe *sqe;
168
+ struct io_uring_cqe *cqe;
169
+ struct futex_waitv fw;
170
+ struct io_uring ring;
171
+ unsigned int *futex;
172
+ int ret, i;
173
+
174
+ ret = io_uring_queue_init(8, &ring, 0);
175
+ if (ret)
176
+ return ret;
177
+
178
+ futex = malloc(sizeof(*futex));
179
+ *futex = 0;
180
+
181
+ fw.val = 0;
182
+ fw.uaddr = (unsigned long) futex;
183
+ fw.flags = FUTEX2_SIZE_U32;
184
+ fw.__reserved = 0;
185
+
186
+ /*
187
+ * Submit two futex waits
188
+ */
189
+ sqe = io_uring_get_sqe(&ring);
190
+ if (!vectored)
191
+ io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
192
+ FUTEX2_SIZE_U32, 0);
193
+ else
194
+ io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
195
+ sqe->user_data = 1;
196
+
197
+ sqe = io_uring_get_sqe(&ring);
198
+ if (!vectored)
199
+ io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
200
+ FUTEX2_SIZE_U32, 0);
201
+ else
202
+ io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
203
+ sqe->user_data = 2;
204
+
205
+ io_uring_submit(&ring);
206
+
207
+ /*
208
+ * Now submit wake for just one futex
209
+ */
210
+ *futex = 1;
211
+ sqe = io_uring_get_sqe(&ring);
212
+ io_uring_prep_futex_wake(sqe, futex, 1, FUTEX_BITSET_MATCH_ANY,
213
+ FUTEX2_SIZE_U32, 0);
214
+ sqe->user_data = 100;
215
+ if (async)
216
+ sqe->flags |= IOSQE_ASYNC;
217
+
218
+ io_uring_submit(&ring);
219
+
220
+ /*
221
+ * We expect to find completions for the first futex wait, and
222
+ * the futex wake. We should not see the last futex wait.
223
+ */
224
+ for (i = 0; i < 2; i++) {
225
+ ret = io_uring_wait_cqe(&ring, &cqe);
226
+ if (ret) {
227
+ fprintf(stderr, "wait %d\n", ret);
228
+ return 1;
229
+ }
230
+ if (cqe->user_data == 1 || cqe->user_data == 100) {
231
+ io_uring_cqe_seen(&ring, cqe);
232
+ continue;
233
+ }
234
+ fprintf(stderr, "unexpected cqe %lu, res %d\n", (unsigned long) cqe->user_data, cqe->res);
235
+ return 1;
236
+ }
237
+
238
+ ret = io_uring_peek_cqe(&ring, &cqe);
239
+ if (ret != -EAGAIN) {
240
+ fprintf(stderr, "Unexpected cqe available: %d\n", cqe->res);
241
+ return 1;
242
+ }
243
+
244
+ io_uring_queue_exit(&ring);
245
+ return 0;
246
+ }
247
+
248
+ static int test_multi_wake(int vectored)
249
+ {
250
+ struct io_uring_sqe *sqe;
251
+ struct io_uring_cqe *cqe;
252
+ struct futex_waitv fw;
253
+ struct io_uring ring;
254
+ unsigned int *futex;
255
+ int ret, i;
256
+
257
+ ret = io_uring_queue_init(8, &ring, 0);
258
+ if (ret)
259
+ return ret;
260
+
261
+ futex = malloc(sizeof(*futex));
262
+ *futex = 0;
263
+
264
+ fw.val = 0;
265
+ fw.uaddr = (unsigned long) futex;
266
+ fw.flags = FUTEX2_SIZE_U32;
267
+ fw.__reserved = 0;
268
+
269
+ /*
270
+ * Submit two futex waits
271
+ */
272
+ sqe = io_uring_get_sqe(&ring);
273
+ if (!vectored)
274
+ io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
275
+ FUTEX2_SIZE_U32, 0);
276
+ else
277
+ io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
278
+ sqe->user_data = 1;
279
+
280
+ sqe = io_uring_get_sqe(&ring);
281
+ if (!vectored)
282
+ io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
283
+ FUTEX2_SIZE_U32, 0);
284
+ else
285
+ io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
286
+ sqe->user_data = 2;
287
+
288
+ io_uring_submit(&ring);
289
+
290
+ /*
291
+ * Now submit wake for both futexes
292
+ */
293
+ *futex = 1;
294
+ sqe = io_uring_get_sqe(&ring);
295
+ io_uring_prep_futex_wake(sqe, futex, 2, FUTEX_BITSET_MATCH_ANY,
296
+ FUTEX2_SIZE_U32, 0);
297
+ sqe->user_data = 100;
298
+
299
+ io_uring_submit(&ring);
300
+
301
+ /*
302
+ * We expect to find completions for the both futex waits, and
303
+ * the futex wake.
304
+ */
305
+ for (i = 0; i < 3; i++) {
306
+ ret = io_uring_wait_cqe(&ring, &cqe);
307
+ if (ret) {
308
+ fprintf(stderr, "wait %d\n", ret);
309
+ return 1;
310
+ }
311
+ if (cqe->res < 0) {
312
+ fprintf(stderr, "cqe error %d\n", cqe->res);
313
+ return 1;
314
+ }
315
+ io_uring_cqe_seen(&ring, cqe);
316
+ }
317
+
318
+ ret = io_uring_peek_cqe(&ring, &cqe);
319
+ if (!ret) {
320
+ fprintf(stderr, "peek found cqe!\n");
321
+ return 1;
322
+ }
323
+
324
+ io_uring_queue_exit(&ring);
325
+ return 0;
326
+ }
327
+
328
+ /*
329
+ * Test that waking 0 futexes returns 0
330
+ */
331
+ static int test_wake_zero(void)
332
+ {
333
+ struct io_uring_sqe *sqe;
334
+ struct io_uring_cqe *cqe;
335
+ struct io_uring ring;
336
+ unsigned int *futex;
337
+ int ret;
338
+
339
+ ret = io_uring_queue_init(8, &ring, 0);
340
+ if (ret)
341
+ return ret;
342
+
343
+ futex = malloc(sizeof(*futex));
344
+ *futex = 0;
345
+
346
+ sqe = io_uring_get_sqe(&ring);
347
+ sqe->user_data = 1;
348
+ io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
349
+ FUTEX2_SIZE_U32, 0);
350
+
351
+ io_uring_submit(&ring);
352
+
353
+ sqe = io_uring_get_sqe(&ring);
354
+ sqe->user_data = 2;
355
+ io_uring_prep_futex_wake(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
356
+ FUTEX2_SIZE_U32, 0);
357
+
358
+ io_uring_submit(&ring);
359
+
360
+ ret = io_uring_wait_cqe(&ring, &cqe);
361
+
362
+ /*
363
+ * Should get zero res and it should be the wake
364
+ */
365
+ if (cqe->res || cqe->user_data != 2) {
366
+ fprintf(stderr, "cqe res %d, data %ld\n", cqe->res, (long) cqe->user_data);
367
+ return 1;
368
+ }
369
+ io_uring_cqe_seen(&ring, cqe);
370
+
371
+ /*
372
+ * Should not have the wait complete
373
+ */
374
+ ret = io_uring_peek_cqe(&ring, &cqe);
375
+ if (!ret) {
376
+ fprintf(stderr, "peek found cqe!\n");
377
+ return 1;
378
+ }
379
+
380
+ io_uring_queue_exit(&ring);
381
+ return 0;
382
+ }
383
+
384
+ /*
385
+ * Test invalid wait/wake/waitv flags
386
+ */
387
+ static int test_invalid(void)
388
+ {
389
+ struct io_uring_sqe *sqe;
390
+ struct io_uring_cqe *cqe;
391
+ struct futex_waitv fw;
392
+ struct io_uring ring;
393
+ unsigned int *futex;
394
+ int ret;
395
+
396
+ ret = io_uring_queue_init(8, &ring, 0);
397
+ if (ret)
398
+ return ret;
399
+
400
+ futex = malloc(sizeof(*futex));
401
+ *futex = 0;
402
+
403
+ sqe = io_uring_get_sqe(&ring);
404
+ sqe->user_data = 1;
405
+ io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0x1000,
406
+ 0);
407
+
408
+ io_uring_submit(&ring);
409
+
410
+ ret = io_uring_wait_cqe(&ring, &cqe);
411
+
412
+ /*
413
+ * Should get zero res and it should be the wake
414
+ */
415
+ if (cqe->res != -EINVAL) {
416
+ fprintf(stderr, "wait cqe res %d\n", cqe->res);
417
+ return 1;
418
+ }
419
+ io_uring_cqe_seen(&ring, cqe);
420
+
421
+ sqe = io_uring_get_sqe(&ring);
422
+ sqe->user_data = 1;
423
+ io_uring_prep_futex_wake(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0x1000,
424
+ 0);
425
+
426
+ io_uring_submit(&ring);
427
+
428
+ ret = io_uring_wait_cqe(&ring, &cqe);
429
+
430
+ /*
431
+ * Should get zero res and it should be the wake
432
+ */
433
+ if (cqe->res != -EINVAL) {
434
+ fprintf(stderr, "wake cqe res %d\n", cqe->res);
435
+ return 1;
436
+ }
437
+ io_uring_cqe_seen(&ring, cqe);
438
+
439
+ fw.val = 0;
440
+ fw.uaddr = (unsigned long) futex;
441
+ fw.flags = FUTEX2_SIZE_U32 | 0x1000;
442
+ fw.__reserved = 0;
443
+
444
+ sqe = io_uring_get_sqe(&ring);
445
+ sqe->user_data = 1;
446
+ io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
447
+
448
+ io_uring_submit(&ring);
449
+
450
+ ret = io_uring_wait_cqe(&ring, &cqe);
451
+
452
+ /*
453
+ * Should get zero res and it should be the wake
454
+ */
455
+ if (cqe->res != -EINVAL) {
456
+ fprintf(stderr, "waitv cqe res %d\n", cqe->res);
457
+ return 1;
458
+ }
459
+ io_uring_cqe_seen(&ring, cqe);
460
+
461
+ io_uring_queue_exit(&ring);
462
+ return 0;
463
+ }
464
+
465
+ int main(int argc, char *argv[])
466
+ {
467
+ int ret;
468
+
469
+ if (argc > 1)
470
+ return T_EXIT_SKIP;
471
+
472
+ ret = test(0, 0);
473
+ if (ret) {
474
+ fprintf(stderr, "test 0 0 failed\n");
475
+ return T_EXIT_FAIL;
476
+ }
477
+ if (no_futex)
478
+ return T_EXIT_SKIP;
479
+
480
+ ret = test(0, 1);
481
+ if (ret) {
482
+ fprintf(stderr, "test 0 1 failed\n");
483
+ return T_EXIT_FAIL;
484
+ }
485
+
486
+ ret = test_wake_zero();
487
+ if (ret) {
488
+ fprintf(stderr, "wake 0 failed\n");
489
+ return T_EXIT_FAIL;
490
+ }
491
+
492
+ ret = test_invalid();
493
+ if (ret) {
494
+ fprintf(stderr, "test invalid failed\n");
495
+ return T_EXIT_FAIL;
496
+ }
497
+
498
+ ret = test(IORING_SETUP_SQPOLL, 0);
499
+ if (ret) {
500
+ fprintf(stderr, "test sqpoll 0 failed\n");
501
+ return T_EXIT_FAIL;
502
+ }
503
+
504
+ ret = test(IORING_SETUP_SQPOLL, 1);
505
+ if (ret) {
506
+ fprintf(stderr, "test sqpoll 1 failed\n");
507
+ return T_EXIT_FAIL;
508
+ }
509
+
510
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 0);
511
+ if (ret) {
512
+ fprintf(stderr, "test single coop 0 failed\n");
513
+ return T_EXIT_FAIL;
514
+ }
515
+
516
+ ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 1);
517
+ if (ret) {
518
+ fprintf(stderr, "test single coop 1 failed\n");
519
+ return T_EXIT_FAIL;
520
+ }
521
+
522
+ ret = test(IORING_SETUP_COOP_TASKRUN, 0);
523
+ if (ret) {
524
+ fprintf(stderr, "test taskrun 0 failed\n");
525
+ return T_EXIT_FAIL;
526
+ }
527
+
528
+ ret = test(IORING_SETUP_COOP_TASKRUN, 1);
529
+ if (ret) {
530
+ fprintf(stderr, "test taskrun 1 failed\n");
531
+ return T_EXIT_FAIL;
532
+ }
533
+
534
+ ret = test_order(0, 0);
535
+ if (ret) {
536
+ fprintf(stderr, "test_order 0 0 failed\n");
537
+ return T_EXIT_FAIL;
538
+ }
539
+
540
+ ret = test_order(1, 0);
541
+ if (ret) {
542
+ fprintf(stderr, "test_order 1 0 failed\n");
543
+ return T_EXIT_FAIL;
544
+ }
545
+
546
+ ret = test_order(0, 1);
547
+ if (ret) {
548
+ fprintf(stderr, "test_order 0 1 failed\n");
549
+ return T_EXIT_FAIL;
550
+ }
551
+
552
+ ret = test_order(1, 1);
553
+ if (ret) {
554
+ fprintf(stderr, "test_order 1 1 failed\n");
555
+ return T_EXIT_FAIL;
556
+ }
557
+
558
+ ret = test_multi_wake(0);
559
+ if (ret) {
560
+ fprintf(stderr, "multi_wake 0 failed\n");
561
+ return T_EXIT_FAIL;
562
+ }
563
+
564
+ ret = test_multi_wake(1);
565
+ if (ret) {
566
+ fprintf(stderr, "multi_wake 1 failed\n");
567
+ return T_EXIT_FAIL;
568
+ }
569
+
570
+ return T_EXIT_PASS;
571
+ }
@@ -0,0 +1,170 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test io_uring linkat 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_linkat(struct io_uring *ring, int olddirfd, const char *oldname,
16
+ const char *newname, int flags)
17
+ {
18
+ struct io_uring_sqe *sqe;
19
+ struct io_uring_cqe *cqe;
20
+ int ret;
21
+
22
+ sqe = io_uring_get_sqe(ring);
23
+ if (!sqe) {
24
+ fprintf(stderr, "sqe get failed\n");
25
+ return 1;
26
+ }
27
+ io_uring_prep_linkat(sqe, olddirfd, oldname, AT_FDCWD, newname, flags);
28
+
29
+ ret = io_uring_submit(ring);
30
+ if (ret != 1) {
31
+ fprintf(stderr, "submit failed: %d\n", ret);
32
+ return 1;
33
+ }
34
+
35
+ ret = io_uring_wait_cqes(ring, &cqe, 1, 0, 0);
36
+ if (ret) {
37
+ fprintf(stderr, "wait_cqe failed: %d\n", ret);
38
+ return 1;
39
+ }
40
+ ret = cqe->res;
41
+ io_uring_cqe_seen(ring, cqe);
42
+ return ret;
43
+ }
44
+
45
+ static int files_linked_ok(const char* fn1, const char *fn2)
46
+ {
47
+ struct stat s1, s2;
48
+
49
+ if (stat(fn1, &s1)) {
50
+ fprintf(stderr, "stat(%s): %s\n", fn1, strerror(errno));
51
+ return 0;
52
+ }
53
+ if (stat(fn2, &s2)) {
54
+ fprintf(stderr, "stat(%s): %s\n", fn2, strerror(errno));
55
+ return 0;
56
+ }
57
+ if (s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino) {
58
+ fprintf(stderr, "linked files have different device / inode numbers\n");
59
+ return 0;
60
+ }
61
+ if (s1.st_nlink != 2 || s2.st_nlink != 2) {
62
+ fprintf(stderr, "linked files have unexpected links count\n");
63
+ return 0;
64
+ }
65
+ return 1;
66
+ }
67
+
68
+ int main(int argc, char *argv[])
69
+ {
70
+ static const char target[] = "io_uring-linkat-test-target";
71
+ static const char emptyname[] = "io_uring-linkat-test-empty";
72
+ static const char linkname[] = "io_uring-linkat-test-link";
73
+ static const char symlinkname[] = "io_uring-linkat-test-symlink";
74
+ struct io_uring ring;
75
+ int ret, fd, exit_status = T_EXIT_FAIL;
76
+
77
+ if (argc > 1)
78
+ return T_EXIT_SKIP;
79
+
80
+ ret = io_uring_queue_init(8, &ring, 0);
81
+ if (ret) {
82
+ fprintf(stderr, "queue init failed: %d\n", ret);
83
+ return ret;
84
+ }
85
+
86
+ ret = fd = open(target, O_CREAT | O_RDWR | O_EXCL, 0600);
87
+ if (ret < 0) {
88
+ perror("open");
89
+ goto out;
90
+ }
91
+ if (write(fd, "linktest", 8) != 8) {
92
+ close(fd);
93
+ goto out;
94
+ }
95
+ if(geteuid()) {
96
+ fprintf(stdout, "not root, skipping AT_EMPTY_PATH test\n");
97
+ } else {
98
+ ret = do_linkat(&ring, fd, "", emptyname, AT_EMPTY_PATH);
99
+ if (ret < 0) {
100
+ if (ret == -EBADF || ret == -EINVAL) {
101
+ fprintf(stdout, "linkat not supported, skipping\n");
102
+ exit_status = T_EXIT_SKIP;
103
+ goto out;
104
+ }
105
+ fprintf(stderr, "linkat: %s\n", strerror(-ret));
106
+ goto out;
107
+ } else if (ret) {
108
+ goto out;
109
+ }
110
+ if (!files_linked_ok(emptyname, target))
111
+ goto out;
112
+ unlinkat(AT_FDCWD, emptyname, 0);
113
+ }
114
+ close(fd);
115
+
116
+ ret = symlink(target, symlinkname);
117
+ if (ret < 0) {
118
+ perror("open");
119
+ goto out;
120
+ }
121
+
122
+ ret = do_linkat(&ring, AT_FDCWD, target, linkname, 0);
123
+ if (ret < 0) {
124
+ if (ret == -EBADF || ret == -EINVAL) {
125
+ fprintf(stdout, "linkat not supported, skipping\n");
126
+ exit_status = T_EXIT_SKIP;
127
+ goto out;
128
+ }
129
+ fprintf(stderr, "linkat: %s\n", strerror(-ret));
130
+ goto out;
131
+ } else if (ret) {
132
+ goto out;
133
+ }
134
+
135
+ if (!files_linked_ok(linkname, target))
136
+ goto out;
137
+
138
+ unlinkat(AT_FDCWD, linkname, 0);
139
+
140
+ ret = do_linkat(&ring, AT_FDCWD, symlinkname, linkname, AT_SYMLINK_FOLLOW);
141
+ if (ret < 0) {
142
+ fprintf(stderr, "linkat: %s\n", strerror(-ret));
143
+ goto out;
144
+ } else if (ret) {
145
+ goto out;
146
+ }
147
+
148
+ if (!files_linked_ok(symlinkname, target))
149
+ goto out;
150
+
151
+ ret = do_linkat(&ring, AT_FDCWD, target, linkname, 0);
152
+ if (ret != -EEXIST) {
153
+ fprintf(stderr, "test_linkat linkname already exists failed: %d\n", ret);
154
+ goto out;
155
+ }
156
+
157
+ ret = do_linkat(&ring, AT_FDCWD, target, "surely/this/does/not/exist", 0);
158
+ if (ret != -ENOENT) {
159
+ fprintf(stderr, "test_linkat no parent failed: %d\n", ret);
160
+ goto out;
161
+ }
162
+ exit_status = T_EXIT_PASS;
163
+ out:
164
+ unlinkat(AT_FDCWD, symlinkname, 0);
165
+ unlinkat(AT_FDCWD, linkname, 0);
166
+ unlinkat(AT_FDCWD, emptyname, 0);
167
+ unlinkat(AT_FDCWD, target, 0);
168
+ io_uring_queue_exit(&ring);
169
+ return exit_status;
170
+ }