polyphony 0.98 → 0.99.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }