uringmachine 0.3 → 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.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +128 -0
  5. data/TODO.md +14 -0
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_write.rb +56 -0
  8. data/examples/dns_client.rb +12 -0
  9. data/examples/echo_server.rb +18 -40
  10. data/examples/http_server.rb +42 -43
  11. data/examples/inout.rb +19 -0
  12. data/examples/nc.rb +36 -0
  13. data/examples/server_client.rb +64 -0
  14. data/examples/snooze.rb +44 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +24 -23
  17. data/ext/um/um.c +524 -278
  18. data/ext/um/um.h +146 -44
  19. data/ext/um/um_buffer.c +49 -0
  20. data/ext/um/um_class.c +217 -106
  21. data/ext/um/um_const.c +213 -0
  22. data/ext/um/um_ext.c +4 -0
  23. data/ext/um/um_mutex_class.c +47 -0
  24. data/ext/um/um_op.c +86 -114
  25. data/ext/um/um_queue_class.c +58 -0
  26. data/ext/um/um_sync.c +273 -0
  27. data/ext/um/um_utils.c +49 -4
  28. data/lib/uringmachine/dns_resolver.rb +84 -0
  29. data/lib/uringmachine/version.rb +1 -1
  30. data/lib/uringmachine.rb +28 -0
  31. data/supressions/ruby.supp +71 -0
  32. data/test/helper.rb +8 -0
  33. data/test/test_um.rb +685 -46
  34. data/vendor/liburing/.github/workflows/build.yml +29 -1
  35. data/vendor/liburing/.gitignore +6 -0
  36. data/vendor/liburing/CHANGELOG +16 -0
  37. data/vendor/liburing/CONTRIBUTING.md +165 -0
  38. data/vendor/liburing/configure +64 -0
  39. data/vendor/liburing/examples/Makefile +9 -1
  40. data/vendor/liburing/examples/kdigest.c +405 -0
  41. data/vendor/liburing/examples/proxy.c +75 -8
  42. data/vendor/liburing/examples/reg-wait.c +159 -0
  43. data/vendor/liburing/liburing.pc.in +1 -1
  44. data/vendor/liburing/liburing.spec +1 -1
  45. data/vendor/liburing/src/Makefile +16 -2
  46. data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
  47. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  48. data/vendor/liburing/src/include/liburing.h +59 -6
  49. data/vendor/liburing/src/int_flags.h +10 -3
  50. data/vendor/liburing/src/liburing-ffi.map +16 -0
  51. data/vendor/liburing/src/liburing.map +10 -0
  52. data/vendor/liburing/src/queue.c +28 -16
  53. data/vendor/liburing/src/register.c +106 -1
  54. data/vendor/liburing/src/sanitize.c +176 -0
  55. data/vendor/liburing/src/setup.c +47 -19
  56. data/vendor/liburing/src/setup.h +6 -0
  57. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  58. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  59. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  60. data/vendor/liburing/test/917257daa0fe.c +7 -0
  61. data/vendor/liburing/test/Makefile +38 -4
  62. data/vendor/liburing/test/a0908ae19763.c +7 -0
  63. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  64. data/vendor/liburing/test/accept.c +14 -4
  65. data/vendor/liburing/test/b19062a56726.c +7 -0
  66. data/vendor/liburing/test/bind-listen.c +2 -2
  67. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  68. data/vendor/liburing/test/buf-ring.c +2 -0
  69. data/vendor/liburing/test/cmd-discard.c +427 -0
  70. data/vendor/liburing/test/coredump.c +7 -0
  71. data/vendor/liburing/test/cq-overflow.c +13 -1
  72. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  73. data/vendor/liburing/test/defer-taskrun.c +2 -2
  74. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  75. data/vendor/liburing/test/defer.c +2 -2
  76. data/vendor/liburing/test/double-poll-crash.c +1 -1
  77. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  78. data/vendor/liburing/test/eventfd.c +0 -1
  79. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  80. data/vendor/liburing/test/fadvise.c +9 -26
  81. data/vendor/liburing/test/fdinfo.c +9 -1
  82. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  83. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  84. data/vendor/liburing/test/file-register.c +14 -2
  85. data/vendor/liburing/test/file-update.c +1 -1
  86. data/vendor/liburing/test/file-verify.c +27 -16
  87. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  88. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  89. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  90. data/vendor/liburing/test/fsnotify.c +1 -0
  91. data/vendor/liburing/test/futex.c +16 -4
  92. data/vendor/liburing/test/helpers.c +47 -0
  93. data/vendor/liburing/test/helpers.h +6 -0
  94. data/vendor/liburing/test/init-mem.c +5 -3
  95. data/vendor/liburing/test/io-cancel.c +0 -24
  96. data/vendor/liburing/test/io_uring_passthrough.c +4 -0
  97. data/vendor/liburing/test/io_uring_register.c +38 -8
  98. data/vendor/liburing/test/iopoll-leak.c +4 -0
  99. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  100. data/vendor/liburing/test/iopoll.c +3 -3
  101. data/vendor/liburing/test/kallsyms.c +203 -0
  102. data/vendor/liburing/test/link-timeout.c +159 -0
  103. data/vendor/liburing/test/linked-defer-close.c +224 -0
  104. data/vendor/liburing/test/madvise.c +12 -25
  105. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  106. data/vendor/liburing/test/min-timeout.c +0 -25
  107. data/vendor/liburing/test/mkdir.c +6 -0
  108. data/vendor/liburing/test/msg-ring.c +8 -2
  109. data/vendor/liburing/test/napi-test.c +16 -3
  110. data/vendor/liburing/test/no-mmap-inval.c +3 -1
  111. data/vendor/liburing/test/nop.c +44 -0
  112. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  113. data/vendor/liburing/test/open-close.c +40 -0
  114. data/vendor/liburing/test/openat2.c +37 -14
  115. data/vendor/liburing/test/poll-many.c +13 -7
  116. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  117. data/vendor/liburing/test/poll-v-poll.c +6 -3
  118. data/vendor/liburing/test/pollfree.c +148 -0
  119. data/vendor/liburing/test/read-mshot-empty.c +158 -153
  120. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  121. data/vendor/liburing/test/read-mshot.c +282 -27
  122. data/vendor/liburing/test/read-write.c +78 -13
  123. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  124. data/vendor/liburing/test/recv-msgall.c +5 -0
  125. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  126. data/vendor/liburing/test/recvsend_bundle.c +94 -31
  127. data/vendor/liburing/test/reg-fd-only.c +15 -5
  128. data/vendor/liburing/test/reg-wait.c +251 -0
  129. data/vendor/liburing/test/regbuf-clone.c +645 -0
  130. data/vendor/liburing/test/regbuf-merge.c +7 -0
  131. data/vendor/liburing/test/register-restrictions.c +86 -85
  132. data/vendor/liburing/test/rename.c +59 -1
  133. data/vendor/liburing/test/resize-rings.c +643 -0
  134. data/vendor/liburing/test/ringbuf-read.c +5 -0
  135. data/vendor/liburing/test/ringbuf-status.c +5 -1
  136. data/vendor/liburing/test/rsrc_tags.c +1 -1
  137. data/vendor/liburing/test/runtests.sh +16 -1
  138. data/vendor/liburing/test/send-zerocopy.c +59 -0
  139. data/vendor/liburing/test/short-read.c +1 -0
  140. data/vendor/liburing/test/socket.c +43 -0
  141. data/vendor/liburing/test/splice.c +3 -1
  142. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  143. data/vendor/liburing/test/sq-poll-share.c +2 -0
  144. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  145. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  146. data/vendor/liburing/test/sqpoll-sleep.c +40 -33
  147. data/vendor/liburing/test/sqwait.c +136 -0
  148. data/vendor/liburing/test/statx.c +89 -0
  149. data/vendor/liburing/test/stdout.c +2 -0
  150. data/vendor/liburing/test/submit-and-wait.c +1 -25
  151. data/vendor/liburing/test/submit-reuse.c +4 -26
  152. data/vendor/liburing/test/symlink.c +12 -1
  153. data/vendor/liburing/test/sync-cancel.c +56 -22
  154. data/vendor/liburing/test/thread-exit.c +5 -0
  155. data/vendor/liburing/test/timeout-new.c +1 -26
  156. data/vendor/liburing/test/timeout.c +25 -34
  157. data/vendor/liburing/test/unlink.c +94 -1
  158. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  159. data/vendor/liburing/test/waitid.c +62 -8
  160. data/vendor/liburing/test/wq-aff.c +35 -0
  161. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  162. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  163. metadata +37 -6
  164. data/examples/event_loop.rb +0 -69
  165. data/examples/fibers.rb +0 -105
  166. data/examples/http_server_multishot.rb +0 -57
  167. data/examples/http_server_simpler.rb +0 -34
data/ext/um/um_class.c CHANGED
@@ -1,16 +1,23 @@
1
1
  #include "um.h"
2
- #include <sys/mman.h>
2
+ #include <arpa/inet.h>
3
3
 
4
4
  VALUE cUM;
5
5
 
6
6
  static void UM_mark(void *ptr) {
7
- // struct um *machine = ptr;
8
- // um_runqueue_mark(machine);
7
+ struct um *machine = ptr;
8
+ rb_gc_mark_movable(machine->self);
9
+
10
+ um_op_list_mark(machine, machine->transient_head);
11
+ um_op_list_mark(machine, machine->runqueue_head);
9
12
  }
10
13
 
11
14
  static void UM_compact(void *ptr) {
12
- // struct um *machine = ptr;
13
- // um_runqueue_compact(machine);
15
+ struct um *machine = ptr;
16
+ machine->self = rb_gc_location(machine->self);
17
+ machine->poll_fiber = rb_gc_location(machine->poll_fiber);
18
+
19
+ um_op_list_compact(machine, machine->transient_head);
20
+ um_op_list_compact(machine, machine->runqueue_head);
14
21
  }
15
22
 
16
23
  static void UM_free(void *ptr) {
@@ -43,63 +50,19 @@ inline struct um *get_machine(VALUE self) {
43
50
 
44
51
  VALUE UM_initialize(VALUE self) {
45
52
  struct um *machine = RTYPEDDATA_DATA(self);
46
- um_setup(machine);
53
+ um_setup(self, machine);
47
54
  return self;
48
55
  }
49
56
 
50
57
  VALUE UM_setup_buffer_ring(VALUE self, VALUE size, VALUE count) {
51
58
  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);
59
+ int bgid = um_setup_buffer_ring(machine, NUM2UINT(size), NUM2UINT(count));
60
+ return INT2NUM(bgid);
98
61
  }
99
62
 
100
63
  VALUE UM_pending_count(VALUE self) {
101
64
  struct um *machine = get_machine(self);
102
- return INT2FIX(machine->pending_count);
65
+ return INT2NUM(machine->pending_count);
103
66
  }
104
67
 
105
68
  VALUE UM_snooze(VALUE self) {
@@ -119,12 +82,6 @@ VALUE UM_schedule(VALUE self, VALUE fiber, VALUE value) {
119
82
  return self;
120
83
  }
121
84
 
122
- VALUE UM_interrupt(VALUE self, VALUE fiber, VALUE value) {
123
- struct um *machine = get_machine(self);
124
- um_interrupt(machine, fiber, value);
125
- return self;
126
- }
127
-
128
85
  VALUE UM_timeout(VALUE self, VALUE interval, VALUE class) {
129
86
  struct um *machine = get_machine(self);
130
87
  return um_timeout(machine, interval, class);
@@ -132,8 +89,7 @@ VALUE UM_timeout(VALUE self, VALUE interval, VALUE class) {
132
89
 
133
90
  VALUE UM_sleep(VALUE self, VALUE duration) {
134
91
  struct um *machine = get_machine(self);
135
- um_sleep(machine, NUM2DBL(duration));
136
- return duration;
92
+ return um_sleep(machine, NUM2DBL(duration));
137
93
  }
138
94
 
139
95
  VALUE UM_read(int argc, VALUE *argv, VALUE self) {
@@ -151,8 +107,12 @@ VALUE UM_read(int argc, VALUE *argv, VALUE self) {
151
107
  }
152
108
 
153
109
  VALUE UM_read_each(VALUE self, VALUE fd, VALUE bgid) {
110
+ #ifdef HAVE_IO_URING_PREP_READ_MULTISHOT
154
111
  struct um *machine = get_machine(self);
155
112
  return um_read_each(machine, NUM2INT(fd), NUM2INT(bgid));
113
+ #else
114
+ rb_raise(rb_eRuntimeError, "Not supported by kernel");
115
+ #endif
156
116
  }
157
117
 
158
118
  VALUE UM_write(int argc, VALUE *argv, VALUE self) {
@@ -166,6 +126,11 @@ VALUE UM_write(int argc, VALUE *argv, VALUE self) {
166
126
  return um_write(machine, NUM2INT(fd), buffer, bytes);
167
127
  }
168
128
 
129
+ VALUE UM_close(VALUE self, VALUE fd) {
130
+ struct um *machine = get_machine(self);
131
+ return um_close(machine, NUM2INT(fd));
132
+ }
133
+
169
134
  VALUE UM_accept(VALUE self, VALUE fd) {
170
135
  struct um *machine = get_machine(self);
171
136
  return um_accept(machine, NUM2INT(fd));
@@ -176,6 +141,166 @@ VALUE UM_accept_each(VALUE self, VALUE fd) {
176
141
  return um_accept_each(machine, NUM2INT(fd));
177
142
  }
178
143
 
144
+ VALUE UM_socket(VALUE self, VALUE domain, VALUE type, VALUE protocol, VALUE flags) {
145
+ struct um *machine = get_machine(self);
146
+ return um_socket(machine, NUM2INT(domain), NUM2INT(type), NUM2INT(protocol), NUM2UINT(flags));
147
+ }
148
+
149
+ VALUE UM_connect(VALUE self, VALUE fd, VALUE host, VALUE port) {
150
+ struct um *machine = get_machine(self);
151
+
152
+ struct sockaddr_in addr;
153
+ memset(&addr, 0, sizeof(addr));
154
+ addr.sin_family = AF_INET;
155
+ addr.sin_addr.s_addr = inet_addr(StringValueCStr(host));
156
+ addr.sin_port = htons(NUM2INT(port));
157
+
158
+ return um_connect(machine, NUM2INT(fd), (struct sockaddr *)&addr, sizeof(addr));
159
+ }
160
+
161
+ VALUE UM_send(VALUE self, VALUE fd, VALUE buffer, VALUE len, VALUE flags) {
162
+ struct um *machine = get_machine(self);
163
+ return um_send(machine, NUM2INT(fd), buffer, NUM2INT(len), NUM2INT(flags));
164
+ }
165
+
166
+ VALUE UM_recv(VALUE self, VALUE fd, VALUE buffer, VALUE maxlen, VALUE flags) {
167
+ struct um *machine = get_machine(self);
168
+ return um_recv(machine, NUM2INT(fd), buffer, NUM2INT(maxlen), NUM2INT(flags));
169
+ }
170
+
171
+ VALUE UM_recv_each(VALUE self, VALUE fd, VALUE bgid, VALUE flags) {
172
+ struct um *machine = get_machine(self);
173
+ return um_recv_each(machine, NUM2INT(fd), NUM2INT(bgid), NUM2INT(flags));
174
+ }
175
+
176
+ VALUE UM_bind(VALUE self, VALUE fd, VALUE host, VALUE port) {
177
+ struct sockaddr_in addr;
178
+ memset(&addr, 0, sizeof(addr));
179
+ addr.sin_family = AF_INET;
180
+ addr.sin_addr.s_addr = inet_addr(StringValueCStr(host));
181
+ addr.sin_port = htons(NUM2INT(port));
182
+
183
+ #ifdef HAVE_IO_URING_PREP_BIND
184
+ struct um *machine = get_machine(self);
185
+ return um_bind(machine, NUM2INT(fd), (struct sockaddr *)&addr, sizeof(addr));
186
+ #else
187
+ int res = bind(NUM2INT(fd), (struct sockaddr *)&addr, sizeof(addr));
188
+ if (res)
189
+ rb_syserr_fail(errno, strerror(errno));
190
+ return INT2NUM(0);
191
+ #endif
192
+ }
193
+
194
+ VALUE UM_listen(VALUE self, VALUE fd, VALUE backlog) {
195
+ #ifdef HAVE_IO_URING_PREP_LISTEN
196
+ struct um *machine = get_machine(self);
197
+ return um_listen(machine, NUM2INT(fd), NUM2INT(backlog));
198
+ #else
199
+ int res = listen(NUM2INT(fd), NUM2INT(backlog));
200
+ if (res)
201
+ rb_syserr_fail(errno, strerror(errno));
202
+ return INT2NUM(0);
203
+ #endif
204
+ }
205
+
206
+ static inline int numeric_value(VALUE value) {
207
+ switch (TYPE(value)) {
208
+ case T_TRUE:
209
+ return 1;
210
+ case T_FALSE:
211
+ return 0;
212
+ default:
213
+ return NUM2INT(value);
214
+ }
215
+ }
216
+
217
+ VALUE UM_getsockopt(VALUE self, VALUE fd, VALUE level, VALUE opt) {
218
+ struct um *machine = get_machine(self);
219
+ return um_getsockopt(machine, NUM2INT(fd), NUM2INT(level), NUM2INT(opt));
220
+ }
221
+
222
+ VALUE UM_setsockopt(VALUE self, VALUE fd, VALUE level, VALUE opt, VALUE value) {
223
+ struct um *machine = get_machine(self);
224
+ return um_setsockopt(machine, NUM2INT(fd), NUM2INT(level), NUM2INT(opt), numeric_value(value));
225
+ }
226
+
227
+ #ifdef HAVE_IO_URING_PREP_FUTEX
228
+
229
+ VALUE UM_mutex_synchronize(VALUE self, VALUE mutex) {
230
+ struct um *machine = get_machine(self);
231
+ struct um_mutex *mutex_data = Mutex_data(mutex);
232
+ return um_mutex_synchronize(machine, &mutex_data->state);
233
+ }
234
+
235
+ VALUE UM_queue_push(VALUE self, VALUE queue, VALUE value) {
236
+ struct um *machine = get_machine(self);
237
+ struct um_queue *que = Queue_data(queue);
238
+ return um_queue_push(machine, que, value);
239
+ }
240
+
241
+ VALUE UM_queue_pop(VALUE self, VALUE queue) {
242
+ struct um *machine = get_machine(self);
243
+ struct um_queue *que = Queue_data(queue);
244
+ return um_queue_pop(machine, que);
245
+ }
246
+
247
+ VALUE UM_queue_unshift(VALUE self, VALUE queue, VALUE value) {
248
+ struct um *machine = get_machine(self);
249
+ struct um_queue *que = Queue_data(queue);
250
+ return um_queue_unshift(machine, que, value);
251
+ }
252
+
253
+ VALUE UM_queue_shift(VALUE self, VALUE queue) {
254
+ struct um *machine = get_machine(self);
255
+ struct um_queue *que = Queue_data(queue);
256
+ return um_queue_shift(machine, que);
257
+ }
258
+
259
+ #endif
260
+
261
+ struct um_open_ctx {
262
+ VALUE self;
263
+ VALUE fd;
264
+ };
265
+
266
+ VALUE UM_open_ensure(VALUE arg) {
267
+ struct um_open_ctx *ctx = (struct um_open_ctx *)arg;
268
+ UM_close(ctx->self, ctx->fd);
269
+ return ctx->self;
270
+ }
271
+
272
+ VALUE UM_open(VALUE self, VALUE pathname, VALUE flags) {
273
+ struct um *machine = get_machine(self);
274
+ // TODO: take optional perm (mode) arg
275
+ VALUE fd = um_open(machine, pathname, NUM2INT(flags), 0666);
276
+ if (rb_block_given_p()) {
277
+ struct um_open_ctx ctx = { self, fd };
278
+ return rb_ensure(rb_yield, fd, UM_open_ensure, (VALUE)&ctx);
279
+ }
280
+ else
281
+ return fd;
282
+ }
283
+
284
+ VALUE UM_waitpid(VALUE self, VALUE pid, VALUE options) {
285
+ struct um *machine = get_machine(self);
286
+ return um_waitpid(machine, NUM2INT(pid), NUM2INT(options));
287
+ }
288
+
289
+ VALUE UM_pipe(VALUE self) {
290
+ int fds[2];
291
+ int ret = pipe(fds);
292
+ if (ret) {
293
+ int e = errno;
294
+ rb_syserr_fail(e, strerror(e));
295
+ }
296
+
297
+ return rb_ary_new_from_args(2, INT2NUM(fds[0]), INT2NUM(fds[1]));
298
+ }
299
+
300
+ VALUE UM_kernel_version(VALUE self) {
301
+ return INT2NUM(UM_KERNEL_VERSION);
302
+ }
303
+
179
304
  void Init_UM(void) {
180
305
  rb_ext_ractor_safe(true);
181
306
 
@@ -183,60 +308,46 @@ void Init_UM(void) {
183
308
  rb_define_alloc_func(cUM, UM_allocate);
184
309
 
185
310
  rb_define_method(cUM, "initialize", UM_initialize, 0);
186
- rb_define_method(cUM, "setup_buffer_ring", UM_setup_buffer_ring, 2);
187
311
  rb_define_method(cUM, "pending_count", UM_pending_count, 0);
312
+ rb_define_method(cUM, "setup_buffer_ring", UM_setup_buffer_ring, 2);
313
+
314
+ rb_define_singleton_method(cUM, "pipe", UM_pipe, 0);
315
+ rb_define_singleton_method(cUM, "kernel_version", UM_kernel_version, 0);
316
+
188
317
 
189
- rb_define_method(cUM, "snooze", UM_snooze, 0);
190
- rb_define_method(cUM, "yield", UM_yield, 0);
191
318
  rb_define_method(cUM, "schedule", UM_schedule, 2);
192
- rb_define_method(cUM, "interrupt", UM_interrupt, 2);
319
+ rb_define_method(cUM, "snooze", UM_snooze, 0);
193
320
  rb_define_method(cUM, "timeout", UM_timeout, 2);
321
+ rb_define_method(cUM, "yield", UM_yield, 0);
194
322
 
195
- rb_define_method(cUM, "sleep", UM_sleep, 1);
323
+ rb_define_method(cUM, "close", UM_close, 1);
324
+ rb_define_method(cUM, "open", UM_open, 2);
196
325
  rb_define_method(cUM, "read", UM_read, -1);
197
326
  rb_define_method(cUM, "read_each", UM_read_each, 2);
327
+ rb_define_method(cUM, "sleep", UM_sleep, 1);
198
328
  rb_define_method(cUM, "write", UM_write, -1);
199
329
 
330
+ rb_define_method(cUM, "waitpid", UM_waitpid, 2);
331
+
200
332
  rb_define_method(cUM, "accept", UM_accept, 1);
201
333
  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");
334
+ rb_define_method(cUM, "bind", UM_bind, 3);
335
+ rb_define_method(cUM, "connect", UM_connect, 3);
336
+ rb_define_method(cUM, "getsockopt", UM_getsockopt, 3);
337
+ rb_define_method(cUM, "listen", UM_listen, 2);
338
+ rb_define_method(cUM, "recv", UM_recv, 4);
339
+ rb_define_method(cUM, "recv_each", UM_recv_each, 3);
340
+ rb_define_method(cUM, "send", UM_send, 4);
341
+ rb_define_method(cUM, "setsockopt", UM_setsockopt, 4);
342
+ rb_define_method(cUM, "socket", UM_socket, 4);
343
+
344
+ #ifdef HAVE_IO_URING_PREP_FUTEX
345
+ rb_define_method(cUM, "pop", UM_queue_pop, 1);
346
+ rb_define_method(cUM, "push", UM_queue_push, 2);
347
+ rb_define_method(cUM, "shift", UM_queue_shift, 1);
348
+ rb_define_method(cUM, "synchronize", UM_mutex_synchronize, 1);
349
+ rb_define_method(cUM, "unshift", UM_queue_unshift, 2);
350
+ #endif
351
+
352
+ um_define_net_constants(cUM);
242
353
  }
data/ext/um/um_const.c ADDED
@@ -0,0 +1,213 @@
1
+ #include "ruby.h"
2
+
3
+ #include <fcntl.h>
4
+ #include <sys/wait.h>
5
+
6
+ #include <arpa/inet.h>
7
+ #include <sys/types.h>
8
+ #include <sys/socket.h>
9
+ #include <netinet/in.h>
10
+ #include <netinet/tcp.h>
11
+ #include <netinet/udp.h>
12
+ #include <netdb.h>
13
+ #include <net/if.h>
14
+
15
+
16
+ #define DEF_CONST_INT(mod, v) rb_define_const(mod, #v, INT2NUM(v))
17
+
18
+ void um_define_net_constants(VALUE mod) {
19
+ DEF_CONST_INT(mod, O_APPEND);
20
+ DEF_CONST_INT(mod, O_CLOEXEC);
21
+ DEF_CONST_INT(mod, O_CREAT);
22
+ DEF_CONST_INT(mod, O_DIRECT);
23
+ DEF_CONST_INT(mod, O_DIRECTORY);
24
+ DEF_CONST_INT(mod, O_DSYNC);
25
+ DEF_CONST_INT(mod, O_EXCL);
26
+ DEF_CONST_INT(mod, O_NOCTTY);
27
+ DEF_CONST_INT(mod, O_NOFOLLOW);
28
+ DEF_CONST_INT(mod, O_PATH);
29
+ DEF_CONST_INT(mod, O_RDONLY);
30
+ DEF_CONST_INT(mod, O_RDWR);
31
+ DEF_CONST_INT(mod, O_SYNC);
32
+ DEF_CONST_INT(mod, O_TMPFILE);
33
+ DEF_CONST_INT(mod, O_TRUNC);
34
+ DEF_CONST_INT(mod, O_WRONLY);
35
+
36
+ DEF_CONST_INT(mod, WNOHANG);
37
+ DEF_CONST_INT(mod, WUNTRACED);
38
+ DEF_CONST_INT(mod, WCONTINUED);
39
+ DEF_CONST_INT(mod, WEXITED);
40
+ DEF_CONST_INT(mod, WSTOPPED);
41
+ DEF_CONST_INT(mod, WCONTINUED);
42
+ DEF_CONST_INT(mod, WNOWAIT);
43
+
44
+ DEF_CONST_INT(mod, SOCK_STREAM);
45
+ DEF_CONST_INT(mod, SOCK_DGRAM);
46
+ DEF_CONST_INT(mod, SOCK_RAW);
47
+ DEF_CONST_INT(mod, SOCK_RDM);
48
+ DEF_CONST_INT(mod, SOCK_SEQPACKET);
49
+ DEF_CONST_INT(mod, SOCK_PACKET);
50
+ DEF_CONST_INT(mod, SOCK_CLOEXEC);
51
+
52
+ DEF_CONST_INT(mod, AF_UNSPEC);
53
+ DEF_CONST_INT(mod, PF_UNSPEC);
54
+ DEF_CONST_INT(mod, AF_INET);
55
+ DEF_CONST_INT(mod, PF_INET);
56
+ DEF_CONST_INT(mod, AF_INET6);
57
+ DEF_CONST_INT(mod, PF_INET6);
58
+ DEF_CONST_INT(mod, AF_UNIX);
59
+ DEF_CONST_INT(mod, PF_UNIX);
60
+ DEF_CONST_INT(mod, AF_LOCAL);
61
+ DEF_CONST_INT(mod, PF_LOCAL);
62
+ DEF_CONST_INT(mod, AF_ROUTE);
63
+ DEF_CONST_INT(mod, PF_ROUTE);
64
+ DEF_CONST_INT(mod, AF_MAX);
65
+ DEF_CONST_INT(mod, PF_MAX);
66
+
67
+ DEF_CONST_INT(mod, MSG_OOB);
68
+ DEF_CONST_INT(mod, MSG_PEEK);
69
+ DEF_CONST_INT(mod, MSG_DONTROUTE);
70
+ DEF_CONST_INT(mod, MSG_WAITALL);
71
+ DEF_CONST_INT(mod, MSG_DONTWAIT);
72
+ DEF_CONST_INT(mod, MSG_MORE);
73
+
74
+ DEF_CONST_INT(mod, SOL_SOCKET);
75
+ DEF_CONST_INT(mod, SOL_IP);
76
+
77
+ DEF_CONST_INT(mod, IPPROTO_IP);
78
+ DEF_CONST_INT(mod, IPPROTO_ICMP);
79
+ DEF_CONST_INT(mod, IPPROTO_IGMP);
80
+ DEF_CONST_INT(mod, IPPROTO_TCP);
81
+ DEF_CONST_INT(mod, IPPROTO_EGP);
82
+ DEF_CONST_INT(mod, IPPROTO_PUP);
83
+ DEF_CONST_INT(mod, IPPROTO_UDP);
84
+ DEF_CONST_INT(mod, IPPROTO_IDP);
85
+ DEF_CONST_INT(mod, IPPROTO_IPV6);
86
+ DEF_CONST_INT(mod, IPPROTO_NONE);
87
+ DEF_CONST_INT(mod, IPPROTO_ROUTING);
88
+ DEF_CONST_INT(mod, IPPROTO_RAW);
89
+ DEF_CONST_INT(mod, IPPROTO_MAX);
90
+
91
+ DEF_CONST_INT(mod, INADDR_ANY);
92
+ DEF_CONST_INT(mod, INADDR_BROADCAST);
93
+ DEF_CONST_INT(mod, INADDR_LOOPBACK);
94
+ DEF_CONST_INT(mod, INADDR_NONE);
95
+
96
+ DEF_CONST_INT(mod, IP_OPTIONS);
97
+ DEF_CONST_INT(mod, IP_HDRINCL);
98
+ DEF_CONST_INT(mod, IP_TOS);
99
+ DEF_CONST_INT(mod, IP_TTL);
100
+ DEF_CONST_INT(mod, IP_RECVOPTS);
101
+ DEF_CONST_INT(mod, IP_MINTTL);
102
+ DEF_CONST_INT(mod, IP_RECVTTL);
103
+
104
+ DEF_CONST_INT(mod, SO_DEBUG);
105
+ DEF_CONST_INT(mod, SO_REUSEADDR);
106
+ DEF_CONST_INT(mod, SO_REUSEPORT);
107
+ DEF_CONST_INT(mod, SO_TYPE);
108
+ DEF_CONST_INT(mod, SO_ERROR);
109
+ DEF_CONST_INT(mod, SO_DONTROUTE);
110
+ DEF_CONST_INT(mod, SO_BROADCAST);
111
+ DEF_CONST_INT(mod, SO_SNDBUF);
112
+ DEF_CONST_INT(mod, SO_RCVBUF);
113
+ DEF_CONST_INT(mod, SO_SNDBUFFORCE);
114
+ DEF_CONST_INT(mod, SO_RCVBUFFORCE);
115
+ DEF_CONST_INT(mod, SO_KEEPALIVE);
116
+ DEF_CONST_INT(mod, SO_OOBINLINE);
117
+ DEF_CONST_INT(mod, SO_PRIORITY);
118
+ DEF_CONST_INT(mod, SO_LINGER);
119
+ DEF_CONST_INT(mod, SO_PASSCRED);
120
+ DEF_CONST_INT(mod, SO_PEERCRED);
121
+ DEF_CONST_INT(mod, SO_RCVLOWAT);
122
+ DEF_CONST_INT(mod, SO_SNDLOWAT);
123
+ DEF_CONST_INT(mod, SO_RCVTIMEO);
124
+ DEF_CONST_INT(mod, SO_SNDTIMEO);
125
+ DEF_CONST_INT(mod, SO_ACCEPTCONN);
126
+ DEF_CONST_INT(mod, SO_PEERNAME);
127
+ DEF_CONST_INT(mod, SO_TIMESTAMP);
128
+ DEF_CONST_INT(mod, SO_MARK);
129
+ DEF_CONST_INT(mod, SO_PROTOCOL);
130
+ DEF_CONST_INT(mod, SO_DOMAIN);
131
+ DEF_CONST_INT(mod, SO_PEEK_OFF);
132
+ DEF_CONST_INT(mod, SO_BUSY_POLL);
133
+
134
+ DEF_CONST_INT(mod, TCP_NODELAY);
135
+ DEF_CONST_INT(mod, TCP_MAXSEG);
136
+ DEF_CONST_INT(mod, TCP_CORK);
137
+ DEF_CONST_INT(mod, TCP_DEFER_ACCEPT);
138
+ DEF_CONST_INT(mod, TCP_INFO);
139
+ DEF_CONST_INT(mod, TCP_KEEPCNT);
140
+ DEF_CONST_INT(mod, TCP_KEEPIDLE);
141
+ DEF_CONST_INT(mod, TCP_KEEPINTVL);
142
+ DEF_CONST_INT(mod, TCP_LINGER2);
143
+ DEF_CONST_INT(mod, TCP_MD5SIG);
144
+ DEF_CONST_INT(mod, TCP_QUICKACK);
145
+ DEF_CONST_INT(mod, TCP_SYNCNT);
146
+ DEF_CONST_INT(mod, TCP_WINDOW_CLAMP);
147
+ DEF_CONST_INT(mod, TCP_FASTOPEN);
148
+ DEF_CONST_INT(mod, TCP_CONGESTION);
149
+ DEF_CONST_INT(mod, TCP_COOKIE_TRANSACTIONS);
150
+ DEF_CONST_INT(mod, TCP_QUEUE_SEQ);
151
+ DEF_CONST_INT(mod, TCP_REPAIR);
152
+ DEF_CONST_INT(mod, TCP_REPAIR_OPTIONS);
153
+ DEF_CONST_INT(mod, TCP_REPAIR_QUEUE);
154
+ DEF_CONST_INT(mod, TCP_THIN_LINEAR_TIMEOUTS);
155
+ DEF_CONST_INT(mod, TCP_TIMESTAMP);
156
+ DEF_CONST_INT(mod, TCP_USER_TIMEOUT);
157
+
158
+ DEF_CONST_INT(mod, UDP_CORK);
159
+
160
+ DEF_CONST_INT(mod, AI_PASSIVE);
161
+ DEF_CONST_INT(mod, AI_CANONNAME);
162
+ DEF_CONST_INT(mod, AI_NUMERICHOST);
163
+ DEF_CONST_INT(mod, AI_NUMERICSERV);
164
+ DEF_CONST_INT(mod, AI_ALL);
165
+ DEF_CONST_INT(mod, AI_ADDRCONFIG);
166
+ DEF_CONST_INT(mod, AI_V4MAPPED);
167
+
168
+ DEF_CONST_INT(mod, NI_MAXHOST);
169
+ DEF_CONST_INT(mod, NI_MAXSERV);
170
+ DEF_CONST_INT(mod, NI_NOFQDN);
171
+ DEF_CONST_INT(mod, NI_NUMERICHOST);
172
+ DEF_CONST_INT(mod, NI_NAMEREQD);
173
+ DEF_CONST_INT(mod, NI_NUMERICSERV);
174
+ DEF_CONST_INT(mod, NI_DGRAM);
175
+
176
+ DEF_CONST_INT(mod, SHUT_RD);
177
+ DEF_CONST_INT(mod, SHUT_WR);
178
+ DEF_CONST_INT(mod, SHUT_RDWR);
179
+
180
+ DEF_CONST_INT(mod, IPV6_JOIN_GROUP);
181
+ DEF_CONST_INT(mod, IPV6_LEAVE_GROUP);
182
+ DEF_CONST_INT(mod, IPV6_MULTICAST_HOPS);
183
+ DEF_CONST_INT(mod, IPV6_MULTICAST_IF);
184
+ DEF_CONST_INT(mod, IPV6_MULTICAST_LOOP);
185
+ DEF_CONST_INT(mod, IPV6_UNICAST_HOPS);
186
+ DEF_CONST_INT(mod, IPV6_V6ONLY);
187
+ DEF_CONST_INT(mod, IPV6_CHECKSUM);
188
+ DEF_CONST_INT(mod, IPV6_DONTFRAG);
189
+ DEF_CONST_INT(mod, IPV6_DSTOPTS);
190
+ DEF_CONST_INT(mod, IPV6_HOPLIMIT);
191
+ DEF_CONST_INT(mod, IPV6_HOPOPTS);
192
+ DEF_CONST_INT(mod, IPV6_NEXTHOP);
193
+ DEF_CONST_INT(mod, IPV6_PATHMTU);
194
+ DEF_CONST_INT(mod, IPV6_PKTINFO);
195
+ DEF_CONST_INT(mod, IPV6_RECVDSTOPTS);
196
+ DEF_CONST_INT(mod, IPV6_RECVHOPLIMIT);
197
+ DEF_CONST_INT(mod, IPV6_RECVHOPOPTS);
198
+ DEF_CONST_INT(mod, IPV6_RECVPKTINFO);
199
+ DEF_CONST_INT(mod, IPV6_RECVRTHDR);
200
+ DEF_CONST_INT(mod, IPV6_RECVTCLASS);
201
+ DEF_CONST_INT(mod, IPV6_RTHDR);
202
+ DEF_CONST_INT(mod, IPV6_RTHDRDSTOPTS);
203
+ DEF_CONST_INT(mod, IPV6_RTHDR_TYPE_0);
204
+ DEF_CONST_INT(mod, IPV6_RECVPATHMTU);
205
+ DEF_CONST_INT(mod, IPV6_TCLASS);
206
+
207
+ DEF_CONST_INT(mod, INET_ADDRSTRLEN);
208
+ DEF_CONST_INT(mod, INET6_ADDRSTRLEN);
209
+
210
+ DEF_CONST_INT(mod, IF_NAMESIZE);
211
+
212
+ DEF_CONST_INT(mod, SOMAXCONN);
213
+ }
data/ext/um/um_ext.c CHANGED
@@ -1,5 +1,9 @@
1
1
  void Init_UM();
2
+ void Init_Mutex();
3
+ void Init_Queue();
2
4
 
3
5
  void Init_um_ext(void) {
4
6
  Init_UM();
7
+ Init_Mutex();
8
+ Init_Queue();
5
9
  }
@@ -0,0 +1,47 @@
1
+ #include "um.h"
2
+ #include <stdlib.h>
3
+
4
+ VALUE cMutex;
5
+
6
+ static void Mutex_mark(void *ptr) {
7
+ struct um_mutex *mutex = ptr;
8
+ rb_gc_mark_movable(mutex->self);
9
+ }
10
+
11
+ static void Mutex_compact(void *ptr) {
12
+ struct um_mutex *mutex = ptr;
13
+ mutex->self = rb_gc_location(mutex->self);
14
+ }
15
+
16
+ static size_t Mutex_size(const void *ptr) {
17
+ return sizeof(struct um_mutex);
18
+ }
19
+
20
+ static const rb_data_type_t Mutex_type = {
21
+ "UringMachineMutex",
22
+ {Mutex_mark, free, Mutex_size, Mutex_compact},
23
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
24
+ };
25
+
26
+ static VALUE Mutex_allocate(VALUE klass) {
27
+ struct um_mutex *mutex = malloc(sizeof(struct um_mutex));
28
+ return TypedData_Wrap_Struct(klass, &Mutex_type, mutex);
29
+ }
30
+
31
+ inline struct um_mutex *Mutex_data(VALUE self) {
32
+ return RTYPEDDATA_DATA(self);
33
+ }
34
+
35
+ VALUE Mutex_initialize(VALUE self) {
36
+ struct um_mutex *mutex = Mutex_data(self);
37
+ mutex->self = self;
38
+ um_mutex_init(mutex);
39
+ return self;
40
+ }
41
+
42
+ void Init_Mutex(void) {
43
+ cMutex = rb_define_class_under(cUM, "Mutex", rb_cObject);
44
+ rb_define_alloc_func(cMutex, Mutex_allocate);
45
+
46
+ rb_define_method(cMutex, "initialize", Mutex_initialize, 0);
47
+ }