uringmachine 0.3 → 0.4

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.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +85 -0
  4. data/TODO.md +5 -0
  5. data/examples/echo_server.rb +18 -40
  6. data/examples/inout.rb +19 -0
  7. data/examples/nc.rb +36 -0
  8. data/ext/um/extconf.rb +6 -15
  9. data/ext/um/um.c +245 -53
  10. data/ext/um/um.h +21 -9
  11. data/ext/um/um_class.c +74 -87
  12. data/ext/um/um_const.c +184 -0
  13. data/ext/um/um_op.c +10 -13
  14. data/ext/um/um_utils.c +48 -3
  15. data/lib/uringmachine/version.rb +1 -1
  16. data/lib/uringmachine.rb +12 -0
  17. data/test/helper.rb +8 -0
  18. data/test/test_um.rb +227 -7
  19. data/vendor/liburing/.github/workflows/build.yml +29 -1
  20. data/vendor/liburing/.gitignore +1 -0
  21. data/vendor/liburing/CHANGELOG +15 -0
  22. data/vendor/liburing/CONTRIBUTING.md +165 -0
  23. data/vendor/liburing/configure +32 -0
  24. data/vendor/liburing/examples/Makefile +8 -1
  25. data/vendor/liburing/examples/kdigest.c +405 -0
  26. data/vendor/liburing/examples/proxy.c +75 -8
  27. data/vendor/liburing/liburing.pc.in +1 -1
  28. data/vendor/liburing/src/Makefile +16 -2
  29. data/vendor/liburing/src/include/liburing/io_uring.h +31 -0
  30. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  31. data/vendor/liburing/src/include/liburing.h +31 -4
  32. data/vendor/liburing/src/liburing-ffi.map +5 -0
  33. data/vendor/liburing/src/liburing.map +1 -0
  34. data/vendor/liburing/src/queue.c +3 -0
  35. data/vendor/liburing/src/register.c +36 -0
  36. data/vendor/liburing/src/sanitize.c +176 -0
  37. data/vendor/liburing/src/setup.c +1 -1
  38. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  39. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  40. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  41. data/vendor/liburing/test/917257daa0fe.c +7 -0
  42. data/vendor/liburing/test/Makefile +31 -4
  43. data/vendor/liburing/test/a0908ae19763.c +7 -0
  44. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  45. data/vendor/liburing/test/accept.c +14 -4
  46. data/vendor/liburing/test/b19062a56726.c +7 -0
  47. data/vendor/liburing/test/bind-listen.c +2 -2
  48. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  49. data/vendor/liburing/test/buf-ring.c +2 -0
  50. data/vendor/liburing/test/coredump.c +7 -0
  51. data/vendor/liburing/test/cq-overflow.c +13 -1
  52. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  53. data/vendor/liburing/test/defer-taskrun.c +2 -2
  54. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  55. data/vendor/liburing/test/defer.c +2 -2
  56. data/vendor/liburing/test/double-poll-crash.c +1 -1
  57. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  58. data/vendor/liburing/test/eventfd.c +0 -1
  59. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  60. data/vendor/liburing/test/fadvise.c +9 -26
  61. data/vendor/liburing/test/fdinfo.c +9 -1
  62. data/vendor/liburing/test/file-register.c +14 -2
  63. data/vendor/liburing/test/file-update.c +1 -1
  64. data/vendor/liburing/test/file-verify.c +27 -16
  65. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  66. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  67. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  68. data/vendor/liburing/test/fsnotify.c +1 -0
  69. data/vendor/liburing/test/futex.c +16 -4
  70. data/vendor/liburing/test/helpers.c +47 -0
  71. data/vendor/liburing/test/helpers.h +6 -0
  72. data/vendor/liburing/test/init-mem.c +5 -3
  73. data/vendor/liburing/test/io-cancel.c +0 -24
  74. data/vendor/liburing/test/io_uring_passthrough.c +2 -0
  75. data/vendor/liburing/test/io_uring_register.c +25 -6
  76. data/vendor/liburing/test/iopoll-leak.c +4 -0
  77. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  78. data/vendor/liburing/test/iopoll.c +3 -3
  79. data/vendor/liburing/test/kallsyms.c +203 -0
  80. data/vendor/liburing/test/link-timeout.c +159 -0
  81. data/vendor/liburing/test/linked-defer-close.c +224 -0
  82. data/vendor/liburing/test/madvise.c +12 -25
  83. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  84. data/vendor/liburing/test/min-timeout.c +0 -25
  85. data/vendor/liburing/test/mkdir.c +6 -0
  86. data/vendor/liburing/test/msg-ring.c +8 -2
  87. data/vendor/liburing/test/napi-test.c +15 -2
  88. data/vendor/liburing/test/no-mmap-inval.c +2 -0
  89. data/vendor/liburing/test/nop.c +44 -0
  90. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  91. data/vendor/liburing/test/open-close.c +40 -0
  92. data/vendor/liburing/test/openat2.c +37 -14
  93. data/vendor/liburing/test/poll-many.c +13 -7
  94. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  95. data/vendor/liburing/test/poll-v-poll.c +6 -3
  96. data/vendor/liburing/test/pollfree.c +148 -0
  97. data/vendor/liburing/test/read-mshot-empty.c +156 -153
  98. data/vendor/liburing/test/read-mshot.c +276 -27
  99. data/vendor/liburing/test/read-write.c +78 -13
  100. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  101. data/vendor/liburing/test/recv-msgall.c +5 -0
  102. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  103. data/vendor/liburing/test/recvsend_bundle.c +92 -29
  104. data/vendor/liburing/test/reg-fd-only.c +14 -4
  105. data/vendor/liburing/test/regbuf-clone.c +187 -0
  106. data/vendor/liburing/test/regbuf-merge.c +7 -0
  107. data/vendor/liburing/test/register-restrictions.c +86 -85
  108. data/vendor/liburing/test/rename.c +59 -1
  109. data/vendor/liburing/test/ringbuf-read.c +5 -0
  110. data/vendor/liburing/test/ringbuf-status.c +5 -1
  111. data/vendor/liburing/test/runtests.sh +16 -1
  112. data/vendor/liburing/test/send-zerocopy.c +59 -0
  113. data/vendor/liburing/test/short-read.c +1 -0
  114. data/vendor/liburing/test/socket.c +43 -0
  115. data/vendor/liburing/test/splice.c +3 -1
  116. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  117. data/vendor/liburing/test/sq-poll-share.c +2 -0
  118. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  119. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  120. data/vendor/liburing/test/sqpoll-sleep.c +1 -25
  121. data/vendor/liburing/test/statx.c +89 -0
  122. data/vendor/liburing/test/stdout.c +2 -0
  123. data/vendor/liburing/test/submit-and-wait.c +1 -25
  124. data/vendor/liburing/test/submit-reuse.c +4 -26
  125. data/vendor/liburing/test/symlink.c +12 -1
  126. data/vendor/liburing/test/sync-cancel.c +48 -21
  127. data/vendor/liburing/test/thread-exit.c +5 -0
  128. data/vendor/liburing/test/timeout-new.c +1 -26
  129. data/vendor/liburing/test/timeout.c +12 -26
  130. data/vendor/liburing/test/unlink.c +94 -1
  131. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  132. data/vendor/liburing/test/waitid.c +62 -8
  133. data/vendor/liburing/test/wq-aff.c +35 -0
  134. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  135. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  136. metadata +17 -4
  137. data/examples/event_loop.rb +0 -69
  138. data/examples/fibers.rb +0 -105
data/ext/um/um_class.c CHANGED
@@ -1,5 +1,5 @@
1
1
  #include "um.h"
2
- #include <sys/mman.h>
2
+ #include <arpa/inet.h>
3
3
 
4
4
  VALUE cUM;
5
5
 
@@ -49,52 +49,8 @@ VALUE UM_initialize(VALUE self) {
49
49
 
50
50
  VALUE UM_setup_buffer_ring(VALUE self, VALUE size, VALUE count) {
51
51
  struct um *machine = get_machine(self);
52
-
53
- if (machine->buffer_ring_count == BUFFER_RING_MAX_COUNT)
54
- rb_raise(rb_eRuntimeError, "Cannot setup more than BUFFER_RING_MAX_COUNT buffer rings");
55
-
56
- struct buf_ring_descriptor *desc = machine->buffer_rings + machine->buffer_ring_count;
57
- desc->buf_count = NUM2UINT(count);
58
- desc->buf_size = NUM2UINT(size);
59
-
60
- desc->br_size = sizeof(struct io_uring_buf) * desc->buf_count;
61
- void *mapped = mmap(
62
- NULL, desc->br_size, PROT_READ | PROT_WRITE,
63
- MAP_ANONYMOUS | MAP_PRIVATE, 0, 0
64
- );
65
- if (mapped == MAP_FAILED)
66
- rb_raise(rb_eRuntimeError, "Failed to allocate buffer ring");
67
-
68
- desc->br = (struct io_uring_buf_ring *)mapped;
69
- io_uring_buf_ring_init(desc->br);
70
-
71
- unsigned bg_id = machine->buffer_ring_count;
72
- struct io_uring_buf_reg reg = {
73
- .ring_addr = (unsigned long)desc->br,
74
- .ring_entries = desc->buf_count,
75
- .bgid = bg_id
76
- };
77
- int ret = io_uring_register_buf_ring(&machine->ring, &reg, 0);
78
- if (ret) {
79
- munmap(desc->br, desc->br_size);
80
- rb_syserr_fail(-ret, strerror(-ret));
81
- }
82
-
83
- desc->buf_base = malloc(desc->buf_count * desc->buf_size);
84
- if (!desc->buf_base) {
85
- io_uring_free_buf_ring(&machine->ring, desc->br, desc->buf_count, bg_id);
86
- rb_raise(rb_eRuntimeError, "Failed to allocate buffers");
87
- }
88
-
89
- int mask = io_uring_buf_ring_mask(desc->buf_count);
90
- for (unsigned i = 0; i < desc->buf_count; i++) {
91
- io_uring_buf_ring_add(
92
- desc->br, desc->buf_base + i * desc->buf_size, desc->buf_size,
93
- i, mask, i);
94
- }
95
- io_uring_buf_ring_advance(desc->br, desc->buf_count);
96
- machine->buffer_ring_count++;
97
- return UINT2NUM(bg_id);
52
+ int bgid = um_setup_buffer_ring(machine, NUM2UINT(size), NUM2UINT(count));
53
+ return INT2NUM(bgid);
98
54
  }
99
55
 
100
56
  VALUE UM_pending_count(VALUE self) {
@@ -166,6 +122,11 @@ VALUE UM_write(int argc, VALUE *argv, VALUE self) {
166
122
  return um_write(machine, NUM2INT(fd), buffer, bytes);
167
123
  }
168
124
 
125
+ VALUE UM_close(VALUE self, VALUE fd) {
126
+ struct um *machine = get_machine(self);
127
+ return um_close(machine, NUM2INT(fd));
128
+ }
129
+
169
130
  VALUE UM_accept(VALUE self, VALUE fd) {
170
131
  struct um *machine = get_machine(self);
171
132
  return um_accept(machine, NUM2INT(fd));
@@ -176,6 +137,63 @@ VALUE UM_accept_each(VALUE self, VALUE fd) {
176
137
  return um_accept_each(machine, NUM2INT(fd));
177
138
  }
178
139
 
140
+ VALUE UM_socket(VALUE self, VALUE domain, VALUE type, VALUE protocol, VALUE flags) {
141
+ struct um *machine = get_machine(self);
142
+ return um_socket(machine, NUM2INT(domain), NUM2INT(type), NUM2INT(protocol), NUM2UINT(flags));
143
+ }
144
+
145
+ VALUE UM_connect(VALUE self, VALUE fd, VALUE host, VALUE port) {
146
+ struct um *machine = get_machine(self);
147
+
148
+ struct sockaddr_in addr;
149
+ memset(&addr, 0, sizeof(addr));
150
+ addr.sin_family = AF_INET;
151
+ addr.sin_addr.s_addr = inet_addr(StringValueCStr(host));
152
+ addr.sin_port = htons(NUM2INT(port));
153
+
154
+ return um_connect(machine, NUM2INT(fd), (struct sockaddr *)&addr, sizeof(addr));
155
+ }
156
+
157
+ VALUE UM_send(VALUE self, VALUE fd, VALUE buffer, VALUE len, VALUE flags) {
158
+ struct um *machine = get_machine(self);
159
+ return um_send(machine, NUM2INT(fd), buffer, NUM2INT(len), NUM2INT(flags));
160
+ }
161
+
162
+ VALUE UM_recv(VALUE self, VALUE fd, VALUE buffer, VALUE maxlen, VALUE flags) {
163
+ struct um *machine = get_machine(self);
164
+ return um_recv(machine, NUM2INT(fd), buffer, NUM2INT(maxlen), NUM2INT(flags));
165
+ }
166
+
167
+ VALUE UM_bind(VALUE self, VALUE fd, VALUE host, VALUE port) {
168
+ struct sockaddr_in addr;
169
+ memset(&addr, 0, sizeof(addr));
170
+ addr.sin_family = AF_INET;
171
+ addr.sin_addr.s_addr = inet_addr(StringValueCStr(host));
172
+ addr.sin_port = htons(NUM2INT(port));
173
+
174
+ #ifdef HAVE_IO_URING_PREP_BIND
175
+ struct um *machine = get_machine(self);
176
+ return um_bind(machine, NUM2INT(fd), (struct sockaddr *)&addr, sizeof(addr));
177
+ #else
178
+ int res = bind(NUM2INT(fd), (struct sockaddr *)&addr, sizeof(addr));
179
+ if (res)
180
+ rb_syserr_fail(errno, strerror(errno));
181
+ return INT2NUM(0);
182
+ #endif
183
+ }
184
+
185
+ VALUE UM_listen(VALUE self, VALUE fd, VALUE backlog) {
186
+ #ifdef HAVE_IO_URING_PREP_LISTEN
187
+ struct um *machine = get_machine(self);
188
+ return um_listen(machine, NUM2INT(fd), NUM2INT(backlog));
189
+ #else
190
+ int res = listen(NUM2INT(fd), NUM2INT(backlog));
191
+ if (res)
192
+ rb_syserr_fail(errno, strerror(errno));
193
+ return INT2NUM(0);
194
+ #endif
195
+ }
196
+
179
197
  void Init_UM(void) {
180
198
  rb_ext_ractor_safe(true);
181
199
 
@@ -196,47 +214,16 @@ void Init_UM(void) {
196
214
  rb_define_method(cUM, "read", UM_read, -1);
197
215
  rb_define_method(cUM, "read_each", UM_read_each, 2);
198
216
  rb_define_method(cUM, "write", UM_write, -1);
217
+ rb_define_method(cUM, "close", UM_close, 1);
199
218
 
200
219
  rb_define_method(cUM, "accept", UM_accept, 1);
201
220
  rb_define_method(cUM, "accept_each", UM_accept_each, 1);
202
-
203
- // rb_define_method(cUM, "emit", UM_emit, 1);
204
-
205
- // rb_define_method(cUM, "prep_accept", UM_prep_accept, 1);
206
- // rb_define_method(cUM, "prep_cancel", UM_prep_cancel, 1);
207
- // rb_define_method(cUM, "prep_close", UM_prep_close, 1);
208
- // rb_define_method(cUM, "prep_nop", UM_prep_nop, 0);
209
- // rb_define_method(cUM, "prep_read", UM_prep_read, 1);
210
- // rb_define_method(cUM, "prep_timeout", UM_prep_timeout, 1);
211
- // rb_define_method(cUM, "prep_write", UM_prep_write, 1);
212
-
213
- // rb_define_method(cUM, "submit", UM_submit, 0);
214
- // rb_define_method(cUM, "wait_for_completion", UM_wait_for_completion, 0);
215
- // rb_define_method(cUM, "process_completions", UM_process_completions, -1);
216
- // rb_define_method(cUM, "process_completions_loop", UM_process_completions_loop, 0);
217
-
218
- // SYM_accept = MAKE_SYM("accept");
219
- // SYM_block = MAKE_SYM("block");
220
- // SYM_buffer = MAKE_SYM("buffer");
221
- // SYM_buffer_group = MAKE_SYM("buffer_group");
222
- // SYM_buffer_offset = MAKE_SYM("buffer_offset");
223
- // SYM_close = MAKE_SYM("close");
224
- // SYM_count = MAKE_SYM("count");
225
- // SYM_emit = MAKE_SYM("emit");
226
- // SYM_fd = MAKE_SYM("fd");
227
- // SYM_id = MAKE_SYM("id");
228
- // SYM_interval = MAKE_SYM("interval");
229
- // SYM_len = MAKE_SYM("len");
230
- // SYM_link = MAKE_SYM("link");
231
- // SYM_multishot = MAKE_SYM("multishot");
232
- // SYM_op = MAKE_SYM("op");
233
- // SYM_read = MAKE_SYM("read");
234
- // SYM_result = MAKE_SYM("result");
235
- // SYM_signal = MAKE_SYM("signal");
236
- // SYM_size = MAKE_SYM("size");
237
- // SYM_spec_data = MAKE_SYM("spec_data");
238
- // SYM_stop = MAKE_SYM("stop");
239
- // SYM_timeout = MAKE_SYM("timeout");
240
- // SYM_utf8 = MAKE_SYM("utf8");
241
- // SYM_write = MAKE_SYM("write");
221
+ rb_define_method(cUM, "socket", UM_socket, 4);
222
+ rb_define_method(cUM, "connect", UM_connect, 3);
223
+ rb_define_method(cUM, "send", UM_send, 4);
224
+ rb_define_method(cUM, "recv", UM_recv, 4);
225
+ rb_define_method(cUM, "bind", UM_bind, 3);
226
+ rb_define_method(cUM, "listen", UM_listen, 2);
227
+
228
+ um_define_net_constants(cUM);
242
229
  }
data/ext/um/um_const.c ADDED
@@ -0,0 +1,184 @@
1
+ #include "ruby.h"
2
+ #include <arpa/inet.h>
3
+ #include <sys/types.h>
4
+ #include <sys/socket.h>
5
+ #include <netinet/in.h>
6
+ #include <netinet/tcp.h>
7
+ #include <netinet/udp.h>
8
+ #include <netdb.h>
9
+ #include <net/if.h>
10
+
11
+
12
+ #define DEF_CONST_INT(mod, v) rb_define_const(mod, #v, INT2NUM(v))
13
+
14
+ void um_define_net_constants(VALUE mod) {
15
+ DEF_CONST_INT(mod, SOCK_STREAM);
16
+ DEF_CONST_INT(mod, SOCK_DGRAM);
17
+ DEF_CONST_INT(mod, SOCK_RAW);
18
+ DEF_CONST_INT(mod, SOCK_RDM);
19
+ DEF_CONST_INT(mod, SOCK_SEQPACKET);
20
+ DEF_CONST_INT(mod, SOCK_PACKET);
21
+ DEF_CONST_INT(mod, SOCK_CLOEXEC);
22
+
23
+ DEF_CONST_INT(mod, AF_UNSPEC);
24
+ DEF_CONST_INT(mod, PF_UNSPEC);
25
+ DEF_CONST_INT(mod, AF_INET);
26
+ DEF_CONST_INT(mod, PF_INET);
27
+ DEF_CONST_INT(mod, AF_INET6);
28
+ DEF_CONST_INT(mod, PF_INET6);
29
+ DEF_CONST_INT(mod, AF_UNIX);
30
+ DEF_CONST_INT(mod, PF_UNIX);
31
+ DEF_CONST_INT(mod, AF_LOCAL);
32
+ DEF_CONST_INT(mod, PF_LOCAL);
33
+ DEF_CONST_INT(mod, AF_ROUTE);
34
+ DEF_CONST_INT(mod, PF_ROUTE);
35
+ DEF_CONST_INT(mod, AF_MAX);
36
+ DEF_CONST_INT(mod, PF_MAX);
37
+
38
+ DEF_CONST_INT(mod, MSG_OOB);
39
+ DEF_CONST_INT(mod, MSG_PEEK);
40
+ DEF_CONST_INT(mod, MSG_DONTROUTE);
41
+ DEF_CONST_INT(mod, MSG_WAITALL);
42
+ DEF_CONST_INT(mod, MSG_DONTWAIT);
43
+ DEF_CONST_INT(mod, MSG_MORE);
44
+
45
+ DEF_CONST_INT(mod, SOL_SOCKET);
46
+ DEF_CONST_INT(mod, SOL_IP);
47
+
48
+ DEF_CONST_INT(mod, IPPROTO_IP);
49
+ DEF_CONST_INT(mod, IPPROTO_ICMP);
50
+ DEF_CONST_INT(mod, IPPROTO_IGMP);
51
+ DEF_CONST_INT(mod, IPPROTO_TCP);
52
+ DEF_CONST_INT(mod, IPPROTO_EGP);
53
+ DEF_CONST_INT(mod, IPPROTO_PUP);
54
+ DEF_CONST_INT(mod, IPPROTO_UDP);
55
+ DEF_CONST_INT(mod, IPPROTO_IDP);
56
+ DEF_CONST_INT(mod, IPPROTO_IPV6);
57
+ DEF_CONST_INT(mod, IPPROTO_NONE);
58
+ DEF_CONST_INT(mod, IPPROTO_ROUTING);
59
+ DEF_CONST_INT(mod, IPPROTO_RAW);
60
+ DEF_CONST_INT(mod, IPPROTO_MAX);
61
+
62
+ DEF_CONST_INT(mod, INADDR_ANY);
63
+ DEF_CONST_INT(mod, INADDR_BROADCAST);
64
+ DEF_CONST_INT(mod, INADDR_LOOPBACK);
65
+ DEF_CONST_INT(mod, INADDR_NONE);
66
+
67
+ DEF_CONST_INT(mod, IP_OPTIONS);
68
+ DEF_CONST_INT(mod, IP_HDRINCL);
69
+ DEF_CONST_INT(mod, IP_TOS);
70
+ DEF_CONST_INT(mod, IP_TTL);
71
+ DEF_CONST_INT(mod, IP_RECVOPTS);
72
+ DEF_CONST_INT(mod, IP_MINTTL);
73
+ DEF_CONST_INT(mod, IP_RECVTTL);
74
+
75
+ DEF_CONST_INT(mod, SO_DEBUG);
76
+ DEF_CONST_INT(mod, SO_REUSEADDR);
77
+ DEF_CONST_INT(mod, SO_REUSEPORT);
78
+ DEF_CONST_INT(mod, SO_TYPE);
79
+ DEF_CONST_INT(mod, SO_ERROR);
80
+ DEF_CONST_INT(mod, SO_DONTROUTE);
81
+ DEF_CONST_INT(mod, SO_BROADCAST);
82
+ DEF_CONST_INT(mod, SO_SNDBUF);
83
+ DEF_CONST_INT(mod, SO_RCVBUF);
84
+ DEF_CONST_INT(mod, SO_SNDBUFFORCE);
85
+ DEF_CONST_INT(mod, SO_RCVBUFFORCE);
86
+ DEF_CONST_INT(mod, SO_KEEPALIVE);
87
+ DEF_CONST_INT(mod, SO_OOBINLINE);
88
+ DEF_CONST_INT(mod, SO_PRIORITY);
89
+ DEF_CONST_INT(mod, SO_LINGER);
90
+ DEF_CONST_INT(mod, SO_PASSCRED);
91
+ DEF_CONST_INT(mod, SO_PEERCRED);
92
+ DEF_CONST_INT(mod, SO_RCVLOWAT);
93
+ DEF_CONST_INT(mod, SO_SNDLOWAT);
94
+ DEF_CONST_INT(mod, SO_RCVTIMEO);
95
+ DEF_CONST_INT(mod, SO_SNDTIMEO);
96
+ DEF_CONST_INT(mod, SO_ACCEPTCONN);
97
+ DEF_CONST_INT(mod, SO_PEERNAME);
98
+ DEF_CONST_INT(mod, SO_TIMESTAMP);
99
+ DEF_CONST_INT(mod, SO_MARK);
100
+ DEF_CONST_INT(mod, SO_PROTOCOL);
101
+ DEF_CONST_INT(mod, SO_DOMAIN);
102
+ DEF_CONST_INT(mod, SO_PEEK_OFF);
103
+ DEF_CONST_INT(mod, SO_BUSY_POLL);
104
+
105
+ DEF_CONST_INT(mod, TCP_NODELAY);
106
+ DEF_CONST_INT(mod, TCP_MAXSEG);
107
+ DEF_CONST_INT(mod, TCP_CORK);
108
+ DEF_CONST_INT(mod, TCP_DEFER_ACCEPT);
109
+ DEF_CONST_INT(mod, TCP_INFO);
110
+ DEF_CONST_INT(mod, TCP_KEEPCNT);
111
+ DEF_CONST_INT(mod, TCP_KEEPIDLE);
112
+ DEF_CONST_INT(mod, TCP_KEEPINTVL);
113
+ DEF_CONST_INT(mod, TCP_LINGER2);
114
+ DEF_CONST_INT(mod, TCP_MD5SIG);
115
+ DEF_CONST_INT(mod, TCP_QUICKACK);
116
+ DEF_CONST_INT(mod, TCP_SYNCNT);
117
+ DEF_CONST_INT(mod, TCP_WINDOW_CLAMP);
118
+ DEF_CONST_INT(mod, TCP_FASTOPEN);
119
+ DEF_CONST_INT(mod, TCP_CONGESTION);
120
+ DEF_CONST_INT(mod, TCP_COOKIE_TRANSACTIONS);
121
+ DEF_CONST_INT(mod, TCP_QUEUE_SEQ);
122
+ DEF_CONST_INT(mod, TCP_REPAIR);
123
+ DEF_CONST_INT(mod, TCP_REPAIR_OPTIONS);
124
+ DEF_CONST_INT(mod, TCP_REPAIR_QUEUE);
125
+ DEF_CONST_INT(mod, TCP_THIN_LINEAR_TIMEOUTS);
126
+ DEF_CONST_INT(mod, TCP_TIMESTAMP);
127
+ DEF_CONST_INT(mod, TCP_USER_TIMEOUT);
128
+
129
+ DEF_CONST_INT(mod, UDP_CORK);
130
+
131
+ DEF_CONST_INT(mod, AI_PASSIVE);
132
+ DEF_CONST_INT(mod, AI_CANONNAME);
133
+ DEF_CONST_INT(mod, AI_NUMERICHOST);
134
+ DEF_CONST_INT(mod, AI_NUMERICSERV);
135
+ DEF_CONST_INT(mod, AI_ALL);
136
+ DEF_CONST_INT(mod, AI_ADDRCONFIG);
137
+ DEF_CONST_INT(mod, AI_V4MAPPED);
138
+
139
+ DEF_CONST_INT(mod, NI_MAXHOST);
140
+ DEF_CONST_INT(mod, NI_MAXSERV);
141
+ DEF_CONST_INT(mod, NI_NOFQDN);
142
+ DEF_CONST_INT(mod, NI_NUMERICHOST);
143
+ DEF_CONST_INT(mod, NI_NAMEREQD);
144
+ DEF_CONST_INT(mod, NI_NUMERICSERV);
145
+ DEF_CONST_INT(mod, NI_DGRAM);
146
+
147
+ DEF_CONST_INT(mod, SHUT_RD);
148
+ DEF_CONST_INT(mod, SHUT_WR);
149
+ DEF_CONST_INT(mod, SHUT_RDWR);
150
+
151
+ DEF_CONST_INT(mod, IPV6_JOIN_GROUP);
152
+ DEF_CONST_INT(mod, IPV6_LEAVE_GROUP);
153
+ DEF_CONST_INT(mod, IPV6_MULTICAST_HOPS);
154
+ DEF_CONST_INT(mod, IPV6_MULTICAST_IF);
155
+ DEF_CONST_INT(mod, IPV6_MULTICAST_LOOP);
156
+ DEF_CONST_INT(mod, IPV6_UNICAST_HOPS);
157
+ DEF_CONST_INT(mod, IPV6_V6ONLY);
158
+ DEF_CONST_INT(mod, IPV6_CHECKSUM);
159
+ DEF_CONST_INT(mod, IPV6_DONTFRAG);
160
+ DEF_CONST_INT(mod, IPV6_DSTOPTS);
161
+ DEF_CONST_INT(mod, IPV6_HOPLIMIT);
162
+ DEF_CONST_INT(mod, IPV6_HOPOPTS);
163
+ DEF_CONST_INT(mod, IPV6_NEXTHOP);
164
+ DEF_CONST_INT(mod, IPV6_PATHMTU);
165
+ DEF_CONST_INT(mod, IPV6_PKTINFO);
166
+ DEF_CONST_INT(mod, IPV6_RECVDSTOPTS);
167
+ DEF_CONST_INT(mod, IPV6_RECVHOPLIMIT);
168
+ DEF_CONST_INT(mod, IPV6_RECVHOPOPTS);
169
+ DEF_CONST_INT(mod, IPV6_RECVPKTINFO);
170
+ DEF_CONST_INT(mod, IPV6_RECVRTHDR);
171
+ DEF_CONST_INT(mod, IPV6_RECVTCLASS);
172
+ DEF_CONST_INT(mod, IPV6_RTHDR);
173
+ DEF_CONST_INT(mod, IPV6_RTHDRDSTOPTS);
174
+ DEF_CONST_INT(mod, IPV6_RTHDR_TYPE_0);
175
+ DEF_CONST_INT(mod, IPV6_RECVPATHMTU);
176
+ DEF_CONST_INT(mod, IPV6_TCLASS);
177
+
178
+ DEF_CONST_INT(mod, INET_ADDRSTRLEN);
179
+ DEF_CONST_INT(mod, INET6_ADDRSTRLEN);
180
+
181
+ DEF_CONST_INT(mod, IF_NAMESIZE);
182
+
183
+ DEF_CONST_INT(mod, SOMAXCONN);
184
+ }
data/ext/um/um_op.c CHANGED
@@ -13,10 +13,10 @@ inline struct um_result_entry *um_result_checkout(struct um *machine) {
13
13
 
14
14
  inline void um_result_checkin(struct um *machine, struct um_result_entry *entry) {
15
15
  entry->next = machine->result_freelist;
16
- machine->result_freelist = entry;
16
+ machine->result_freelist = entry;
17
17
  }
18
18
 
19
- inline void um_op_result_cleanup(struct um *machine, struct um_op *op) {
19
+ inline void um_op_result_cleanup(struct um *machine, struct um_op *op) {
20
20
  struct um_result_entry *entry = op->results_head;
21
21
  while (entry) {
22
22
  struct um_result_entry *next = entry->next;
@@ -26,7 +26,7 @@ inline void um_op_result_cleanup(struct um *machine, struct um_op *op) {
26
26
  op->results_head = op->results_tail = NULL;
27
27
  }
28
28
 
29
- inline void um_op_result_push(struct um *machine, struct um_op *op, int result, int flags) {
29
+ inline void um_op_result_push(struct um *machine, struct um_op *op, __s32 result, __u32 flags) {
30
30
  struct um_result_entry *entry = um_result_checkout(machine);
31
31
  entry->next = 0;
32
32
  entry->result = result;
@@ -40,7 +40,7 @@ inline void um_op_result_push(struct um *machine, struct um_op *op, int result,
40
40
  }
41
41
  }
42
42
 
43
- inline int um_op_result_shift(struct um *machine, struct um_op *op, int *result, int *flags) {
43
+ inline int um_op_result_shift(struct um *machine, struct um_op *op, __s32 *result, __u32 *flags) {
44
44
  if (!op->results_head) return 0;
45
45
 
46
46
  struct um_result_entry *entry = op->results_head;
@@ -61,23 +61,20 @@ inline void um_op_clear(struct um_op *op) {
61
61
  inline struct um_op *um_op_checkout(struct um *machine) {
62
62
  machine->pending_count++;
63
63
 
64
- if (machine->op_freelist) {
65
- struct um_op *op = machine->op_freelist;
64
+ struct um_op *op = machine->op_freelist;
65
+ if (op)
66
66
  machine->op_freelist = op->next;
67
- um_op_clear(op);
68
- return op;
69
- }
67
+ else
68
+ op = malloc(sizeof(struct um_op));
70
69
 
71
- struct um_op *op = malloc(sizeof(struct um_op));
72
70
  um_op_clear(op);
73
71
  return op;
74
72
  }
75
73
 
76
74
  inline void um_op_checkin(struct um *machine, struct um_op *op) {
77
- um_op_result_cleanup(machine, op);
78
-
79
75
  machine->pending_count--;
80
76
 
77
+ um_op_result_cleanup(machine, op);
81
78
  op->next = machine->op_freelist;
82
79
  machine->op_freelist = op;
83
80
  }
@@ -124,7 +121,7 @@ inline struct um_op *um_runqueue_shift(struct um *machine) {
124
121
 
125
122
  op->prev = NULL;
126
123
  if (!op->next) {
127
- machine->runqueue_head = machine->runqueue_tail = NULL;
124
+ machine->runqueue_head = machine->runqueue_tail = NULL;
128
125
  }
129
126
  else {
130
127
  machine->runqueue_head = op->next;
data/ext/um/um_utils.c CHANGED
@@ -1,4 +1,6 @@
1
1
  #include "um.h"
2
+ #include <sys/mman.h>
3
+ #include <stdlib.h>
2
4
 
3
5
  inline struct __kernel_timespec um_double_to_timespec(double value) {
4
6
  double integral;
@@ -46,13 +48,56 @@ static inline void adjust_read_buffer_len(VALUE buffer, int result, int ofs) {
46
48
  rb_str_set_len(buffer, len + (unsigned)ofs);
47
49
  }
48
50
 
49
- inline void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset, int result, int flags) {
51
+ inline void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset, __s32 result, __u32 flags) {
50
52
  if (!result) return;
51
53
 
52
54
  adjust_read_buffer_len(buffer, result, buffer_offset);
53
55
  }
54
56
 
55
- inline VALUE get_string_from_buffer_ring(struct um *machine, int bgid, int result, int flags) {
57
+ int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count) {
58
+ if (machine->buffer_ring_count == BUFFER_RING_MAX_COUNT)
59
+ rb_raise(rb_eRuntimeError, "Cannot setup more than BUFFER_RING_MAX_COUNT buffer rings");
60
+
61
+ struct buf_ring_descriptor *desc = machine->buffer_rings + machine->buffer_ring_count;
62
+ desc->buf_count = count;
63
+ desc->buf_size = size;
64
+
65
+ desc->br_size = sizeof(struct io_uring_buf) * desc->buf_count;
66
+ void *mapped = mmap(
67
+ NULL, desc->br_size, PROT_READ | PROT_WRITE,
68
+ MAP_ANONYMOUS | MAP_PRIVATE, 0, 0
69
+ );
70
+ if (mapped == MAP_FAILED)
71
+ rb_raise(rb_eRuntimeError, "Failed to allocate buffer ring");
72
+
73
+ desc->br = (struct io_uring_buf_ring *)mapped;
74
+ io_uring_buf_ring_init(desc->br);
75
+
76
+ unsigned bg_id = machine->buffer_ring_count;
77
+ int ret;
78
+ desc->br = io_uring_setup_buf_ring(&machine->ring, count, bg_id, 0, &ret);
79
+ if (!desc->br) {
80
+ munmap(desc->br, desc->br_size);
81
+ rb_syserr_fail(ret, strerror(ret));
82
+ }
83
+
84
+ if (posix_memalign(&desc->buf_base, 4096, desc->buf_count * desc->buf_size)) {
85
+ io_uring_free_buf_ring(&machine->ring, desc->br, desc->buf_count, bg_id);
86
+ rb_raise(rb_eRuntimeError, "Failed to allocate buffers");
87
+ }
88
+
89
+ desc->buf_mask = io_uring_buf_ring_mask(desc->buf_count);
90
+ void *ptr = desc->buf_base;
91
+ for (unsigned i = 0; i < desc->buf_count; i++) {
92
+ io_uring_buf_ring_add(desc->br, ptr, desc->buf_size, i, desc->buf_mask, i);
93
+ ptr += desc->buf_size;
94
+ }
95
+ io_uring_buf_ring_advance(desc->br, desc->buf_count);
96
+ machine->buffer_ring_count++;
97
+ return bg_id;
98
+ }
99
+
100
+ inline VALUE um_get_string_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags) {
56
101
  if (!result) return Qnil;
57
102
 
58
103
  unsigned buf_idx = flags >> IORING_CQE_BUFFER_SHIFT;
@@ -64,7 +109,7 @@ inline VALUE get_string_from_buffer_ring(struct um *machine, int bgid, int resul
64
109
 
65
110
  // add buffer back to buffer ring
66
111
  io_uring_buf_ring_add(
67
- desc->br, src, desc->buf_size, buf_idx, io_uring_buf_ring_mask(desc->buf_count), 0
112
+ desc->br, src, desc->buf_size, buf_idx, desc->buf_mask, 0
68
113
  );
69
114
  io_uring_buf_ring_advance(desc->br, 1);
70
115
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UringMachine
4
- VERSION = '0.3'
4
+ VERSION = '0.4'
5
5
  end
data/lib/uringmachine.rb CHANGED
@@ -3,3 +3,15 @@
3
3
  require_relative './um_ext'
4
4
 
5
5
  UM = UringMachine
6
+
7
+ class UringMachine
8
+ def spin(value = nil, &block)
9
+ Fiber.new do |resume_value|
10
+ block.(resume_value)
11
+ rescue Exception => e
12
+ raise RuntimeError, "Unhandled fiber exception: #{e.inspect}"
13
+ ensure
14
+ self.yield
15
+ end.tap { |f| schedule(f, value) }
16
+ end
17
+ end
data/test/helper.rb CHANGED
@@ -60,4 +60,12 @@ class UMBaseTest < Minitest::Test
60
60
  def teardown
61
61
  # @machine&.cleanup
62
62
  end
63
+
64
+ def assign_port
65
+ @@port_assign_mutex ||= Mutex.new
66
+ @@port_assign_mutex.synchronize do
67
+ @@port ||= 1024 + rand(60000)
68
+ @@port += 1
69
+ end
70
+ end
63
71
  end