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.h CHANGED
@@ -20,38 +20,64 @@
20
20
  #define likely(cond) __builtin_expect(!!(cond), 1)
21
21
  #endif
22
22
 
23
- enum op_state {
24
- OP_initial, // initial state
25
- OP_submitted, // op has been submitted (SQE prepared)
26
- OP_completed, // op has been completed (CQE processed)
27
- OP_cancelled, // op is cancelled (after CQE is processed)
28
- OP_abandonned, // op is abandonned by fiber (before CQE is processed)
29
- OP_schedule, // the corresponding fiber is scheduled
23
+ enum op_kind {
24
+ OP_TIMEOUT,
25
+ OP_SCHEDULE,
26
+
27
+ OP_SLEEP,
28
+ OP_READ,
29
+ OP_WRITE,
30
+ OP_CLOSE,
31
+ OP_ACCEPT,
32
+ OP_RECV,
33
+ OP_SEND,
34
+ OP_SOCKET,
35
+ OP_CONNECT,
36
+ OP_BIND,
37
+ OP_LISTEN,
38
+ OP_GETSOCKOPT,
39
+ OP_SETSOCKOPT,
40
+
41
+ OP_FUTEX_WAIT,
42
+ OP_FUTEX_WAKE,
43
+
44
+ OP_ACCEPT_MULTISHOT,
45
+ OP_READ_MULTISHOT,
46
+ OP_RECV_MULTISHOT
30
47
  };
31
48
 
32
- struct um_result_entry {
33
- struct um_result_entry *next;
49
+ #define OP_F_COMPLETED (1U << 0)
50
+ #define OP_F_TRANSIENT (1U << 1)
51
+ #define OP_F_IGNORE_CANCELED (1U << 2)
52
+ #define OP_F_MULTISHOT (1U << 3)
34
53
 
35
- int result;
36
- int flags;
54
+ struct um_op_result {
55
+ __s32 res;
56
+ __u32 flags;
57
+ struct um_op_result *next;
37
58
  };
38
59
 
39
60
  struct um_op {
40
- enum op_state state;
41
61
  struct um_op *prev;
42
62
  struct um_op *next;
43
63
 
44
- // linked list for multishot results
45
- struct um_result_entry *results_head;
46
- struct um_result_entry *results_tail;
47
-
64
+ enum op_kind kind;
65
+ unsigned flags;
66
+
48
67
  VALUE fiber;
49
- VALUE resume_value;
50
- int is_multishot;
51
- struct __kernel_timespec ts;
52
-
53
- int cqe_result;
54
- int cqe_flags;
68
+ VALUE value;
69
+
70
+ struct um_op_result result;
71
+ struct um_op_result *multishot_result_tail;
72
+ unsigned multishot_result_count;
73
+
74
+ struct __kernel_timespec ts; // used for timeout operation
75
+ };
76
+
77
+ struct um_buffer {
78
+ struct um_buffer *next;
79
+ void *ptr;
80
+ long len;
55
81
  };
56
82
 
57
83
  struct buf_ring_descriptor {
@@ -59,17 +85,17 @@ struct buf_ring_descriptor {
59
85
  size_t br_size;
60
86
  unsigned buf_count;
61
87
  unsigned buf_size;
62
- char *buf_base;
88
+ unsigned buf_mask;
89
+ void *buf_base;
63
90
  };
64
91
 
65
92
  #define BUFFER_RING_MAX_COUNT 10
66
93
 
67
94
  struct um {
68
- struct um_op *op_freelist;
69
- struct um_result_entry *result_freelist;
95
+ VALUE self;
96
+ VALUE poll_fiber;
70
97
 
71
- struct um_op *runqueue_head;
72
- struct um_op *runqueue_tail;
98
+ struct um_buffer *buffer_freelist;
73
99
 
74
100
  struct io_uring ring;
75
101
 
@@ -79,47 +105,123 @@ struct um {
79
105
 
80
106
  struct buf_ring_descriptor buffer_rings[BUFFER_RING_MAX_COUNT];
81
107
  unsigned int buffer_ring_count;
108
+
109
+ struct um_op *transient_head;
110
+ struct um_op *runqueue_head;
111
+ struct um_op *runqueue_tail;
112
+
113
+ struct um_op *op_freelist;
114
+ struct um_op_result *result_freelist;
115
+ };
116
+
117
+ struct um_mutex {
118
+ VALUE self;
119
+ uint32_t state;
120
+ };
121
+
122
+ struct um_queue_entry {
123
+ struct um_queue_entry *prev;
124
+ struct um_queue_entry *next;
125
+ VALUE value;
126
+ };
127
+
128
+ struct um_queue {
129
+ VALUE self;
130
+
131
+ struct um_queue_entry *head;
132
+ struct um_queue_entry *tail;
133
+ struct um_queue_entry *free_head;
134
+
135
+ uint32_t num_waiters;
136
+ uint32_t state;
137
+ uint32_t count;
82
138
  };
83
139
 
84
140
  extern VALUE cUM;
141
+ extern VALUE cMutex;
142
+ extern VALUE cQueue;
85
143
 
86
- void um_setup(struct um *machine);
144
+ void um_setup(VALUE self, struct um *machine);
87
145
  void um_teardown(struct um *machine);
88
- void um_free_op_linked_list(struct um *machine, struct um_op *op);
89
- void um_free_result_linked_list(struct um *machine, struct um_result_entry *entry);
146
+
147
+ struct um_op *um_op_alloc(struct um *machine);
148
+ void um_op_free(struct um *machine, struct um_op *op);
149
+ void um_op_clear(struct um *machine, struct um_op *op);
150
+ void um_op_transient_add(struct um *machine, struct um_op *op);
151
+ void um_op_transient_remove(struct um *machine, struct um_op *op);
152
+ void um_op_list_mark(struct um *machine, struct um_op *head);
153
+ void um_op_list_compact(struct um *machine, struct um_op *head);
154
+
155
+ void um_op_multishot_results_push(struct um *machine, struct um_op *op, __s32 res, __u32 flags);
156
+ void um_op_multishot_results_clear(struct um *machine, struct um_op *op);
157
+
158
+ void um_runqueue_push(struct um *machine, struct um_op *op);
159
+ struct um_op *um_runqueue_shift(struct um *machine);
160
+
161
+ struct um_buffer *um_buffer_checkout(struct um *machine, int len);
162
+ void um_buffer_checkin(struct um *machine, struct um_buffer *buffer);
163
+ void um_free_buffer_linked_list(struct um *machine);
90
164
 
91
165
  struct __kernel_timespec um_double_to_timespec(double value);
92
166
  int um_value_is_exception_p(VALUE v);
93
167
  VALUE um_raise_exception(VALUE v);
94
- void um_raise_on_system_error(int result);
95
168
 
169
+ #define raise_if_exception(v) (um_value_is_exception_p(v) ? um_raise_exception(v) : v)
170
+
171
+ void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind);
172
+ void um_raise_on_error_result(int result);
96
173
  void * um_prepare_read_buffer(VALUE buffer, unsigned len, int ofs);
97
- void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset, int result, int flags);
98
- VALUE get_string_from_buffer_ring(struct um *machine, int bgid, int result, int flags);
174
+ void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset, __s32 result, __u32 flags);
175
+ int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count);
176
+ VALUE um_get_string_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags);
177
+
178
+ struct io_uring_sqe *um_get_sqe(struct um *machine, struct um_op *op);
99
179
 
100
180
  VALUE um_fiber_switch(struct um *machine);
101
181
  VALUE um_await(struct um *machine);
182
+ void um_cancel_and_wait(struct um *machine, struct um_op *op);
183
+ int um_check_completion(struct um *machine, struct um_op *op);
102
184
 
103
- void um_op_checkin(struct um *machine, struct um_op *op);
104
- struct um_op* um_op_checkout(struct um *machine);
105
- void um_op_result_push(struct um *machine, struct um_op *op, int result, int flags);
106
- int um_op_result_shift(struct um *machine, struct um_op *op, int *result, int *flags);
107
-
108
- struct um_op *um_runqueue_find_by_fiber(struct um *machine, VALUE fiber);
109
- void um_runqueue_push(struct um *machine, struct um_op *op);
110
- struct um_op *um_runqueue_shift(struct um *machine);
111
- void um_runqueue_unshift(struct um *machine, struct um_op *op);
185
+ #define um_op_completed_p(op) ((op)->flags & OP_F_COMPLETED)
112
186
 
113
187
  void um_schedule(struct um *machine, VALUE fiber, VALUE value);
114
- void um_interrupt(struct um *machine, VALUE fiber, VALUE value);
115
188
  VALUE um_timeout(struct um *machine, VALUE interval, VALUE class);
116
189
 
117
190
  VALUE um_sleep(struct um *machine, double duration);
118
191
  VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int buffer_offset);
119
192
  VALUE um_read_each(struct um *machine, int fd, int bgid);
120
- VALUE um_write(struct um *machine, int fd, VALUE buffer, int len);
193
+ VALUE um_write(struct um *machine, int fd, VALUE str, int len);
194
+ VALUE um_close(struct um *machine, int fd);
195
+ VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode);
196
+ VALUE um_waitpid(struct um *machine, int pid, int options);
121
197
 
122
198
  VALUE um_accept(struct um *machine, int fd);
123
199
  VALUE um_accept_each(struct um *machine, int fd);
200
+ VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint flags);
201
+ VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, socklen_t addrlen);
202
+ VALUE um_send(struct um *machine, int fd, VALUE buffer, int len, int flags);
203
+ VALUE um_recv(struct um *machine, int fd, VALUE buffer, int maxlen, int flags);
204
+ VALUE um_recv_each(struct um *machine, int fd, int bgid, int flags);
205
+ VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrlen);
206
+ VALUE um_listen(struct um *machine, int fd, int backlog);
207
+ VALUE um_getsockopt(struct um *machine, int fd, int level, int opt);
208
+ VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value);
209
+
210
+ struct um_mutex *Mutex_data(VALUE self);
211
+ struct um_queue *Queue_data(VALUE self);
212
+
213
+ void um_mutex_init(struct um_mutex *mutex);
214
+ VALUE um_mutex_synchronize(struct um *machine, uint32_t *state);
215
+
216
+ void um_queue_init(struct um_queue *queue);
217
+ void um_queue_free(struct um_queue *queue);
218
+ void um_queue_mark(struct um_queue *queue);
219
+ void um_queue_compact(struct um_queue *queue);
220
+ VALUE um_queue_push(struct um *machine, struct um_queue *queue, VALUE value);
221
+ VALUE um_queue_pop(struct um *machine, struct um_queue *queue);
222
+ VALUE um_queue_unshift(struct um *machine, struct um_queue *queue, VALUE value);
223
+ VALUE um_queue_shift(struct um *machine, struct um_queue *queue);
224
+
225
+ void um_define_net_constants(VALUE mod);
124
226
 
125
227
  #endif // UM_H
@@ -0,0 +1,49 @@
1
+ #include "um.h"
2
+
3
+ inline long buffer_size(long len) {
4
+ len--;
5
+ len |= len >> 1;
6
+ len |= len >> 2;
7
+ len |= len >> 4;
8
+ len |= len >> 8;
9
+ len |= len >> 16;
10
+ len++;
11
+ return (len > 4096) ? len : 4096;
12
+ }
13
+
14
+ inline struct um_buffer *um_buffer_checkout(struct um *machine, int len) {
15
+ struct um_buffer *buffer = machine->buffer_freelist;
16
+ if (buffer)
17
+ machine->buffer_freelist = buffer->next;
18
+ else {
19
+ buffer = malloc(sizeof(struct um_buffer));
20
+ memset(buffer, 0, sizeof(struct um_buffer));
21
+ }
22
+
23
+ if (buffer->len < len) {
24
+ if (buffer->ptr) {
25
+ free(buffer->ptr);
26
+ buffer->ptr = NULL;
27
+ }
28
+
29
+ buffer->len = buffer_size(len);
30
+ if (posix_memalign(&buffer->ptr, 4096, buffer->len))
31
+ rb_raise(rb_eRuntimeError, "Failed to allocate buffer");
32
+ }
33
+ return buffer;
34
+ }
35
+
36
+ inline void um_buffer_checkin(struct um *machine, struct um_buffer *buffer) {
37
+ buffer->next = machine->buffer_freelist;
38
+ machine->buffer_freelist = buffer;
39
+ }
40
+
41
+ inline void um_free_buffer_linked_list(struct um *machine) {
42
+ struct um_buffer *buffer = machine->buffer_freelist;
43
+ while (buffer) {
44
+ struct um_buffer *next = buffer->next;
45
+ if (buffer->ptr) free(buffer->ptr);
46
+ free(buffer);
47
+ buffer = next;
48
+ }
49
+ }