polyphony 1.5 → 1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +14 -0
- data/TODO.md +0 -4
- data/ext/polyphony/backend_io_uring.c +34 -1
- 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 +4 -7
- data/ext/polyphony/event.c +21 -0
- data/ext/polyphony/extconf.rb +20 -18
- data/ext/polyphony/fiber.c +0 -2
- data/ext/polyphony/polyphony.c +2 -0
- data/ext/polyphony/polyphony.h +5 -0
- 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/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/thread.rb +19 -27
- 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 +7 -2
- data/test/test_event.rb +10 -3
- data/test/test_ext.rb +2 -1
- data/test/test_fiber.rb +16 -4
- data/test/test_global_api.rb +13 -12
- 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 -3
- 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 +14 -3
- 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");
|