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
@@ -0,0 +1,146 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test that importing a buffer node ties the lifetime to the
4
+ * notification io_kiocb, not the normal request.
5
+ *
6
+ * Based on a test case from Google Big Sleep.
7
+ *
8
+ */
9
+ #include <arpa/inet.h>
10
+ #include <err.h>
11
+ #include <fcntl.h>
12
+ #include <netinet/in.h>
13
+ #include <poll.h>
14
+ #include <pthread.h>
15
+ #include <stdint.h>
16
+ #include <stdio.h>
17
+ #include <stdlib.h>
18
+ #include <string.h>
19
+ #include <sys/mman.h>
20
+ #include <sys/socket.h>
21
+ #include <sys/stat.h>
22
+ #include <sys/syscall.h>
23
+ #include <sys/types.h>
24
+ #include <sys/wait.h>
25
+ #include <unistd.h>
26
+
27
+ #include "liburing.h"
28
+ #include "helpers.h"
29
+
30
+ #define BUF_SIZE (1024 * 1024)
31
+ static uint8_t read_buffer[BUF_SIZE] = { 0 };
32
+
33
+ /* Creates a pair of connected TCP sockets. */
34
+ static void tcp_socketpair(int sv[2])
35
+ {
36
+ struct sockaddr_in addr_in = {
37
+ .sin_family = AF_INET,
38
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
39
+ .sin_port = 0,
40
+ };
41
+ struct sockaddr *addr = (struct sockaddr *) &addr_in;
42
+ socklen_t addr_len = sizeof(addr_in);
43
+ int listener_fd;
44
+
45
+ listener_fd = socket(AF_INET, SOCK_STREAM, 0);
46
+ if (listener_fd < 0)
47
+ err(EXIT_FAILURE, "listener socket");
48
+
49
+ if (bind(listener_fd, addr, addr_len) < 0)
50
+ err(EXIT_FAILURE, "bind");
51
+
52
+ if (listen(listener_fd, 1) < 0)
53
+ err(EXIT_FAILURE, "listen");
54
+
55
+ if (getsockname(listener_fd, addr, &addr_len) < 0)
56
+ err(EXIT_FAILURE, "getsockname");
57
+
58
+ sv[0] = socket(AF_INET, SOCK_STREAM, 0);
59
+ if (sv[0] < 0)
60
+ err(EXIT_FAILURE, "socket(AF_INET, SOCK_STREAM, 0)");
61
+
62
+ if (connect(sv[0], addr, addr_len) < 0)
63
+ err(EXIT_FAILURE, "connect");
64
+
65
+ sv[1] = accept(listener_fd, NULL, NULL);
66
+ if (sv[1] == -1)
67
+ err(EXIT_FAILURE, "accept");
68
+
69
+ close(listener_fd);
70
+ }
71
+
72
+ int main(int argc, char *argv[])
73
+ {
74
+ struct io_uring_sqe *sqe;
75
+ struct io_uring_cqe* cqe;
76
+ struct iovec send_iov;
77
+ struct io_uring ring;
78
+ struct iovec iov_reg;
79
+ struct msghdr msg = {
80
+ .msg_iov = &send_iov,
81
+ .msg_iovlen = 1,
82
+ };
83
+ void *send_buffer;
84
+ int sockets[2];
85
+ int val, ret;
86
+
87
+ if (argc > 1)
88
+ return T_EXIT_SKIP;
89
+
90
+ tcp_socketpair(sockets);
91
+
92
+ val = 1;
93
+ if (setsockopt(sockets[0], SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val)))
94
+ err(EXIT_FAILURE, "setsockopt(SO_ZEROCOPY)");
95
+
96
+ ret = io_uring_queue_init(1, &ring, 0);
97
+ if (ret < 0)
98
+ errx(EXIT_FAILURE, "io_uring_queue_init: %s", strerror(-ret));
99
+
100
+ /* mmap send_buffer so we can unmap it later. */
101
+ send_buffer = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
102
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
103
+ if (send_buffer == MAP_FAILED)
104
+ err(EXIT_FAILURE, "mapping iouring buffer");
105
+
106
+ iov_reg.iov_base = send_buffer;
107
+ iov_reg.iov_len = BUF_SIZE;
108
+ ret = io_uring_register_buffers(&ring, &iov_reg, 1);
109
+ if (ret < 0)
110
+ errx(EXIT_FAILURE, "io_uring_register_buffers: %s", strerror(-ret));
111
+
112
+ sqe = io_uring_get_sqe(&ring);
113
+
114
+ send_iov.iov_base = send_buffer;
115
+ send_iov.iov_len = BUF_SIZE;
116
+
117
+ io_uring_prep_sendmsg_zc(sqe, sockets[0], &msg, 0);
118
+ sqe->ioprio = IORING_RECVSEND_FIXED_BUF;
119
+ sqe->buf_index = 0;
120
+
121
+ memset(send_buffer, 'B', BUF_SIZE);
122
+
123
+ io_uring_submit(&ring);
124
+
125
+ ret = io_uring_wait_cqe(&ring, &cqe);
126
+ if (ret < 0)
127
+ errx(EXIT_FAILURE, "io_uring_wait_cqe: %s", strerror(-ret));
128
+
129
+ if (cqe->res < 0) {
130
+ if (cqe->res == -EINVAL)
131
+ return T_EXIT_SKIP;
132
+ errx(EXIT_FAILURE, "readv failed: %s", strerror(-cqe->res));
133
+ }
134
+
135
+ io_uring_cqe_seen(&ring, cqe);
136
+
137
+ io_uring_unregister_buffers(&ring);
138
+ munmap(send_buffer, BUF_SIZE);
139
+
140
+ ret = read(sockets[1], read_buffer, BUF_SIZE);
141
+ if (ret < 0)
142
+ err(EXIT_FAILURE, "read");
143
+
144
+ io_uring_queue_exit(&ring);
145
+ return T_EXIT_PASS;
146
+ }
@@ -9,9 +9,11 @@
9
9
  #include "helpers.h"
10
10
  #include "test.h"
11
11
 
12
+ #define NENTRIES 8
13
+
12
14
  static int seq;
13
15
 
14
- static int test_single_nop(struct io_uring *ring, bool sqe128)
16
+ static int test_single_nop(struct io_uring *ring, bool sqe128, int offset)
15
17
  {
16
18
  struct io_uring_cqe *cqe;
17
19
  struct io_uring_sqe *sqe;
@@ -54,15 +56,123 @@ static int test_single_nop(struct io_uring *ring, bool sqe128)
54
56
  return T_EXIT_FAIL;
55
57
  }
56
58
 
57
- int main(int argc, char *argv[])
59
+ static int check_sq(struct io_uring *ring, unsigned int ready,
60
+ unsigned int left, const char *msg)
61
+ {
62
+ unsigned int pspace, pready;
63
+
64
+ pready = io_uring_sq_ready(ring);
65
+ if (pready != ready) {
66
+ fprintf(stderr, "%s: %d ready, should be %d\n", msg, pready, ready);
67
+ return 1;
68
+ }
69
+ pspace = io_uring_sq_space_left(ring);
70
+ if (pspace != left) {
71
+ fprintf(stderr, "%s: %d entries, should be %d\n", msg, pspace, left);
72
+ return 1;
73
+ }
74
+
75
+ return 0;
76
+ }
77
+
78
+ static void submit_and_reap(struct io_uring *ring, int to_reap, const char *msg)
79
+ {
80
+ struct io_uring_cqe *cqe;
81
+ unsigned long ud = 1000;
82
+ int i;
83
+
84
+ io_uring_submit(ring);
85
+
86
+ for (i = 0; i < to_reap; i++) {
87
+ io_uring_wait_cqe(ring, &cqe);
88
+ if (cqe->res < 0) {
89
+ fprintf(stderr, "cqe res %d\n", cqe->res);
90
+ io_uring_cqe_seen(ring, cqe);
91
+ continue;
92
+ }
93
+ if (cqe->user_data != ud)
94
+ fprintf(stderr, "%s: cqe=%d, %ld != %ld\n", msg, i, (long) cqe->user_data, ud);
95
+ ud++;
96
+ io_uring_cqe_seen(ring, cqe);
97
+ }
98
+ }
99
+
100
+ static int test_sq_space(struct io_uring *ring, unsigned int flags)
101
+ {
102
+ struct io_uring_sqe *sqe;
103
+ int nop_adj;
104
+
105
+ /*
106
+ * For SQ_REWIND, sqe_tail resets to 0 after each submit, so we always
107
+ * start at position 0 and never hit wrap cases. For non-SQ_REWIND,
108
+ * after 32 test_single_nop iterations, sqe_tail ends up at position 7
109
+ * (modulo 8), so step5's sqe128 triggers the wrap case with a NOP.
110
+ */
111
+ nop_adj = 0;
112
+ if (!(flags & IORING_SETUP_SQ_REWIND))
113
+ nop_adj = 1;
114
+
115
+ if (check_sq(ring, 0, NENTRIES, "initial"))
116
+ return 1;
117
+
118
+ sqe = io_uring_get_sqe(ring);
119
+ io_uring_prep_nop(sqe);
120
+ sqe->user_data = 1000;
121
+
122
+ if (check_sq(ring, 1, NENTRIES - 1, "step1"))
123
+ return 1;
124
+
125
+ sqe = io_uring_get_sqe128(ring);
126
+ io_uring_prep_nop128(sqe);
127
+ sqe->user_data = 1001;
128
+
129
+ if (check_sq(ring, 3, NENTRIES - 3, "step2"))
130
+ return 1;
131
+
132
+ sqe = io_uring_get_sqe(ring);
133
+ io_uring_prep_nop(sqe);
134
+ sqe->user_data = 1002;
135
+
136
+ if (check_sq(ring, 4, NENTRIES - 4, "step3"))
137
+ return 1;
138
+
139
+ submit_and_reap(ring, 3, "round1");
140
+
141
+ if (check_sq(ring, 0, NENTRIES, "step4"))
142
+ return 1;
143
+
144
+ sqe = io_uring_get_sqe128(ring);
145
+ io_uring_prep_nop128(sqe);
146
+ sqe->user_data = 1000;
147
+
148
+ /* SQ_REWIND: no wrap at position 0, just 2 slots. Non-rewind: wrap at 7, 3 slots */
149
+ if (check_sq(ring, 2 + nop_adj, NENTRIES - 2 - nop_adj, "step5"))
150
+ return 1;
151
+
152
+ sqe = io_uring_get_sqe(ring);
153
+ io_uring_prep_nop(sqe);
154
+ sqe->user_data = 1001;
155
+
156
+ if (check_sq(ring, 3 + nop_adj, NENTRIES - 3 - nop_adj, "step6"))
157
+ return 1;
158
+
159
+ sqe = io_uring_get_sqe128(ring);
160
+ io_uring_prep_nop128(sqe);
161
+ sqe->user_data = 1002;
162
+
163
+ if (check_sq(ring, 5 + nop_adj, NENTRIES - 5 - nop_adj, "step7"))
164
+ return 1;
165
+
166
+ submit_and_reap(ring, 3, "round2");
167
+ return 0;
168
+ }
169
+
170
+ static int test_flags(unsigned int flags)
58
171
  {
59
172
  struct io_uring ring;
60
173
  int ret, i;
61
174
 
62
- if (argc > 1)
63
- return T_EXIT_SKIP;
64
-
65
- ret = io_uring_queue_init(8, &ring, IORING_SETUP_SQE_MIXED);
175
+ ret = io_uring_queue_init(NENTRIES, &ring, IORING_SETUP_SQE_MIXED | flags);
66
176
  if (ret) {
67
177
  if (ret == -EINVAL)
68
178
  return T_EXIT_SKIP;
@@ -72,11 +182,45 @@ int main(int argc, char *argv[])
72
182
 
73
183
  /* alternate big and little sqe's */
74
184
  for (i = 0; i < 32; i++) {
75
- ret = test_single_nop(&ring, i & 1);
185
+ ret = test_single_nop(&ring, i & 1, i);
76
186
  if (ret != T_EXIT_PASS)
77
187
  break;
78
188
  }
79
189
 
190
+ if (ret) {
191
+ fprintf(stderr, "Single nop test failed\n");
192
+ io_uring_queue_exit(&ring);
193
+ return ret;
194
+ }
195
+
196
+ ret = test_sq_space(&ring, flags);
80
197
  io_uring_queue_exit(&ring);
81
198
  return ret;
199
+
200
+ }
201
+
202
+ int main(int argc, char *argv[])
203
+ {
204
+ int ret;
205
+
206
+ if (argc > 1)
207
+ return T_EXIT_SKIP;
208
+
209
+ ret = test_flags(0);
210
+ if (ret == T_EXIT_SKIP) {
211
+ return T_EXIT_SKIP;
212
+ } else if (ret) {
213
+ fprintf(stderr, "test flags 0 failed\n");
214
+ return T_EXIT_FAIL;
215
+ }
216
+
217
+ ret = test_flags(IORING_SETUP_SQ_REWIND);
218
+ if (ret == T_EXIT_SKIP) {
219
+ return T_EXIT_SKIP;
220
+ } else if (ret) {
221
+ fprintf(stderr, "test flags REWIND failed\n");
222
+ return T_EXIT_FAIL;
223
+ }
224
+
225
+ return ret;
82
226
  }
@@ -20,6 +20,8 @@ static io_uring_test_config io_uring_test_configs[] = {
20
20
  { IORING_SETUP_SQE128, "large SQE"},
21
21
  { IORING_SETUP_CQE32, "large CQE"},
22
22
  { IORING_SETUP_SQE128 | IORING_SETUP_CQE32, "large SQE/CQE" },
23
+ { IORING_SETUP_SQ_REWIND, "rewind SQ"},
24
+ { IORING_SETUP_SQ_REWIND | IORING_SETUP_SQE128, "large rewind SQ"},
23
25
  };
24
26
 
25
27
  #define FOR_ALL_TEST_CONFIGS \
@@ -0,0 +1,135 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: verify that timestamp retrieval that needs retrying with
4
+ * a current list of SKBs works.
5
+ *
6
+ * Based on a test case from Google Big Sleep.
7
+ *
8
+ */
9
+ #include <arpa/inet.h>
10
+ #include <err.h>
11
+ #include <fcntl.h>
12
+ #include <sys/time.h>
13
+ #include <linux/errqueue.h>
14
+ #include <linux/net_tstamp.h>
15
+ #include <netinet/in.h>
16
+ #include <stdio.h>
17
+ #include <stdlib.h>
18
+ #include <string.h>
19
+ #include <sys/socket.h>
20
+ #include <sys/uio.h>
21
+ #include <unistd.h>
22
+
23
+ #include "liburing.h"
24
+ #include "helpers.h"
25
+
26
+ /* Compatibility with slightly older kernel headers */
27
+ #ifndef SOCKET_URING_OP_TX_TIMESTAMP
28
+ #define SOCKET_URING_OP_TX_TIMESTAMP 4
29
+ #endif
30
+
31
+ /*
32
+ * Create a socket whose error queue contains both timestamp information and
33
+ * actual errors.
34
+ */
35
+ static int create_sock_with_timestamps_and_errors(void)
36
+ {
37
+ struct sockaddr_in recv_addr = { };
38
+ struct sockaddr_in closed = { };
39
+ int recv_sock, sock, val;
40
+ char data = 'A';
41
+
42
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
43
+ if (sock < 0)
44
+ err(1, "socket");
45
+
46
+ /* Enable TX timestamps */
47
+ val = SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_SOFTWARE |
48
+ SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_OPT_TSONLY;
49
+ if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, sizeof(val)) < 0)
50
+ err(1, "setsockopt(SO_TIMESTAMPING)");
51
+
52
+ /* Enable IP_RECVERR */
53
+ val = 1;
54
+ if (setsockopt(sock, IPPROTO_IP, IP_RECVERR, &val, sizeof(val)) < 0)
55
+ err(1, "setsockopt(IP_RECVERR)");
56
+
57
+ recv_sock = socket(AF_INET, SOCK_DGRAM, 0);
58
+ if (recv_sock < 0)
59
+ err(1, "socket");
60
+
61
+ recv_addr.sin_family = AF_INET;
62
+ recv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
63
+ if (bind(recv_sock, (struct sockaddr*)&recv_addr, sizeof(recv_addr)) < 0)
64
+ err(1, "bind receiver");
65
+
66
+ socklen_t recv_len = sizeof(recv_addr);
67
+ if (getsockname(recv_sock, (struct sockaddr*)&recv_addr, &recv_len) < 0)
68
+ err(1, "getsockname");
69
+
70
+ /* Send packets to generate TX timestamps. */
71
+ for (int i = 0; i < 2; i++) {
72
+ if (sendto(sock, &data, sizeof(data), 0, (struct sockaddr*)&recv_addr, sizeof(recv_addr)) < 0)
73
+ err(1, "sendto (%d)", i);
74
+ }
75
+
76
+ closed.sin_family = AF_INET;
77
+ closed.sin_addr.s_addr = inet_addr("127.0.0.1");
78
+ closed.sin_port = htons(9); /* assuming no one is listening on port 9 */
79
+ if (sendto(sock, &data, sizeof(data), 0, (struct sockaddr*) &closed, sizeof(closed)) < 0)
80
+ warn("sendto");
81
+
82
+ return sock;
83
+ }
84
+
85
+ int main(int argc, char *argv[])
86
+ {
87
+ struct io_uring_sqe *sqe;
88
+ struct io_uring_cqe *cqe;
89
+ struct io_uring ring;
90
+ struct io_uring_params params = {
91
+ .flags = IORING_SETUP_CQE32, /* required for timestamps */
92
+ };
93
+ char buf[1024], ctrl_recv[1024];
94
+ struct iovec iov_recv = { .iov_base = buf, .iov_len = sizeof(buf) };
95
+ struct msghdr msg_recv = {
96
+ .msg_iov = &iov_recv,
97
+ .msg_iovlen = 1,
98
+ .msg_control = ctrl_recv,
99
+ .msg_controllen = sizeof(ctrl_recv),
100
+ };
101
+ int sock, ret;
102
+
103
+ if (argc > 1)
104
+ return T_EXIT_SKIP;
105
+
106
+ sock = create_sock_with_timestamps_and_errors();
107
+
108
+ ret = io_uring_queue_init_params(1, &ring, &params);
109
+ if (ret < 0) {
110
+ if (ret == -EINVAL)
111
+ return T_EXIT_SKIP;
112
+ err(1, "io_uring_queue_init_params: %d", ret);
113
+ }
114
+
115
+ sqe = io_uring_get_sqe(&ring);
116
+ *sqe = (struct io_uring_sqe) {
117
+ .opcode = IORING_OP_URING_CMD,
118
+ .fd = sock,
119
+ .cmd_op = SOCKET_URING_OP_TX_TIMESTAMP,
120
+ };
121
+
122
+ io_uring_submit(&ring);
123
+
124
+ ret = io_uring_wait_cqe(&ring, &cqe);
125
+ if (ret < 0)
126
+ errx(1, "io_uring_wait_cqe: %d", ret);
127
+ ret = cqe->res;
128
+ io_uring_cqe_seen(&ring, cqe);
129
+ /* kernel doesn't support retrieving timestamps */
130
+ if (ret == -EOPNOTSUPP)
131
+ return T_EXIT_SKIP;
132
+
133
+ recvmsg(sock, &msg_recv, MSG_ERRQUEUE | MSG_DONTWAIT);
134
+ return T_EXIT_PASS;
135
+ }
@@ -1,3 +1,8 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test timestamp retrieving
4
+ *
5
+ */
1
6
  #include <time.h>
2
7
  #include <arpa/inet.h>
3
8
  #include <inttypes.h>
@@ -520,6 +520,135 @@ static void test_basic(struct buf_desc *bd)
520
520
  }
521
521
  }
522
522
 
523
+ static int test_readv_fixed(struct buf_desc *bd, struct iovec *vecs, int nr_vec)
524
+ {
525
+ unsigned buf_idx = bd->buf_idx;
526
+ struct io_uring *ring = &bd->ring;
527
+ struct io_uring_sqe *sqe;
528
+ struct io_uring_cqe *cqe;
529
+ size_t total_len, i, offset;
530
+ int ret, fd;
531
+ char *expected;
532
+ char filename[] = ".readv_fixed.XXXXXX";
533
+
534
+ total_len = t_iovec_data_length(vecs, nr_vec);
535
+
536
+ expected = malloc(total_len);
537
+ if (!expected) {
538
+ fprintf(stderr, "malloc failed\n");
539
+ return 1;
540
+ }
541
+
542
+ /* Fill expected buffer with pattern */
543
+ for (i = 0; i < total_len; i++)
544
+ expected[i] = i & 0xff;
545
+
546
+ fd = mkstemp(filename);
547
+ if (fd < 0) {
548
+ perror("mkstemp");
549
+ free(expected);
550
+ return 1;
551
+ }
552
+ unlink(filename);
553
+
554
+ /* Write expected data to file */
555
+ ret = write(fd, expected, total_len);
556
+ if (ret != total_len) {
557
+ fprintf(stderr, "file write failed: %d\n", ret);
558
+ close(fd);
559
+ free(expected);
560
+ return 1;
561
+ }
562
+
563
+ /* Clear registered buffer before reading into it */
564
+ memset(bd->buf_wr, 0, bd->size);
565
+
566
+ /* Read using READV_FIXED - vecs already point to bd->buf_wr (registered) */
567
+ sqe = io_uring_get_sqe(ring);
568
+ io_uring_prep_readv_fixed(sqe, fd, vecs, nr_vec, 0, 0, buf_idx);
569
+
570
+ ret = io_uring_submit(ring);
571
+ if (ret != 1) {
572
+ fprintf(stderr, "submit failed %i\n", ret);
573
+ close(fd);
574
+ free(expected);
575
+ return 1;
576
+ }
577
+
578
+ ret = io_uring_wait_cqe(ring, &cqe);
579
+ if (ret) {
580
+ fprintf(stderr, "wait_cqe=%d\n", ret);
581
+ close(fd);
582
+ free(expected);
583
+ return 1;
584
+ }
585
+
586
+ ret = cqe->res;
587
+ io_uring_cqe_seen(ring, cqe);
588
+
589
+ close(fd);
590
+
591
+ if (ret != total_len) {
592
+ fprintf(stderr, "readv_fixed: got %d, expected %zu\n", ret, total_len);
593
+ free(expected);
594
+ return 1;
595
+ }
596
+
597
+ /* Verify data across all iovec segments */
598
+ offset = 0;
599
+ for (i = 0; i < nr_vec; i++) {
600
+ if (memcmp(vecs[i].iov_base, expected + offset, vecs[i].iov_len) != 0) {
601
+ fprintf(stderr, "readv_fixed: data mismatch at segment %zu\n", i);
602
+ free(expected);
603
+ return 1;
604
+ }
605
+ offset += vecs[i].iov_len;
606
+ }
607
+
608
+ free(expected);
609
+ return 0;
610
+ }
611
+
612
+ static int test_readv(struct buf_desc *bd)
613
+ {
614
+ void *p = bd->buf_wr;
615
+ int ret;
616
+ struct iovec iov_page = { .iov_base = p, .iov_len = page_sz };
617
+ struct iovec iov_multi[] = {
618
+ { .iov_base = p, .iov_len = page_sz },
619
+ { .iov_base = p + page_sz, .iov_len = page_sz },
620
+ { .iov_base = p + page_sz * 2, .iov_len = page_sz },
621
+ };
622
+ struct iovec iov_unalign = { .iov_base = p + 1, .iov_len = page_sz - 1 };
623
+
624
+ reinit_ring(bd);
625
+
626
+ /* Single page read */
627
+ ret = test_readv_fixed(bd, &iov_page, 1);
628
+ if (ret) {
629
+ fprintf(stderr, "readv_fixed: single page failed\n");
630
+ return ret;
631
+ }
632
+
633
+ /* Multi-segment read */
634
+ reinit_ring(bd);
635
+ ret = test_readv_fixed(bd, iov_multi, 3);
636
+ if (ret) {
637
+ fprintf(stderr, "readv_fixed: multi-segment failed\n");
638
+ return ret;
639
+ }
640
+
641
+ /* Unaligned read */
642
+ reinit_ring(bd);
643
+ ret = test_readv_fixed(bd, &iov_unalign, 1);
644
+ if (ret) {
645
+ fprintf(stderr, "readv_fixed: unaligned failed\n");
646
+ return ret;
647
+ }
648
+
649
+ return 0;
650
+ }
651
+
523
652
  static void test_fail(struct buf_desc *bd)
524
653
  {
525
654
  int ret, cqe_ret;
@@ -576,7 +705,7 @@ static void test_fail(struct buf_desc *bd)
576
705
  int main(int argc, char *argv[])
577
706
  {
578
707
  struct buf_desc bd = {};
579
- int i = 0;
708
+ int ret, i;
580
709
 
581
710
  if (argc > 1)
582
711
  return T_EXIT_SKIP;
@@ -601,6 +730,12 @@ int main(int argc, char *argv[])
601
730
  test_fail(&bd);
602
731
  }
603
732
 
733
+ ret = test_readv(&bd);
734
+ if (ret) {
735
+ fprintf(stderr, "test_readv failed\n");
736
+ return T_EXIT_FAIL;
737
+ }
738
+
604
739
  free(bd.buf_rd);
605
740
  io_uring_queue_exit(&bd.ring);
606
741
  return 0;