uringmachine 0.4 → 0.5
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/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
|