polyphony 0.98 → 0.99.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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -1
  3. data/.rubocop.yml +3 -3
  4. data/.yardopts +30 -0
  5. data/CHANGELOG.md +11 -0
  6. data/LICENSE +1 -1
  7. data/README.md +63 -29
  8. data/Rakefile +1 -5
  9. data/TODO.md +0 -4
  10. data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
  11. data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
  12. data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
  13. data/docs/{main-concepts/extending.md → extending.md} +2 -9
  14. data/docs/faq.md +3 -16
  15. data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
  16. data/docs/link_rewriter.rb +16 -0
  17. data/docs/{getting-started/overview.md → overview.md} +1 -30
  18. data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
  19. data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
  20. data/examples/adapters/redis_client.rb +3 -2
  21. data/examples/io/echo_server.rb +1 -1
  22. data/examples/io/echo_server_plain_ruby.rb +26 -0
  23. data/examples/io/https_server_sni_2.rb +14 -8
  24. data/ext/polyphony/backend_io_uring.c +154 -9
  25. data/ext/polyphony/backend_io_uring_context.c +21 -12
  26. data/ext/polyphony/backend_io_uring_context.h +12 -7
  27. data/ext/polyphony/backend_libev.c +1 -1
  28. data/ext/polyphony/extconf.rb +25 -8
  29. data/ext/polyphony/fiber.c +79 -2
  30. data/ext/polyphony/io_extensions.c +53 -0
  31. data/ext/polyphony/libev.h +0 -2
  32. data/ext/polyphony/pipe.c +42 -2
  33. data/ext/polyphony/polyphony.c +345 -31
  34. data/ext/polyphony/polyphony.h +9 -2
  35. data/ext/polyphony/queue.c +181 -0
  36. data/ext/polyphony/ring_buffer.c +0 -1
  37. data/ext/polyphony/runqueue.c +8 -1
  38. data/ext/polyphony/runqueue_ring_buffer.c +13 -0
  39. data/ext/polyphony/runqueue_ring_buffer.h +2 -1
  40. data/ext/polyphony/socket_extensions.c +6 -0
  41. data/ext/polyphony/thread.c +34 -2
  42. data/lib/polyphony/adapters/process.rb +11 -1
  43. data/lib/polyphony/adapters/sequel.rb +1 -1
  44. data/lib/polyphony/core/channel.rb +2 -0
  45. data/lib/polyphony/core/debug.rb +1 -1
  46. data/lib/polyphony/core/global_api.rb +25 -24
  47. data/lib/polyphony/core/resource_pool.rb +7 -6
  48. data/lib/polyphony/core/sync.rb +55 -2
  49. data/lib/polyphony/core/thread_pool.rb +3 -3
  50. data/lib/polyphony/core/timer.rb +8 -8
  51. data/lib/polyphony/extensions/exception.rb +2 -0
  52. data/lib/polyphony/extensions/fiber.rb +15 -13
  53. data/lib/polyphony/extensions/io.rb +161 -16
  54. data/lib/polyphony/extensions/kernel.rb +20 -2
  55. data/lib/polyphony/extensions/openssl.rb +101 -12
  56. data/lib/polyphony/extensions/pipe.rb +103 -7
  57. data/lib/polyphony/extensions/process.rb +13 -1
  58. data/lib/polyphony/extensions/socket.rb +93 -27
  59. data/lib/polyphony/extensions/thread.rb +9 -1
  60. data/lib/polyphony/extensions/timeout.rb +1 -1
  61. data/lib/polyphony/version.rb +2 -1
  62. data/lib/polyphony.rb +27 -7
  63. data/polyphony.gemspec +1 -8
  64. data/test/stress.rb +1 -1
  65. data/test/test_global_api.rb +45 -7
  66. data/test/test_io.rb +6 -7
  67. data/test/test_socket.rb +157 -0
  68. data/test/test_sync.rb +42 -1
  69. data/test/test_timer.rb +5 -5
  70. data/vendor/liburing/.github/workflows/build.yml +7 -16
  71. data/vendor/liburing/.gitignore +5 -0
  72. data/vendor/liburing/CHANGELOG +23 -1
  73. data/vendor/liburing/Makefile +4 -3
  74. data/vendor/liburing/Makefile.common +1 -0
  75. data/vendor/liburing/README +48 -0
  76. data/vendor/liburing/configure +76 -6
  77. data/vendor/liburing/debian/changelog +11 -0
  78. data/vendor/liburing/debian/control +7 -16
  79. data/vendor/liburing/debian/liburing-dev.manpages +3 -6
  80. data/vendor/liburing/debian/liburing2.install +1 -0
  81. data/vendor/liburing/debian/liburing2.symbols +56 -0
  82. data/vendor/liburing/debian/rules +15 -68
  83. data/vendor/liburing/examples/Makefile +4 -0
  84. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  85. data/vendor/liburing/examples/io_uring-udp.c +1 -1
  86. data/vendor/liburing/examples/send-zerocopy.c +315 -56
  87. data/vendor/liburing/examples/ucontext-cp.c +2 -17
  88. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  89. data/vendor/liburing/liburing.pc.in +1 -1
  90. data/vendor/liburing/liburing.spec +1 -1
  91. data/vendor/liburing/make-debs.sh +3 -3
  92. data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
  93. data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
  94. data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
  95. data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
  96. data/vendor/liburing/man/io_uring_check_version.3 +72 -0
  97. data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
  98. data/vendor/liburing/man/io_uring_major_version.3 +1 -0
  99. data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
  100. data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
  101. data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
  102. data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
  103. data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
  104. data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
  105. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
  106. data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
  107. data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
  108. data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
  109. data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
  110. data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
  111. data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
  112. data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
  113. data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
  114. data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
  115. data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
  116. data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
  117. data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
  118. data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
  119. data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
  120. data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
  121. data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
  122. data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
  123. data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
  124. data/vendor/liburing/man/io_uring_register.2 +15 -9
  125. data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
  126. data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
  127. data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
  128. data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
  129. data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
  130. data/vendor/liburing/man/io_uring_register_files.3 +60 -5
  131. data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
  132. data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
  133. data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
  134. data/vendor/liburing/man/io_uring_setup.2 +31 -2
  135. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
  136. data/vendor/liburing/src/Makefile +25 -3
  137. data/vendor/liburing/src/ffi.c +15 -0
  138. data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
  139. data/vendor/liburing/src/include/liburing.h +190 -148
  140. data/vendor/liburing/src/int_flags.h +1 -0
  141. data/vendor/liburing/src/lib.h +5 -16
  142. data/vendor/liburing/src/liburing-ffi.map +172 -0
  143. data/vendor/liburing/src/liburing.map +11 -0
  144. data/vendor/liburing/src/nolibc.c +9 -2
  145. data/vendor/liburing/src/queue.c +2 -2
  146. data/vendor/liburing/src/register.c +66 -96
  147. data/vendor/liburing/src/setup.c +5 -4
  148. data/vendor/liburing/src/version.c +21 -0
  149. data/vendor/liburing/test/232c93d07b74.c +3 -3
  150. data/vendor/liburing/test/35fa71a030ca.c +3 -3
  151. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  152. data/vendor/liburing/test/917257daa0fe.c +1 -1
  153. data/vendor/liburing/test/Makefile +27 -7
  154. data/vendor/liburing/test/a0908ae19763.c +2 -2
  155. data/vendor/liburing/test/a4c0b3decb33.c +2 -2
  156. data/vendor/liburing/test/accept-link.c +4 -4
  157. data/vendor/liburing/test/accept-reuse.c +5 -7
  158. data/vendor/liburing/test/accept.c +34 -31
  159. data/vendor/liburing/test/b19062a56726.c +1 -1
  160. data/vendor/liburing/test/buf-ring.c +58 -4
  161. data/vendor/liburing/test/ce593a6c480a.c +2 -2
  162. data/vendor/liburing/test/close-opath.c +2 -1
  163. data/vendor/liburing/test/connect.c +8 -0
  164. data/vendor/liburing/test/cq-overflow.c +14 -8
  165. data/vendor/liburing/test/d4ae271dfaae.c +1 -1
  166. data/vendor/liburing/test/defer-taskrun.c +64 -9
  167. data/vendor/liburing/test/defer.c +1 -1
  168. data/vendor/liburing/test/double-poll-crash.c +3 -3
  169. data/vendor/liburing/test/eeed8b54e0df.c +8 -3
  170. data/vendor/liburing/test/eploop.c +74 -0
  171. data/vendor/liburing/test/eventfd-ring.c +1 -1
  172. data/vendor/liburing/test/eventfd.c +1 -1
  173. data/vendor/liburing/test/evloop.c +73 -0
  174. data/vendor/liburing/test/exit-no-cleanup.c +1 -1
  175. data/vendor/liburing/test/fadvise.c +1 -1
  176. data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
  177. data/vendor/liburing/test/fd-pass.c +35 -16
  178. data/vendor/liburing/test/file-register.c +61 -0
  179. data/vendor/liburing/test/file-verify.c +2 -2
  180. data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
  181. data/vendor/liburing/test/fixed-link.c +1 -1
  182. data/vendor/liburing/test/fsnotify.c +118 -0
  183. data/vendor/liburing/test/hardlink.c +1 -1
  184. data/vendor/liburing/test/helpers.c +54 -2
  185. data/vendor/liburing/test/helpers.h +4 -0
  186. data/vendor/liburing/test/io-cancel.c +3 -1
  187. data/vendor/liburing/test/io_uring_passthrough.c +39 -8
  188. data/vendor/liburing/test/io_uring_setup.c +3 -80
  189. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  190. data/vendor/liburing/test/iopoll.c +90 -4
  191. data/vendor/liburing/test/lfs-openat-write.c +7 -9
  192. data/vendor/liburing/test/lfs-openat.c +6 -8
  193. data/vendor/liburing/test/link_drain.c +31 -5
  194. data/vendor/liburing/test/madvise.c +1 -1
  195. data/vendor/liburing/test/msg-ring-flags.c +192 -0
  196. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  197. data/vendor/liburing/test/msg-ring.c +173 -13
  198. data/vendor/liburing/test/multicqes_drain.c +22 -19
  199. data/vendor/liburing/test/nvme.h +4 -3
  200. data/vendor/liburing/test/pipe-bug.c +95 -0
  201. data/vendor/liburing/test/poll-link.c +3 -3
  202. data/vendor/liburing/test/poll-many.c +41 -19
  203. data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
  204. data/vendor/liburing/test/poll-race-mshot.c +292 -0
  205. data/vendor/liburing/test/poll-race.c +105 -0
  206. data/vendor/liburing/test/poll.c +244 -26
  207. data/vendor/liburing/test/pollfree.c +5 -5
  208. data/vendor/liburing/test/read-before-exit.c +20 -3
  209. data/vendor/liburing/test/read-write.c +2 -0
  210. data/vendor/liburing/test/recv-multishot.c +96 -3
  211. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  212. data/vendor/liburing/test/rename.c +1 -1
  213. data/vendor/liburing/test/ring-leak.c +0 -1
  214. data/vendor/liburing/test/ring-leak2.c +1 -1
  215. data/vendor/liburing/test/ringbuf-read.c +10 -6
  216. data/vendor/liburing/test/send-zerocopy.c +273 -103
  217. data/vendor/liburing/test/send_recv.c +7 -4
  218. data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
  219. data/vendor/liburing/test/single-issuer.c +7 -9
  220. data/vendor/liburing/test/skip-cqe.c +3 -4
  221. data/vendor/liburing/test/socket.c +0 -1
  222. data/vendor/liburing/test/sq-poll-dup.c +10 -3
  223. data/vendor/liburing/test/sq-poll-kthread.c +1 -1
  224. data/vendor/liburing/test/sq-poll-share.c +3 -2
  225. data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
  226. data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
  227. data/vendor/liburing/test/symlink.c +2 -1
  228. data/vendor/liburing/test/test.h +2 -1
  229. data/vendor/liburing/test/timeout-new.c +11 -7
  230. data/vendor/liburing/test/timeout.c +1 -2
  231. data/vendor/liburing/test/unlink.c +1 -1
  232. data/vendor/liburing/test/version.c +25 -0
  233. data/vendor/liburing/test/wakeup-hang.c +1 -1
  234. data/vendor/liburing/test/xattr.c +8 -4
  235. metadata +57 -44
  236. data/docs/_config.yml +0 -64
  237. data/docs/_includes/head.html +0 -40
  238. data/docs/_includes/title.html +0 -1
  239. data/docs/_sass/custom/custom.scss +0 -10
  240. data/docs/_sass/overrides.scss +0 -0
  241. data/docs/api-reference/exception.md +0 -31
  242. data/docs/api-reference/fiber.md +0 -425
  243. data/docs/api-reference/index.md +0 -9
  244. data/docs/api-reference/io.md +0 -36
  245. data/docs/api-reference/object.md +0 -99
  246. data/docs/api-reference/polyphony-baseexception.md +0 -33
  247. data/docs/api-reference/polyphony-cancel.md +0 -26
  248. data/docs/api-reference/polyphony-moveon.md +0 -24
  249. data/docs/api-reference/polyphony-net.md +0 -20
  250. data/docs/api-reference/polyphony-process.md +0 -28
  251. data/docs/api-reference/polyphony-resourcepool.md +0 -59
  252. data/docs/api-reference/polyphony-restart.md +0 -18
  253. data/docs/api-reference/polyphony-terminate.md +0 -18
  254. data/docs/api-reference/polyphony-threadpool.md +0 -67
  255. data/docs/api-reference/polyphony-throttler.md +0 -77
  256. data/docs/api-reference/polyphony.md +0 -36
  257. data/docs/api-reference/thread.md +0 -88
  258. data/docs/favicon.ico +0 -0
  259. data/docs/getting-started/index.md +0 -10
  260. data/docs/getting-started/installing.md +0 -34
  261. data/vendor/liburing/debian/compat +0 -1
  262. data/vendor/liburing/debian/liburing1-udeb.install +0 -1
  263. data/vendor/liburing/debian/liburing1.install +0 -1
  264. data/vendor/liburing/debian/liburing1.symbols +0 -32
  265. /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
  266. /data/{docs → assets}/polyphony-logo.png +0 -0
  267. /data/{docs/assets/img → assets}/sleeping-fiber.svg +0 -0
@@ -12,7 +12,7 @@
12
12
  #include "liburing.h"
13
13
  #include "helpers.h"
14
14
 
15
- int check_final_cqe(struct io_uring *ring)
15
+ static int check_final_cqe(struct io_uring *ring)
16
16
  {
17
17
  struct io_uring_cqe *cqe;
18
18
  int count = 0;
@@ -137,20 +137,123 @@ static int test(bool defer_taskrun)
137
137
  return ret;
138
138
  }
139
139
 
140
+ static int test_downgrade(bool support_defer)
141
+ {
142
+ struct io_uring_cqe cqes[128];
143
+ struct io_uring_cqe *cqe;
144
+ struct io_uring_sqe *sqe;
145
+ struct io_uring ring;
146
+ int fds[2];
147
+ int ret, i, cqe_count, tmp = 0, more_cqe_count;
148
+
149
+ if (pipe(fds) != 0) {
150
+ perror("pipe");
151
+ return -1;
152
+ }
153
+
154
+ struct io_uring_params params = {
155
+ .flags = IORING_SETUP_CQSIZE,
156
+ .cq_entries = 2
157
+ };
158
+
159
+ ret = io_uring_queue_init_params(2, &ring, &params);
160
+ if (ret) {
161
+ fprintf(stderr, "queue init: %d\n", ret);
162
+ return -1;
163
+ }
164
+
165
+ sqe = io_uring_get_sqe(&ring);
166
+ if (!sqe) {
167
+ fprintf(stderr, "get sqe failed\n");
168
+ return -1;
169
+ }
170
+ io_uring_prep_poll_multishot(sqe, fds[0], POLLIN);
171
+ io_uring_sqe_set_data64(sqe, 1);
172
+ io_uring_submit(&ring);
173
+
174
+ for (i = 0; i < 8; i++) {
175
+ ret = write(fds[1], &tmp, sizeof(tmp));
176
+ if (ret != sizeof(tmp)) {
177
+ perror("write");
178
+ return -1;
179
+ }
180
+ ret = read(fds[0], &tmp, sizeof(tmp));
181
+ if (ret != sizeof(tmp)) {
182
+ perror("read");
183
+ return -1;
184
+ }
185
+ }
186
+
187
+ cqe_count = 0;
188
+ while (!io_uring_peek_cqe(&ring, &cqe)) {
189
+ cqes[cqe_count++] = *cqe;
190
+ io_uring_cqe_seen(&ring, cqe);
191
+ }
192
+
193
+ /* Some kernels might allow overflows to poll,
194
+ * but if they didn't it should stop the MORE flag
195
+ */
196
+ if (cqe_count < 3) {
197
+ fprintf(stderr, "too few cqes: %d\n", cqe_count);
198
+ return -1;
199
+ } else if (cqe_count == 8) {
200
+ more_cqe_count = cqe_count;
201
+ /* downgrade only available since support_defer */
202
+ if (support_defer) {
203
+ fprintf(stderr, "did not downgrade on overflow\n");
204
+ return -1;
205
+ }
206
+ } else {
207
+ more_cqe_count = cqe_count - 1;
208
+ cqe = &cqes[cqe_count - 1];
209
+ if (cqe->flags & IORING_CQE_F_MORE) {
210
+ fprintf(stderr, "incorrect MORE flag %x\n", cqe->flags);
211
+ return -1;
212
+ }
213
+ }
214
+
215
+ for (i = 0; i < more_cqe_count; i++) {
216
+ cqe = &cqes[i];
217
+ if (!(cqe->flags & IORING_CQE_F_MORE)) {
218
+ fprintf(stderr, "missing MORE flag\n");
219
+ return -1;
220
+ }
221
+ if (cqe->res < 0) {
222
+ fprintf(stderr, "bad res: %d\n", cqe->res);
223
+ return -1;
224
+ }
225
+ }
226
+
227
+ close(fds[0]);
228
+ close(fds[1]);
229
+ io_uring_queue_exit(&ring);
230
+ return 0;
231
+ }
232
+
140
233
  int main(int argc, char *argv[])
141
234
  {
142
235
  int ret;
236
+ bool support_defer;
143
237
 
144
238
  if (argc > 1)
145
239
  return T_EXIT_SKIP;
146
240
 
241
+ support_defer = t_probe_defer_taskrun();
242
+ ret = test_downgrade(support_defer);
243
+ if (ret) {
244
+ fprintf(stderr, "%s: test_downgrade(%d) failed\n", argv[0], support_defer);
245
+ return T_EXIT_FAIL;
246
+ }
247
+
147
248
  ret = test(false);
249
+ if (ret == T_EXIT_SKIP)
250
+ return ret;
148
251
  if (ret != T_EXIT_PASS) {
149
252
  fprintf(stderr, "%s: test(false) failed\n", argv[0]);
150
253
  return ret;
151
254
  }
152
255
 
153
- if (t_probe_defer_taskrun()) {
256
+ if (support_defer) {
154
257
  ret = test(true);
155
258
  if (ret != T_EXIT_PASS) {
156
259
  fprintf(stderr, "%s: test(true) failed\n", argv[0]);
@@ -0,0 +1,292 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: check that racing wakeups don't re-issue a poll multishot,
4
+ * this can leak ring provided buffers. also test if ring
5
+ * provided buffers for regular receive can leak if we hit a
6
+ * poll race.
7
+ */
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <unistd.h>
11
+ #include <pthread.h>
12
+ #include <string.h>
13
+ #include <sys/socket.h>
14
+
15
+ #include "liburing.h"
16
+ #include "helpers.h"
17
+
18
+ #define NREQS 64
19
+ #define BUF_SIZE 64
20
+
21
+ static int no_buf_ring;
22
+
23
+ struct data {
24
+ pthread_barrier_t barrier;
25
+ int fd;
26
+ };
27
+
28
+ static void *thread(void *data)
29
+ {
30
+ struct data *d = data;
31
+ char buf[BUF_SIZE];
32
+ int ret, i, fd;
33
+
34
+ memset(buf, 0x5a, BUF_SIZE);
35
+ pthread_barrier_wait(&d->barrier);
36
+ fd = d->fd;
37
+ for (i = 0; i < NREQS; i++) {
38
+ ret = write(fd, buf, sizeof(buf));
39
+ if (ret != BUF_SIZE) {
40
+ if (ret < 0) {
41
+ perror("write");
42
+ printf("bad fd %d\n", fd);
43
+ } else
44
+ fprintf(stderr, "wrote short %d\n", ret);
45
+ }
46
+ }
47
+ return NULL;
48
+ }
49
+
50
+ static int test(struct io_uring *ring, struct data *d)
51
+ {
52
+ struct io_uring_buf_reg reg = { };
53
+ struct io_uring_buf_ring *br;
54
+ struct io_uring_sqe *sqe;
55
+ struct io_uring_cqe *cqe;
56
+ int fd[2], ret, i;
57
+ pthread_t t;
58
+ void *buf, *ptr;
59
+ void *ret2;
60
+
61
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fd) < 0) {
62
+ perror("socketpair");
63
+ return T_EXIT_FAIL;
64
+ }
65
+
66
+ d->fd = fd[1];
67
+
68
+ if (posix_memalign((void **) &buf, 16384, BUF_SIZE * NREQS))
69
+ return T_EXIT_FAIL;
70
+ if (posix_memalign((void **) &br, 16384, sizeof(struct io_uring_buf) * NREQS))
71
+ return T_EXIT_FAIL;
72
+
73
+ io_uring_buf_ring_init(br);
74
+ reg.ring_addr = (unsigned long) br;
75
+ reg.ring_entries = NREQS;
76
+ reg.bgid = 1;
77
+
78
+ ret = io_uring_register_buf_ring(ring, &reg, 0);
79
+ if (ret) {
80
+ if (ret == -EINVAL) {
81
+ no_buf_ring = 1;
82
+ return T_EXIT_SKIP;
83
+ }
84
+ fprintf(stderr, "buf ring reg %d\n", ret);
85
+ return T_EXIT_FAIL;
86
+ }
87
+
88
+ ptr = buf;
89
+ for (i = 0; i < NREQS; i++) {
90
+ io_uring_buf_ring_add(br, ptr, BUF_SIZE, i + 1,
91
+ io_uring_buf_ring_mask(NREQS), i);
92
+ ptr += BUF_SIZE;
93
+ }
94
+ io_uring_buf_ring_advance(br, NREQS);
95
+
96
+ pthread_create(&t, NULL, thread, d);
97
+
98
+ for (i = 0; i < NREQS; i++) {
99
+ sqe = io_uring_get_sqe(ring);
100
+ io_uring_prep_recv(sqe, fd[0], NULL, 0, 0);
101
+ sqe->flags |= IOSQE_BUFFER_SELECT;
102
+ sqe->buf_group = 1;
103
+ }
104
+
105
+ pthread_barrier_wait(&d->barrier);
106
+
107
+ ret = io_uring_submit(ring);
108
+ if (ret != NREQS) {
109
+ fprintf(stderr, "submit %d\n", ret);
110
+ return T_EXIT_FAIL;
111
+ }
112
+
113
+ i = 0;
114
+ do {
115
+ ret = io_uring_wait_cqe(ring, &cqe);
116
+ if (ret) {
117
+ fprintf(stderr, "cqe wait %d\n", ret);
118
+ return T_EXIT_FAIL;
119
+ }
120
+ i++;
121
+ if (cqe->res != BUF_SIZE) {
122
+ fprintf(stderr, "Bad cqe res %d\n", cqe->res);
123
+ break;
124
+ }
125
+ if (cqe->flags & IORING_CQE_F_BUFFER) {
126
+ int bid = cqe->flags >> 16;
127
+
128
+ if (bid > NREQS) {
129
+ fprintf(stderr, "Bad BID %d\n", bid);
130
+ return T_EXIT_FAIL;
131
+ }
132
+ } else {
133
+ fprintf(stderr, "No BID set!\n");
134
+ printf("ret=%d\n", cqe->res);
135
+ return T_EXIT_FAIL;
136
+ }
137
+ io_uring_cqe_seen(ring, cqe);
138
+ if (i > NREQS) {
139
+ fprintf(stderr, "Got too many requests?\n");
140
+ return T_EXIT_FAIL;
141
+ }
142
+ } while (i < NREQS);
143
+
144
+ pthread_join(t, &ret2);
145
+ free(buf);
146
+ free(br);
147
+ close(fd[0]);
148
+ close(fd[1]);
149
+ return T_EXIT_PASS;
150
+ }
151
+
152
+ static int test_mshot(struct io_uring *ring, struct data *d)
153
+ {
154
+ struct io_uring_buf_reg reg = { };
155
+ struct io_uring_buf_ring *br;
156
+ struct io_uring_sqe *sqe;
157
+ struct io_uring_cqe *cqe;
158
+ int fd[2], ret, i;
159
+ pthread_t t;
160
+ void *buf, *ptr;
161
+ void *ret2;
162
+
163
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fd) < 0) {
164
+ perror("socketpair");
165
+ return T_EXIT_FAIL;
166
+ }
167
+
168
+ d->fd = fd[1];
169
+
170
+ if (posix_memalign((void *) &buf, 16384, BUF_SIZE * NREQS))
171
+ return T_EXIT_FAIL;
172
+ if (posix_memalign((void *) &br, 16384, sizeof(struct io_uring_buf) * NREQS))
173
+ return T_EXIT_FAIL;
174
+
175
+ io_uring_buf_ring_init(br);
176
+ reg.ring_addr = (unsigned long) br;
177
+ reg.ring_entries = NREQS;
178
+ reg.bgid = 1;
179
+
180
+ ret = io_uring_register_buf_ring(ring, &reg, 0);
181
+ if (ret) {
182
+ fprintf(stderr, "buf ring reg %d\n", ret);
183
+ return T_EXIT_FAIL;
184
+ }
185
+
186
+ ptr = buf;
187
+ for (i = 0; i < NREQS; i++) {
188
+ io_uring_buf_ring_add(br, ptr, BUF_SIZE, i + 1,
189
+ io_uring_buf_ring_mask(NREQS), i);
190
+ ptr += BUF_SIZE;
191
+ }
192
+ io_uring_buf_ring_advance(br, NREQS);
193
+
194
+ pthread_create(&t, NULL, thread, d);
195
+
196
+ sqe = io_uring_get_sqe(ring);
197
+ io_uring_prep_recv_multishot(sqe, fd[0], NULL, 0, 0);
198
+ sqe->flags |= IOSQE_BUFFER_SELECT;
199
+ sqe->buf_group = 1;
200
+
201
+ pthread_barrier_wait(&d->barrier);
202
+
203
+ ret = io_uring_submit(ring);
204
+ if (ret != 1) {
205
+ fprintf(stderr, "submit %d\n", ret);
206
+ return T_EXIT_FAIL;
207
+ }
208
+
209
+ i = 0;
210
+ do {
211
+ ret = io_uring_wait_cqe(ring, &cqe);
212
+ if (ret) {
213
+ fprintf(stderr, "cqe wait %d\n", ret);
214
+ return T_EXIT_FAIL;
215
+ }
216
+ i++;
217
+ if (!(cqe->flags & IORING_CQE_F_MORE))
218
+ break;
219
+ if (cqe->res != BUF_SIZE) {
220
+ fprintf(stderr, "Bad cqe res %d\n", cqe->res);
221
+ break;
222
+ }
223
+ if (cqe->flags & IORING_CQE_F_BUFFER) {
224
+ int bid = cqe->flags >> 16;
225
+
226
+ if (bid > NREQS) {
227
+ fprintf(stderr, "Bad BID %d\n", bid);
228
+ return T_EXIT_FAIL;
229
+ }
230
+ } else {
231
+ fprintf(stderr, "No BID set!\n");
232
+ printf("ret=%d\n", cqe->res);
233
+ return T_EXIT_FAIL;
234
+ }
235
+ io_uring_cqe_seen(ring, cqe);
236
+ if (i > NREQS) {
237
+ fprintf(stderr, "Got too many requests?\n");
238
+ return T_EXIT_FAIL;
239
+ }
240
+ } while (1);
241
+
242
+ if (i != NREQS + 1) {
243
+ fprintf(stderr, "Only got %d requests\n", i);
244
+ return T_EXIT_FAIL;
245
+ }
246
+
247
+ pthread_join(t, &ret2);
248
+ free(buf);
249
+ free(br);
250
+ close(fd[0]);
251
+ close(fd[1]);
252
+ return T_EXIT_PASS;
253
+ }
254
+
255
+ int main(int argc, char *argv[])
256
+ {
257
+ struct io_uring ring;
258
+ struct data d;
259
+ int i, ret;
260
+
261
+ if (argc > 1)
262
+ return T_EXIT_SKIP;
263
+
264
+ pthread_barrier_init(&d.barrier, NULL, 2);
265
+
266
+ for (i = 0; i < 1000; i++) {
267
+ io_uring_queue_init(NREQS, &ring, 0);
268
+ ret = test(&ring, &d);
269
+ if (ret != T_EXIT_PASS) {
270
+ if (no_buf_ring)
271
+ break;
272
+ fprintf(stderr, "Test failed loop %d\n", i);
273
+ return T_EXIT_FAIL;
274
+ }
275
+ io_uring_queue_exit(&ring);
276
+ }
277
+
278
+ if (no_buf_ring)
279
+ return T_EXIT_SKIP;
280
+
281
+ for (i = 0; i < 1000; i++) {
282
+ io_uring_queue_init(NREQS, &ring, 0);
283
+ ret = test_mshot(&ring, &d);
284
+ if (ret != T_EXIT_PASS) {
285
+ fprintf(stderr, "Test mshot failed loop %d\n", i);
286
+ return T_EXIT_FAIL;
287
+ }
288
+ io_uring_queue_exit(&ring);
289
+ }
290
+
291
+ return T_EXIT_PASS;
292
+ }
@@ -0,0 +1,105 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: check that multiple receives on the same socket don't get
4
+ * stalled if multiple wakers race with the socket readiness.
5
+ */
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <unistd.h>
9
+ #include <pthread.h>
10
+ #include <sys/socket.h>
11
+
12
+ #include "liburing.h"
13
+ #include "helpers.h"
14
+
15
+ #define NREQS 64
16
+
17
+ struct data {
18
+ pthread_barrier_t barrier;
19
+ int fd;
20
+ };
21
+
22
+ static void *thread(void *data)
23
+ {
24
+ struct data *d = data;
25
+ char buf[64];
26
+ int ret, i;
27
+
28
+ pthread_barrier_wait(&d->barrier);
29
+ for (i = 0; i < NREQS; i++) {
30
+ ret = write(d->fd, buf, sizeof(buf));
31
+ if (ret != 64)
32
+ fprintf(stderr, "wrote short %d\n", ret);
33
+ }
34
+ return NULL;
35
+ }
36
+
37
+ static int test(struct io_uring *ring, struct data *d)
38
+ {
39
+ struct io_uring_sqe *sqe;
40
+ struct io_uring_cqe *cqe;
41
+ int fd[2], ret, i;
42
+ char buf[64];
43
+ pthread_t t;
44
+ void *ret2;
45
+
46
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fd) < 0) {
47
+ perror("socketpair");
48
+ return T_EXIT_FAIL;
49
+ }
50
+
51
+ d->fd = fd[1];
52
+
53
+ pthread_create(&t, NULL, thread, d);
54
+
55
+ for (i = 0; i < NREQS; i++) {
56
+ sqe = io_uring_get_sqe(ring);
57
+ io_uring_prep_recv(sqe, fd[0], buf, sizeof(buf), 0);
58
+ }
59
+
60
+ pthread_barrier_wait(&d->barrier);
61
+
62
+ ret = io_uring_submit(ring);
63
+ if (ret != NREQS) {
64
+ fprintf(stderr, "submit %d\n", ret);
65
+ return T_EXIT_FAIL;
66
+ }
67
+
68
+ for (i = 0; i < NREQS; i++) {
69
+ ret = io_uring_wait_cqe(ring, &cqe);
70
+ if (ret) {
71
+ fprintf(stderr, "cqe wait %d\n", ret);
72
+ return T_EXIT_FAIL;
73
+ }
74
+ io_uring_cqe_seen(ring, cqe);
75
+ }
76
+
77
+ close(fd[0]);
78
+ close(fd[1]);
79
+ pthread_join(t, &ret2);
80
+ return T_EXIT_PASS;
81
+ }
82
+
83
+ int main(int argc, char *argv[])
84
+ {
85
+ struct io_uring ring;
86
+ struct data d;
87
+ int i, ret;
88
+
89
+ if (argc > 1)
90
+ return T_EXIT_SKIP;
91
+
92
+ pthread_barrier_init(&d.barrier, NULL, 2);
93
+
94
+ io_uring_queue_init(NREQS, &ring, 0);
95
+
96
+ for (i = 0; i < 1000; i++) {
97
+ ret = test(&ring, &d);
98
+ if (ret != T_EXIT_PASS) {
99
+ fprintf(stderr, "Test failed\n");
100
+ return T_EXIT_FAIL;
101
+ }
102
+ }
103
+
104
+ return T_EXIT_PASS;
105
+ }