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,468 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ #define _POSIX_C_SOURCE 200112L
3
+
4
+ #include "lib.h"
5
+ #include "syscall.h"
6
+ #include "liburing.h"
7
+ #include "int_flags.h"
8
+ #include "liburing/compat.h"
9
+ #include "liburing/io_uring.h"
10
+
11
+ /*
12
+ * Returns true if we're not using SQ thread (thus nobody submits but us)
13
+ * or if IORING_SQ_NEED_WAKEUP is set, so submit thread must be explicitly
14
+ * awakened. For the latter case, we set the thread wakeup flag.
15
+ * If no SQEs are ready for submission, returns false.
16
+ */
17
+ static inline bool sq_ring_needs_enter(struct io_uring *ring,
18
+ unsigned submit,
19
+ unsigned *flags)
20
+ {
21
+ if (!submit)
22
+ return false;
23
+
24
+ if (!(ring->flags & IORING_SETUP_SQPOLL))
25
+ return true;
26
+
27
+ /*
28
+ * Ensure the kernel can see the store to the SQ tail before we read
29
+ * the flags.
30
+ */
31
+ io_uring_smp_mb();
32
+
33
+ if (uring_unlikely(IO_URING_READ_ONCE(*ring->sq.kflags) &
34
+ IORING_SQ_NEED_WAKEUP)) {
35
+ *flags |= IORING_ENTER_SQ_WAKEUP;
36
+ return true;
37
+ }
38
+
39
+ return false;
40
+ }
41
+
42
+ static inline bool cq_ring_needs_flush(struct io_uring *ring)
43
+ {
44
+ return IO_URING_READ_ONCE(*ring->sq.kflags) &
45
+ (IORING_SQ_CQ_OVERFLOW | IORING_SQ_TASKRUN);
46
+ }
47
+
48
+ static inline bool cq_ring_needs_enter(struct io_uring *ring)
49
+ {
50
+ return (ring->flags & IORING_SETUP_IOPOLL) || cq_ring_needs_flush(ring);
51
+ }
52
+
53
+ struct get_data {
54
+ unsigned submit;
55
+ unsigned wait_nr;
56
+ unsigned get_flags;
57
+ int sz;
58
+ int has_ts;
59
+ void *arg;
60
+ };
61
+
62
+ static int _io_uring_get_cqe(struct io_uring *ring,
63
+ struct io_uring_cqe **cqe_ptr,
64
+ struct get_data *data)
65
+ {
66
+ struct io_uring_cqe *cqe = NULL;
67
+ bool looped = false;
68
+ int err = 0;
69
+
70
+ do {
71
+ bool need_enter = false;
72
+ unsigned flags = 0;
73
+ unsigned nr_available;
74
+ int ret;
75
+
76
+ ret = __io_uring_peek_cqe(ring, &cqe, &nr_available);
77
+ if (ret) {
78
+ if (!err)
79
+ err = ret;
80
+ break;
81
+ }
82
+ if (!cqe && !data->wait_nr && !data->submit) {
83
+ /*
84
+ * If we already looped once, we already entered
85
+ * the kernel. Since there's nothing to submit or
86
+ * wait for, don't keep retrying.
87
+ */
88
+ if (looped || !cq_ring_needs_enter(ring)) {
89
+ if (!err)
90
+ err = -EAGAIN;
91
+ break;
92
+ }
93
+ need_enter = true;
94
+ }
95
+ if (data->wait_nr > nr_available || need_enter) {
96
+ flags = IORING_ENTER_GETEVENTS | data->get_flags;
97
+ need_enter = true;
98
+ }
99
+ if (sq_ring_needs_enter(ring, data->submit, &flags))
100
+ need_enter = true;
101
+ if (!need_enter)
102
+ break;
103
+ if (looped && data->has_ts) {
104
+ struct io_uring_getevents_arg *arg = data->arg;
105
+
106
+ if (!cqe && arg->ts && !err)
107
+ err = -ETIME;
108
+ break;
109
+ }
110
+
111
+ if (ring->int_flags & INT_FLAG_REG_RING)
112
+ flags |= IORING_ENTER_REGISTERED_RING;
113
+ ret = __sys_io_uring_enter2(ring->enter_ring_fd, data->submit,
114
+ data->wait_nr, flags, data->arg,
115
+ data->sz);
116
+ if (ret < 0) {
117
+ if (!err)
118
+ err = ret;
119
+ break;
120
+ }
121
+
122
+ data->submit -= ret;
123
+ if (cqe)
124
+ break;
125
+ if (!looped) {
126
+ looped = true;
127
+ err = ret;
128
+ }
129
+ } while (1);
130
+
131
+ *cqe_ptr = cqe;
132
+ return err;
133
+ }
134
+
135
+ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
136
+ unsigned submit, unsigned wait_nr, sigset_t *sigmask)
137
+ {
138
+ struct get_data data = {
139
+ .submit = submit,
140
+ .wait_nr = wait_nr,
141
+ .get_flags = 0,
142
+ .sz = _NSIG / 8,
143
+ .arg = sigmask,
144
+ };
145
+
146
+ return _io_uring_get_cqe(ring, cqe_ptr, &data);
147
+ }
148
+
149
+ int io_uring_get_events(struct io_uring *ring)
150
+ {
151
+ int flags = IORING_ENTER_GETEVENTS;
152
+
153
+ if (ring->int_flags & INT_FLAG_REG_RING)
154
+ flags |= IORING_ENTER_REGISTERED_RING;
155
+ return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
156
+ }
157
+
158
+ /*
159
+ * Fill in an array of IO completions up to count, if any are available.
160
+ * Returns the amount of IO completions filled.
161
+ */
162
+ unsigned io_uring_peek_batch_cqe(struct io_uring *ring,
163
+ struct io_uring_cqe **cqes, unsigned count)
164
+ {
165
+ unsigned ready;
166
+ bool overflow_checked = false;
167
+ int shift = 0;
168
+
169
+ if (ring->flags & IORING_SETUP_CQE32)
170
+ shift = 1;
171
+
172
+ again:
173
+ ready = io_uring_cq_ready(ring);
174
+ if (ready) {
175
+ unsigned head = *ring->cq.khead;
176
+ unsigned mask = ring->cq.ring_mask;
177
+ unsigned last;
178
+ int i = 0;
179
+
180
+ count = count > ready ? ready : count;
181
+ last = head + count;
182
+ for (;head != last; head++, i++)
183
+ cqes[i] = &ring->cq.cqes[(head & mask) << shift];
184
+
185
+ return count;
186
+ }
187
+
188
+ if (overflow_checked)
189
+ return 0;
190
+
191
+ if (cq_ring_needs_flush(ring)) {
192
+ io_uring_get_events(ring);
193
+ overflow_checked = true;
194
+ goto again;
195
+ }
196
+
197
+ return 0;
198
+ }
199
+
200
+ /*
201
+ * Sync internal state with kernel ring state on the SQ side. Returns the
202
+ * number of pending items in the SQ ring, for the shared ring.
203
+ */
204
+ static unsigned __io_uring_flush_sq(struct io_uring *ring)
205
+ {
206
+ struct io_uring_sq *sq = &ring->sq;
207
+ unsigned tail = sq->sqe_tail;
208
+
209
+ if (sq->sqe_head != tail) {
210
+ sq->sqe_head = tail;
211
+ /*
212
+ * Ensure kernel sees the SQE updates before the tail update.
213
+ */
214
+ if (!(ring->flags & IORING_SETUP_SQPOLL))
215
+ *sq->ktail = tail;
216
+ else
217
+ io_uring_smp_store_release(sq->ktail, tail);
218
+ }
219
+ /*
220
+ * This load needs to be atomic, since sq->khead is written concurrently
221
+ * by the kernel, but it doesn't need to be load_acquire, since the
222
+ * kernel doesn't store to the submission queue; it advances khead just
223
+ * to indicate that it's finished reading the submission queue entries
224
+ * so they're available for us to write to.
225
+ */
226
+ return tail - IO_URING_READ_ONCE(*sq->khead);
227
+ }
228
+
229
+ /*
230
+ * If we have kernel support for IORING_ENTER_EXT_ARG, then we can use that
231
+ * more efficiently than queueing an internal timeout command.
232
+ */
233
+ static int io_uring_wait_cqes_new(struct io_uring *ring,
234
+ struct io_uring_cqe **cqe_ptr,
235
+ unsigned wait_nr,
236
+ struct __kernel_timespec *ts,
237
+ unsigned int min_wait_usec,
238
+ sigset_t *sigmask)
239
+ {
240
+ struct io_uring_getevents_arg arg = {
241
+ .sigmask = (unsigned long) sigmask,
242
+ .sigmask_sz = _NSIG / 8,
243
+ .ts = (unsigned long) ts
244
+ };
245
+ struct get_data data = {
246
+ .wait_nr = wait_nr,
247
+ .get_flags = IORING_ENTER_EXT_ARG,
248
+ .sz = sizeof(arg),
249
+ .has_ts = ts != NULL,
250
+ .arg = &arg
251
+ };
252
+
253
+ if (min_wait_usec && ring->features & IORING_FEAT_MIN_TIMEOUT)
254
+ arg.min_wait_usec = min_wait_usec;
255
+
256
+ return _io_uring_get_cqe(ring, cqe_ptr, &data);
257
+ }
258
+
259
+ /*
260
+ * Like io_uring_wait_cqe(), except it accepts a timeout value as well. Note
261
+ * that an sqe is used internally to handle the timeout. For kernel doesn't
262
+ * support IORING_FEAT_EXT_ARG, applications using this function must never
263
+ * set sqe->user_data to LIBURING_UDATA_TIMEOUT!
264
+ *
265
+ * For kernels without IORING_FEAT_EXT_ARG (5.10 and older), if 'ts' is
266
+ * specified, the application need not call io_uring_submit() before
267
+ * calling this function, as we will do that on its behalf. From this it also
268
+ * follows that this function isn't safe to use for applications that split SQ
269
+ * and CQ handling between two threads and expect that to work without
270
+ * synchronization, as this function manipulates both the SQ and CQ side.
271
+ *
272
+ * For kernels with IORING_FEAT_EXT_ARG, no implicit submission is done and
273
+ * hence this function is safe to use for applications that split SQ and CQ
274
+ * handling between two threads.
275
+ */
276
+ static int __io_uring_submit_timeout(struct io_uring *ring, unsigned wait_nr,
277
+ struct __kernel_timespec *ts)
278
+ {
279
+ struct io_uring_sqe *sqe;
280
+ int ret;
281
+
282
+ /*
283
+ * If the SQ ring is full, we may need to submit IO first
284
+ */
285
+ sqe = io_uring_get_sqe(ring);
286
+ if (!sqe) {
287
+ ret = io_uring_submit(ring);
288
+ if (ret < 0)
289
+ return ret;
290
+ sqe = io_uring_get_sqe(ring);
291
+ if (!sqe)
292
+ return -EAGAIN;
293
+ }
294
+ io_uring_prep_timeout(sqe, ts, wait_nr, 0);
295
+ sqe->user_data = LIBURING_UDATA_TIMEOUT;
296
+ return __io_uring_flush_sq(ring);
297
+ }
298
+
299
+ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
300
+ unsigned wait_nr, struct __kernel_timespec *ts,
301
+ sigset_t *sigmask)
302
+ {
303
+ int to_submit = 0;
304
+
305
+ if (ts) {
306
+ if (ring->features & IORING_FEAT_EXT_ARG)
307
+ return io_uring_wait_cqes_new(ring, cqe_ptr, wait_nr,
308
+ ts, 0, sigmask);
309
+ to_submit = __io_uring_submit_timeout(ring, wait_nr, ts);
310
+ if (to_submit < 0)
311
+ return to_submit;
312
+ }
313
+
314
+ return __io_uring_get_cqe(ring, cqe_ptr, to_submit, wait_nr, sigmask);
315
+ }
316
+
317
+ int io_uring_wait_cqes_min_timeout(struct io_uring *ring,
318
+ struct io_uring_cqe **cqe_ptr,
319
+ unsigned wait_nr,
320
+ struct __kernel_timespec *ts,
321
+ unsigned int min_wait_usec, sigset_t *sigmask)
322
+ {
323
+ return io_uring_wait_cqes_new(ring, cqe_ptr, wait_nr, ts, min_wait_usec,
324
+ sigmask);
325
+ }
326
+
327
+ static int __io_uring_submit_and_wait_timeout(struct io_uring *ring,
328
+ struct io_uring_cqe **cqe_ptr, unsigned wait_nr,
329
+ struct __kernel_timespec *ts,
330
+ unsigned int min_wait, sigset_t *sigmask)
331
+ {
332
+ int to_submit;
333
+
334
+ if (ts) {
335
+ if (ring->features & IORING_FEAT_EXT_ARG) {
336
+ struct io_uring_getevents_arg arg = {
337
+ .sigmask = (unsigned long) sigmask,
338
+ .sigmask_sz = _NSIG / 8,
339
+ .min_wait_usec = min_wait,
340
+ .ts = (unsigned long) ts
341
+ };
342
+ struct get_data data = {
343
+ .submit = __io_uring_flush_sq(ring),
344
+ .wait_nr = wait_nr,
345
+ .get_flags = IORING_ENTER_EXT_ARG,
346
+ .sz = sizeof(arg),
347
+ .has_ts = ts != NULL,
348
+ .arg = &arg
349
+ };
350
+
351
+ return _io_uring_get_cqe(ring, cqe_ptr, &data);
352
+ }
353
+ to_submit = __io_uring_submit_timeout(ring, wait_nr, ts);
354
+ if (to_submit < 0)
355
+ return to_submit;
356
+ } else
357
+ to_submit = __io_uring_flush_sq(ring);
358
+
359
+ return __io_uring_get_cqe(ring, cqe_ptr, to_submit, wait_nr, sigmask);
360
+ }
361
+
362
+ int io_uring_submit_and_wait_min_timeout(struct io_uring *ring,
363
+ struct io_uring_cqe **cqe_ptr,
364
+ unsigned wait_nr,
365
+ struct __kernel_timespec *ts,
366
+ unsigned min_wait,
367
+ sigset_t *sigmask)
368
+ {
369
+ if (!(ring->features & IORING_FEAT_MIN_TIMEOUT))
370
+ return -EINVAL;
371
+ return __io_uring_submit_and_wait_timeout(ring, cqe_ptr, wait_nr, ts,
372
+ min_wait, sigmask);
373
+ }
374
+
375
+ int io_uring_submit_and_wait_timeout(struct io_uring *ring,
376
+ struct io_uring_cqe **cqe_ptr,
377
+ unsigned wait_nr,
378
+ struct __kernel_timespec *ts,
379
+ sigset_t *sigmask)
380
+ {
381
+ return __io_uring_submit_and_wait_timeout(ring, cqe_ptr, wait_nr, ts, 0,
382
+ sigmask);
383
+ }
384
+
385
+ /*
386
+ * See io_uring_wait_cqes() - this function is the same, it just always uses
387
+ * '1' as the wait_nr.
388
+ */
389
+ int io_uring_wait_cqe_timeout(struct io_uring *ring,
390
+ struct io_uring_cqe **cqe_ptr,
391
+ struct __kernel_timespec *ts)
392
+ {
393
+ return io_uring_wait_cqes(ring, cqe_ptr, 1, ts, NULL);
394
+ }
395
+
396
+ /*
397
+ * Submit sqes acquired from io_uring_get_sqe() to the kernel.
398
+ *
399
+ * Returns number of sqes submitted
400
+ */
401
+ static int __io_uring_submit(struct io_uring *ring, unsigned submitted,
402
+ unsigned wait_nr, bool getevents)
403
+ {
404
+ bool cq_needs_enter = getevents || wait_nr || cq_ring_needs_enter(ring);
405
+ unsigned flags;
406
+ int ret;
407
+
408
+ flags = 0;
409
+ if (sq_ring_needs_enter(ring, submitted, &flags) || cq_needs_enter) {
410
+ if (cq_needs_enter)
411
+ flags |= IORING_ENTER_GETEVENTS;
412
+ if (ring->int_flags & INT_FLAG_REG_RING)
413
+ flags |= IORING_ENTER_REGISTERED_RING;
414
+
415
+ ret = __sys_io_uring_enter(ring->enter_ring_fd, submitted,
416
+ wait_nr, flags, NULL);
417
+ } else
418
+ ret = submitted;
419
+
420
+ return ret;
421
+ }
422
+
423
+ static int __io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr)
424
+ {
425
+ return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr, false);
426
+ }
427
+
428
+ /*
429
+ * Submit sqes acquired from io_uring_get_sqe() to the kernel.
430
+ *
431
+ * Returns number of sqes submitted
432
+ */
433
+ int io_uring_submit(struct io_uring *ring)
434
+ {
435
+ return __io_uring_submit_and_wait(ring, 0);
436
+ }
437
+
438
+ /*
439
+ * Like io_uring_submit(), but allows waiting for events as well.
440
+ *
441
+ * Returns number of sqes submitted
442
+ */
443
+ int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr)
444
+ {
445
+ return __io_uring_submit_and_wait(ring, wait_nr);
446
+ }
447
+
448
+ int io_uring_submit_and_get_events(struct io_uring *ring)
449
+ {
450
+ return __io_uring_submit(ring, __io_uring_flush_sq(ring), 0, true);
451
+ }
452
+
453
+ #ifdef LIBURING_INTERNAL
454
+ struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring)
455
+ {
456
+ return _io_uring_get_sqe(ring);
457
+ }
458
+ #endif
459
+
460
+ int __io_uring_sqring_wait(struct io_uring *ring)
461
+ {
462
+ int flags = IORING_ENTER_SQ_WAIT;
463
+
464
+ if (ring->int_flags & INT_FLAG_REG_RING)
465
+ flags |= IORING_ENTER_REGISTERED_RING;
466
+
467
+ return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
468
+ }