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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -1
- data/.rubocop.yml +3 -3
- data/.yardopts +30 -0
- data/CHANGELOG.md +11 -0
- data/LICENSE +1 -1
- data/README.md +63 -29
- data/Rakefile +1 -5
- data/TODO.md +0 -4
- data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
- data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
- data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
- data/docs/{main-concepts/extending.md → extending.md} +2 -9
- data/docs/faq.md +3 -16
- data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
- data/docs/link_rewriter.rb +16 -0
- data/docs/{getting-started/overview.md → overview.md} +1 -30
- data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
- data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
- data/examples/adapters/redis_client.rb +3 -2
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_plain_ruby.rb +26 -0
- data/examples/io/https_server_sni_2.rb +14 -8
- data/ext/polyphony/backend_io_uring.c +154 -9
- data/ext/polyphony/backend_io_uring_context.c +21 -12
- data/ext/polyphony/backend_io_uring_context.h +12 -7
- data/ext/polyphony/backend_libev.c +1 -1
- data/ext/polyphony/extconf.rb +25 -8
- data/ext/polyphony/fiber.c +79 -2
- data/ext/polyphony/io_extensions.c +53 -0
- data/ext/polyphony/libev.h +0 -2
- data/ext/polyphony/pipe.c +42 -2
- data/ext/polyphony/polyphony.c +345 -31
- data/ext/polyphony/polyphony.h +9 -2
- data/ext/polyphony/queue.c +181 -0
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/runqueue.c +8 -1
- data/ext/polyphony/runqueue_ring_buffer.c +13 -0
- data/ext/polyphony/runqueue_ring_buffer.h +2 -1
- data/ext/polyphony/socket_extensions.c +6 -0
- data/ext/polyphony/thread.c +34 -2
- data/lib/polyphony/adapters/process.rb +11 -1
- data/lib/polyphony/adapters/sequel.rb +1 -1
- data/lib/polyphony/core/channel.rb +2 -0
- data/lib/polyphony/core/debug.rb +1 -1
- data/lib/polyphony/core/global_api.rb +25 -24
- data/lib/polyphony/core/resource_pool.rb +7 -6
- data/lib/polyphony/core/sync.rb +55 -2
- data/lib/polyphony/core/thread_pool.rb +3 -3
- data/lib/polyphony/core/timer.rb +8 -8
- data/lib/polyphony/extensions/exception.rb +2 -0
- data/lib/polyphony/extensions/fiber.rb +15 -13
- data/lib/polyphony/extensions/io.rb +161 -16
- data/lib/polyphony/extensions/kernel.rb +20 -2
- data/lib/polyphony/extensions/openssl.rb +101 -12
- data/lib/polyphony/extensions/pipe.rb +103 -7
- data/lib/polyphony/extensions/process.rb +13 -1
- data/lib/polyphony/extensions/socket.rb +93 -27
- data/lib/polyphony/extensions/thread.rb +9 -1
- data/lib/polyphony/extensions/timeout.rb +1 -1
- data/lib/polyphony/version.rb +2 -1
- data/lib/polyphony.rb +27 -7
- data/polyphony.gemspec +1 -8
- data/test/stress.rb +1 -1
- data/test/test_global_api.rb +45 -7
- data/test/test_io.rb +6 -7
- data/test/test_socket.rb +157 -0
- data/test/test_sync.rb +42 -1
- data/test/test_timer.rb +5 -5
- data/vendor/liburing/.github/workflows/build.yml +7 -16
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +23 -1
- data/vendor/liburing/Makefile +4 -3
- data/vendor/liburing/Makefile.common +1 -0
- data/vendor/liburing/README +48 -0
- data/vendor/liburing/configure +76 -6
- data/vendor/liburing/debian/changelog +11 -0
- data/vendor/liburing/debian/control +7 -16
- data/vendor/liburing/debian/liburing-dev.manpages +3 -6
- data/vendor/liburing/debian/liburing2.install +1 -0
- data/vendor/liburing/debian/liburing2.symbols +56 -0
- data/vendor/liburing/debian/rules +15 -68
- data/vendor/liburing/examples/Makefile +4 -0
- data/vendor/liburing/examples/io_uring-close-test.c +123 -0
- data/vendor/liburing/examples/io_uring-udp.c +1 -1
- data/vendor/liburing/examples/send-zerocopy.c +315 -56
- data/vendor/liburing/examples/ucontext-cp.c +2 -17
- data/vendor/liburing/liburing-ffi.pc.in +12 -0
- data/vendor/liburing/liburing.pc.in +1 -1
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/make-debs.sh +3 -3
- data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
- data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
- data/vendor/liburing/man/io_uring_check_version.3 +72 -0
- data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
- data/vendor/liburing/man/io_uring_major_version.3 +1 -0
- data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
- data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
- data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
- data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
- data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
- data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
- data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
- data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
- data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
- data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
- data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
- data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
- data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
- data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
- data/vendor/liburing/man/io_uring_register.2 +15 -9
- data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
- data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
- data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files.3 +60 -5
- data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_setup.2 +31 -2
- data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
- data/vendor/liburing/src/Makefile +25 -3
- data/vendor/liburing/src/ffi.c +15 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
- data/vendor/liburing/src/include/liburing.h +190 -148
- data/vendor/liburing/src/int_flags.h +1 -0
- data/vendor/liburing/src/lib.h +5 -16
- data/vendor/liburing/src/liburing-ffi.map +172 -0
- data/vendor/liburing/src/liburing.map +11 -0
- data/vendor/liburing/src/nolibc.c +9 -2
- data/vendor/liburing/src/queue.c +2 -2
- data/vendor/liburing/src/register.c +66 -96
- data/vendor/liburing/src/setup.c +5 -4
- data/vendor/liburing/src/version.c +21 -0
- data/vendor/liburing/test/232c93d07b74.c +3 -3
- data/vendor/liburing/test/35fa71a030ca.c +3 -3
- data/vendor/liburing/test/500f9fbadef8.c +2 -0
- data/vendor/liburing/test/917257daa0fe.c +1 -1
- data/vendor/liburing/test/Makefile +27 -7
- data/vendor/liburing/test/a0908ae19763.c +2 -2
- data/vendor/liburing/test/a4c0b3decb33.c +2 -2
- data/vendor/liburing/test/accept-link.c +4 -4
- data/vendor/liburing/test/accept-reuse.c +5 -7
- data/vendor/liburing/test/accept.c +34 -31
- data/vendor/liburing/test/b19062a56726.c +1 -1
- data/vendor/liburing/test/buf-ring.c +58 -4
- data/vendor/liburing/test/ce593a6c480a.c +2 -2
- data/vendor/liburing/test/close-opath.c +2 -1
- data/vendor/liburing/test/connect.c +8 -0
- data/vendor/liburing/test/cq-overflow.c +14 -8
- data/vendor/liburing/test/d4ae271dfaae.c +1 -1
- data/vendor/liburing/test/defer-taskrun.c +64 -9
- data/vendor/liburing/test/defer.c +1 -1
- data/vendor/liburing/test/double-poll-crash.c +3 -3
- data/vendor/liburing/test/eeed8b54e0df.c +8 -3
- data/vendor/liburing/test/eploop.c +74 -0
- data/vendor/liburing/test/eventfd-ring.c +1 -1
- data/vendor/liburing/test/eventfd.c +1 -1
- data/vendor/liburing/test/evloop.c +73 -0
- data/vendor/liburing/test/exit-no-cleanup.c +1 -1
- data/vendor/liburing/test/fadvise.c +1 -1
- data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
- data/vendor/liburing/test/fd-pass.c +35 -16
- data/vendor/liburing/test/file-register.c +61 -0
- data/vendor/liburing/test/file-verify.c +2 -2
- data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
- data/vendor/liburing/test/fixed-link.c +1 -1
- data/vendor/liburing/test/fsnotify.c +118 -0
- data/vendor/liburing/test/hardlink.c +1 -1
- data/vendor/liburing/test/helpers.c +54 -2
- data/vendor/liburing/test/helpers.h +4 -0
- data/vendor/liburing/test/io-cancel.c +3 -1
- data/vendor/liburing/test/io_uring_passthrough.c +39 -8
- data/vendor/liburing/test/io_uring_setup.c +3 -80
- data/vendor/liburing/test/iopoll-overflow.c +118 -0
- data/vendor/liburing/test/iopoll.c +90 -4
- data/vendor/liburing/test/lfs-openat-write.c +7 -9
- data/vendor/liburing/test/lfs-openat.c +6 -8
- data/vendor/liburing/test/link_drain.c +31 -5
- data/vendor/liburing/test/madvise.c +1 -1
- data/vendor/liburing/test/msg-ring-flags.c +192 -0
- data/vendor/liburing/test/msg-ring-overflow.c +159 -0
- data/vendor/liburing/test/msg-ring.c +173 -13
- data/vendor/liburing/test/multicqes_drain.c +22 -19
- data/vendor/liburing/test/nvme.h +4 -3
- data/vendor/liburing/test/pipe-bug.c +95 -0
- data/vendor/liburing/test/poll-link.c +3 -3
- data/vendor/liburing/test/poll-many.c +41 -19
- data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
- data/vendor/liburing/test/poll-race-mshot.c +292 -0
- data/vendor/liburing/test/poll-race.c +105 -0
- data/vendor/liburing/test/poll.c +244 -26
- data/vendor/liburing/test/pollfree.c +5 -5
- data/vendor/liburing/test/read-before-exit.c +20 -3
- data/vendor/liburing/test/read-write.c +2 -0
- data/vendor/liburing/test/recv-multishot.c +96 -3
- data/vendor/liburing/test/reg-reg-ring.c +90 -0
- data/vendor/liburing/test/rename.c +1 -1
- data/vendor/liburing/test/ring-leak.c +0 -1
- data/vendor/liburing/test/ring-leak2.c +1 -1
- data/vendor/liburing/test/ringbuf-read.c +10 -6
- data/vendor/liburing/test/send-zerocopy.c +273 -103
- data/vendor/liburing/test/send_recv.c +7 -4
- data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
- data/vendor/liburing/test/single-issuer.c +7 -9
- data/vendor/liburing/test/skip-cqe.c +3 -4
- data/vendor/liburing/test/socket.c +0 -1
- data/vendor/liburing/test/sq-poll-dup.c +10 -3
- data/vendor/liburing/test/sq-poll-kthread.c +1 -1
- data/vendor/liburing/test/sq-poll-share.c +3 -2
- data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
- data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
- data/vendor/liburing/test/symlink.c +2 -1
- data/vendor/liburing/test/test.h +2 -1
- data/vendor/liburing/test/timeout-new.c +11 -7
- data/vendor/liburing/test/timeout.c +1 -2
- data/vendor/liburing/test/unlink.c +1 -1
- data/vendor/liburing/test/version.c +25 -0
- data/vendor/liburing/test/wakeup-hang.c +1 -1
- data/vendor/liburing/test/xattr.c +8 -4
- metadata +57 -44
- data/docs/_config.yml +0 -64
- data/docs/_includes/head.html +0 -40
- data/docs/_includes/title.html +0 -1
- data/docs/_sass/custom/custom.scss +0 -10
- data/docs/_sass/overrides.scss +0 -0
- data/docs/api-reference/exception.md +0 -31
- data/docs/api-reference/fiber.md +0 -425
- data/docs/api-reference/index.md +0 -9
- data/docs/api-reference/io.md +0 -36
- data/docs/api-reference/object.md +0 -99
- data/docs/api-reference/polyphony-baseexception.md +0 -33
- data/docs/api-reference/polyphony-cancel.md +0 -26
- data/docs/api-reference/polyphony-moveon.md +0 -24
- data/docs/api-reference/polyphony-net.md +0 -20
- data/docs/api-reference/polyphony-process.md +0 -28
- data/docs/api-reference/polyphony-resourcepool.md +0 -59
- data/docs/api-reference/polyphony-restart.md +0 -18
- data/docs/api-reference/polyphony-terminate.md +0 -18
- data/docs/api-reference/polyphony-threadpool.md +0 -67
- data/docs/api-reference/polyphony-throttler.md +0 -77
- data/docs/api-reference/polyphony.md +0 -36
- data/docs/api-reference/thread.md +0 -88
- data/docs/favicon.ico +0 -0
- data/docs/getting-started/index.md +0 -10
- data/docs/getting-started/installing.md +0 -34
- data/vendor/liburing/debian/compat +0 -1
- data/vendor/liburing/debian/liburing1-udeb.install +0 -1
- data/vendor/liburing/debian/liburing1.install +0 -1
- data/vendor/liburing/debian/liburing1.symbols +0 -32
- /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
- /data/{docs → assets}/polyphony-logo.png +0 -0
- /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, ¶ms);
|
|
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 (
|
|
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, ®, 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, ®, 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
|
+
}
|