uringmachine 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -1
- data/CHANGELOG.md +14 -0
- data/README.md +44 -1
- data/TODO.md +12 -3
- data/examples/bm_snooze.rb +89 -0
- data/examples/bm_write.rb +56 -0
- data/examples/dns_client.rb +12 -0
- data/examples/http_server.rb +42 -43
- data/examples/server_client.rb +64 -0
- data/examples/snooze.rb +44 -0
- data/examples/write_dev_null.rb +16 -0
- data/ext/um/extconf.rb +24 -14
- data/ext/um/um.c +468 -414
- data/ext/um/um.h +129 -39
- data/ext/um/um_buffer.c +49 -0
- data/ext/um/um_class.c +148 -24
- data/ext/um/um_const.c +30 -1
- data/ext/um/um_ext.c +4 -0
- data/ext/um/um_mutex_class.c +47 -0
- data/ext/um/um_op.c +86 -111
- data/ext/um/um_queue_class.c +58 -0
- data/ext/um/um_sync.c +273 -0
- data/ext/um/um_utils.c +1 -1
- data/lib/uringmachine/dns_resolver.rb +84 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +19 -3
- data/supressions/ruby.supp +71 -0
- data/test/test_um.rb +466 -47
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +1 -0
- data/vendor/liburing/configure +32 -0
- data/vendor/liburing/examples/Makefile +1 -0
- data/vendor/liburing/examples/reg-wait.c +159 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
- data/vendor/liburing/src/include/liburing.h +28 -2
- data/vendor/liburing/src/int_flags.h +10 -3
- data/vendor/liburing/src/liburing-ffi.map +13 -2
- data/vendor/liburing/src/liburing.map +9 -0
- data/vendor/liburing/src/queue.c +25 -16
- data/vendor/liburing/src/register.c +73 -4
- data/vendor/liburing/src/setup.c +46 -18
- data/vendor/liburing/src/setup.h +6 -0
- data/vendor/liburing/test/Makefile +7 -0
- data/vendor/liburing/test/cmd-discard.c +427 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
- data/vendor/liburing/test/file-exit-unreg.c +48 -0
- data/vendor/liburing/test/io_uring_passthrough.c +2 -0
- data/vendor/liburing/test/io_uring_register.c +13 -2
- data/vendor/liburing/test/napi-test.c +1 -1
- data/vendor/liburing/test/no-mmap-inval.c +1 -1
- data/vendor/liburing/test/read-mshot-empty.c +2 -0
- data/vendor/liburing/test/read-mshot-stdin.c +121 -0
- data/vendor/liburing/test/read-mshot.c +6 -0
- data/vendor/liburing/test/recvsend_bundle.c +2 -2
- data/vendor/liburing/test/reg-fd-only.c +1 -1
- data/vendor/liburing/test/reg-wait.c +251 -0
- data/vendor/liburing/test/regbuf-clone.c +458 -0
- data/vendor/liburing/test/resize-rings.c +643 -0
- data/vendor/liburing/test/rsrc_tags.c +1 -1
- data/vendor/liburing/test/sqpoll-sleep.c +39 -8
- data/vendor/liburing/test/sqwait.c +136 -0
- data/vendor/liburing/test/sync-cancel.c +8 -1
- data/vendor/liburing/test/timeout.c +13 -8
- metadata +22 -4
- data/examples/http_server_multishot.rb +0 -57
- data/examples/http_server_simpler.rb +0 -34
@@ -0,0 +1,136 @@
|
|
1
|
+
/* SPDX-License-Identifier: MIT */
|
2
|
+
/*
|
3
|
+
* Description: test that the app can always get a new sqe after having
|
4
|
+
* called io_uring_sqring_wait().
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <unistd.h>
|
10
|
+
|
11
|
+
#include "liburing.h"
|
12
|
+
#include "helpers.h"
|
13
|
+
|
14
|
+
#define NR_IOS 10000
|
15
|
+
#define INFLIGHT 256
|
16
|
+
#define FILE_SIZE (256 * 1024 * 1024)
|
17
|
+
|
18
|
+
static int inflight;
|
19
|
+
|
20
|
+
static int reap(struct io_uring *ring)
|
21
|
+
{
|
22
|
+
struct io_uring_cqe *cqe;
|
23
|
+
int ret;
|
24
|
+
|
25
|
+
while (inflight >= INFLIGHT / 2) {
|
26
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
27
|
+
if (ret < 0) {
|
28
|
+
fprintf(stderr, "wait=%d\n", ret);
|
29
|
+
return 1;
|
30
|
+
}
|
31
|
+
if (cqe->res < 0) {
|
32
|
+
printf("cqe res %d\n", cqe->res);
|
33
|
+
return 1;
|
34
|
+
}
|
35
|
+
io_uring_cqe_seen(ring, cqe);
|
36
|
+
inflight--;
|
37
|
+
}
|
38
|
+
|
39
|
+
return 0;
|
40
|
+
}
|
41
|
+
|
42
|
+
int main(int argc, char *argv[])
|
43
|
+
{
|
44
|
+
struct io_uring_sqe *sqe;
|
45
|
+
struct io_uring ring;
|
46
|
+
int fd = -1, i, iov_off, ret, fret;
|
47
|
+
struct iovec iovs[INFLIGHT];
|
48
|
+
const char *fname;
|
49
|
+
char buf[256];
|
50
|
+
loff_t off;
|
51
|
+
|
52
|
+
if (argc > 1) {
|
53
|
+
fname = argv[1];
|
54
|
+
} else {
|
55
|
+
srand((unsigned)time(NULL));
|
56
|
+
snprintf(buf, sizeof(buf), ".sqwait-%u-%u", (unsigned)rand(),
|
57
|
+
(unsigned)getpid());
|
58
|
+
fname = buf;
|
59
|
+
t_create_file(fname, FILE_SIZE);
|
60
|
+
}
|
61
|
+
|
62
|
+
fret = T_EXIT_SKIP;
|
63
|
+
ret = io_uring_queue_init(8, &ring, IORING_SETUP_SQPOLL);
|
64
|
+
if (ret < 0) {
|
65
|
+
if (errno == EINVAL || errno == EPERM)
|
66
|
+
goto err;
|
67
|
+
fprintf(stderr, "queue init %d\n", ret);
|
68
|
+
fret = T_EXIT_FAIL;
|
69
|
+
goto err;
|
70
|
+
}
|
71
|
+
|
72
|
+
fd = open(fname, O_RDONLY | O_DIRECT);
|
73
|
+
if (fd < 0) {
|
74
|
+
if (errno == EACCES || errno == EPERM || errno == EINVAL)
|
75
|
+
return T_EXIT_SKIP;
|
76
|
+
perror("open");
|
77
|
+
fret = T_EXIT_FAIL;
|
78
|
+
goto err;
|
79
|
+
}
|
80
|
+
|
81
|
+
for (i = 0; i < INFLIGHT; i++) {
|
82
|
+
if (posix_memalign(&iovs[i].iov_base, 4096, 4096))
|
83
|
+
goto err;
|
84
|
+
iovs[i].iov_len = 4096;
|
85
|
+
}
|
86
|
+
|
87
|
+
iov_off = off = 0;
|
88
|
+
for (i = 0; i < NR_IOS; i++) {
|
89
|
+
struct iovec *iov = &iovs[iov_off];
|
90
|
+
|
91
|
+
sqe = io_uring_get_sqe(&ring);
|
92
|
+
if (!sqe) {
|
93
|
+
ret = io_uring_sqring_wait(&ring);
|
94
|
+
if (ret < 0) {
|
95
|
+
if (ret == -EINVAL)
|
96
|
+
return T_EXIT_SKIP;
|
97
|
+
fprintf(stderr, "sqwait=%d\n", ret);
|
98
|
+
fret = T_EXIT_FAIL;
|
99
|
+
goto err;
|
100
|
+
}
|
101
|
+
sqe = io_uring_get_sqe(&ring);
|
102
|
+
if (!sqe) {
|
103
|
+
fprintf(stderr, "No sqe post wait\n");
|
104
|
+
fret = T_EXIT_FAIL;
|
105
|
+
goto err;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
io_uring_prep_read(sqe, fd, iov->iov_base, iov->iov_len, 0);
|
109
|
+
io_uring_submit(&ring);
|
110
|
+
inflight++;
|
111
|
+
|
112
|
+
iov_off++;
|
113
|
+
if (iov_off == INFLIGHT)
|
114
|
+
iov_off = 0;
|
115
|
+
off += 8192;
|
116
|
+
if (off > FILE_SIZE - 8192)
|
117
|
+
off = 0;
|
118
|
+
if (reap(&ring)) {
|
119
|
+
fret = T_EXIT_FAIL;
|
120
|
+
goto err;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
if (fd != -1)
|
125
|
+
close(fd);
|
126
|
+
if (fname != argv[1])
|
127
|
+
unlink(fname);
|
128
|
+
io_uring_queue_exit(&ring);
|
129
|
+
return T_EXIT_PASS;
|
130
|
+
err:
|
131
|
+
if (fd != -1)
|
132
|
+
close(fd);
|
133
|
+
if (fname != argv[1])
|
134
|
+
unlink(fname);
|
135
|
+
return fret;
|
136
|
+
}
|
@@ -13,7 +13,7 @@
|
|
13
13
|
#include "liburing.h"
|
14
14
|
#include "helpers.h"
|
15
15
|
|
16
|
-
static int no_sync_cancel;
|
16
|
+
static int no_sync_cancel, no_sync_cancel_op;
|
17
17
|
|
18
18
|
static int test_sync_cancel_timeout(struct io_uring *ring, int async, int by_op)
|
19
19
|
{
|
@@ -47,6 +47,11 @@ static int test_sync_cancel_timeout(struct io_uring *ring, int async, int by_op)
|
|
47
47
|
reg.opcode = IORING_OP_READ;
|
48
48
|
reg.timeout.tv_nsec = 1;
|
49
49
|
ret = io_uring_register_sync_cancel(ring, ®);
|
50
|
+
/* earlier kernels had sync cancel, but not per-op */
|
51
|
+
if (ret == -EINVAL) {
|
52
|
+
no_sync_cancel_op = 1;
|
53
|
+
return 0;
|
54
|
+
}
|
50
55
|
if (async) {
|
51
56
|
/* we expect -ETIME here, but can race and get 0 */
|
52
57
|
if (ret != -ETIME && ret != 0) {
|
@@ -244,6 +249,8 @@ int main(int argc, char *argv[])
|
|
244
249
|
fprintf(stderr, "test_sync_cancel_timeout 0 0\n");
|
245
250
|
return T_EXIT_FAIL;
|
246
251
|
}
|
252
|
+
if (no_sync_cancel_op)
|
253
|
+
return T_EXIT_PASS;
|
247
254
|
|
248
255
|
ret = test_sync_cancel_timeout(&ring, 0, 1);
|
249
256
|
if (ret) {
|
@@ -1228,14 +1228,19 @@ static int test_timeout_link_cancel(void)
|
|
1228
1228
|
exit(0);
|
1229
1229
|
}
|
1230
1230
|
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1231
|
+
do {
|
1232
|
+
if (waitpid(p, &wstatus, 0) == (pid_t)-1) {
|
1233
|
+
perror("waitpid()");
|
1234
|
+
return 1;
|
1235
|
+
}
|
1236
|
+
if (!WIFEXITED(wstatus))
|
1237
|
+
continue;
|
1238
|
+
if (WEXITSTATUS(wstatus)) {
|
1239
|
+
fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus));
|
1240
|
+
return 1;
|
1241
|
+
}
|
1242
|
+
break;
|
1243
|
+
} while (1);
|
1239
1244
|
|
1240
1245
|
for (i = 0; i < 2; ++i) {
|
1241
1246
|
ret = io_uring_wait_cqe(&ring, &cqe);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uringmachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -84,22 +84,32 @@ files:
|
|
84
84
|
- README.md
|
85
85
|
- Rakefile
|
86
86
|
- TODO.md
|
87
|
+
- examples/bm_snooze.rb
|
88
|
+
- examples/bm_write.rb
|
89
|
+
- examples/dns_client.rb
|
87
90
|
- examples/echo_server.rb
|
88
91
|
- examples/http_server.rb
|
89
|
-
- examples/http_server_multishot.rb
|
90
|
-
- examples/http_server_simpler.rb
|
91
92
|
- examples/inout.rb
|
92
93
|
- examples/nc.rb
|
94
|
+
- examples/server_client.rb
|
95
|
+
- examples/snooze.rb
|
96
|
+
- examples/write_dev_null.rb
|
93
97
|
- ext/um/extconf.rb
|
94
98
|
- ext/um/um.c
|
95
99
|
- ext/um/um.h
|
100
|
+
- ext/um/um_buffer.c
|
96
101
|
- ext/um/um_class.c
|
97
102
|
- ext/um/um_const.c
|
98
103
|
- ext/um/um_ext.c
|
104
|
+
- ext/um/um_mutex_class.c
|
99
105
|
- ext/um/um_op.c
|
106
|
+
- ext/um/um_queue_class.c
|
107
|
+
- ext/um/um_sync.c
|
100
108
|
- ext/um/um_utils.c
|
101
109
|
- lib/uringmachine.rb
|
110
|
+
- lib/uringmachine/dns_resolver.rb
|
102
111
|
- lib/uringmachine/version.rb
|
112
|
+
- supressions/ruby.supp
|
103
113
|
- test/helper.rb
|
104
114
|
- test/test_um.rb
|
105
115
|
- uringmachine.gemspec
|
@@ -149,6 +159,7 @@ files:
|
|
149
159
|
- vendor/liburing/examples/poll-bench.c
|
150
160
|
- vendor/liburing/examples/proxy.c
|
151
161
|
- vendor/liburing/examples/proxy.h
|
162
|
+
- vendor/liburing/examples/reg-wait.c
|
152
163
|
- vendor/liburing/examples/rsrc-update-bench.c
|
153
164
|
- vendor/liburing/examples/send-zerocopy.c
|
154
165
|
- vendor/liburing/examples/ucontext-cp.c
|
@@ -207,6 +218,7 @@ files:
|
|
207
218
|
- vendor/liburing/test/buf-ring.c
|
208
219
|
- vendor/liburing/test/ce593a6c480a.c
|
209
220
|
- vendor/liburing/test/close-opath.c
|
221
|
+
- vendor/liburing/test/cmd-discard.c
|
210
222
|
- vendor/liburing/test/config
|
211
223
|
- vendor/liburing/test/connect-rep.c
|
212
224
|
- vendor/liburing/test/connect.c
|
@@ -239,6 +251,8 @@ files:
|
|
239
251
|
- vendor/liburing/test/fd-install.c
|
240
252
|
- vendor/liburing/test/fd-pass.c
|
241
253
|
- vendor/liburing/test/fdinfo.c
|
254
|
+
- vendor/liburing/test/fifo-nonblock-read.c
|
255
|
+
- vendor/liburing/test/file-exit-unreg.c
|
242
256
|
- vendor/liburing/test/file-register.c
|
243
257
|
- vendor/liburing/test/file-update.c
|
244
258
|
- vendor/liburing/test/file-verify.c
|
@@ -314,6 +328,7 @@ files:
|
|
314
328
|
- vendor/liburing/test/probe.c
|
315
329
|
- vendor/liburing/test/read-before-exit.c
|
316
330
|
- vendor/liburing/test/read-mshot-empty.c
|
331
|
+
- vendor/liburing/test/read-mshot-stdin.c
|
317
332
|
- vendor/liburing/test/read-mshot.c
|
318
333
|
- vendor/liburing/test/read-write.c
|
319
334
|
- vendor/liburing/test/recv-msgall-stream.c
|
@@ -324,10 +339,12 @@ files:
|
|
324
339
|
- vendor/liburing/test/reg-fd-only.c
|
325
340
|
- vendor/liburing/test/reg-hint.c
|
326
341
|
- vendor/liburing/test/reg-reg-ring.c
|
342
|
+
- vendor/liburing/test/reg-wait.c
|
327
343
|
- vendor/liburing/test/regbuf-clone.c
|
328
344
|
- vendor/liburing/test/regbuf-merge.c
|
329
345
|
- vendor/liburing/test/register-restrictions.c
|
330
346
|
- vendor/liburing/test/rename.c
|
347
|
+
- vendor/liburing/test/resize-rings.c
|
331
348
|
- vendor/liburing/test/ring-leak.c
|
332
349
|
- vendor/liburing/test/ring-leak2.c
|
333
350
|
- vendor/liburing/test/ringbuf-read.c
|
@@ -364,6 +381,7 @@ files:
|
|
364
381
|
- vendor/liburing/test/sqpoll-exec.c
|
365
382
|
- vendor/liburing/test/sqpoll-exit-hang.c
|
366
383
|
- vendor/liburing/test/sqpoll-sleep.c
|
384
|
+
- vendor/liburing/test/sqwait.c
|
367
385
|
- vendor/liburing/test/statx.c
|
368
386
|
- vendor/liburing/test/stdout.c
|
369
387
|
- vendor/liburing/test/submit-and-wait.c
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require_relative '../lib/iou'
|
2
|
-
require 'socket'
|
3
|
-
require 'http/parser'
|
4
|
-
|
5
|
-
def log(msg)
|
6
|
-
# return
|
7
|
-
STDERR.puts msg
|
8
|
-
end
|
9
|
-
|
10
|
-
socket = TCPServer.open('127.0.0.1', 1234)
|
11
|
-
log 'Listening on port 1234... (multishot read)'
|
12
|
-
|
13
|
-
@ring = IOU::Ring.new
|
14
|
-
@bg_id = @ring.setup_buffer_ring(count: 1024, size: 4096)
|
15
|
-
|
16
|
-
@ring.prep_accept(fd: socket.fileno, multishot: true) do |c|
|
17
|
-
setup_connection(c[:result]) if c[:result] > 0
|
18
|
-
end
|
19
|
-
|
20
|
-
def setup_connection(fd)
|
21
|
-
log "Connection accepted fd #{fd}"
|
22
|
-
|
23
|
-
parser = Http::Parser.new
|
24
|
-
parser.on_message_complete = -> {
|
25
|
-
http_send_response(fd, "Hello, world!\n")
|
26
|
-
}
|
27
|
-
|
28
|
-
http_prep_read(fd, parser)
|
29
|
-
end
|
30
|
-
|
31
|
-
def http_prep_read(fd, parser)
|
32
|
-
id = @ring.prep_read(fd: fd, multishot: true, buffer_group: @bg_id) do |c|
|
33
|
-
if c[:result] > 0
|
34
|
-
parser << c[:buffer]
|
35
|
-
elsif c[:result] == 0
|
36
|
-
log "Connection closed by client on fd #{fd}"
|
37
|
-
else
|
38
|
-
if c[:result] != -Errno::ECANCELED::Errno
|
39
|
-
log "Got error #{c[:result]} on fd #{fd}, closing connection..."
|
40
|
-
end
|
41
|
-
@ring.prep_close(fd: fd) do |c|
|
42
|
-
log "Connection closed on fd #{fd}, result #{c[:result]}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
rescue HTTP::Parser::Error
|
46
|
-
puts "Error parsing, closing connection..."
|
47
|
-
@ring.prep_cancel(id)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def http_send_response(fd, body)
|
52
|
-
msg = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: keep-alive\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}"
|
53
|
-
@ring.prep_write(fd: fd, buffer: msg)
|
54
|
-
end
|
55
|
-
|
56
|
-
trap('SIGINT') { exit! }
|
57
|
-
@ring.process_completions_loop
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require_relative '../lib/iou'
|
2
|
-
require 'socket'
|
3
|
-
require 'http/parser'
|
4
|
-
|
5
|
-
socket = TCPServer.open('127.0.0.1', 1234)
|
6
|
-
puts 'Listening on port 1234... (multishot read)'
|
7
|
-
|
8
|
-
@ring = IOU::Ring.new
|
9
|
-
@buffer_group = @ring.setup_buffer_ring(count: 1024, size: 4096)
|
10
|
-
|
11
|
-
@ring.prep_accept(fd: socket.fileno, multishot: true) do |c|
|
12
|
-
http_handle_connection(c[:result]) if c[:result] > 0
|
13
|
-
end
|
14
|
-
|
15
|
-
def http_handle_connection(fd)
|
16
|
-
parser = Http::Parser.new
|
17
|
-
parser.on_message_complete = -> { http_send_response(fd, "Hello, world!\n") }
|
18
|
-
|
19
|
-
@ring.prep_read(fd: fd, multishot: true, buffer_group: @buffer_group) do |c|
|
20
|
-
if c[:result] > 0
|
21
|
-
parser << c[:buffer]
|
22
|
-
else
|
23
|
-
puts "Connection closed on fd #{fd}"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def http_send_response(fd, body)
|
29
|
-
msg = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: keep-alive\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}"
|
30
|
-
@ring.prep_write(fd: fd, buffer: msg)
|
31
|
-
end
|
32
|
-
|
33
|
-
trap('SIGINT') { exit! }
|
34
|
-
@ring.process_completions_loop
|