polyphony 0.93 → 0.95

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 (312) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -2
  3. data/.gitignore +3 -3
  4. data/CHANGELOG.md +14 -0
  5. data/docs/api-reference/fiber.md +2 -2
  6. data/docs/api-reference/object.md +3 -3
  7. data/docs/main-concepts/exception-handling.md +2 -2
  8. data/examples/pipes/echo_server.rb +1 -1
  9. data/examples/pipes/http_server.rb +33 -0
  10. data/ext/polyphony/backend_common.c +53 -8
  11. data/ext/polyphony/backend_common.h +21 -13
  12. data/ext/polyphony/backend_io_uring.c +85 -147
  13. data/ext/polyphony/backend_libev.c +58 -89
  14. data/ext/polyphony/event.c +1 -1
  15. data/ext/polyphony/extconf.rb +7 -5
  16. data/ext/polyphony/fiber.c +5 -13
  17. data/ext/polyphony/io_extensions.c +68 -68
  18. data/ext/polyphony/pipe.c +1 -1
  19. data/ext/polyphony/polyphony.c +23 -23
  20. data/ext/polyphony/polyphony.h +0 -9
  21. data/ext/polyphony/polyphony_ext.c +1 -1
  22. data/ext/polyphony/queue.c +1 -1
  23. data/ext/polyphony/ring_buffer.c +1 -0
  24. data/ext/polyphony/socket_extensions.c +1 -1
  25. data/ext/polyphony/thread.c +1 -1
  26. data/lib/polyphony/extensions/enumerator.rb +16 -0
  27. data/lib/polyphony/extensions/socket.rb +2 -0
  28. data/lib/polyphony/extensions.rb +1 -0
  29. data/lib/polyphony/version.rb +1 -1
  30. data/polyphony.gemspec +2 -2
  31. data/test/test_backend.rb +5 -1
  32. data/test/test_enumerator.rb +46 -0
  33. data/test/test_global_api.rb +1 -1
  34. data/test/test_io.rb +241 -216
  35. data/test/test_socket.rb +1 -1
  36. data/test/test_thread_pool.rb +3 -3
  37. data/vendor/liburing/.github/workflows/build.yml +51 -5
  38. data/vendor/liburing/.github/workflows/shellcheck.yml +1 -1
  39. data/vendor/liburing/.gitignore +6 -123
  40. data/vendor/liburing/CHANGELOG +35 -0
  41. data/vendor/liburing/CITATION.cff +11 -0
  42. data/vendor/liburing/LICENSE +16 -3
  43. data/vendor/liburing/Makefile +3 -1
  44. data/vendor/liburing/Makefile.common +1 -0
  45. data/vendor/liburing/README +14 -2
  46. data/vendor/liburing/SECURITY.md +6 -0
  47. data/vendor/liburing/configure +16 -15
  48. data/vendor/liburing/examples/Makefile +4 -1
  49. data/vendor/liburing/examples/io_uring-udp.c +395 -0
  50. data/vendor/liburing/examples/poll-bench.c +101 -0
  51. data/vendor/liburing/examples/send-zerocopy.c +339 -0
  52. data/vendor/liburing/liburing.spec +1 -1
  53. data/vendor/liburing/man/io_uring.7 +38 -11
  54. data/vendor/liburing/man/io_uring_buf_ring_add.3 +53 -0
  55. data/vendor/liburing/man/io_uring_buf_ring_advance.3 +31 -0
  56. data/vendor/liburing/man/io_uring_buf_ring_cq_advance.3 +41 -0
  57. data/vendor/liburing/man/io_uring_buf_ring_init.3 +30 -0
  58. data/vendor/liburing/man/io_uring_buf_ring_mask.3 +27 -0
  59. data/vendor/liburing/man/io_uring_cq_advance.3 +29 -15
  60. data/vendor/liburing/man/io_uring_cq_has_overflow.3 +25 -0
  61. data/vendor/liburing/man/io_uring_cq_ready.3 +9 -8
  62. data/vendor/liburing/man/io_uring_cqe_get_data.3 +32 -13
  63. data/vendor/liburing/man/io_uring_cqe_get_data64.3 +1 -0
  64. data/vendor/liburing/man/io_uring_cqe_seen.3 +22 -12
  65. data/vendor/liburing/man/io_uring_enter.2 +249 -32
  66. data/vendor/liburing/man/io_uring_enter2.2 +1 -0
  67. data/vendor/liburing/man/io_uring_free_probe.3 +11 -8
  68. data/vendor/liburing/man/io_uring_get_events.3 +33 -0
  69. data/vendor/liburing/man/io_uring_get_probe.3 +9 -8
  70. data/vendor/liburing/man/io_uring_get_sqe.3 +29 -10
  71. data/vendor/liburing/man/io_uring_opcode_supported.3 +11 -10
  72. data/vendor/liburing/man/io_uring_peek_cqe.3 +38 -0
  73. data/vendor/liburing/man/io_uring_prep_accept.3 +197 -0
  74. data/vendor/liburing/man/io_uring_prep_accept_direct.3 +1 -0
  75. data/vendor/liburing/man/io_uring_prep_cancel.3 +118 -0
  76. data/vendor/liburing/man/io_uring_prep_cancel64.3 +1 -0
  77. data/vendor/liburing/man/io_uring_prep_close.3 +59 -0
  78. data/vendor/liburing/man/io_uring_prep_close_direct.3 +1 -0
  79. data/vendor/liburing/man/io_uring_prep_connect.3 +66 -0
  80. data/vendor/liburing/man/io_uring_prep_fadvise.3 +59 -0
  81. data/vendor/liburing/man/io_uring_prep_fallocate.3 +59 -0
  82. data/vendor/liburing/man/io_uring_prep_files_update.3 +92 -0
  83. data/vendor/liburing/man/io_uring_prep_fsync.3 +70 -0
  84. data/vendor/liburing/man/io_uring_prep_link.3 +1 -0
  85. data/vendor/liburing/man/io_uring_prep_linkat.3 +91 -0
  86. data/vendor/liburing/man/io_uring_prep_madvise.3 +56 -0
  87. data/vendor/liburing/man/io_uring_prep_mkdir.3 +1 -0
  88. data/vendor/liburing/man/io_uring_prep_mkdirat.3 +83 -0
  89. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +39 -25
  90. data/vendor/liburing/man/io_uring_prep_multishot_accept.3 +1 -0
  91. data/vendor/liburing/man/io_uring_prep_multishot_accept_direct.3 +1 -0
  92. data/vendor/liburing/man/io_uring_prep_nop.3 +28 -0
  93. data/vendor/liburing/man/io_uring_prep_openat.3 +117 -0
  94. data/vendor/liburing/man/io_uring_prep_openat2.3 +117 -0
  95. data/vendor/liburing/man/io_uring_prep_openat2_direct.3 +1 -0
  96. data/vendor/liburing/man/io_uring_prep_openat_direct.3 +1 -0
  97. data/vendor/liburing/man/io_uring_prep_poll_add.3 +72 -0
  98. data/vendor/liburing/man/io_uring_prep_poll_multishot.3 +1 -0
  99. data/vendor/liburing/man/io_uring_prep_poll_remove.3 +55 -0
  100. data/vendor/liburing/man/io_uring_prep_poll_update.3 +89 -0
  101. data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +131 -0
  102. data/vendor/liburing/man/io_uring_prep_read.3 +33 -14
  103. data/vendor/liburing/man/io_uring_prep_read_fixed.3 +39 -21
  104. data/vendor/liburing/man/io_uring_prep_readv.3 +49 -15
  105. data/vendor/liburing/man/io_uring_prep_readv2.3 +49 -17
  106. data/vendor/liburing/man/io_uring_prep_recv.3 +105 -0
  107. data/vendor/liburing/man/io_uring_prep_recv_multishot.3 +1 -0
  108. data/vendor/liburing/man/io_uring_prep_recvmsg.3 +124 -0
  109. data/vendor/liburing/man/io_uring_prep_recvmsg_multishot.3 +1 -0
  110. data/vendor/liburing/man/io_uring_prep_remove_buffers.3 +52 -0
  111. data/vendor/liburing/man/io_uring_prep_rename.3 +1 -0
  112. data/vendor/liburing/man/io_uring_prep_renameat.3 +96 -0
  113. data/vendor/liburing/man/io_uring_prep_send.3 +57 -0
  114. data/vendor/liburing/man/io_uring_prep_send_zc.3 +64 -0
  115. data/vendor/liburing/man/io_uring_prep_sendmsg.3 +69 -0
  116. data/vendor/liburing/man/io_uring_prep_shutdown.3 +53 -0
  117. data/vendor/liburing/man/io_uring_prep_socket.3 +118 -0
  118. data/vendor/liburing/man/io_uring_prep_socket_direct.3 +1 -0
  119. data/vendor/liburing/man/io_uring_prep_socket_direct_alloc.3 +1 -0
  120. data/vendor/liburing/man/io_uring_prep_splice.3 +80 -0
  121. data/vendor/liburing/man/io_uring_prep_statx.3 +74 -0
  122. data/vendor/liburing/man/io_uring_prep_symlink.3 +1 -0
  123. data/vendor/liburing/man/io_uring_prep_symlinkat.3 +85 -0
  124. data/vendor/liburing/man/io_uring_prep_sync_file_range.3 +59 -0
  125. data/vendor/liburing/man/io_uring_prep_tee.3 +74 -0
  126. data/vendor/liburing/man/io_uring_prep_timeout.3 +95 -0
  127. data/vendor/liburing/man/io_uring_prep_timeout_remove.3 +1 -0
  128. data/vendor/liburing/man/io_uring_prep_timeout_update.3 +98 -0
  129. data/vendor/liburing/man/io_uring_prep_unlink.3 +1 -0
  130. data/vendor/liburing/man/io_uring_prep_unlinkat.3 +82 -0
  131. data/vendor/liburing/man/io_uring_prep_write.3 +32 -15
  132. data/vendor/liburing/man/io_uring_prep_write_fixed.3 +39 -21
  133. data/vendor/liburing/man/io_uring_prep_writev.3 +50 -16
  134. data/vendor/liburing/man/io_uring_prep_writev2.3 +50 -17
  135. data/vendor/liburing/man/io_uring_queue_exit.3 +3 -4
  136. data/vendor/liburing/man/io_uring_queue_init.3 +58 -13
  137. data/vendor/liburing/man/io_uring_queue_init_params.3 +1 -0
  138. data/vendor/liburing/man/io_uring_recvmsg_cmsg_firsthdr.3 +1 -0
  139. data/vendor/liburing/man/io_uring_recvmsg_cmsg_nexthdr.3 +1 -0
  140. data/vendor/liburing/man/io_uring_recvmsg_name.3 +1 -0
  141. data/vendor/liburing/man/io_uring_recvmsg_out.3 +78 -0
  142. data/vendor/liburing/man/io_uring_recvmsg_payload.3 +1 -0
  143. data/vendor/liburing/man/io_uring_recvmsg_payload_length.3 +1 -0
  144. data/vendor/liburing/man/io_uring_recvmsg_validate.3 +1 -0
  145. data/vendor/liburing/man/io_uring_register.2 +153 -13
  146. data/vendor/liburing/man/io_uring_register_buf_ring.3 +140 -0
  147. data/vendor/liburing/man/io_uring_register_buffers.3 +32 -12
  148. data/vendor/liburing/man/io_uring_register_eventfd.3 +51 -0
  149. data/vendor/liburing/man/io_uring_register_eventfd_async.3 +1 -0
  150. data/vendor/liburing/man/io_uring_register_file_alloc_range.3 +52 -0
  151. data/vendor/liburing/man/io_uring_register_files.3 +33 -11
  152. data/vendor/liburing/man/io_uring_register_files_sparse.3 +1 -0
  153. data/vendor/liburing/man/io_uring_register_iowq_aff.3 +61 -0
  154. data/vendor/liburing/man/io_uring_register_iowq_max_workers.3 +71 -0
  155. data/vendor/liburing/man/io_uring_register_ring_fd.3 +49 -0
  156. data/vendor/liburing/man/io_uring_register_sync_cancel.3 +71 -0
  157. data/vendor/liburing/man/io_uring_setup.2 +119 -13
  158. data/vendor/liburing/man/io_uring_sq_ready.3 +14 -8
  159. data/vendor/liburing/man/io_uring_sq_space_left.3 +9 -9
  160. data/vendor/liburing/man/io_uring_sqe_set_data.3 +29 -11
  161. data/vendor/liburing/man/io_uring_sqe_set_data64.3 +1 -0
  162. data/vendor/liburing/man/io_uring_sqe_set_flags.3 +38 -11
  163. data/vendor/liburing/man/io_uring_sqring_wait.3 +13 -9
  164. data/vendor/liburing/man/io_uring_submit.3 +29 -12
  165. data/vendor/liburing/man/io_uring_submit_and_get_events.3 +31 -0
  166. data/vendor/liburing/man/io_uring_submit_and_wait.3 +16 -12
  167. data/vendor/liburing/man/io_uring_submit_and_wait_timeout.3 +30 -23
  168. data/vendor/liburing/man/io_uring_unregister_buf_ring.3 +30 -0
  169. data/vendor/liburing/man/io_uring_unregister_buffers.3 +11 -10
  170. data/vendor/liburing/man/io_uring_unregister_eventfd.3 +1 -0
  171. data/vendor/liburing/man/io_uring_unregister_files.3 +11 -10
  172. data/vendor/liburing/man/io_uring_unregister_iowq_aff.3 +1 -0
  173. data/vendor/liburing/man/io_uring_unregister_ring_fd.3 +32 -0
  174. data/vendor/liburing/man/io_uring_wait_cqe.3 +19 -12
  175. data/vendor/liburing/man/io_uring_wait_cqe_nr.3 +21 -14
  176. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +27 -13
  177. data/vendor/liburing/man/io_uring_wait_cqes.3 +24 -14
  178. data/vendor/liburing/src/Makefile +8 -7
  179. data/vendor/liburing/src/arch/aarch64/lib.h +48 -0
  180. data/vendor/liburing/src/arch/aarch64/syscall.h +0 -4
  181. data/vendor/liburing/src/arch/generic/lib.h +0 -4
  182. data/vendor/liburing/src/arch/generic/syscall.h +29 -16
  183. data/vendor/liburing/src/arch/syscall-defs.h +41 -14
  184. data/vendor/liburing/src/arch/x86/lib.h +0 -21
  185. data/vendor/liburing/src/arch/x86/syscall.h +146 -10
  186. data/vendor/liburing/src/include/liburing/io_uring.h +245 -5
  187. data/vendor/liburing/src/include/liburing.h +468 -35
  188. data/vendor/liburing/src/int_flags.h +1 -0
  189. data/vendor/liburing/src/lib.h +20 -16
  190. data/vendor/liburing/src/liburing.map +16 -0
  191. data/vendor/liburing/src/nolibc.c +1 -1
  192. data/vendor/liburing/src/queue.c +87 -55
  193. data/vendor/liburing/src/register.c +129 -53
  194. data/vendor/liburing/src/setup.c +65 -28
  195. data/vendor/liburing/src/syscall.c +14 -32
  196. data/vendor/liburing/src/syscall.h +12 -64
  197. data/vendor/liburing/test/{232c93d07b74-test.c → 232c93d07b74.c} +8 -9
  198. data/vendor/liburing/test/{35fa71a030ca-test.c → 35fa71a030ca.c} +4 -4
  199. data/vendor/liburing/test/{500f9fbadef8-test.c → 500f9fbadef8.c} +7 -7
  200. data/vendor/liburing/test/{7ad0e4b2f83c-test.c → 7ad0e4b2f83c.c} +8 -7
  201. data/vendor/liburing/test/{8a9973408177-test.c → 8a9973408177.c} +4 -3
  202. data/vendor/liburing/test/{917257daa0fe-test.c → 917257daa0fe.c} +3 -2
  203. data/vendor/liburing/test/Makefile +60 -62
  204. data/vendor/liburing/test/{a0908ae19763-test.c → a0908ae19763.c} +3 -2
  205. data/vendor/liburing/test/{a4c0b3decb33-test.c → a4c0b3decb33.c} +3 -2
  206. data/vendor/liburing/test/accept-link.c +5 -4
  207. data/vendor/liburing/test/accept-reuse.c +17 -16
  208. data/vendor/liburing/test/accept-test.c +14 -10
  209. data/vendor/liburing/test/accept.c +529 -107
  210. data/vendor/liburing/test/across-fork.c +7 -6
  211. data/vendor/liburing/test/{b19062a56726-test.c → b19062a56726.c} +3 -2
  212. data/vendor/liburing/test/{b5837bd5311d-test.c → b5837bd5311d.c} +10 -9
  213. data/vendor/liburing/test/buf-ring.c +420 -0
  214. data/vendor/liburing/test/{ce593a6c480a-test.c → ce593a6c480a.c} +15 -12
  215. data/vendor/liburing/test/connect.c +8 -7
  216. data/vendor/liburing/test/cq-full.c +5 -4
  217. data/vendor/liburing/test/cq-overflow.c +242 -12
  218. data/vendor/liburing/test/cq-peek-batch.c +5 -4
  219. data/vendor/liburing/test/cq-ready.c +5 -4
  220. data/vendor/liburing/test/cq-size.c +5 -4
  221. data/vendor/liburing/test/{d4ae271dfaae-test.c → d4ae271dfaae.c} +2 -2
  222. data/vendor/liburing/test/{d77a67ed5f27-test.c → d77a67ed5f27.c} +6 -6
  223. data/vendor/liburing/test/defer-taskrun.c +336 -0
  224. data/vendor/liburing/test/defer.c +26 -14
  225. data/vendor/liburing/test/double-poll-crash.c +15 -5
  226. data/vendor/liburing/test/drop-submit.c +5 -3
  227. data/vendor/liburing/test/{eeed8b54e0df-test.c → eeed8b54e0df.c} +7 -6
  228. data/vendor/liburing/test/empty-eownerdead.c +4 -4
  229. data/vendor/liburing/test/eventfd-disable.c +48 -20
  230. data/vendor/liburing/test/eventfd-reg.c +10 -9
  231. data/vendor/liburing/test/eventfd-ring.c +13 -12
  232. data/vendor/liburing/test/eventfd.c +13 -12
  233. data/vendor/liburing/test/exit-no-cleanup.c +1 -1
  234. data/vendor/liburing/test/fadvise.c +3 -3
  235. data/vendor/liburing/test/fallocate.c +16 -9
  236. data/vendor/liburing/test/{fc2a85cb02ef-test.c → fc2a85cb02ef.c} +4 -3
  237. data/vendor/liburing/test/fd-pass.c +187 -0
  238. data/vendor/liburing/test/file-register.c +302 -36
  239. data/vendor/liburing/test/file-update.c +62 -4
  240. data/vendor/liburing/test/file-verify.c +6 -2
  241. data/vendor/liburing/test/files-exit-hang-poll.c +11 -25
  242. data/vendor/liburing/test/files-exit-hang-timeout.c +13 -10
  243. data/vendor/liburing/test/fixed-buf-iter.c +115 -0
  244. data/vendor/liburing/test/fixed-link.c +10 -10
  245. data/vendor/liburing/test/fixed-reuse.c +160 -0
  246. data/vendor/liburing/test/fpos.c +6 -3
  247. data/vendor/liburing/test/fsync.c +3 -3
  248. data/vendor/liburing/test/hardlink.c +10 -6
  249. data/vendor/liburing/test/helpers.c +137 -4
  250. data/vendor/liburing/test/helpers.h +27 -0
  251. data/vendor/liburing/test/io-cancel.c +16 -11
  252. data/vendor/liburing/test/io_uring_enter.c +46 -81
  253. data/vendor/liburing/test/io_uring_passthrough.c +451 -0
  254. data/vendor/liburing/test/io_uring_register.c +59 -229
  255. data/vendor/liburing/test/io_uring_setup.c +24 -29
  256. data/vendor/liburing/test/iopoll-leak.c +85 -0
  257. data/vendor/liburing/test/iopoll.c +16 -9
  258. data/vendor/liburing/test/lfs-openat-write.c +3 -1
  259. data/vendor/liburing/test/link-timeout.c +4 -3
  260. data/vendor/liburing/test/link.c +8 -7
  261. data/vendor/liburing/test/madvise.c +2 -2
  262. data/vendor/liburing/test/mkdir.c +9 -5
  263. data/vendor/liburing/test/msg-ring.c +46 -20
  264. data/vendor/liburing/test/multicqes_drain.c +51 -12
  265. data/vendor/liburing/test/nolibc.c +60 -0
  266. data/vendor/liburing/test/nop.c +78 -16
  267. data/vendor/liburing/test/nvme.h +168 -0
  268. data/vendor/liburing/test/open-direct-link.c +188 -0
  269. data/vendor/liburing/test/open-direct-pick.c +180 -0
  270. data/vendor/liburing/test/openat2.c +3 -3
  271. data/vendor/liburing/test/poll-cancel-all.c +472 -0
  272. data/vendor/liburing/test/poll-link.c +9 -18
  273. data/vendor/liburing/test/poll-mshot-overflow.c +162 -0
  274. data/vendor/liburing/test/poll-mshot-update.c +83 -33
  275. data/vendor/liburing/test/pollfree.c +2 -2
  276. data/vendor/liburing/test/read-before-exit.c +112 -0
  277. data/vendor/liburing/test/read-write.c +83 -1
  278. data/vendor/liburing/test/recv-msgall-stream.c +398 -0
  279. data/vendor/liburing/test/recv-msgall.c +265 -0
  280. data/vendor/liburing/test/recv-multishot.c +505 -0
  281. data/vendor/liburing/test/rename.c +2 -5
  282. data/vendor/liburing/test/ring-leak.c +97 -0
  283. data/vendor/liburing/test/ringbuf-read.c +200 -0
  284. data/vendor/liburing/test/rsrc_tags.c +25 -13
  285. data/vendor/liburing/test/runtests-quiet.sh +11 -0
  286. data/vendor/liburing/test/runtests.sh +18 -20
  287. data/vendor/liburing/test/rw_merge_test.c +3 -2
  288. data/vendor/liburing/test/send-zerocopy.c +684 -0
  289. data/vendor/liburing/test/send_recv.c +49 -2
  290. data/vendor/liburing/test/send_recvmsg.c +165 -55
  291. data/vendor/liburing/test/shutdown.c +3 -4
  292. data/vendor/liburing/test/sigfd-deadlock.c +22 -8
  293. data/vendor/liburing/test/single-issuer.c +171 -0
  294. data/vendor/liburing/test/socket-rw-eagain.c +2 -12
  295. data/vendor/liburing/test/socket-rw-offset.c +2 -11
  296. data/vendor/liburing/test/socket-rw.c +2 -11
  297. data/vendor/liburing/test/socket.c +409 -0
  298. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  299. data/vendor/liburing/test/sq-poll-share.c +1 -1
  300. data/vendor/liburing/test/statx.c +2 -2
  301. data/vendor/liburing/test/submit-and-wait.c +108 -0
  302. data/vendor/liburing/test/submit-link-fail.c +5 -3
  303. data/vendor/liburing/test/submit-reuse.c +0 -2
  304. data/vendor/liburing/test/sync-cancel.c +235 -0
  305. data/vendor/liburing/test/test.h +35 -0
  306. data/vendor/liburing/test/timeout-overflow.c +11 -11
  307. data/vendor/liburing/test/timeout.c +7 -7
  308. data/vendor/liburing/test/tty-write-dpoll.c +60 -0
  309. data/vendor/liburing/test/unlink.c +1 -1
  310. data/vendor/liburing/test/xattr.c +425 -0
  311. metadata +148 -26
  312. data/Gemfile.lock +0 -82
@@ -11,6 +11,7 @@
11
11
  #include <fcntl.h>
12
12
 
13
13
  #include "liburing.h"
14
+ #include "helpers.h"
14
15
 
15
16
  static int queue_n_nops(struct io_uring *ring, int n)
16
17
  {
@@ -49,13 +50,13 @@ int main(int argc, char *argv[])
49
50
  int i, ret;
50
51
 
51
52
  if (argc > 1)
52
- return 0;
53
+ return T_EXIT_SKIP;
53
54
 
54
55
  memset(&p, 0, sizeof(p));
55
56
  ret = io_uring_queue_init_params(4, &ring, &p);
56
57
  if (ret) {
57
58
  printf("ring setup failed\n");
58
- return 1;
59
+ return T_EXIT_FAIL;
59
60
 
60
61
  }
61
62
 
@@ -89,8 +90,8 @@ int main(int argc, char *argv[])
89
90
  }
90
91
 
91
92
  io_uring_queue_exit(&ring);
92
- return 0;
93
+ return T_EXIT_PASS;
93
94
  err:
94
95
  io_uring_queue_exit(&ring);
95
- return 1;
96
+ return T_EXIT_FAIL;
96
97
  }
@@ -9,6 +9,7 @@
9
9
  #include <stdlib.h>
10
10
  #include <string.h>
11
11
  #include <fcntl.h>
12
+ #include <assert.h>
12
13
 
13
14
  #include "helpers.h"
14
15
  #include "liburing.h"
@@ -21,6 +22,32 @@ static struct iovec *vecs;
21
22
 
22
23
  #define ENTRIES 8
23
24
 
25
+ /*
26
+ * io_uring has rare cases where CQEs are lost.
27
+ * This happens when there is no space in the CQ ring, and also there is no
28
+ * GFP_ATOMIC memory available. In reality this probably means that the process
29
+ * is about to be killed as many other things might start failing, but we still
30
+ * want to test that liburing and the kernel deal with this properly. The fault
31
+ * injection framework allows us to test this scenario. Unfortunately this
32
+ * requires some system wide changes and so we do not enable this by default.
33
+ * The tests in this file should work in both cases (where overflows are queued
34
+ * and where they are dropped) on recent kernels.
35
+ *
36
+ * In order to test dropped CQEs you should enable fault injection in the kernel
37
+ * config:
38
+ *
39
+ * CONFIG_FAULT_INJECTION=y
40
+ * CONFIG_FAILSLAB=y
41
+ * CONFIG_FAULT_INJECTION_DEBUG_FS=y
42
+ *
43
+ * and then run the test as follows:
44
+ * echo Y > /sys/kernel/debug/failslab/task-filter
45
+ * echo 100 > /sys/kernel/debug/failslab/probability
46
+ * echo 0 > /sys/kernel/debug/failslab/verbose
47
+ * echo 100000 > /sys/kernel/debug/failslab/times
48
+ * bash -c "echo 1 > /proc/self/make-it-fail && exec ./cq-overflow.t"
49
+ */
50
+
24
51
  static int test_io(const char *file, unsigned long usecs, unsigned *drops, int fault)
25
52
  {
26
53
  struct io_uring_sqe *sqe;
@@ -29,18 +56,20 @@ static int test_io(const char *file, unsigned long usecs, unsigned *drops, int f
29
56
  unsigned reaped, total;
30
57
  struct io_uring ring;
31
58
  int nodrop, i, fd, ret;
59
+ bool cqe_dropped = false;
32
60
 
33
61
  fd = open(file, O_RDONLY | O_DIRECT);
34
62
  if (fd < 0) {
35
63
  perror("file open");
36
- goto err;
64
+ return 1;
37
65
  }
38
66
 
39
67
  memset(&p, 0, sizeof(p));
40
68
  ret = io_uring_queue_init_params(ENTRIES, &ring, &p);
41
69
  if (ret) {
70
+ close(fd);
42
71
  fprintf(stderr, "ring create failed: %d\n", ret);
43
- goto err;
72
+ return 1;
44
73
  }
45
74
  nodrop = 0;
46
75
  if (p.features & IORING_FEAT_NODROP)
@@ -103,8 +132,8 @@ static int test_io(const char *file, unsigned long usecs, unsigned *drops, int f
103
132
  reap_it:
104
133
  reaped = 0;
105
134
  do {
106
- if (nodrop) {
107
- /* nodrop should never lose events */
135
+ if (nodrop && !cqe_dropped) {
136
+ /* nodrop should never lose events unless cqe_dropped */
108
137
  if (reaped == total)
109
138
  break;
110
139
  } else {
@@ -112,7 +141,10 @@ reap_it:
112
141
  break;
113
142
  }
114
143
  ret = io_uring_wait_cqe(&ring, &cqe);
115
- if (ret) {
144
+ if (nodrop && ret == -EBADR) {
145
+ cqe_dropped = true;
146
+ continue;
147
+ } else if (ret) {
116
148
  fprintf(stderr, "wait_cqe=%d\n", ret);
117
149
  goto err;
118
150
  }
@@ -132,7 +164,7 @@ reap_it:
132
164
  goto err;
133
165
  }
134
166
 
135
- if (!nodrop) {
167
+ if (!nodrop || cqe_dropped) {
136
168
  *drops = *ring.cq.koverflow;
137
169
  } else if (*ring.cq.koverflow) {
138
170
  fprintf(stderr, "Found %u overflows\n", *ring.cq.koverflow);
@@ -153,18 +185,29 @@ static int reap_events(struct io_uring *ring, unsigned nr_events, int do_wait)
153
185
  {
154
186
  struct io_uring_cqe *cqe;
155
187
  int i, ret = 0, seq = 0;
188
+ unsigned int start_overflow = *ring->cq.koverflow;
189
+ bool dropped = false;
156
190
 
157
191
  for (i = 0; i < nr_events; i++) {
158
192
  if (do_wait)
159
193
  ret = io_uring_wait_cqe(ring, &cqe);
160
194
  else
161
195
  ret = io_uring_peek_cqe(ring, &cqe);
162
- if (ret) {
196
+ if (do_wait && ret == -EBADR) {
197
+ unsigned int this_drop = *ring->cq.koverflow -
198
+ start_overflow;
199
+
200
+ dropped = true;
201
+ start_overflow = *ring->cq.koverflow;
202
+ assert(this_drop > 0);
203
+ i += (this_drop - 1);
204
+ continue;
205
+ } else if (ret) {
163
206
  if (ret != -EAGAIN)
164
207
  fprintf(stderr, "cqe peek failed: %d\n", ret);
165
208
  break;
166
209
  }
167
- if (cqe->user_data != seq) {
210
+ if (!dropped && cqe->user_data != seq) {
168
211
  fprintf(stderr, "cqe sequence out-of-order\n");
169
212
  fprintf(stderr, "got %d, wanted %d\n", (int) cqe->user_data,
170
213
  seq);
@@ -241,19 +284,206 @@ err:
241
284
  return 1;
242
285
  }
243
286
 
287
+
288
+ static void submit_one_nop(struct io_uring *ring, int ud)
289
+ {
290
+ struct io_uring_sqe *sqe;
291
+ int ret;
292
+
293
+ sqe = io_uring_get_sqe(ring);
294
+ assert(sqe);
295
+ io_uring_prep_nop(sqe);
296
+ sqe->user_data = ud;
297
+ ret = io_uring_submit(ring);
298
+ assert(ret == 1);
299
+ }
300
+
301
+ /*
302
+ * Create an overflow condition and ensure that SQEs are still processed
303
+ */
304
+ static int test_overflow_handling(bool batch, int cqe_multiple, bool poll,
305
+ bool defer)
306
+ {
307
+ struct io_uring ring;
308
+ struct io_uring_params p;
309
+ int ret, i, j, ud, cqe_count;
310
+ unsigned int count;
311
+ int const N = 8;
312
+ int const LOOPS = 128;
313
+ int const QUEUE_LENGTH = 1024;
314
+ int completions[N];
315
+ int queue[QUEUE_LENGTH];
316
+ int queued = 0;
317
+ int outstanding = 0;
318
+ bool cqe_dropped = false;
319
+
320
+ memset(&completions, 0, sizeof(int) * N);
321
+ memset(&p, 0, sizeof(p));
322
+ p.cq_entries = 2 * cqe_multiple;
323
+ p.flags |= IORING_SETUP_CQSIZE;
324
+
325
+ if (poll)
326
+ p.flags |= IORING_SETUP_IOPOLL;
327
+
328
+ if (defer)
329
+ p.flags |= IORING_SETUP_SINGLE_ISSUER |
330
+ IORING_SETUP_DEFER_TASKRUN;
331
+
332
+ ret = io_uring_queue_init_params(2, &ring, &p);
333
+ if (ret) {
334
+ fprintf(stderr, "io_uring_queue_init failed %d\n", ret);
335
+ return 1;
336
+ }
337
+
338
+ assert(p.cq_entries < N);
339
+ /* submit N SQEs, some should overflow */
340
+ for (i = 0; i < N; i++) {
341
+ submit_one_nop(&ring, i);
342
+ outstanding++;
343
+ }
344
+
345
+ for (i = 0; i < LOOPS; i++) {
346
+ struct io_uring_cqe *cqes[N];
347
+
348
+ if (io_uring_cq_has_overflow(&ring)) {
349
+ /*
350
+ * Flush any overflowed CQEs and process those. Actively
351
+ * flush these to make sure CQEs arrive in vague order
352
+ * of being sent.
353
+ */
354
+ ret = io_uring_get_events(&ring);
355
+ if (ret != 0) {
356
+ fprintf(stderr,
357
+ "io_uring_get_events returned %d\n",
358
+ ret);
359
+ goto err;
360
+ }
361
+ } else if (!cqe_dropped) {
362
+ for (j = 0; j < queued; j++) {
363
+ submit_one_nop(&ring, queue[j]);
364
+ outstanding++;
365
+ }
366
+ queued = 0;
367
+ }
368
+
369
+ /* We have lost some random cqes, stop if no remaining. */
370
+ if (cqe_dropped && outstanding == *ring.cq.koverflow)
371
+ break;
372
+
373
+ ret = io_uring_wait_cqe(&ring, &cqes[0]);
374
+ if (ret == -EBADR) {
375
+ cqe_dropped = true;
376
+ fprintf(stderr, "CQE dropped\n");
377
+ continue;
378
+ } else if (ret != 0) {
379
+ fprintf(stderr, "io_uring_wait_cqes failed %d\n", ret);
380
+ goto err;
381
+ }
382
+ cqe_count = 1;
383
+ if (batch) {
384
+ ret = io_uring_peek_batch_cqe(&ring, &cqes[0], 2);
385
+ if (ret < 0) {
386
+ fprintf(stderr,
387
+ "io_uring_peek_batch_cqe failed %d\n",
388
+ ret);
389
+ goto err;
390
+ }
391
+ cqe_count = ret;
392
+ }
393
+ for (j = 0; j < cqe_count; j++) {
394
+ assert(cqes[j]->user_data < N);
395
+ ud = cqes[j]->user_data;
396
+ completions[ud]++;
397
+ assert(queued < QUEUE_LENGTH);
398
+ queue[queued++] = (int)ud;
399
+ }
400
+ io_uring_cq_advance(&ring, cqe_count);
401
+ outstanding -= cqe_count;
402
+ }
403
+
404
+ /* See if there were any drops by flushing the CQ ring *and* overflow */
405
+ do {
406
+ struct io_uring_cqe *cqe;
407
+
408
+ ret = io_uring_get_events(&ring);
409
+ if (ret < 0) {
410
+ if (ret == -EBADR) {
411
+ fprintf(stderr, "CQE dropped\n");
412
+ cqe_dropped = true;
413
+ break;
414
+ }
415
+ goto err;
416
+ }
417
+ if (outstanding && !io_uring_cq_ready(&ring))
418
+ ret = io_uring_wait_cqe_timeout(&ring, &cqe, NULL);
419
+
420
+ if (ret && ret != -ETIME) {
421
+ if (ret == -EBADR) {
422
+ fprintf(stderr, "CQE dropped\n");
423
+ cqe_dropped = true;
424
+ break;
425
+ }
426
+ fprintf(stderr, "wait_cqe_timeout = %d\n", ret);
427
+ goto err;
428
+ }
429
+ count = io_uring_cq_ready(&ring);
430
+ io_uring_cq_advance(&ring, count);
431
+ outstanding -= count;
432
+ } while (count);
433
+
434
+ io_uring_queue_exit(&ring);
435
+
436
+ /* Make sure that completions come back in the same order they were
437
+ * sent. If they come back unfairly then this will concentrate on a
438
+ * couple of indices.
439
+ */
440
+ for (i = 1; !cqe_dropped && i < N; i++) {
441
+ if (abs(completions[i] - completions[i - 1]) > 1) {
442
+ fprintf(stderr, "bad completion size %d %d\n",
443
+ completions[i], completions[i - 1]);
444
+ goto err;
445
+ }
446
+ }
447
+ return 0;
448
+ err:
449
+ io_uring_queue_exit(&ring);
450
+ return 1;
451
+ }
452
+
244
453
  int main(int argc, char *argv[])
245
454
  {
246
455
  const char *fname = ".cq-overflow";
247
456
  unsigned iters, drops;
248
457
  unsigned long usecs;
249
458
  int ret;
459
+ int i;
460
+ bool can_defer;
250
461
 
251
462
  if (argc > 1)
252
- return 0;
463
+ return T_EXIT_SKIP;
464
+
465
+ can_defer = t_probe_defer_taskrun();
466
+ for (i = 0; i < 16; i++) {
467
+ bool batch = i & 1;
468
+ int mult = (i & 2) ? 1 : 2;
469
+ bool poll = i & 4;
470
+ bool defer = i & 8;
471
+
472
+ if (defer && !can_defer)
473
+ continue;
474
+
475
+ ret = test_overflow_handling(batch, mult, poll, defer);
476
+ if (ret) {
477
+ fprintf(stderr, "test_overflow_handling("
478
+ "batch=%d, mult=%d, poll=%d, defer=%d) failed\n",
479
+ batch, mult, poll, defer);
480
+ goto err;
481
+ }
482
+ }
253
483
 
254
484
  ret = test_overflow();
255
485
  if (ret) {
256
- printf("test_overflow failed\n");
486
+ fprintf(stderr, "test_overflow failed\n");
257
487
  return ret;
258
488
  }
259
489
 
@@ -287,8 +517,8 @@ int main(int argc, char *argv[])
287
517
  }
288
518
 
289
519
  unlink(fname);
290
- return 0;
520
+ return T_EXIT_PASS;
291
521
  err:
292
522
  unlink(fname);
293
- return 1;
523
+ return T_EXIT_FAIL;
294
524
  }
@@ -11,6 +11,7 @@
11
11
  #include <fcntl.h>
12
12
 
13
13
  #include "liburing.h"
14
+ #include "helpers.h"
14
15
 
15
16
  static int queue_n_nops(struct io_uring *ring, int n, int offset)
16
17
  {
@@ -58,12 +59,12 @@ int main(int argc, char *argv[])
58
59
  unsigned got;
59
60
 
60
61
  if (argc > 1)
61
- return 0;
62
+ return T_EXIT_SKIP;
62
63
 
63
64
  ret = io_uring_queue_init(4, &ring, 0);
64
65
  if (ret) {
65
66
  printf("ring setup failed\n");
66
- return 1;
67
+ return T_EXIT_FAIL;
67
68
 
68
69
  }
69
70
 
@@ -95,8 +96,8 @@ int main(int argc, char *argv[])
95
96
 
96
97
  io_uring_cq_advance(&ring, 8);
97
98
  io_uring_queue_exit(&ring);
98
- return 0;
99
+ return T_EXIT_PASS;
99
100
  err:
100
101
  io_uring_queue_exit(&ring);
101
- return 1;
102
+ return T_EXIT_FAIL;
102
103
  }
@@ -11,6 +11,7 @@
11
11
  #include <fcntl.h>
12
12
 
13
13
  #include "liburing.h"
14
+ #include "helpers.h"
14
15
 
15
16
  static int queue_n_nops(struct io_uring *ring, int n)
16
17
  {
@@ -56,12 +57,12 @@ int main(int argc, char *argv[])
56
57
  unsigned ready;
57
58
 
58
59
  if (argc > 1)
59
- return 0;
60
+ return T_EXIT_SKIP;
60
61
 
61
62
  ret = io_uring_queue_init(4, &ring, 0);
62
63
  if (ret) {
63
64
  printf("ring setup failed\n");
64
- return 1;
65
+ return T_EXIT_FAIL;
65
66
 
66
67
  }
67
68
 
@@ -87,8 +88,8 @@ int main(int argc, char *argv[])
87
88
  CHECK_READY(&ring, 0);
88
89
 
89
90
  io_uring_queue_exit(&ring);
90
- return 0;
91
+ return T_EXIT_PASS;
91
92
  err:
92
93
  io_uring_queue_exit(&ring);
93
- return 1;
94
+ return T_EXIT_FAIL;
94
95
  }
@@ -10,6 +10,7 @@
10
10
  #include <fcntl.h>
11
11
 
12
12
  #include "liburing.h"
13
+ #include "helpers.h"
13
14
 
14
15
  int main(int argc, char *argv[])
15
16
  {
@@ -18,7 +19,7 @@ int main(int argc, char *argv[])
18
19
  int ret;
19
20
 
20
21
  if (argc > 1)
21
- return 0;
22
+ return T_EXIT_SKIP;
22
23
 
23
24
  memset(&p, 0, sizeof(p));
24
25
  p.flags = IORING_SETUP_CQSIZE;
@@ -31,7 +32,7 @@ int main(int argc, char *argv[])
31
32
  goto done;
32
33
  }
33
34
  printf("ring setup failed\n");
34
- return 1;
35
+ return T_EXIT_FAIL;
35
36
  }
36
37
 
37
38
  if (p.cq_entries < 64) {
@@ -58,7 +59,7 @@ int main(int argc, char *argv[])
58
59
  }
59
60
 
60
61
  done:
61
- return 0;
62
+ return T_EXIT_PASS;
62
63
  err:
63
- return 1;
64
+ return T_EXIT_FAIL;
64
65
  }
@@ -31,9 +31,9 @@ int main(int argc, char *argv[])
31
31
  p.flags = IORING_SETUP_SQPOLL;
32
32
  ret = t_create_ring_params(4, &ring, &p);
33
33
  if (ret == T_SETUP_SKIP)
34
- return 0;
34
+ return T_EXIT_SKIP;
35
35
  else if (ret < 0)
36
- return 1;
36
+ return T_EXIT_FAIL;
37
37
 
38
38
  if (argc > 1) {
39
39
  fname = argv[1];
@@ -22,7 +22,7 @@ int main(int argc, char *argv[])
22
22
  int ret, data;
23
23
 
24
24
  if (argc > 1)
25
- return 0;
25
+ return T_EXIT_SKIP;
26
26
 
27
27
  signal(SIGALRM, sig_alrm);
28
28
 
@@ -31,9 +31,9 @@ int main(int argc, char *argv[])
31
31
  p.flags = IORING_SETUP_SQPOLL;
32
32
  ret = t_create_ring_params(4, &ring, &p);
33
33
  if (ret == T_SETUP_SKIP)
34
- return 0;
34
+ return T_EXIT_SKIP;
35
35
  else if (ret < 0)
36
- return 1;
36
+ return T_EXIT_FAIL;
37
37
 
38
38
  /* make sure sq thread is sleeping at this point */
39
39
  usleep(150000);
@@ -42,7 +42,7 @@ int main(int argc, char *argv[])
42
42
  sqe = io_uring_get_sqe(&ring);
43
43
  if (!sqe) {
44
44
  fprintf(stderr, "sqe get failed\n");
45
- return 1;
45
+ return T_EXIT_FAIL;
46
46
  }
47
47
 
48
48
  io_uring_prep_nop(sqe);
@@ -58,8 +58,8 @@ int main(int argc, char *argv[])
58
58
  data = (unsigned long) io_uring_cqe_get_data(cqe);
59
59
  if (data != 42) {
60
60
  fprintf(stderr, "invalid data: %d\n", data);
61
- return 1;
61
+ return T_EXIT_FAIL;
62
62
  }
63
63
 
64
- return 0;
64
+ return T_EXIT_PASS;
65
65
  }