polyphony 1.4 → 1.6
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/.rubocop.yml +3 -0
- data/CHANGELOG.md +22 -0
- data/TODO.md +5 -14
- data/examples/pipes/http_server.rb +42 -12
- data/examples/pipes/http_server2.rb +45 -0
- data/ext/polyphony/backend_common.h +5 -0
- data/ext/polyphony/backend_io_uring.c +174 -121
- data/ext/polyphony/backend_io_uring_context.c +24 -18
- data/ext/polyphony/backend_io_uring_context.h +4 -2
- data/ext/polyphony/backend_libev.c +46 -22
- data/ext/polyphony/event.c +21 -0
- data/ext/polyphony/extconf.rb +25 -19
- data/ext/polyphony/fiber.c +0 -2
- data/ext/polyphony/pipe.c +1 -1
- data/ext/polyphony/polyphony.c +2 -20
- data/ext/polyphony/polyphony.h +5 -5
- data/ext/polyphony/ring_buffer.c +1 -0
- data/ext/polyphony/runqueue_ring_buffer.c +1 -0
- data/ext/polyphony/thread.c +63 -0
- data/ext/polyphony/win_uio.h +18 -0
- data/lib/polyphony/adapters/open3.rb +190 -0
- data/lib/polyphony/core/sync.rb +83 -13
- data/lib/polyphony/core/timer.rb +7 -25
- data/lib/polyphony/extensions/exception.rb +15 -0
- data/lib/polyphony/extensions/fiber.rb +14 -13
- data/lib/polyphony/extensions/io.rb +56 -14
- data/lib/polyphony/extensions/kernel.rb +1 -1
- data/lib/polyphony/extensions/object.rb +1 -13
- data/lib/polyphony/extensions/process.rb +76 -1
- data/lib/polyphony/extensions/socket.rb +0 -14
- data/lib/polyphony/extensions/thread.rb +19 -27
- data/lib/polyphony/extensions/timeout.rb +5 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +11 -5
- data/test/helper.rb +46 -4
- data/test/open3/envutil.rb +380 -0
- data/test/open3/find_executable.rb +24 -0
- data/test/stress.rb +11 -7
- data/test/test_backend.rb +11 -4
- data/test/test_event.rb +10 -3
- data/test/test_ext.rb +16 -1
- data/test/test_fiber.rb +16 -4
- data/test/test_global_api.rb +17 -16
- data/test/test_io.rb +39 -0
- data/test/test_kernel.rb +2 -2
- data/test/test_monitor.rb +356 -0
- data/test/test_open3.rb +338 -0
- data/test/test_signal.rb +5 -1
- data/test/test_socket.rb +6 -98
- data/test/test_sync.rb +46 -0
- data/test/test_thread.rb +10 -1
- data/test/test_thread_pool.rb +5 -0
- data/test/test_throttler.rb +1 -1
- data/test/test_timer.rb +8 -2
- data/test/test_trace.rb +2 -0
- data/vendor/liburing/.github/workflows/build.yml +8 -0
- data/vendor/liburing/.gitignore +1 -0
- data/vendor/liburing/CHANGELOG +8 -0
- data/vendor/liburing/configure +17 -25
- data/vendor/liburing/debian/liburing-dev.manpages +2 -0
- data/vendor/liburing/debian/rules +2 -1
- data/vendor/liburing/examples/Makefile +2 -1
- data/vendor/liburing/examples/io_uring-udp.c +11 -3
- data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/make-debs.sh +4 -2
- data/vendor/liburing/src/Makefile +5 -5
- data/vendor/liburing/src/arch/aarch64/lib.h +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +41 -16
- data/vendor/liburing/src/include/liburing.h +86 -11
- data/vendor/liburing/src/int_flags.h +1 -0
- data/vendor/liburing/src/liburing-ffi.map +12 -0
- data/vendor/liburing/src/liburing.map +8 -0
- data/vendor/liburing/src/register.c +7 -2
- data/vendor/liburing/src/setup.c +373 -81
- data/vendor/liburing/test/232c93d07b74.c +3 -3
- data/vendor/liburing/test/Makefile +10 -3
- data/vendor/liburing/test/accept.c +2 -1
- data/vendor/liburing/test/buf-ring.c +35 -75
- data/vendor/liburing/test/connect-rep.c +204 -0
- data/vendor/liburing/test/coredump.c +59 -0
- data/vendor/liburing/test/fallocate.c +9 -0
- data/vendor/liburing/test/fd-pass.c +34 -3
- data/vendor/liburing/test/file-verify.c +27 -6
- data/vendor/liburing/test/helpers.c +3 -1
- data/vendor/liburing/test/io_uring_register.c +25 -28
- data/vendor/liburing/test/io_uring_setup.c +1 -1
- data/vendor/liburing/test/poll-cancel-all.c +29 -5
- data/vendor/liburing/test/poll-race-mshot.c +6 -22
- data/vendor/liburing/test/read-write.c +53 -0
- data/vendor/liburing/test/recv-msgall.c +21 -23
- data/vendor/liburing/test/reg-fd-only.c +55 -0
- data/vendor/liburing/test/reg-hint.c +56 -0
- data/vendor/liburing/test/regbuf-merge.c +91 -0
- data/vendor/liburing/test/ringbuf-read.c +2 -10
- data/vendor/liburing/test/send_recvmsg.c +5 -16
- data/vendor/liburing/test/shutdown.c +2 -1
- data/vendor/liburing/test/socket-io-cmd.c +215 -0
- data/vendor/liburing/test/socket-rw-eagain.c +2 -1
- data/vendor/liburing/test/socket-rw-offset.c +2 -1
- data/vendor/liburing/test/socket-rw.c +2 -1
- data/vendor/liburing/test/timeout.c +276 -0
- data/vendor/liburing/test/xattr.c +38 -25
- metadata +20 -7
- data/vendor/liburing/test/timeout-overflow.c +0 -204
@@ -37,7 +37,6 @@ static int verify_buffer(char *buf, char val)
|
|
37
37
|
|
38
38
|
static int test(const char *filename, int dio, int async)
|
39
39
|
{
|
40
|
-
struct io_uring_buf_reg reg = { };
|
41
40
|
struct io_uring_sqe *sqe;
|
42
41
|
struct io_uring_cqe *cqe;
|
43
42
|
struct io_uring ring;
|
@@ -68,16 +67,9 @@ static int test(const char *filename, int dio, int async)
|
|
68
67
|
|
69
68
|
if (posix_memalign((void **) &buf, 4096, FSIZE))
|
70
69
|
return 1;
|
71
|
-
if (posix_memalign((void **) &br, 4096, NR_BUFS * sizeof(struct io_uring_buf)))
|
72
|
-
return 1;
|
73
|
-
|
74
|
-
io_uring_buf_ring_init(br);
|
75
|
-
reg.ring_addr = (unsigned long) br;
|
76
|
-
reg.ring_entries = NR_BUFS;
|
77
|
-
reg.bgid = 1;
|
78
70
|
|
79
|
-
|
80
|
-
if (
|
71
|
+
br = io_uring_setup_buf_ring(&ring, NR_BUFS, 1, 0, &ret);
|
72
|
+
if (!br) {
|
81
73
|
if (ret == -EINVAL) {
|
82
74
|
no_buf_ring = 1;
|
83
75
|
return 0;
|
@@ -184,22 +184,11 @@ static void *recv_fn(void *data)
|
|
184
184
|
|
185
185
|
if ((rd->buf_ring || rd->buf_select) && !rd->no_buf_add) {
|
186
186
|
if (rd->buf_ring) {
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
if (posix_memalign(&ptr, 4096, 4096))
|
191
|
-
goto err;
|
192
|
-
|
193
|
-
reg.ring_addr = (unsigned long) ptr;
|
194
|
-
reg.ring_entries = 1;
|
195
|
-
reg.bgid = BUF_BGID;
|
196
|
-
if (io_uring_register_buf_ring(&ring, ®, 0)) {
|
187
|
+
br = io_uring_setup_buf_ring(&ring, 1, BUF_BGID, 0, &ret);
|
188
|
+
if (!br) {
|
197
189
|
no_pbuf_ring = 1;
|
198
190
|
goto out;
|
199
191
|
}
|
200
|
-
|
201
|
-
br = ptr;
|
202
|
-
io_uring_buf_ring_init(br);
|
203
192
|
io_uring_buf_ring_add(br, buf, sizeof(buf), BUF_BID,
|
204
193
|
io_uring_buf_ring_mask(1), 0);
|
205
194
|
io_uring_buf_ring_advance(br, 1);
|
@@ -246,9 +235,9 @@ static void *recv_fn(void *data)
|
|
246
235
|
ret = do_recvmsg(&ring, buf, rd);
|
247
236
|
close(sockfd);
|
248
237
|
|
249
|
-
io_uring_queue_exit(&ring);
|
250
238
|
if (br)
|
251
|
-
|
239
|
+
io_uring_free_buf_ring(&ring, br, 1, BUF_BGID);
|
240
|
+
io_uring_queue_exit(&ring);
|
252
241
|
err:
|
253
242
|
return (void *)(intptr_t)ret;
|
254
243
|
out:
|
@@ -256,7 +245,7 @@ out:
|
|
256
245
|
out_no_ring:
|
257
246
|
pthread_mutex_unlock(mutex);
|
258
247
|
if (br)
|
259
|
-
|
248
|
+
io_uring_free_buf_ring(&ring, br, 1, BUF_BGID);
|
260
249
|
return NULL;
|
261
250
|
}
|
262
251
|
|
@@ -47,7 +47,8 @@ int main(int argc, char *argv[])
|
|
47
47
|
addr.sin_family = AF_INET;
|
48
48
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
49
49
|
|
50
|
-
|
50
|
+
ret = t_bind_ephemeral_port(recv_s0, &addr);
|
51
|
+
assert(!ret);
|
51
52
|
ret = listen(recv_s0, 128);
|
52
53
|
assert(ret != -1);
|
53
54
|
|
@@ -0,0 +1,215 @@
|
|
1
|
+
/* SPDX-License-Identifier: MIT */
|
2
|
+
/*
|
3
|
+
* Check that CMD operations on sockets are consistent.
|
4
|
+
*/
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <stdlib.h>
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <assert.h>
|
9
|
+
#include <string.h>
|
10
|
+
#include <unistd.h>
|
11
|
+
#include <linux/sockios.h>
|
12
|
+
#include <sys/ioctl.h>
|
13
|
+
|
14
|
+
#include "liburing.h"
|
15
|
+
#include "helpers.h"
|
16
|
+
|
17
|
+
#define USERDATA 0x1234
|
18
|
+
#define MSG "foobarbaz"
|
19
|
+
|
20
|
+
struct fds {
|
21
|
+
int tx;
|
22
|
+
int rx;
|
23
|
+
};
|
24
|
+
|
25
|
+
/* Create 2 sockets (tx, rx) given the socket type */
|
26
|
+
static struct fds create_sockets(bool stream)
|
27
|
+
{
|
28
|
+
struct fds retval;
|
29
|
+
int fd[2];
|
30
|
+
|
31
|
+
t_create_socket_pair(fd, stream);
|
32
|
+
|
33
|
+
retval.tx = fd[0];
|
34
|
+
retval.rx = fd[1];
|
35
|
+
|
36
|
+
return retval;
|
37
|
+
}
|
38
|
+
|
39
|
+
static int create_sqe_and_submit(struct io_uring *ring, int32_t fd, int op)
|
40
|
+
{
|
41
|
+
struct io_uring_sqe *sqe;
|
42
|
+
int ret;
|
43
|
+
|
44
|
+
assert(fd > 0);
|
45
|
+
sqe = io_uring_get_sqe(ring);
|
46
|
+
assert(sqe != NULL);
|
47
|
+
|
48
|
+
io_uring_prep_cmd_sock(sqe, op, fd, 0, 0, NULL, 0);
|
49
|
+
sqe->user_data = USERDATA;
|
50
|
+
|
51
|
+
/* Submitting SQE */
|
52
|
+
ret = io_uring_submit_and_wait(ring, 1);
|
53
|
+
if (ret <= 0)
|
54
|
+
return ret;
|
55
|
+
|
56
|
+
return 0;
|
57
|
+
}
|
58
|
+
|
59
|
+
static int receive_cqe(struct io_uring *ring)
|
60
|
+
{
|
61
|
+
struct io_uring_cqe *cqe;
|
62
|
+
int err;
|
63
|
+
|
64
|
+
err = io_uring_wait_cqe(ring, &cqe);
|
65
|
+
assert(err == 0);
|
66
|
+
assert(cqe->user_data == USERDATA);
|
67
|
+
io_uring_cqe_seen(ring, cqe);
|
68
|
+
|
69
|
+
/* Return the result of the operation */
|
70
|
+
return cqe->res;
|
71
|
+
}
|
72
|
+
|
73
|
+
static ssize_t send_data(struct fds *s, char *str)
|
74
|
+
{
|
75
|
+
size_t written_bytes;
|
76
|
+
|
77
|
+
written_bytes = write(s->tx, str, strlen(str));
|
78
|
+
assert(written_bytes == strlen(MSG));
|
79
|
+
|
80
|
+
return written_bytes;
|
81
|
+
}
|
82
|
+
|
83
|
+
static int run_test(bool stream)
|
84
|
+
{
|
85
|
+
struct fds sockfds;
|
86
|
+
size_t bytes_in, bytes_out;
|
87
|
+
struct io_uring ring;
|
88
|
+
size_t written_bytes;
|
89
|
+
int error;
|
90
|
+
|
91
|
+
/* Create three sockets */
|
92
|
+
sockfds = create_sockets(stream);
|
93
|
+
assert(sockfds.tx > 0);
|
94
|
+
assert(sockfds.rx > 0);
|
95
|
+
/* Send data sing the sockfds->send */
|
96
|
+
written_bytes = send_data(&sockfds, MSG);
|
97
|
+
|
98
|
+
/* Simply io_uring ring creation */
|
99
|
+
error = t_create_ring(1, &ring, 0);
|
100
|
+
if (error == T_SETUP_SKIP)
|
101
|
+
return error;
|
102
|
+
else if (error != T_SETUP_OK)
|
103
|
+
return T_EXIT_FAIL;
|
104
|
+
|
105
|
+
error = create_sqe_and_submit(&ring, sockfds.rx,
|
106
|
+
SOCKET_URING_OP_SIOCINQ);
|
107
|
+
bytes_in = receive_cqe(&ring);
|
108
|
+
if (error)
|
109
|
+
return T_EXIT_FAIL;
|
110
|
+
|
111
|
+
error = create_sqe_and_submit(&ring, sockfds.tx,
|
112
|
+
SOCKET_URING_OP_SIOCOUTQ);
|
113
|
+
if (error)
|
114
|
+
return T_EXIT_FAIL;
|
115
|
+
|
116
|
+
bytes_out = receive_cqe(&ring);
|
117
|
+
if (bytes_in == -ENOTSUP || bytes_out == -ENOTSUP) {
|
118
|
+
fprintf(stderr, "Skipping tests. -ENOTSUP returned\n");
|
119
|
+
return T_EXIT_SKIP;
|
120
|
+
}
|
121
|
+
|
122
|
+
/*
|
123
|
+
* Assert the number of written bytes are either in the socket buffer
|
124
|
+
* or on the receive side
|
125
|
+
*/
|
126
|
+
if (bytes_in + bytes_out != written_bytes) {
|
127
|
+
fprintf(stderr, "values does not match: %zu+%zu != %zu\n",
|
128
|
+
bytes_in, bytes_out, written_bytes);
|
129
|
+
return T_EXIT_FAIL;
|
130
|
+
}
|
131
|
+
|
132
|
+
io_uring_queue_exit(&ring);
|
133
|
+
|
134
|
+
return T_EXIT_PASS;
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Make sure that siocoutq and siocinq returns the same value
|
139
|
+
* using ioctl(2) and uring commands for raw sockets
|
140
|
+
*/
|
141
|
+
static int run_test_raw(void)
|
142
|
+
{
|
143
|
+
int ioctl_siocoutq, ioctl_siocinq;
|
144
|
+
int uring_siocoutq, uring_siocinq;
|
145
|
+
struct io_uring ring;
|
146
|
+
int sock, error;
|
147
|
+
|
148
|
+
sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
|
149
|
+
if (sock == -1) {
|
150
|
+
/* You need root to create raw socket */
|
151
|
+
perror("Not able to create a raw socket");
|
152
|
+
return T_EXIT_SKIP;
|
153
|
+
}
|
154
|
+
|
155
|
+
/* Simple SIOCOUTQ using ioctl */
|
156
|
+
error = ioctl(sock, SIOCOUTQ, &ioctl_siocoutq);
|
157
|
+
if (error < 0) {
|
158
|
+
fprintf(stderr, "Failed to run ioctl(SIOCOUTQ): %d\n", error);
|
159
|
+
return T_EXIT_FAIL;
|
160
|
+
}
|
161
|
+
|
162
|
+
error = ioctl(sock, SIOCINQ, &ioctl_siocinq);
|
163
|
+
if (error < 0) {
|
164
|
+
fprintf(stderr, "Failed to run ioctl(SIOCINQ): %d\n", error);
|
165
|
+
return T_EXIT_FAIL;
|
166
|
+
}
|
167
|
+
|
168
|
+
/* Get the same operation using uring cmd */
|
169
|
+
error = t_create_ring(1, &ring, 0);
|
170
|
+
if (error == T_SETUP_SKIP)
|
171
|
+
return error;
|
172
|
+
else if (error != T_SETUP_OK)
|
173
|
+
return T_EXIT_FAIL;
|
174
|
+
|
175
|
+
create_sqe_and_submit(&ring, sock, SOCKET_URING_OP_SIOCOUTQ);
|
176
|
+
uring_siocoutq = receive_cqe(&ring);
|
177
|
+
|
178
|
+
create_sqe_and_submit(&ring, sock, SOCKET_URING_OP_SIOCINQ);
|
179
|
+
uring_siocinq = receive_cqe(&ring);
|
180
|
+
|
181
|
+
/* Compare that both values (ioctl and uring CMD) should be similar */
|
182
|
+
if (uring_siocoutq != ioctl_siocoutq) {
|
183
|
+
fprintf(stderr, "values does not match: %d != %d\n",
|
184
|
+
uring_siocoutq, ioctl_siocoutq);
|
185
|
+
return T_EXIT_FAIL;
|
186
|
+
}
|
187
|
+
if (uring_siocinq != ioctl_siocinq) {
|
188
|
+
fprintf(stderr, "values does not match: %d != %d\n",
|
189
|
+
uring_siocinq, ioctl_siocinq);
|
190
|
+
return T_EXIT_FAIL;
|
191
|
+
}
|
192
|
+
|
193
|
+
return T_EXIT_PASS;
|
194
|
+
}
|
195
|
+
|
196
|
+
int main(int argc, char *argv[])
|
197
|
+
{
|
198
|
+
int err;
|
199
|
+
|
200
|
+
if (argc > 1)
|
201
|
+
return 0;
|
202
|
+
|
203
|
+
/* Test SOCK_STREAM */
|
204
|
+
err = run_test(true);
|
205
|
+
if (err)
|
206
|
+
return err;
|
207
|
+
|
208
|
+
/* Test SOCK_DGRAM */
|
209
|
+
err = run_test(false);
|
210
|
+
if (err)
|
211
|
+
return err;
|
212
|
+
|
213
|
+
/* Test raw sockets */
|
214
|
+
return run_test_raw();
|
215
|
+
}
|
@@ -42,7 +42,8 @@ int main(int argc, char *argv[])
|
|
42
42
|
|
43
43
|
addr.sin_family = AF_INET;
|
44
44
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
45
|
-
|
45
|
+
ret = t_bind_ephemeral_port(recv_s0, &addr);
|
46
|
+
assert(!ret);
|
46
47
|
ret = listen(recv_s0, 128);
|
47
48
|
assert(ret != -1);
|
48
49
|
|
@@ -44,7 +44,8 @@ int main(int argc, char *argv[])
|
|
44
44
|
|
45
45
|
addr.sin_family = AF_INET;
|
46
46
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
47
|
-
|
47
|
+
ret = t_bind_ephemeral_port(recv_s0, &addr);
|
48
|
+
assert(!ret);
|
48
49
|
ret = listen(recv_s0, 128);
|
49
50
|
assert(ret != -1);
|
50
51
|
|
@@ -44,7 +44,8 @@ int main(int argc, char *argv[])
|
|
44
44
|
|
45
45
|
addr.sin_family = AF_INET;
|
46
46
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
47
|
-
|
47
|
+
ret = t_bind_ephemeral_port(recv_s0, &addr);
|
48
|
+
assert(!ret);
|
48
49
|
ret = listen(recv_s0, 128);
|
49
50
|
assert(ret != -1);
|
50
51
|
|
@@ -14,12 +14,14 @@
|
|
14
14
|
#include <sys/types.h>
|
15
15
|
#include <sys/stat.h>
|
16
16
|
|
17
|
+
#include "helpers.h"
|
17
18
|
#include "liburing.h"
|
18
19
|
#include "../src/syscall.h"
|
19
20
|
|
20
21
|
#define TIMEOUT_MSEC 200
|
21
22
|
static int not_supported;
|
22
23
|
static int no_modify;
|
24
|
+
static int no_multishot;
|
23
25
|
|
24
26
|
static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
|
25
27
|
{
|
@@ -1327,6 +1329,246 @@ done:
|
|
1327
1329
|
}
|
1328
1330
|
|
1329
1331
|
|
1332
|
+
static int test_timeout_multishot(struct io_uring *ring)
|
1333
|
+
{
|
1334
|
+
struct io_uring_cqe *cqe;
|
1335
|
+
struct io_uring_sqe *sqe;
|
1336
|
+
struct __kernel_timespec ts;
|
1337
|
+
int ret;
|
1338
|
+
|
1339
|
+
sqe = io_uring_get_sqe(ring);
|
1340
|
+
if (!sqe) {
|
1341
|
+
fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
|
1342
|
+
goto err;
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
msec_to_ts(&ts, TIMEOUT_MSEC);
|
1346
|
+
io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_MULTISHOT);
|
1347
|
+
io_uring_sqe_set_data(sqe, (void *) 1);
|
1348
|
+
|
1349
|
+
ret = io_uring_submit(ring);
|
1350
|
+
if (ret <= 0) {
|
1351
|
+
fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
|
1352
|
+
goto err;
|
1353
|
+
}
|
1354
|
+
|
1355
|
+
for (int i = 0; i < 2; i++) {
|
1356
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
1357
|
+
if (ret < 0) {
|
1358
|
+
fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
|
1359
|
+
goto err;
|
1360
|
+
}
|
1361
|
+
|
1362
|
+
ret = cqe->res;
|
1363
|
+
if (ret == -EINVAL) {
|
1364
|
+
no_multishot = 1;
|
1365
|
+
return T_EXIT_SKIP;
|
1366
|
+
}
|
1367
|
+
|
1368
|
+
if (!(cqe->flags & IORING_CQE_F_MORE)) {
|
1369
|
+
fprintf(stderr, "%s: flag not set in cqe\n", __FUNCTION__);
|
1370
|
+
goto err;
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
if (ret != -ETIME) {
|
1374
|
+
fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
|
1375
|
+
goto err;
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
io_uring_cqe_seen(ring, cqe);
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
sqe = io_uring_get_sqe(ring);
|
1382
|
+
if (!sqe) {
|
1383
|
+
fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
|
1384
|
+
goto err;
|
1385
|
+
}
|
1386
|
+
|
1387
|
+
io_uring_prep_timeout_remove(sqe, 1, 0);
|
1388
|
+
io_uring_sqe_set_data(sqe, (void *) 2);
|
1389
|
+
|
1390
|
+
ret = io_uring_submit(ring);
|
1391
|
+
if (ret <= 0) {
|
1392
|
+
fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
|
1393
|
+
goto err;
|
1394
|
+
}
|
1395
|
+
|
1396
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
1397
|
+
if (ret < 0) {
|
1398
|
+
fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
|
1399
|
+
goto err;
|
1400
|
+
}
|
1401
|
+
|
1402
|
+
ret = cqe->res;
|
1403
|
+
if (ret < 0) {
|
1404
|
+
fprintf(stderr, "%s: remove failed: %s\n", __FUNCTION__, strerror(-ret));
|
1405
|
+
goto err;
|
1406
|
+
}
|
1407
|
+
|
1408
|
+
io_uring_cqe_seen(ring, cqe);
|
1409
|
+
|
1410
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
1411
|
+
if (ret < 0) {
|
1412
|
+
fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
|
1413
|
+
goto err;
|
1414
|
+
}
|
1415
|
+
|
1416
|
+
ret = cqe->res;
|
1417
|
+
if (ret != -ECANCELED) {
|
1418
|
+
fprintf(stderr, "%s: timeout canceled: %s %llu\n", __FUNCTION__, strerror(-ret), cqe->user_data);
|
1419
|
+
goto err;
|
1420
|
+
}
|
1421
|
+
|
1422
|
+
io_uring_cqe_seen(ring, cqe);
|
1423
|
+
return 0;
|
1424
|
+
err:
|
1425
|
+
return 1;
|
1426
|
+
}
|
1427
|
+
|
1428
|
+
|
1429
|
+
static int test_timeout_multishot_nr(struct io_uring *ring)
|
1430
|
+
{
|
1431
|
+
struct io_uring_cqe *cqe;
|
1432
|
+
struct io_uring_sqe *sqe;
|
1433
|
+
struct __kernel_timespec ts;
|
1434
|
+
int ret;
|
1435
|
+
|
1436
|
+
if (no_multishot)
|
1437
|
+
return T_EXIT_SKIP;
|
1438
|
+
|
1439
|
+
sqe = io_uring_get_sqe(ring);
|
1440
|
+
if (!sqe) {
|
1441
|
+
fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
|
1442
|
+
goto err;
|
1443
|
+
}
|
1444
|
+
|
1445
|
+
msec_to_ts(&ts, TIMEOUT_MSEC);
|
1446
|
+
io_uring_prep_timeout(sqe, &ts, 3, IORING_TIMEOUT_MULTISHOT);
|
1447
|
+
io_uring_sqe_set_data(sqe, (void *) 1);
|
1448
|
+
|
1449
|
+
ret = io_uring_submit(ring);
|
1450
|
+
if (ret <= 0) {
|
1451
|
+
fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
|
1452
|
+
goto err;
|
1453
|
+
}
|
1454
|
+
|
1455
|
+
for (int i = 0; i < 3; i++) {
|
1456
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
1457
|
+
if (ret < 0) {
|
1458
|
+
fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
|
1459
|
+
goto err;
|
1460
|
+
}
|
1461
|
+
|
1462
|
+
if (i < 2 && !(cqe->flags & IORING_CQE_F_MORE)) {
|
1463
|
+
fprintf(stderr, "%s: flag not set in cqe\n", __FUNCTION__);
|
1464
|
+
goto err;
|
1465
|
+
}
|
1466
|
+
if (i == 3 && (cqe->flags & IORING_CQE_F_MORE)) {
|
1467
|
+
fprintf(stderr, "%s: flag set in cqe\n", __FUNCTION__);
|
1468
|
+
goto err;
|
1469
|
+
}
|
1470
|
+
|
1471
|
+
ret = cqe->res;
|
1472
|
+
if (ret != -ETIME) {
|
1473
|
+
fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
|
1474
|
+
goto err;
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
io_uring_cqe_seen(ring, cqe);
|
1478
|
+
}
|
1479
|
+
|
1480
|
+
msec_to_ts(&ts, 2 * TIMEOUT_MSEC);
|
1481
|
+
ret = io_uring_wait_cqe_timeout(ring, &cqe, &ts);
|
1482
|
+
if (ret != -ETIME) {
|
1483
|
+
fprintf(stderr, "%s: wait completion timeout %s\n", __FUNCTION__, strerror(-ret));
|
1484
|
+
goto err;
|
1485
|
+
}
|
1486
|
+
|
1487
|
+
return 0;
|
1488
|
+
err:
|
1489
|
+
return 1;
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
|
1493
|
+
static int test_timeout_multishot_overflow(struct io_uring *ring)
|
1494
|
+
{
|
1495
|
+
struct io_uring_cqe *cqe;
|
1496
|
+
struct io_uring_sqe *sqe;
|
1497
|
+
struct __kernel_timespec ts;
|
1498
|
+
int ret;
|
1499
|
+
|
1500
|
+
if (no_multishot)
|
1501
|
+
return T_EXIT_SKIP;
|
1502
|
+
|
1503
|
+
sqe = io_uring_get_sqe(ring);
|
1504
|
+
if (!sqe) {
|
1505
|
+
fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
|
1506
|
+
goto err;
|
1507
|
+
}
|
1508
|
+
|
1509
|
+
msec_to_ts(&ts, 10);
|
1510
|
+
io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_MULTISHOT);
|
1511
|
+
io_uring_sqe_set_data(sqe, (void *) 1);
|
1512
|
+
|
1513
|
+
ret = io_uring_submit(ring);
|
1514
|
+
if (ret <= 0) {
|
1515
|
+
fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
|
1516
|
+
goto err;
|
1517
|
+
}
|
1518
|
+
|
1519
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
1520
|
+
if (ret < 0) {
|
1521
|
+
fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
|
1522
|
+
goto err;
|
1523
|
+
}
|
1524
|
+
|
1525
|
+
ret = cqe->res;
|
1526
|
+
if (ret != -ETIME) {
|
1527
|
+
fprintf(stderr, "%s: Timeout: %s\n", __FUNCTION__, strerror(-ret));
|
1528
|
+
goto err;
|
1529
|
+
}
|
1530
|
+
|
1531
|
+
io_uring_cqe_seen(ring, cqe);
|
1532
|
+
sleep(1);
|
1533
|
+
|
1534
|
+
if (!((*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW)) {
|
1535
|
+
goto err;
|
1536
|
+
}
|
1537
|
+
|
1538
|
+
/* multishot timer should be gone */
|
1539
|
+
sqe = io_uring_get_sqe(ring);
|
1540
|
+
if (!sqe) {
|
1541
|
+
fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
|
1542
|
+
goto err;
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
io_uring_prep_timeout_remove(sqe, 1, 0);
|
1546
|
+
|
1547
|
+
ret = io_uring_submit(ring);
|
1548
|
+
if (ret <= 0) {
|
1549
|
+
fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
|
1550
|
+
goto err;
|
1551
|
+
}
|
1552
|
+
|
1553
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
1554
|
+
if (ret < 0) {
|
1555
|
+
fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
|
1556
|
+
goto err;
|
1557
|
+
}
|
1558
|
+
|
1559
|
+
ret = cqe->res;
|
1560
|
+
io_uring_cqe_seen(ring, cqe);
|
1561
|
+
if (ret != -ETIME) {
|
1562
|
+
fprintf(stderr, "%s: remove failed: %d %s\n", __FUNCTION__, ret, strerror(-ret));
|
1563
|
+
goto err;
|
1564
|
+
}
|
1565
|
+
|
1566
|
+
return 0;
|
1567
|
+
err:
|
1568
|
+
return 1;
|
1569
|
+
}
|
1570
|
+
|
1571
|
+
|
1330
1572
|
int main(int argc, char *argv[])
|
1331
1573
|
{
|
1332
1574
|
struct io_uring ring, sqpoll_ring;
|
@@ -1419,6 +1661,40 @@ int main(int argc, char *argv[])
|
|
1419
1661
|
return ret;
|
1420
1662
|
}
|
1421
1663
|
|
1664
|
+
ret = test_timeout_multishot(&ring);
|
1665
|
+
if (ret && ret != T_EXIT_SKIP) {
|
1666
|
+
fprintf(stderr, "test_timeout_multishot failed\n");
|
1667
|
+
return ret;
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
ret = test_timeout_multishot_nr(&ring);
|
1671
|
+
if (ret && ret != T_EXIT_SKIP) {
|
1672
|
+
fprintf(stderr, "test_timeout_multishot_nr failed\n");
|
1673
|
+
return ret;
|
1674
|
+
}
|
1675
|
+
|
1676
|
+
/* io_uring_wait_cqe_timeout() may have left a timeout, reinit ring */
|
1677
|
+
io_uring_queue_exit(&ring);
|
1678
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
1679
|
+
if (ret) {
|
1680
|
+
fprintf(stderr, "ring setup failed\n");
|
1681
|
+
return 1;
|
1682
|
+
}
|
1683
|
+
|
1684
|
+
ret = test_timeout_multishot_overflow(&ring);
|
1685
|
+
if (ret && ret != T_EXIT_SKIP) {
|
1686
|
+
fprintf(stderr, "test_timeout_multishot_overflow failed\n");
|
1687
|
+
return ret;
|
1688
|
+
}
|
1689
|
+
|
1690
|
+
/* io_uring_wait_cqe_timeout() may have left a timeout, reinit ring */
|
1691
|
+
io_uring_queue_exit(&ring);
|
1692
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
1693
|
+
if (ret) {
|
1694
|
+
fprintf(stderr, "ring setup failed\n");
|
1695
|
+
return 1;
|
1696
|
+
}
|
1697
|
+
|
1422
1698
|
ret = test_single_timeout_wait(&ring, &p);
|
1423
1699
|
if (ret) {
|
1424
1700
|
fprintf(stderr, "test_single_timeout_wait failed\n");
|