uringmachine 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +0 -3
  4. data/CHANGELOG.md +13 -0
  5. data/Gemfile +11 -0
  6. data/README.md +266 -112
  7. data/Rakefile +8 -0
  8. data/TODO.md +14 -21
  9. data/benchmark/common.rb +2 -0
  10. data/benchmark/openssl.rb +77 -0
  11. data/benchmark/openssl_socketpair.rb +112 -0
  12. data/benchmark/sqlite.rb +1 -1
  13. data/docs/design/buffer_pool.md +1 -1
  14. data/docs/wroclove.rb.md +52 -0
  15. data/ext/um/extconf.rb +15 -0
  16. data/ext/um/um.c +392 -358
  17. data/ext/um/um.h +48 -23
  18. data/ext/um/um_async_op.c +9 -8
  19. data/ext/um/um_async_op_class.c +34 -3
  20. data/ext/um/um_class.c +705 -19
  21. data/ext/um/um_const.c +31 -0
  22. data/ext/um/um_mutex_class.c +12 -0
  23. data/ext/um/um_op.c +15 -1
  24. data/ext/um/um_queue_class.c +16 -0
  25. data/ext/um/um_ssl.c +109 -0
  26. data/ext/um/um_stream.c +9 -8
  27. data/ext/um/um_sync.c +18 -11
  28. data/ext/um/um_utils.c +17 -8
  29. data/grant-2025/interim-report.md +1 -1
  30. data/grant-2025/journal.md +4 -4
  31. data/grant-2025/tasks.md +6 -4
  32. data/lib/uringmachine/dns_resolver.rb +38 -0
  33. data/lib/uringmachine/fiber_scheduler.rb +7 -5
  34. data/lib/uringmachine/version.rb +1 -1
  35. data/lib/uringmachine.rb +106 -6
  36. data/test/helper.rb +15 -0
  37. data/test/test_async_op.rb +3 -2
  38. data/test/test_fiber_scheduler.rb +41 -1
  39. data/test/test_ssl.rb +85 -0
  40. data/test/test_stream.rb +11 -0
  41. data/test/test_um.rb +445 -11
  42. data/uringmachine.gemspec +1 -7
  43. data/vendor/liburing/examples/send-zerocopy.c +43 -31
  44. data/vendor/liburing/examples/zcrx.c +260 -69
  45. data/vendor/liburing/liburing.spec +1 -1
  46. data/vendor/liburing/src/include/liburing/io_uring.h +12 -0
  47. data/vendor/liburing/src/include/liburing.h +3 -2
  48. data/vendor/liburing/src/liburing-ffi.map +4 -0
  49. data/vendor/liburing/src/liburing.map +4 -0
  50. data/vendor/liburing/src/queue.c +12 -0
  51. data/vendor/liburing/src/register.c +1 -0
  52. data/vendor/liburing/src/setup.c +15 -7
  53. data/vendor/liburing/test/Makefile +8 -4
  54. data/vendor/liburing/test/conn-unreach.c +1 -1
  55. data/vendor/liburing/test/epwait.c +32 -6
  56. data/vendor/liburing/test/io-wq-exit.c +131 -0
  57. data/vendor/liburing/test/iowait.c +1 -1
  58. data/vendor/liburing/test/min-timeout.c +3 -1
  59. data/vendor/liburing/test/open-close.c +39 -0
  60. data/vendor/liburing/test/poll-update-trigger.c +85 -0
  61. data/vendor/liburing/test/recvsend_bundle.c +14 -11
  62. data/vendor/liburing/test/sendzc-bug.c +146 -0
  63. data/vendor/liburing/test/sqe-mixed-nop.c +151 -7
  64. data/vendor/liburing/test/test.h +2 -0
  65. data/vendor/liburing/test/timestamp-bug.c +135 -0
  66. data/vendor/liburing/test/timestamp.c +5 -0
  67. data/vendor/liburing/test/vec-regbuf.c +136 -1
  68. metadata +38 -283
  69. data/vendor/libressl/.github/scripts/changelog.sh +0 -74
  70. data/vendor/libressl/.github/workflows/android.yml +0 -35
  71. data/vendor/libressl/.github/workflows/cifuzz.yml +0 -33
  72. data/vendor/libressl/.github/workflows/cmake-config.yml +0 -98
  73. data/vendor/libressl/.github/workflows/coverity.yml +0 -69
  74. data/vendor/libressl/.github/workflows/emscripten.yml +0 -71
  75. data/vendor/libressl/.github/workflows/fedora-rawhide.yml +0 -39
  76. data/vendor/libressl/.github/workflows/freebsd.yml +0 -71
  77. data/vendor/libressl/.github/workflows/linux.yml +0 -71
  78. data/vendor/libressl/.github/workflows/macos.yml +0 -37
  79. data/vendor/libressl/.github/workflows/release.yml +0 -81
  80. data/vendor/libressl/.github/workflows/rust-openssl.yml +0 -47
  81. data/vendor/libressl/.github/workflows/solaris.yml +0 -37
  82. data/vendor/libressl/.github/workflows/windows.yml +0 -70
  83. data/vendor/libressl/.gitignore +0 -333
  84. data/vendor/libressl/CMakeLists.txt +0 -581
  85. data/vendor/libressl/COPYING +0 -133
  86. data/vendor/libressl/ChangeLog +0 -3280
  87. data/vendor/libressl/FindLibreSSL.cmake +0 -232
  88. data/vendor/libressl/LibreSSLConfig.cmake.in +0 -36
  89. data/vendor/libressl/Makefile.am +0 -60
  90. data/vendor/libressl/Makefile.am.common +0 -20
  91. data/vendor/libressl/OPENBSD_BRANCH +0 -1
  92. data/vendor/libressl/README.md +0 -238
  93. data/vendor/libressl/README.mingw.md +0 -43
  94. data/vendor/libressl/apps/CMakeLists.txt +0 -18
  95. data/vendor/libressl/apps/Makefile.am +0 -5
  96. data/vendor/libressl/apps/nc/CMakeLists.txt +0 -67
  97. data/vendor/libressl/apps/nc/Makefile.am +0 -64
  98. data/vendor/libressl/apps/nc/compat/accept4.c +0 -17
  99. data/vendor/libressl/apps/nc/compat/readpassphrase.c +0 -205
  100. data/vendor/libressl/apps/nc/compat/socket.c +0 -29
  101. data/vendor/libressl/apps/nc/compat/sys/socket.h +0 -30
  102. data/vendor/libressl/apps/ocspcheck/CMakeLists.txt +0 -44
  103. data/vendor/libressl/apps/ocspcheck/Makefile.am +0 -45
  104. data/vendor/libressl/apps/ocspcheck/compat/.gitignore +0 -0
  105. data/vendor/libressl/apps/openssl/CMakeLists.txt +0 -97
  106. data/vendor/libressl/apps/openssl/Makefile.am +0 -108
  107. data/vendor/libressl/apps/openssl/apps_win.c +0 -138
  108. data/vendor/libressl/apps/openssl/certhash_win.c +0 -13
  109. data/vendor/libressl/apps/openssl/compat/clock_gettime_osx.c +0 -26
  110. data/vendor/libressl/apps/openssl/compat/poll_win.c +0 -329
  111. data/vendor/libressl/appveyor.yml +0 -53
  112. data/vendor/libressl/autogen.sh +0 -15
  113. data/vendor/libressl/check-release.sh +0 -86
  114. data/vendor/libressl/cmake_export_symbol.cmake +0 -71
  115. data/vendor/libressl/cmake_uninstall.cmake.in +0 -36
  116. data/vendor/libressl/config +0 -17
  117. data/vendor/libressl/configure.ac +0 -165
  118. data/vendor/libressl/crypto/CMakeLists.txt +0 -863
  119. data/vendor/libressl/crypto/Makefile.am +0 -962
  120. data/vendor/libressl/crypto/Makefile.am.arc4random +0 -46
  121. data/vendor/libressl/crypto/Makefile.am.elf-mips +0 -14
  122. data/vendor/libressl/crypto/Makefile.am.elf-mips64 +0 -14
  123. data/vendor/libressl/crypto/Makefile.am.elf-x86_64 +0 -35
  124. data/vendor/libressl/crypto/Makefile.am.macosx-x86_64 +0 -35
  125. data/vendor/libressl/crypto/Makefile.am.masm-x86_64 +0 -22
  126. data/vendor/libressl/crypto/Makefile.am.mingw64-x86_64 +0 -23
  127. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_darwin.c +0 -60
  128. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_linux.c +0 -62
  129. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_none.c +0 -26
  130. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_windows.c +0 -36
  131. data/vendor/libressl/crypto/arch/loongarch64/crypto_arch.h +0 -21
  132. data/vendor/libressl/crypto/arch/mips/crypto_arch.h +0 -21
  133. data/vendor/libressl/crypto/bn/arch/loongarch64/bn_arch.h +0 -23
  134. data/vendor/libressl/crypto/bn/arch/mips/bn_arch.h +0 -24
  135. data/vendor/libressl/crypto/compat/.gitignore +0 -31
  136. data/vendor/libressl/crypto/compat/arc4random.h +0 -41
  137. data/vendor/libressl/crypto/compat/b_win.c +0 -55
  138. data/vendor/libressl/crypto/compat/bsd-asprintf.c +0 -96
  139. data/vendor/libressl/crypto/compat/crypto_lock_win.c +0 -56
  140. data/vendor/libressl/crypto/compat/explicit_bzero_win.c +0 -13
  141. data/vendor/libressl/crypto/compat/freezero.c +0 -32
  142. data/vendor/libressl/crypto/compat/getdelim.c +0 -78
  143. data/vendor/libressl/crypto/compat/getline.c +0 -40
  144. data/vendor/libressl/crypto/compat/getopt_long.c +0 -528
  145. data/vendor/libressl/crypto/compat/getpagesize.c +0 -18
  146. data/vendor/libressl/crypto/compat/getprogname_linux.c +0 -23
  147. data/vendor/libressl/crypto/compat/getprogname_unimpl.c +0 -7
  148. data/vendor/libressl/crypto/compat/getprogname_windows.c +0 -13
  149. data/vendor/libressl/crypto/compat/posix_win.c +0 -296
  150. data/vendor/libressl/crypto/compat/syslog_r.c +0 -19
  151. data/vendor/libressl/crypto/compat/ui_openssl_win.c +0 -334
  152. data/vendor/libressl/dist.sh +0 -22
  153. data/vendor/libressl/gen-coverage-report.sh +0 -58
  154. data/vendor/libressl/gen-openbsd-tags.sh +0 -20
  155. data/vendor/libressl/include/CMakeLists.txt +0 -61
  156. data/vendor/libressl/include/Makefile.am +0 -79
  157. data/vendor/libressl/include/arch/loongarch64/opensslconf.h +0 -150
  158. data/vendor/libressl/include/arch/mips/opensslconf.h +0 -150
  159. data/vendor/libressl/include/compat/arpa/inet.h +0 -15
  160. data/vendor/libressl/include/compat/arpa/nameser.h +0 -25
  161. data/vendor/libressl/include/compat/cet.h +0 -19
  162. data/vendor/libressl/include/compat/dirent.h +0 -17
  163. data/vendor/libressl/include/compat/dirent_msvc.h +0 -611
  164. data/vendor/libressl/include/compat/endian.h +0 -161
  165. data/vendor/libressl/include/compat/err.h +0 -95
  166. data/vendor/libressl/include/compat/fcntl.h +0 -32
  167. data/vendor/libressl/include/compat/getopt.h +0 -50
  168. data/vendor/libressl/include/compat/limits.h +0 -25
  169. data/vendor/libressl/include/compat/netdb.h +0 -10
  170. data/vendor/libressl/include/compat/netinet/in.h +0 -19
  171. data/vendor/libressl/include/compat/netinet/ip.h +0 -49
  172. data/vendor/libressl/include/compat/netinet/tcp.h +0 -10
  173. data/vendor/libressl/include/compat/poll.h +0 -63
  174. data/vendor/libressl/include/compat/pthread.h +0 -122
  175. data/vendor/libressl/include/compat/readpassphrase.h +0 -44
  176. data/vendor/libressl/include/compat/resolv.h +0 -24
  177. data/vendor/libressl/include/compat/stdint.h +0 -31
  178. data/vendor/libressl/include/compat/stdio.h +0 -65
  179. data/vendor/libressl/include/compat/stdlib.h +0 -57
  180. data/vendor/libressl/include/compat/string.h +0 -98
  181. data/vendor/libressl/include/compat/sys/_null.h +0 -18
  182. data/vendor/libressl/include/compat/sys/ioctl.h +0 -11
  183. data/vendor/libressl/include/compat/sys/mman.h +0 -19
  184. data/vendor/libressl/include/compat/sys/param.h +0 -15
  185. data/vendor/libressl/include/compat/sys/queue.h +0 -536
  186. data/vendor/libressl/include/compat/sys/select.h +0 -10
  187. data/vendor/libressl/include/compat/sys/socket.h +0 -18
  188. data/vendor/libressl/include/compat/sys/stat.h +0 -129
  189. data/vendor/libressl/include/compat/sys/time.h +0 -37
  190. data/vendor/libressl/include/compat/sys/tree.h +0 -1006
  191. data/vendor/libressl/include/compat/sys/types.h +0 -69
  192. data/vendor/libressl/include/compat/sys/uio.h +0 -17
  193. data/vendor/libressl/include/compat/syslog.h +0 -38
  194. data/vendor/libressl/include/compat/time.h +0 -59
  195. data/vendor/libressl/include/compat/unistd.h +0 -83
  196. data/vendor/libressl/include/compat/win32netcompat.h +0 -57
  197. data/vendor/libressl/include/openssl/Makefile.am.tpl +0 -45
  198. data/vendor/libressl/libcrypto.pc.in +0 -28
  199. data/vendor/libressl/libressl.pub +0 -2
  200. data/vendor/libressl/libssl.pc.in +0 -28
  201. data/vendor/libressl/libtls.pc.in +0 -28
  202. data/vendor/libressl/m4/ax_add_fortify_source.m4 +0 -80
  203. data/vendor/libressl/m4/ax_check_compile_flag.m4 +0 -53
  204. data/vendor/libressl/m4/check-hardening-options.m4 +0 -110
  205. data/vendor/libressl/m4/check-libc.m4 +0 -189
  206. data/vendor/libressl/m4/check-os-options.m4 +0 -181
  207. data/vendor/libressl/m4/disable-compiler-warnings.m4 +0 -44
  208. data/vendor/libressl/man/CMakeLists.txt +0 -26
  209. data/vendor/libressl/man/links +0 -2780
  210. data/vendor/libressl/man/update_links.sh +0 -25
  211. data/vendor/libressl/openssl.pc.in +0 -11
  212. data/vendor/libressl/patches/bn_shift.patch +0 -34
  213. data/vendor/libressl/patches/crypto_arch.h.patch +0 -34
  214. data/vendor/libressl/patches/crypto_namespace.h.patch +0 -22
  215. data/vendor/libressl/patches/netcat.c.patch +0 -178
  216. data/vendor/libressl/patches/openssl.c.patch +0 -12
  217. data/vendor/libressl/patches/opensslfeatures.h.patch +0 -49
  218. data/vendor/libressl/patches/patch-amd64-crypto-cpu-caps.c.patch +0 -20
  219. data/vendor/libressl/patches/patch-i386-crypto-cpu-caps.c.patch +0 -20
  220. data/vendor/libressl/patches/speed.c.patch +0 -114
  221. data/vendor/libressl/patches/ssl_namespace.h.patch +0 -21
  222. data/vendor/libressl/patches/tls.h.patch +0 -16
  223. data/vendor/libressl/patches/tls_config.c.patch +0 -15
  224. data/vendor/libressl/patches/win32_amd64_bn_arch.h.patch +0 -28
  225. data/vendor/libressl/patches/windows_headers.patch +0 -80
  226. data/vendor/libressl/scripts/config.guess +0 -1774
  227. data/vendor/libressl/scripts/config.sub +0 -1907
  228. data/vendor/libressl/scripts/i686-w64-mingw32.cmake +0 -9
  229. data/vendor/libressl/scripts/test +0 -210
  230. data/vendor/libressl/scripts/wrap-compiler-for-flag-check +0 -31
  231. data/vendor/libressl/scripts/x86_64-w64-mingw32.cmake +0 -9
  232. data/vendor/libressl/ssl/CMakeLists.txt +0 -183
  233. data/vendor/libressl/ssl/Makefile.am +0 -187
  234. data/vendor/libressl/tests/CMakeLists.txt +0 -970
  235. data/vendor/libressl/tests/Makefile.am +0 -944
  236. data/vendor/libressl/tests/aeadtest.sh +0 -30
  237. data/vendor/libressl/tests/arc4randomforktest.sh +0 -21
  238. data/vendor/libressl/tests/asn1time_small.test +0 -10
  239. data/vendor/libressl/tests/cmake/CMakeLists.txt +0 -52
  240. data/vendor/libressl/tests/cmake/crypto.c +0 -7
  241. data/vendor/libressl/tests/cmake/ssl.c +0 -6
  242. data/vendor/libressl/tests/cmake/tls.c +0 -6
  243. data/vendor/libressl/tests/compat/pipe2.c +0 -186
  244. data/vendor/libressl/tests/dtlstest.sh +0 -28
  245. data/vendor/libressl/tests/evptest.sh +0 -22
  246. data/vendor/libressl/tests/keypairtest.sh +0 -27
  247. data/vendor/libressl/tests/mlkem_tests.sh +0 -39
  248. data/vendor/libressl/tests/ocsptest.bat +0 -25
  249. data/vendor/libressl/tests/ocsptest.sh +0 -23
  250. data/vendor/libressl/tests/openssl.cnf +0 -29
  251. data/vendor/libressl/tests/optionstest.c +0 -381
  252. data/vendor/libressl/tests/pidwraptest.c +0 -85
  253. data/vendor/libressl/tests/pidwraptest.sh +0 -26
  254. data/vendor/libressl/tests/quictest.bat +0 -27
  255. data/vendor/libressl/tests/quictest.sh +0 -30
  256. data/vendor/libressl/tests/renegotiation_test.bat +0 -27
  257. data/vendor/libressl/tests/renegotiation_test.sh +0 -30
  258. data/vendor/libressl/tests/rfc5280time_small.test +0 -10
  259. data/vendor/libressl/tests/servertest.bat +0 -27
  260. data/vendor/libressl/tests/servertest.sh +0 -30
  261. data/vendor/libressl/tests/shutdowntest.bat +0 -27
  262. data/vendor/libressl/tests/shutdowntest.sh +0 -30
  263. data/vendor/libressl/tests/ssltest.bat +0 -32
  264. data/vendor/libressl/tests/ssltest.sh +0 -48
  265. data/vendor/libressl/tests/testdsa.bat +0 -47
  266. data/vendor/libressl/tests/testdsa.sh +0 -57
  267. data/vendor/libressl/tests/testenc.bat +0 -85
  268. data/vendor/libressl/tests/testenc.sh +0 -93
  269. data/vendor/libressl/tests/testrsa.bat +0 -47
  270. data/vendor/libressl/tests/testrsa.sh +0 -57
  271. data/vendor/libressl/tests/testssl.bat +0 -171
  272. data/vendor/libressl/tests/tlstest.bat +0 -27
  273. data/vendor/libressl/tests/tlstest.sh +0 -28
  274. data/vendor/libressl/tls/CMakeLists.txt +0 -125
  275. data/vendor/libressl/tls/Makefile.am +0 -76
  276. data/vendor/libressl/tls/compat/ftruncate.c +0 -17
  277. data/vendor/libressl/tls/compat/pread.c +0 -29
  278. data/vendor/libressl/tls/compat/pwrite.c +0 -29
  279. data/vendor/libressl/update.sh +0 -460
@@ -138,7 +138,8 @@ struct io_uring_sq {
138
138
  unsigned ring_mask;
139
139
  unsigned ring_entries;
140
140
 
141
- unsigned pad[2];
141
+ unsigned sqes_sz;
142
+ unsigned pad;
142
143
  };
143
144
 
144
145
  struct io_uring_cq {
@@ -947,7 +948,7 @@ IOURINGINLINE void io_uring_prep_epoll_wait(struct io_uring_sqe *sqe, int fd,
947
948
  }
948
949
 
949
950
  IOURINGINLINE void io_uring_prep_files_update(struct io_uring_sqe *sqe,
950
- const int *fds, unsigned nr_fds,
951
+ int *fds, unsigned nr_fds,
951
952
  int offset)
952
953
  LIBURING_NOEXCEPT
953
954
  {
@@ -260,3 +260,7 @@ LIBURING_2.13 {
260
260
  io_uring_get_sqe128;
261
261
  io_uring_prep_cmd_getsockname;
262
262
  } LIBURING_2.12;
263
+
264
+ LIBURING_2.14 {
265
+
266
+ } LIBURING_2.13;
@@ -134,3 +134,7 @@ LIBURING_2.12 {
134
134
  LIBURING_2.13 {
135
135
 
136
136
  } LIBURING_2.12;
137
+
138
+ LIBURING_2.14 {
139
+
140
+ } LIBURING_2.13;
@@ -205,6 +205,18 @@ static unsigned __io_uring_flush_sq(struct io_uring *ring)
205
205
  struct io_uring_sq *sq = &ring->sq;
206
206
  unsigned tail = sq->sqe_tail;
207
207
 
208
+ /*
209
+ * With IORING_SETUP_SQ_REWIND, the kernel ignores the SQ head / tail
210
+ * and submits entries from the beginning of the queue. Continue using
211
+ * the indices as before but reset the tail on submission. With the
212
+ * head kept to be zero, io_uring_get_sqe() / etc. will work without
213
+ * any extra changes.
214
+ */
215
+ if (ring->flags & IORING_SETUP_SQ_REWIND) {
216
+ sq->sqe_tail = 0;
217
+ return tail;
218
+ }
219
+
208
220
  if (sq->sqe_head != tail) {
209
221
  sq->sqe_head = tail;
210
222
  /*
@@ -465,6 +465,7 @@ int io_uring_resize_rings(struct io_uring *ring, struct io_uring_params *p)
465
465
 
466
466
  sq_head = ring->sq.sqe_head;
467
467
  sq_tail = ring->sq.sqe_tail;
468
+ __sys_munmap(ring->sq.sqes, ring->sq.sqes_sz);
468
469
  io_uring_unmap_rings(&ring->sq, &ring->cq);
469
470
  memset(&ring->sq, 0, sizeof(ring->sq));
470
471
  memset(&ring->cq, 0, sizeof(ring->cq));
@@ -110,6 +110,7 @@ static size_t params_cq_size(const struct io_uring_params *p, unsigned cqes)
110
110
  int io_uring_mmap(int fd, struct io_uring_params *p, struct io_uring_sq *sq,
111
111
  struct io_uring_cq *cq)
112
112
  {
113
+ size_t sqes_sz;
113
114
  int ret;
114
115
 
115
116
  sq->ring_sz = p->sq_off.array + p->sq_entries * sizeof(unsigned);
@@ -139,7 +140,14 @@ int io_uring_mmap(int fd, struct io_uring_params *p, struct io_uring_sq *sq,
139
140
  }
140
141
  }
141
142
 
142
- sq->sqes = __sys_mmap(0, params_sqes_size(p, p->sq_entries),
143
+ sqes_sz = params_sqes_size(p, p->sq_entries);
144
+ sq->sqes_sz = (unsigned int) sqes_sz;
145
+ if (sq->sqes_sz != sqes_sz) {
146
+ ret = -EINVAL;
147
+ goto err;
148
+ }
149
+
150
+ sq->sqes = __sys_mmap(0, sq->sqes_sz,
143
151
  PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
144
152
  fd, IORING_OFF_SQES);
145
153
  if (IS_ERR(sq->sqes)) {
@@ -227,15 +235,14 @@ static int io_uring_alloc_huge(unsigned entries, struct io_uring_params *p,
227
235
  if (ret)
228
236
  return ret;
229
237
 
230
- ring_mem = KRING_SIZE;
231
-
232
238
  sqes_mem = params_sqes_size(p, sq_entries);
233
239
  if (!(p->flags & IORING_SETUP_NO_SQARRAY))
234
240
  sqes_mem += sq_entries * sizeof(unsigned);
235
241
  sqes_mem = (sqes_mem + page_size - 1) & ~(page_size - 1);
236
242
 
237
- ring_mem += sqes_mem + params_cq_size(p, cq_entries);
238
- mem_used = ring_mem;
243
+ ring_mem = KRING_SIZE;
244
+ ring_mem += params_cq_size(p, cq_entries);
245
+ mem_used = sqes_mem + ring_mem;
239
246
  mem_used = (mem_used + page_size - 1) & ~(page_size - 1);
240
247
 
241
248
  /*
@@ -269,6 +276,7 @@ static int io_uring_alloc_huge(unsigned entries, struct io_uring_params *p,
269
276
  }
270
277
 
271
278
  sq->sqes = ptr;
279
+ sq->sqes_sz = (unsigned int) sqes_size;
272
280
  if (mem_used <= buf_size) {
273
281
  sq->ring_ptr = (void *) sq->sqes + sqes_mem;
274
282
  /* clear ring sizes, we have just one mmap() to undo */
@@ -332,7 +340,7 @@ int __io_uring_queue_init_params(unsigned entries, struct io_uring *ring,
332
340
  if (fd < 0) {
333
341
  if ((p->flags & IORING_SETUP_NO_MMAP) &&
334
342
  !(ring->int_flags & INT_FLAG_APP_MEM)) {
335
- __sys_munmap(ring->sq.sqes, ret);
343
+ __sys_munmap(ring->sq.sqes, ring->sq.sqes_sz);
336
344
  io_uring_unmap_rings(&ring->sq, &ring->cq);
337
345
  }
338
346
  return fd;
@@ -447,7 +455,7 @@ __cold void io_uring_queue_exit(struct io_uring *ring)
447
455
  struct io_uring_cq *cq = &ring->cq;
448
456
 
449
457
  if (!(ring->int_flags & INT_FLAG_APP_MEM)) {
450
- __sys_munmap(sq->sqes, io_uring_sqes_size(ring));
458
+ __sys_munmap(sq->sqes, sq->sqes_sz);
451
459
  io_uring_unmap_rings(sq, cq);
452
460
  }
453
461
 
@@ -132,6 +132,7 @@ test_srcs := \
132
132
  io_uring_passthrough.c \
133
133
  io_uring_register.c \
134
134
  io_uring_setup.c \
135
+ io-wq-exit.c \
135
136
  iowait.c \
136
137
  kallsyms.c \
137
138
  lfs-openat.c \
@@ -144,6 +145,7 @@ test_srcs := \
144
145
  min-timeout.c \
145
146
  min-timeout-wait.c \
146
147
  mkdir.c \
148
+ mock_file.c \
147
149
  msg-ring.c \
148
150
  msg-ring-fd.c \
149
151
  msg-ring-flags.c \
@@ -176,6 +178,7 @@ test_srcs := \
176
178
  poll-race.c \
177
179
  poll-race-mshot.c \
178
180
  poll-ring.c \
181
+ poll-update-trigger.c \
179
182
  poll-v-poll.c \
180
183
  pollfree.c \
181
184
  probe.c \
@@ -205,6 +208,7 @@ test_srcs := \
205
208
  ringbuf-status.c \
206
209
  ring-leak2.c \
207
210
  ring-leak.c \
211
+ ring-query.c \
208
212
  rsrc_tags.c \
209
213
  rw_merge_test.c \
210
214
  self.c \
@@ -214,6 +218,7 @@ test_srcs := \
214
218
  send_recvmsg.c \
215
219
  send-zerocopy.c \
216
220
  sendmsg_iov_clean.c \
221
+ sendzc-bug.c \
217
222
  shared-wq.c \
218
223
  short-read.c \
219
224
  shutdown.c \
@@ -252,10 +257,13 @@ test_srcs := \
252
257
  timerfd-short-read.c \
253
258
  timeout.c \
254
259
  timeout-new.c \
260
+ timestamp.c \
261
+ timestamp-bug.c \
255
262
  truncate.c \
256
263
  tty-write-dpoll.c \
257
264
  unlink.c \
258
265
  uring_cmd_ublk.c \
266
+ vec-regbuf.c \
259
267
  version.c \
260
268
  waitid.c \
261
269
  wait-timeout.c \
@@ -263,10 +271,6 @@ test_srcs := \
263
271
  wq-aff.c \
264
272
  xattr.c \
265
273
  zcrx.c \
266
- vec-regbuf.c \
267
- timestamp.c \
268
- ring-query.c \
269
- mock_file.c \
270
274
  # EOL
271
275
 
272
276
  # Please keep this list sorted alphabetically.
@@ -30,7 +30,7 @@ static int check_cqe(struct io_uring *ring, struct io_uring_cqe *cqe)
30
30
 
31
31
  switch (cqe->user_data) {
32
32
  case 1:
33
- if (cqe->res != -ECONNRESET) {
33
+ if (cqe->res != -ECONNRESET && cqe->res != -ENETUNREACH) {
34
34
  fprintf(stderr, "Unexpected connect: %d\n", cqe->res);
35
35
  return T_EXIT_FAIL;
36
36
  }
@@ -10,11 +10,13 @@
10
10
  #include <poll.h>
11
11
  #include <string.h>
12
12
  #include <pthread.h>
13
+ #include <stdatomic.h>
13
14
  #include "liburing.h"
14
15
  #include "helpers.h"
15
16
 
16
17
  static int fds[2][2];
17
18
  static int no_epoll_wait;
19
+ static atomic_bool keep_running;
18
20
 
19
21
  static int test_ready(struct io_uring *ring, int efd)
20
22
  {
@@ -193,8 +195,8 @@ static int test_remove(struct io_uring *ring, int efd)
193
195
  return 0;
194
196
  }
195
197
 
196
- #define LOOPS 500
197
198
  #define NPIPES 8
199
+ #define MAX_QE 1000
198
200
 
199
201
  struct d {
200
202
  int pipes[NPIPES][2];
@@ -203,9 +205,9 @@ struct d {
203
205
  static void *thread_fn(void *data)
204
206
  {
205
207
  struct d *d = data;
206
- int i, j;
208
+ int i;
207
209
 
208
- for (j = 0; j < LOOPS; j++) {
210
+ while (atomic_load_explicit(&keep_running, memory_order_relaxed)) {
209
211
  usleep(150);
210
212
  for (i = 0; i < NPIPES; i++) {
211
213
  int ret;
@@ -240,8 +242,12 @@ static int test_race(int flags)
240
242
  struct epoll_event ev;
241
243
  struct epoll_event out[NPIPES];
242
244
  pthread_t thread;
243
- int i, j, efd, ret;
245
+ int i, efd, ret;
244
246
  void *tret;
247
+ int sqe_id = 0;
248
+ int submitted = 0, completed = 0;
249
+ int sqe_ids[MAX_QE];
250
+ int cqe_ids[MAX_QE];
245
251
 
246
252
  ret = t_create_ring(32, &ring, flags);
247
253
  if (ret == T_SETUP_SKIP) {
@@ -278,16 +284,19 @@ static int test_race(int flags)
278
284
  io_uring_prep_epoll_wait(sqe, efd, out, NPIPES, 0);
279
285
  io_uring_submit(&ring);
280
286
 
287
+ atomic_store(&keep_running, true);
281
288
  pthread_create(&thread, NULL, thread_fn, &d);
282
289
 
283
- for (j = 0; j < LOOPS; j++) {
290
+ while (completed < 1000) {
284
291
  io_uring_submit_and_wait(&ring, 1);
285
-
292
+ sqe_ids[submitted] = sqe->user_data;
286
293
  ret = io_uring_wait_cqe(&ring, &cqe);
287
294
  if (ret) {
288
295
  fprintf(stderr, "wait %d\n", ret);
289
296
  return 1;
290
297
  }
298
+ cqe_ids[completed] = cqe->user_data;
299
+ completed++;
291
300
  if (cqe->res < 0) {
292
301
  fprintf(stderr, "race res %d\n", cqe->res);
293
302
  return 1;
@@ -297,10 +306,27 @@ static int test_race(int flags)
297
306
  usleep(100);
298
307
  sqe = io_uring_get_sqe(&ring);
299
308
  io_uring_prep_epoll_wait(sqe, efd, out, NPIPES, 0);
309
+ sqe->user_data = ++sqe_id;
310
+ submitted++;
300
311
  }
301
312
 
313
+ atomic_store(&keep_running, false);
302
314
  pthread_join(thread, &tret);
303
315
 
316
+ if (submitted != completed) {
317
+ fprintf(stderr, "SQE/CQE mismatch: submitted=%d completed=%d\n",
318
+ submitted, completed);
319
+ return 1;
320
+ }
321
+
322
+ for (i = 0; i < completed; i++) {
323
+ if (sqe_ids[i] != cqe_ids[i]) {
324
+ fprintf(stderr, "user_data mismatch at %d: sqe=%d cqe=%d\n",
325
+ i, sqe_ids[i], cqe_ids[i]);
326
+ return 1;
327
+ }
328
+ }
329
+
304
330
  for (i = 0; i < NPIPES; i++) {
305
331
  close(d.pipes[i][0]);
306
332
  close(d.pipes[i][1]);
@@ -0,0 +1,131 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: Test that created thread that sets up a ring and causes io-wq
4
+ * worker creation doesn't need to wait for io-wq idle worker
5
+ * timeout to exit.
6
+ *
7
+ */
8
+ #include <fcntl.h>
9
+ #include <pthread.h>
10
+ #include <stddef.h>
11
+ #include <stdint.h>
12
+ #include <stdio.h>
13
+ #include <string.h>
14
+ #include <time.h>
15
+ #include <unistd.h>
16
+
17
+ #include "liburing.h"
18
+ #include "helpers.h"
19
+
20
+ #define BUF_LEN 20
21
+
22
+ static void *test(void *data)
23
+ {
24
+ int fd_src = -1, fd_dst = -1, pipe_fds[2] = { -1, -1 };
25
+ uint8_t buffer_write[BUF_LEN], buffer_read[BUF_LEN];
26
+ char dst_fname[PATH_MAX], src_fname[PATH_MAX];
27
+ struct io_uring_sqe *sqe;
28
+ struct io_uring_cqe *cqe;
29
+ struct io_uring ring;
30
+ int ret;
31
+
32
+ ret = io_uring_queue_init(4, &ring, 0);
33
+ if (ret < 0) {
34
+ fprintf(stderr, "io_uring_queue_init failed: %d\n", ret);
35
+ return NULL;
36
+ }
37
+
38
+ sprintf(src_fname, ".splice.%d.src", getpid());
39
+ fd_src = open(src_fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
40
+ if (fd_src < 0) {
41
+ perror("open source");
42
+ goto cleanup;
43
+ }
44
+
45
+ sprintf(dst_fname, ".splice.%d.dst", getpid());
46
+ fd_dst = open(dst_fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
47
+ if (fd_dst < 0) {
48
+ perror("open destination");
49
+ goto cleanup;
50
+ }
51
+
52
+ memset(buffer_write, 97, BUF_LEN);
53
+ memset(buffer_read, 98, BUF_LEN);
54
+ ret = pwrite(fd_src, buffer_write, BUF_LEN, 0);
55
+ if (ret < 0) {
56
+ perror("pwrite src");
57
+ goto cleanup;
58
+ }
59
+
60
+ if (pipe(pipe_fds) < 0) {
61
+ perror("pipe");
62
+ goto cleanup;
63
+ }
64
+
65
+ sqe = io_uring_get_sqe(&ring);
66
+ io_uring_prep_splice(sqe, fd_src, 0, pipe_fds[1], -1, 20, 0);
67
+ sqe->user_data = 1;
68
+
69
+ sqe = io_uring_get_sqe(&ring);
70
+ io_uring_prep_splice(sqe, pipe_fds[0], -1, fd_dst, 10, 20, 0);
71
+ sqe->user_data = 2;
72
+
73
+ io_uring_submit(&ring);
74
+
75
+ ret = io_uring_wait_cqe(&ring, &cqe);
76
+ if (ret) {
77
+ fprintf(stderr, "wait cqe %d\n", ret);
78
+ goto cleanup;
79
+ }
80
+ io_uring_cqe_seen(&ring, cqe);
81
+
82
+ ret = io_uring_wait_cqe(&ring, &cqe);
83
+ if (ret) {
84
+ fprintf(stderr, "wait cqe %d\n", ret);
85
+ goto cleanup;
86
+ }
87
+ io_uring_cqe_seen(&ring, cqe);
88
+ cleanup:
89
+ if (pipe_fds[0] != -1)
90
+ close(pipe_fds[0]);
91
+ if (pipe_fds[1] != -1)
92
+ close(pipe_fds[1]);
93
+ if (fd_src != -1)
94
+ close(fd_src);
95
+ if (fd_src != -1)
96
+ close(fd_dst);
97
+ io_uring_queue_exit(&ring);
98
+ unlink(src_fname);
99
+ unlink(dst_fname);
100
+ return NULL;
101
+ }
102
+
103
+ static long get_time_ns(void)
104
+ {
105
+ struct timespec ts;
106
+
107
+ clock_gettime(CLOCK_MONOTONIC, &ts);
108
+ return ts.tv_sec * 1000000000L + ts.tv_nsec;
109
+ }
110
+
111
+ int main(int argc, char *argv[])
112
+ {
113
+ pthread_t thread;
114
+ long start, end;
115
+
116
+ if (argc > 1)
117
+ return T_EXIT_SKIP;
118
+
119
+ start = get_time_ns();
120
+ pthread_create(&thread, NULL, test, NULL);
121
+ pthread_join(thread, NULL);
122
+ end = get_time_ns();
123
+ end -= start;
124
+ end /= 1000000;
125
+ if (end >= 500) {
126
+ fprintf(stderr, "Test took too long: %lu msec\n", end);
127
+ return T_EXIT_FAIL;
128
+ }
129
+
130
+ return T_EXIT_PASS;
131
+ }
@@ -90,7 +90,7 @@ static int test(struct io_uring *ring, int with_iowait, int cpu)
90
90
  io_uring_cqe_seen(ring, cqe);
91
91
 
92
92
  if (with_iowait) {
93
- if (diff < 90) {
93
+ if (diff < 50) {
94
94
  fprintf(stderr, "iowait diff too small: %d\n", diff);
95
95
  return T_EXIT_FAIL;
96
96
  }
@@ -133,8 +133,10 @@ static int test(int flags, int expected_ctx, int min_wait, int write_delay,
133
133
  io_uring_cqe_seen(&ring, cqe);
134
134
  }
135
135
 
136
- if (i != nr_cqes)
136
+ if (i != nr_cqes) {
137
137
  fprintf(stderr, "Got %d CQEs, expected %d\n", i, nr_cqes);
138
+ return T_EXIT_FAIL;
139
+ }
138
140
 
139
141
  pthread_join(thread, &tret);
140
142
 
@@ -217,6 +217,39 @@ err:
217
217
  return -1;
218
218
  }
219
219
 
220
+ static int test_open_direct_cloexec(struct io_uring *ring, const char *path, int dfd)
221
+ {
222
+ struct io_uring_cqe *cqe;
223
+ struct io_uring_sqe *sqe;
224
+ int ret;
225
+
226
+ sqe = io_uring_get_sqe(ring);
227
+ if (!sqe) {
228
+ fprintf(stderr, "get sqe failed\n");
229
+ goto err;
230
+ }
231
+ io_uring_prep_openat(sqe, dfd, path, O_RDONLY | O_CLOEXEC, 0);
232
+ sqe->file_index = 1;
233
+
234
+ ret = io_uring_submit(ring);
235
+ if (ret <= 0) {
236
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
237
+ goto err;
238
+ }
239
+
240
+ ret = io_uring_wait_cqe(ring, &cqe);
241
+ if (ret < 0) {
242
+ fprintf(stderr, "wait completion %d\n", ret);
243
+ goto err;
244
+ }
245
+ if (cqe->res != -EINVAL)
246
+ return 1;
247
+ io_uring_cqe_seen(ring, cqe);
248
+ return 0;
249
+ err:
250
+ return 1;
251
+ }
252
+
220
253
  int main(int argc, char *argv[])
221
254
  {
222
255
  struct io_uring ring;
@@ -288,6 +321,12 @@ int main(int argc, char *argv[])
288
321
  goto err;
289
322
  }
290
323
 
324
+ ret = test_open_direct_cloexec(&ring, path, -1);
325
+ if (ret) {
326
+ fprintf(stderr, "test_open_direct_cloexex failed\n");
327
+ goto err;
328
+ }
329
+
291
330
  done:
292
331
  unlink(path);
293
332
  if (do_unlink)
@@ -0,0 +1,85 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test POLL_ADD being added with a mask that doesn't make it
4
+ * trigger, but then updated with POLL_REMOVE to a mask that does
5
+ * trigger it.
6
+ */
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+ #include <unistd.h>
10
+ #include <fcntl.h>
11
+ #include <sys/stat.h>
12
+ #include <sys/types.h>
13
+ #include <poll.h>
14
+
15
+ #include "liburing.h"
16
+ #include "helpers.h"
17
+
18
+ int main(int argc, char *argv[])
19
+ {
20
+ struct io_uring_sqe *sqe;
21
+ struct io_uring_cqe *cqe;
22
+ struct io_uring ring;
23
+ int ret, fd[2], i;
24
+
25
+ if (argc > 1)
26
+ return T_EXIT_SKIP;
27
+
28
+ ret = io_uring_queue_init(4, &ring, 0);
29
+ if (ret) {
30
+ fprintf(stderr, "queue_init: %d\n", ret);
31
+ return T_EXIT_FAIL;
32
+ }
33
+
34
+ if (pipe(fd) < 0) {
35
+ perror("pipe");
36
+ return T_EXIT_FAIL;
37
+ }
38
+
39
+ /*
40
+ * Attach POLLIN request to output side of pipe, won't complete as
41
+ * that will never be readabable.
42
+ */
43
+ sqe = io_uring_get_sqe(&ring);
44
+ io_uring_prep_poll_add(sqe, fd[1], POLLIN);
45
+ sqe->user_data = 1;
46
+ io_uring_submit(&ring);
47
+
48
+ /*
49
+ * Now update the previously submitted poll request, adding POLLOUT.
50
+ * This will cause it to trigger immediately, as the pipe is indeed
51
+ * writeable.
52
+ */
53
+ sqe = io_uring_get_sqe(&ring);
54
+ io_uring_prep_poll_remove(sqe, 1);
55
+ sqe->len = IORING_POLL_UPDATE_EVENTS;
56
+ sqe->poll32_events = POLLOUT;
57
+ sqe->user_data = 2;
58
+ io_uring_submit(&ring);
59
+
60
+ /*
61
+ * Expect both requests to complete - the update with 0 for success,
62
+ * and the original poll_add with POLLOUT as the result.
63
+ */
64
+ for (i = 0; i < 2; i++) {
65
+ ret = io_uring_wait_cqe(&ring, &cqe);
66
+ if (ret) {
67
+ fprintf(stderr, "wait_cqe: %d\n", ret);
68
+ return T_EXIT_FAIL;
69
+ }
70
+ if (cqe->user_data == 1) {
71
+ if (cqe->res != POLLOUT) {
72
+ fprintf(stderr, "Original poll: %d\n", cqe->res);
73
+ return T_EXIT_FAIL;
74
+ }
75
+ } else if (cqe->user_data == 2) {
76
+ if (cqe->res) {
77
+ fprintf(stderr, "Poll update: %d\n", cqe->res);
78
+ return T_EXIT_FAIL;
79
+ }
80
+ }
81
+ io_uring_cqe_seen(&ring, cqe);
82
+ }
83
+
84
+ return T_EXIT_PASS;
85
+ }
@@ -333,12 +333,9 @@ err:
333
333
  return (void *)(intptr_t)ret;
334
334
  }
335
335
 
336
- static int __do_send_bundle(struct recv_data *rd, struct io_uring *ring, int sockfd)
336
+ static void submit_bundle(struct io_uring *ring, int sockfd)
337
337
  {
338
- struct io_uring_cqe *cqe;
339
338
  struct io_uring_sqe *sqe;
340
- int bytes_needed = MSG_SIZE * nr_msgs;
341
- int i, ret;
342
339
 
343
340
  sqe = io_uring_get_sqe(ring);
344
341
  io_uring_prep_send_bundle(sqe, sockfd, 0, 0);
@@ -346,9 +343,16 @@ static int __do_send_bundle(struct recv_data *rd, struct io_uring *ring, int soc
346
343
  sqe->buf_group = SEND_BGID;
347
344
  sqe->user_data = 1;
348
345
 
349
- ret = io_uring_submit(ring);
350
- if (ret != 1)
351
- return 1;
346
+ io_uring_submit(ring);
347
+ }
348
+
349
+ static int __do_send_bundle(struct recv_data *rd, struct io_uring *ring, int sockfd)
350
+ {
351
+ struct io_uring_cqe *cqe;
352
+ int bytes_needed = MSG_SIZE * nr_msgs;
353
+ int i, ret;
354
+
355
+ submit_bundle(ring, sockfd);
352
356
 
353
357
  pthread_barrier_wait(&rd->barrier);
354
358
 
@@ -372,10 +376,9 @@ static int __do_send_bundle(struct recv_data *rd, struct io_uring *ring, int soc
372
376
  io_uring_cqe_seen(ring, cqe);
373
377
  break;
374
378
  }
375
- if (!(cqe->flags & IORING_CQE_F_MORE)) {
376
- fprintf(stderr, "expected more, but MORE not set\n");
377
- return 1;
378
- }
379
+ /* bundle finished, resubmit as more is pending */
380
+ if (!(cqe->flags & IORING_CQE_F_MORE))
381
+ submit_bundle(ring, sockfd);
379
382
  io_uring_cqe_seen(ring, cqe);
380
383
  }
381
384