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
@@ -11,16 +11,27 @@
11
11
  #include <signal.h>
12
12
  #include <poll.h>
13
13
  #include <sys/wait.h>
14
+ #include <assert.h>
14
15
 
16
+ #include "helpers.h"
15
17
  #include "liburing.h"
16
18
 
17
- static void sig_alrm(int sig)
19
+ static void do_setsockopt(int fd, int level, int optname, int val)
18
20
  {
19
- fprintf(stderr, "Timed out!\n");
20
- exit(1);
21
+ if (setsockopt(fd, level, optname, &val, sizeof(val)))
22
+ t_error(1, errno, "setsockopt %d.%d: %d", level, optname, val);
21
23
  }
22
24
 
23
- int main(int argc, char *argv[])
25
+ static bool check_cq_empty(struct io_uring *ring)
26
+ {
27
+ struct io_uring_cqe *cqe = NULL;
28
+ int ret;
29
+
30
+ ret = io_uring_peek_cqe(ring, &cqe); /* nothing should be there */
31
+ return ret == -EAGAIN;
32
+ }
33
+
34
+ static int test_basic(void)
24
35
  {
25
36
  struct io_uring_cqe *cqe;
26
37
  struct io_uring_sqe *sqe;
@@ -29,34 +40,22 @@ int main(int argc, char *argv[])
29
40
  pid_t p;
30
41
  int ret;
31
42
 
32
- if (argc > 1)
33
- return 0;
34
-
35
43
  if (pipe(pipe1) != 0) {
36
44
  perror("pipe");
37
45
  return 1;
38
46
  }
39
47
 
40
48
  p = fork();
41
- switch (p) {
42
- case -1:
49
+ if (p == -1) {
43
50
  perror("fork");
44
51
  exit(2);
45
- case 0: {
46
- struct sigaction act;
47
-
52
+ } else if (p == 0) {
48
53
  ret = io_uring_queue_init(1, &ring, 0);
49
54
  if (ret) {
50
55
  fprintf(stderr, "child: ring setup failed: %d\n", ret);
51
56
  return 1;
52
57
  }
53
58
 
54
- memset(&act, 0, sizeof(act));
55
- act.sa_handler = sig_alrm;
56
- act.sa_flags = SA_RESTART;
57
- sigaction(SIGALRM, &act, NULL);
58
- alarm(1);
59
-
60
59
  sqe = io_uring_get_sqe(&ring);
61
60
  if (!sqe) {
62
61
  fprintf(stderr, "get sqe failed\n");
@@ -92,18 +91,237 @@ int main(int argc, char *argv[])
92
91
  (long) cqe->res);
93
92
  return 1;
94
93
  }
94
+
95
+ io_uring_queue_exit(&ring);
95
96
  exit(0);
96
- }
97
- default:
98
- do {
99
- errno = 0;
100
- ret = write(pipe1[1], "foo", 3);
101
- } while (ret == -1 && errno == EINTR);
97
+ }
98
+
99
+ do {
100
+ errno = 0;
101
+ ret = write(pipe1[1], "foo", 3);
102
+ } while (ret == -1 && errno == EINTR);
103
+
104
+ if (ret != 3) {
105
+ fprintf(stderr, "parent: bad write return %d\n", ret);
106
+ return 1;
107
+ }
108
+ close(pipe1[0]);
109
+ close(pipe1[1]);
110
+ return 0;
111
+ }
112
+
113
+ static int test_missing_events(void)
114
+ {
115
+ struct io_uring_cqe *cqe;
116
+ struct io_uring_sqe *sqe;
117
+ struct io_uring ring;
118
+ int i, ret, sp[2];
119
+ char buf[2] = {};
120
+ int res_mask = 0;
121
+
122
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER |
123
+ IORING_SETUP_DEFER_TASKRUN);
124
+ if (ret) {
125
+ fprintf(stderr, "ring setup failed: %d\n", ret);
126
+ return 1;
127
+ }
102
128
 
103
- if (ret != 3) {
104
- fprintf(stderr, "parent: bad write return %d\n", ret);
129
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) {
130
+ perror("Failed to create Unix-domain socket pair\n");
131
+ return 1;
132
+ }
133
+ do_setsockopt(sp[0], SOL_SOCKET, SO_SNDBUF, 1);
134
+ ret = send(sp[0], buf, sizeof(buf), 0);
135
+ if (ret != sizeof(buf)) {
136
+ perror("send failed\n");
137
+ return 1;
138
+ }
139
+
140
+ sqe = io_uring_get_sqe(&ring);
141
+ io_uring_prep_poll_multishot(sqe, sp[0], POLLIN|POLLOUT);
142
+ ret = io_uring_submit(&ring);
143
+ if (ret != 1) {
144
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
145
+ return 1;
146
+ }
147
+
148
+ /* trigger EPOLLIN */
149
+ ret = send(sp[1], buf, sizeof(buf), 0);
150
+ if (ret != sizeof(buf)) {
151
+ fprintf(stderr, "send sp[1] failed %i %i\n", ret, errno);
152
+ return 1;
153
+ }
154
+
155
+ /* trigger EPOLLOUT */
156
+ ret = recv(sp[1], buf, sizeof(buf), 0);
157
+ if (ret != sizeof(buf)) {
158
+ perror("recv failed\n");
159
+ return 1;
160
+ }
161
+
162
+ for (i = 0; ; i++) {
163
+ if (i == 0)
164
+ ret = io_uring_wait_cqe(&ring, &cqe);
165
+ else
166
+ ret = io_uring_peek_cqe(&ring, &cqe);
167
+
168
+ if (i != 0 && ret == -EAGAIN) {
169
+ break;
170
+ }
171
+ if (ret) {
172
+ fprintf(stderr, "wait completion %d, %i\n", ret, i);
105
173
  return 1;
106
174
  }
175
+ res_mask |= cqe->res;
176
+ io_uring_cqe_seen(&ring, cqe);
177
+ }
178
+
179
+ if ((res_mask & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
180
+ fprintf(stderr, "missing poll events %i\n", res_mask);
181
+ return 1;
182
+ }
183
+ io_uring_queue_exit(&ring);
184
+ close(sp[0]);
185
+ close(sp[1]);
186
+ return 0;
187
+ }
188
+
189
+ #define NR_SQES 2048
190
+
191
+ static int test_self_poll(void)
192
+ {
193
+ struct io_uring_cqe *cqe;
194
+ struct io_uring_sqe *sqe;
195
+ struct io_uring ring;
196
+ int ret, i, j;
197
+
198
+ ret = io_uring_queue_init(NR_SQES, &ring, 0);
199
+ if (ret) {
200
+ fprintf(stderr, "ring setup failed: %d\n", ret);
201
+ return T_EXIT_FAIL;
202
+ }
203
+
204
+ for (j = 0; j < 32; j++) {
205
+ for (i = 0; i < NR_SQES; i++) {
206
+ sqe = io_uring_get_sqe(&ring);
207
+ io_uring_prep_poll_add(sqe, ring.ring_fd, POLLIN);
208
+ }
209
+
210
+ ret = io_uring_submit(&ring);
211
+ assert(ret == NR_SQES);
212
+ }
213
+
214
+ sqe = io_uring_get_sqe(&ring);
215
+ io_uring_prep_nop(sqe);
216
+ ret = io_uring_submit(&ring);
217
+ assert(ret == 1);
218
+
219
+ ret = io_uring_wait_cqe(&ring, &cqe);
220
+ io_uring_cqe_seen(&ring, cqe);
221
+
222
+ io_uring_queue_exit(&ring);
223
+ return T_EXIT_PASS;
224
+ }
225
+
226
+ static int test_disabled_ring_lazy_polling(int early_poll)
227
+ {
228
+ struct io_uring_cqe *cqe;
229
+ struct io_uring_sqe *sqe;
230
+ struct io_uring ring, ring2;
231
+ unsigned head;
232
+ int ret, i = 0;
233
+
234
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER |
235
+ IORING_SETUP_DEFER_TASKRUN |
236
+ IORING_SETUP_R_DISABLED);
237
+ if (ret) {
238
+ fprintf(stderr, "ring setup failed: %d\n", ret);
239
+ return 1;
240
+ }
241
+ ret = io_uring_queue_init(8, &ring2, 0);
242
+ if (ret) {
243
+ fprintf(stderr, "ring2 setup failed: %d\n", ret);
244
+ return 1;
245
+ }
246
+
247
+ if (early_poll) {
248
+ /* start polling disabled DEFER_TASKRUN ring */
249
+ sqe = io_uring_get_sqe(&ring2);
250
+ io_uring_prep_poll_add(sqe, ring.ring_fd, POLLIN);
251
+ ret = io_uring_submit(&ring2);
252
+ assert(ret == 1);
253
+ assert(check_cq_empty(&ring2));
254
+ }
255
+
256
+ /* enable rings, which should also activate pollwq */
257
+ ret = io_uring_enable_rings(&ring);
258
+ assert(ret >= 0);
259
+
260
+ if (!early_poll) {
261
+ /* start polling enabled DEFER_TASKRUN ring */
262
+ sqe = io_uring_get_sqe(&ring2);
263
+ io_uring_prep_poll_add(sqe, ring.ring_fd, POLLIN);
264
+ ret = io_uring_submit(&ring2);
265
+ assert(ret == 1);
266
+ assert(check_cq_empty(&ring2));
267
+ }
268
+
269
+ sqe = io_uring_get_sqe(&ring);
270
+ io_uring_prep_nop(sqe);
271
+ ret = io_uring_submit(&ring);
272
+ assert(ret == 1);
273
+
274
+ io_uring_for_each_cqe(&ring2, head, cqe) {
275
+ i++;
276
+ }
277
+ if (i != 1) {
278
+ fprintf(stderr, "fail, polling stuck\n");
279
+ return 1;
280
+ }
281
+ io_uring_queue_exit(&ring);
282
+ io_uring_queue_exit(&ring2);
283
+ return 0;
284
+ }
285
+
286
+ int main(int argc, char *argv[])
287
+ {
288
+ int ret;
289
+
290
+ if (argc > 1)
107
291
  return 0;
292
+
293
+ ret = test_basic();
294
+ if (ret) {
295
+ fprintf(stderr, "test_basic() failed %i\n", ret);
296
+ return T_EXIT_FAIL;
108
297
  }
298
+
299
+
300
+ if (t_probe_defer_taskrun()) {
301
+ ret = test_missing_events();
302
+ if (ret) {
303
+ fprintf(stderr, "test_missing_events() failed %i\n", ret);
304
+ return T_EXIT_FAIL;
305
+ }
306
+
307
+ ret = test_disabled_ring_lazy_polling(false);
308
+ if (ret) {
309
+ fprintf(stderr, "test_disabled_ring_lazy_polling(false) failed %i\n", ret);
310
+ return T_EXIT_FAIL;
311
+ }
312
+
313
+ ret = test_disabled_ring_lazy_polling(true);
314
+ if (ret) {
315
+ fprintf(stderr, "test_disabled_ring_lazy_polling(true) failed %i\n", ret);
316
+ return T_EXIT_FAIL;
317
+ }
318
+ }
319
+
320
+ ret = test_self_poll();
321
+ if (ret) {
322
+ fprintf(stderr, "test_self_poll failed\n");
323
+ return T_EXIT_FAIL;
324
+ }
325
+
326
+ return 0;
109
327
  }
@@ -252,7 +252,7 @@ static void kill_and_wait(int pid, int* status)
252
252
  }
253
253
  }
254
254
 
255
- static void setup_test()
255
+ static void setup_test(void)
256
256
  {
257
257
  prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
258
258
  setpgrp();
@@ -342,7 +342,7 @@ static void loop(void)
342
342
  #define __NR_io_uring_enter 426
343
343
  #endif
344
344
 
345
- uint64_t r[4] = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0};
345
+ static uint64_t r[4] = {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x0};
346
346
 
347
347
  void execute_call(int call)
348
348
  {
@@ -403,13 +403,13 @@ int main(int argc, char *argv[])
403
403
  if (argc > 1)
404
404
  return 0;
405
405
 
406
- ret = mmap((void *)0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
406
+ ret = mmap((void *)0x1ffff000ul, 0x1000ul, 0ul, MAP_ANON|MAP_PRIVATE, -1, 0ul);
407
407
  if (ret == MAP_FAILED)
408
408
  return 0;
409
- ret = mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul);
409
+ ret = mmap((void *)0x20000000ul, 0x1000000ul, 7ul, MAP_ANON|MAP_PRIVATE, -1, 0ul);
410
410
  if (ret == MAP_FAILED)
411
411
  return 0;
412
- ret = mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
412
+ ret = mmap((void *)0x21000000ul, 0x1000ul, 0ul, MAP_ANON|MAP_PRIVATE, -1, 0ul);
413
413
  if (ret == MAP_FAILED)
414
414
  return 0;
415
415
  loop();
@@ -14,6 +14,8 @@
14
14
  #include "liburing.h"
15
15
  #include "helpers.h"
16
16
 
17
+ static int no_iopoll;
18
+
17
19
  struct data {
18
20
  struct io_uring *ring;
19
21
  int timer_fd1;
@@ -22,7 +24,7 @@ struct data {
22
24
  uint64_t buf2;
23
25
  };
24
26
 
25
- void *submit(void *data)
27
+ static void *submit(void *data)
26
28
  {
27
29
  struct io_uring_sqe *sqe;
28
30
  struct data *d = data;
@@ -35,8 +37,21 @@ void *submit(void *data)
35
37
  io_uring_prep_read(sqe, d->timer_fd2, &d->buf2, sizeof(d->buf2), 0);
36
38
 
37
39
  ret = io_uring_submit(d->ring);
38
- if (ret != 2)
40
+ if (ret != 2) {
41
+ struct io_uring_cqe *cqe;
42
+
43
+ /*
44
+ * Kernels without submit-all-on-error behavior will
45
+ * fail submitting all, check if that's the case and
46
+ * don't error
47
+ */
48
+ ret = io_uring_peek_cqe(d->ring, &cqe);
49
+ if (!ret && cqe->res == -EOPNOTSUPP) {
50
+ no_iopoll = 1;
51
+ return NULL;
52
+ }
39
53
  return (void *) (uintptr_t) 1;
54
+ }
40
55
 
41
56
  /* Exit suddenly. */
42
57
  return NULL;
@@ -95,9 +110,11 @@ int main(int argc, char *argv[])
95
110
  for (i = 0; i < 1000; i++) {
96
111
  ret = test(IORING_SETUP_IOPOLL);
97
112
  if (ret) {
98
- fprintf(stderr, "Test IOPOLL failed\n");
113
+ fprintf(stderr, "Test IOPOLL failed loop %d\n", ret);
99
114
  return ret;
100
115
  }
116
+ if (no_iopoll)
117
+ break;
101
118
  }
102
119
 
103
120
  for (i = 0; i < 100; i++) {
@@ -76,6 +76,8 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
76
76
 
77
77
  fd = open(file, open_flags);
78
78
  if (fd < 0) {
79
+ if (errno == EINVAL)
80
+ return 0;
79
81
  perror("file open");
80
82
  goto err;
81
83
  }
@@ -9,6 +9,7 @@
9
9
  #include <sys/types.h>
10
10
  #include <sys/socket.h>
11
11
  #include <pthread.h>
12
+ #include <assert.h>
12
13
 
13
14
  #include "liburing.h"
14
15
  #include "helpers.h"
@@ -264,11 +265,19 @@ static int test(struct args *args)
264
265
 
265
266
  bool const is_last = i == recv_cqes - 1;
266
267
 
268
+ /*
269
+ * Older kernels could terminate multishot early due to overflow,
270
+ * but later ones will not. So discriminate based on the MORE flag.
271
+ */
272
+ bool const early_last = args->early_error == ERROR_EARLY_OVERFLOW &&
273
+ !args->wait_each &&
274
+ i == N_CQE_OVERFLOW &&
275
+ !(cqe->flags & IORING_CQE_F_MORE);
276
+
267
277
  bool const should_be_last =
268
278
  (cqe->res <= 0) ||
269
279
  (args->stream && is_last) ||
270
- (args->early_error == ERROR_EARLY_OVERFLOW &&
271
- !args->wait_each && i == N_CQE_OVERFLOW);
280
+ early_last;
272
281
  int *this_recv;
273
282
  int orig_payload_size = cqe->res;
274
283
 
@@ -328,7 +337,7 @@ static int test(struct args *args)
328
337
  case ERROR_EARLY_LAST:
329
338
  fprintf(stderr, "bad error_early\n");
330
339
  goto cleanup;
331
- };
340
+ }
332
341
 
333
342
  if (cqe->res <= 0 && cqe->flags & IORING_CQE_F_BUFFER) {
334
343
  fprintf(stderr, "final BUFFER flag set\n");
@@ -461,6 +470,84 @@ cleanup:
461
470
  return ret;
462
471
  }
463
472
 
473
+ static int test_enobuf(void)
474
+ {
475
+ struct io_uring ring;
476
+ struct io_uring_sqe *sqe;
477
+ struct io_uring_cqe *cqes[16];
478
+ char buffs[256];
479
+ int ret, i, fds[2];
480
+
481
+ if (t_create_ring(8, &ring, 0) != T_SETUP_OK) {
482
+ fprintf(stderr, "ring create\n");
483
+ return -1;
484
+ }
485
+
486
+ ret = t_create_socket_pair(fds, false);
487
+ if (ret) {
488
+ fprintf(stderr, "t_create_socket_pair\n");
489
+ return ret;
490
+ }
491
+
492
+ sqe = io_uring_get_sqe(&ring);
493
+ assert(sqe);
494
+ /* deliberately only 2 provided buffers */
495
+ io_uring_prep_provide_buffers(sqe, &buffs[0], 1, 2, 0, 0);
496
+ io_uring_sqe_set_data64(sqe, 0);
497
+
498
+ sqe = io_uring_get_sqe(&ring);
499
+ assert(sqe);
500
+ io_uring_prep_recv_multishot(sqe, fds[0], NULL, 0, 0);
501
+ io_uring_sqe_set_data64(sqe, 1);
502
+ sqe->buf_group = 0;
503
+ sqe->flags |= IOSQE_BUFFER_SELECT;
504
+
505
+ ret = io_uring_submit(&ring);
506
+ if (ret != 2) {
507
+ fprintf(stderr, "bad submit %d\n", ret);
508
+ return -1;
509
+ }
510
+ for (i = 0; i < 3; i++) {
511
+ do {
512
+ ret = write(fds[1], "?", 1);
513
+ } while (ret == -1 && errno == EINTR);
514
+ }
515
+
516
+ ret = io_uring_wait_cqes(&ring, &cqes[0], 4, NULL, NULL);
517
+ if (ret) {
518
+ fprintf(stderr, "wait cqes\n");
519
+ return ret;
520
+ }
521
+
522
+ ret = io_uring_peek_batch_cqe(&ring, &cqes[0], 4);
523
+ if (ret != 4) {
524
+ fprintf(stderr, "peek batch cqes\n");
525
+ return -1;
526
+ }
527
+
528
+ /* provide buffers */
529
+ assert(cqes[0]->user_data == 0);
530
+ assert(cqes[0]->res == 0);
531
+
532
+ /* valid recv */
533
+ assert(cqes[1]->user_data == 1);
534
+ assert(cqes[2]->user_data == 1);
535
+ assert(cqes[1]->res == 1);
536
+ assert(cqes[2]->res == 1);
537
+ assert(cqes[1]->flags & (IORING_CQE_F_BUFFER | IORING_CQE_F_MORE));
538
+ assert(cqes[2]->flags & (IORING_CQE_F_BUFFER | IORING_CQE_F_MORE));
539
+
540
+ /* missing buffer */
541
+ assert(cqes[3]->user_data == 1);
542
+ assert(cqes[3]->res == -ENOBUFS);
543
+ assert(!(cqes[3]->flags & (IORING_CQE_F_BUFFER | IORING_CQE_F_MORE)));
544
+
545
+ close(fds[0]);
546
+ close(fds[1]);
547
+ io_uring_queue_exit(&ring);
548
+ return 0;
549
+ }
550
+
464
551
  int main(int argc, char *argv[])
465
552
  {
466
553
  int ret;
@@ -501,5 +588,11 @@ int main(int argc, char *argv[])
501
588
  }
502
589
  }
503
590
 
591
+ ret = test_enobuf();
592
+ if (ret) {
593
+ fprintf(stderr, "test_enobuf() failed: %d\n", ret);
594
+ return T_EXIT_FAIL;
595
+ }
596
+
504
597
  return T_EXIT_PASS;
505
598
  }
@@ -0,0 +1,90 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Test io_uring_register with a registered ring (IORING_REGISTER_USE_REGISTERED_RING)
4
+ *
5
+ */
6
+ #include <stdio.h>
7
+
8
+ #include "helpers.h"
9
+
10
+ int main(int argc, char *argv[])
11
+ {
12
+ struct io_uring ring;
13
+ unsigned values[2];
14
+ int ret;
15
+
16
+ if (argc > 1)
17
+ return T_EXIT_SKIP;
18
+
19
+ ret = io_uring_queue_init(8, &ring, 0);
20
+ if (ret) {
21
+ fprintf(stderr, "ring setup failed\n");
22
+ return T_EXIT_FAIL;
23
+ }
24
+
25
+ if (!(ring.features & IORING_FEAT_REG_REG_RING)) {
26
+ fprintf(stderr, "IORING_FEAT_REG_REG_RING not available in kernel\n");
27
+ io_uring_queue_exit(&ring);
28
+ return T_EXIT_SKIP;
29
+ }
30
+
31
+ ret = io_uring_close_ring_fd(&ring);
32
+ if (ret != -EINVAL) {
33
+ fprintf(stderr, "closing ring fd should EINVAL before register\n");
34
+ goto err;
35
+ }
36
+
37
+ ret = io_uring_unregister_ring_fd(&ring);
38
+ if (ret != -EINVAL) {
39
+ fprintf(stderr, "unregistering not-registered ring fd should fail\n");
40
+ goto err;
41
+ }
42
+
43
+ ret = io_uring_register_ring_fd(&ring);
44
+ if (ret != 1) {
45
+ fprintf(stderr, "registering ring fd failed\n");
46
+ goto err;
47
+ }
48
+
49
+ ret = io_uring_register_ring_fd(&ring);
50
+ if (ret != -EEXIST) {
51
+ fprintf(stderr, "registering already-registered ring fd should fail\n");
52
+ goto err;
53
+ }
54
+
55
+ /* Test a simple io_uring_register operation expected to work.
56
+ * io_uring_register_iowq_max_workers is arbitrary.
57
+ */
58
+ values[0] = values[1] = 0;
59
+ ret = io_uring_register_iowq_max_workers(&ring, values);
60
+ if (ret || (values[0] == 0 && values[1] == 0)) {
61
+ fprintf(stderr, "io_uring_register operation failed before closing ring fd\n");
62
+ goto err;
63
+ }
64
+
65
+ ret = io_uring_close_ring_fd(&ring);
66
+ if (ret != 1) {
67
+ fprintf(stderr, "closing ring fd failed\n");
68
+ goto err;
69
+ }
70
+
71
+ values[0] = values[1] = 0;
72
+ ret = io_uring_register_iowq_max_workers(&ring, values);
73
+ if (ret || (values[0] == 0 && values[1] == 0)) {
74
+ fprintf(stderr, "io_uring_register operation failed after closing ring fd\n");
75
+ goto err;
76
+ }
77
+
78
+ ret = io_uring_close_ring_fd(&ring);
79
+ if (ret != -EBADF) {
80
+ fprintf(stderr, "closing already-closed ring fd should fail\n");
81
+ goto err;
82
+ }
83
+
84
+ io_uring_queue_exit(&ring);
85
+ return T_EXIT_PASS;
86
+
87
+ err:
88
+ io_uring_queue_exit(&ring);
89
+ return T_EXIT_FAIL;
90
+ }
@@ -1,6 +1,6 @@
1
1
  /* SPDX-License-Identifier: MIT */
2
2
  /*
3
- * Description: run various nop tests
3
+ * Description: run various rename tests
4
4
  *
5
5
  */
6
6
  #include <errno.h>
@@ -241,7 +241,6 @@ int main(int argc, char *argv[])
241
241
  update);
242
242
  return 1;
243
243
  }
244
- break;
245
244
  }
246
245
 
247
246
  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) {
@@ -46,7 +46,7 @@ static struct io_uring *client_ring;
46
46
 
47
47
  static int client_eventfd = -1;
48
48
 
49
- int setup_io_uring(struct io_uring *ring)
49
+ static int setup_io_uring(struct io_uring *ring)
50
50
  {
51
51
  struct io_uring_params p = { };
52
52
  int ret;