io-event 1.2.3 → 1.3.1
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
- checksums.yaml.gz.sig +0 -0
- data/ext/extconf.rb +6 -23
- data/ext/io/event/selector/array.h +135 -0
- data/ext/io/event/selector/epoll.c +435 -196
- data/ext/io/event/selector/kqueue.c +481 -218
- data/ext/io/event/selector/list.h +87 -0
- data/ext/io/event/selector/selector.c +14 -14
- data/ext/io/event/selector/selector.h +20 -6
- data/ext/io/event/selector/uring.c +441 -218
- data/lib/io/event/selector/select.rb +34 -14
- data/lib/io/event/selector.rb +2 -6
- data/lib/io/event/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
@@ -20,6 +20,8 @@
|
|
20
20
|
|
21
21
|
#include "uring.h"
|
22
22
|
#include "selector.h"
|
23
|
+
#include "list.h"
|
24
|
+
#include "array.h"
|
23
25
|
|
24
26
|
#include <liburing.h>
|
25
27
|
#include <poll.h>
|
@@ -32,7 +34,7 @@
|
|
32
34
|
|
33
35
|
enum {
|
34
36
|
DEBUG = 0,
|
35
|
-
|
37
|
+
DEBUG_COMPLETION = 0,
|
36
38
|
};
|
37
39
|
|
38
40
|
static VALUE IO_Event_Selector_URing = Qnil;
|
@@ -41,45 +43,109 @@ enum {URING_ENTRIES = 64};
|
|
41
43
|
|
42
44
|
#pragma mark - Data Type
|
43
45
|
|
44
|
-
struct IO_Event_Selector_URing
|
46
|
+
struct IO_Event_Selector_URing
|
47
|
+
{
|
45
48
|
struct IO_Event_Selector backend;
|
46
49
|
struct io_uring ring;
|
47
50
|
size_t pending;
|
48
51
|
int blocked;
|
52
|
+
|
53
|
+
struct IO_Event_Array completions;
|
54
|
+
struct IO_Event_List free_list;
|
55
|
+
};
|
56
|
+
|
57
|
+
struct IO_Event_Selector_URing_Completion;
|
58
|
+
|
59
|
+
struct IO_Event_Selector_URing_Waiting
|
60
|
+
{
|
61
|
+
struct IO_Event_Selector_URing_Completion *completion;
|
62
|
+
|
63
|
+
VALUE fiber;
|
64
|
+
|
65
|
+
// The result of the operation.
|
66
|
+
int32_t result;
|
67
|
+
|
68
|
+
// Any associated flags.
|
69
|
+
uint32_t flags;
|
49
70
|
};
|
50
71
|
|
51
|
-
|
72
|
+
struct IO_Event_Selector_URing_Completion
|
73
|
+
{
|
74
|
+
struct IO_Event_List list;
|
75
|
+
|
76
|
+
struct IO_Event_Selector_URing_Waiting *waiting;
|
77
|
+
};
|
78
|
+
|
79
|
+
static
|
80
|
+
void IO_Event_Selector_URing_Completion_mark(void *_completion)
|
81
|
+
{
|
82
|
+
struct IO_Event_Selector_URing_Completion *completion = _completion;
|
83
|
+
|
84
|
+
if (completion->waiting) {
|
85
|
+
rb_gc_mark_movable(completion->waiting->fiber);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
void IO_Event_Selector_URing_Type_mark(void *_selector)
|
52
90
|
{
|
53
|
-
struct IO_Event_Selector_URing *
|
54
|
-
IO_Event_Selector_mark(&
|
91
|
+
struct IO_Event_Selector_URing *selector = _selector;
|
92
|
+
IO_Event_Selector_mark(&selector->backend);
|
93
|
+
IO_Event_Array_each(&selector->completions, IO_Event_Selector_URing_Completion_mark);
|
55
94
|
}
|
56
95
|
|
57
96
|
static
|
58
|
-
void
|
59
|
-
|
60
|
-
|
61
|
-
|
97
|
+
void IO_Event_Selector_URing_Completion_compact(void *_completion)
|
98
|
+
{
|
99
|
+
struct IO_Event_Selector_URing_Completion *completion = _completion;
|
100
|
+
|
101
|
+
if (completion->waiting) {
|
102
|
+
completion->waiting->fiber = rb_gc_location(completion->waiting->fiber);
|
62
103
|
}
|
63
104
|
}
|
64
105
|
|
65
|
-
void
|
106
|
+
void IO_Event_Selector_URing_Type_compact(void *_selector)
|
107
|
+
{
|
108
|
+
struct IO_Event_Selector_URing *selector = _selector;
|
109
|
+
IO_Event_Selector_compact(&selector->backend);
|
110
|
+
IO_Event_Array_each(&selector->completions, IO_Event_Selector_URing_Completion_compact);
|
111
|
+
}
|
112
|
+
|
113
|
+
static
|
114
|
+
void close_internal(struct IO_Event_Selector_URing *selector)
|
66
115
|
{
|
67
|
-
|
116
|
+
if (selector->ring.ring_fd >= 0) {
|
117
|
+
io_uring_queue_exit(&selector->ring);
|
118
|
+
selector->ring.ring_fd = -1;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
static
|
123
|
+
void IO_Event_Selector_URing_Type_free(void *_selector)
|
124
|
+
{
|
125
|
+
struct IO_Event_Selector_URing *selector = _selector;
|
126
|
+
|
127
|
+
close_internal(selector);
|
68
128
|
|
69
|
-
|
129
|
+
IO_Event_Array_free(&selector->completions);
|
70
130
|
|
71
|
-
free(
|
131
|
+
free(selector);
|
72
132
|
}
|
73
133
|
|
74
|
-
|
134
|
+
static
|
135
|
+
size_t IO_Event_Selector_URing_Type_size(const void *_selector)
|
75
136
|
{
|
76
|
-
|
137
|
+
const struct IO_Event_Selector_URing *selector = _selector;
|
138
|
+
|
139
|
+
return sizeof(struct IO_Event_Selector_URing)
|
140
|
+
+ IO_Event_Array_memory_size(&selector->completions)
|
141
|
+
;
|
77
142
|
}
|
78
143
|
|
79
144
|
static const rb_data_type_t IO_Event_Selector_URing_Type = {
|
80
145
|
.wrap_struct_name = "IO_Event::Backend::URing",
|
81
146
|
.function = {
|
82
147
|
.dmark = IO_Event_Selector_URing_Type_mark,
|
148
|
+
.dcompact = IO_Event_Selector_URing_Type_compact,
|
83
149
|
.dfree = IO_Event_Selector_URing_Type_free,
|
84
150
|
.dsize = IO_Event_Selector_URing_Type_size,
|
85
151
|
},
|
@@ -87,15 +153,90 @@ static const rb_data_type_t IO_Event_Selector_URing_Type = {
|
|
87
153
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
88
154
|
};
|
89
155
|
|
156
|
+
inline static
|
157
|
+
struct IO_Event_Selector_URing_Completion * IO_Event_Selector_URing_Completion_acquire(struct IO_Event_Selector_URing *selector, struct IO_Event_Selector_URing_Waiting *waiting)
|
158
|
+
{
|
159
|
+
struct IO_Event_Selector_URing_Completion *completion = NULL;
|
160
|
+
|
161
|
+
if (!IO_Event_List_empty(&selector->free_list)) {
|
162
|
+
completion = (struct IO_Event_Selector_URing_Completion*)selector->free_list.tail;
|
163
|
+
IO_Event_List_pop(&completion->list);
|
164
|
+
} else {
|
165
|
+
completion = IO_Event_Array_push(&selector->completions);
|
166
|
+
IO_Event_List_clear(&completion->list);
|
167
|
+
}
|
168
|
+
|
169
|
+
if (DEBUG_COMPLETION) fprintf(stderr, "IO_Event_Selector_URing_Completion_acquire(%p, limit=%ld)\n", (void*)completion, selector->completions.limit);
|
170
|
+
|
171
|
+
waiting->completion = completion;
|
172
|
+
completion->waiting = waiting;
|
173
|
+
|
174
|
+
return completion;
|
175
|
+
}
|
176
|
+
|
177
|
+
inline static
|
178
|
+
void IO_Event_Selector_URing_Completion_cancel(struct IO_Event_Selector_URing_Completion *completion)
|
179
|
+
{
|
180
|
+
if (DEBUG_COMPLETION) fprintf(stderr, "IO_Event_Selector_URing_Completion_cancel(%p)\n", (void*)completion);
|
181
|
+
|
182
|
+
if (completion->waiting) {
|
183
|
+
completion->waiting->completion = NULL;
|
184
|
+
completion->waiting = NULL;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
inline static
|
189
|
+
void IO_Event_Selector_URing_Completion_release(struct IO_Event_Selector_URing *selector, struct IO_Event_Selector_URing_Completion *completion)
|
190
|
+
{
|
191
|
+
if (DEBUG_COMPLETION) fprintf(stderr, "IO_Event_Selector_URing_Completion_release(%p)\n", (void*)completion);
|
192
|
+
|
193
|
+
IO_Event_Selector_URing_Completion_cancel(completion);
|
194
|
+
IO_Event_List_prepend(&selector->free_list, &completion->list);
|
195
|
+
}
|
196
|
+
|
197
|
+
inline static
|
198
|
+
void IO_Event_Selector_URing_Waiting_cancel(struct IO_Event_Selector_URing_Waiting *waiting)
|
199
|
+
{
|
200
|
+
if (DEBUG_COMPLETION) fprintf(stderr, "IO_Event_Selector_URing_Waiting_cancel(%p, %p)\n", (void*)waiting, (void*)waiting->completion);
|
201
|
+
|
202
|
+
if (waiting->completion) {
|
203
|
+
waiting->completion->waiting = NULL;
|
204
|
+
waiting->completion = NULL;
|
205
|
+
}
|
206
|
+
|
207
|
+
waiting->fiber = 0;
|
208
|
+
}
|
209
|
+
|
210
|
+
struct IO_Event_List_Type IO_Event_Selector_URing_Completion_Type = {};
|
211
|
+
|
212
|
+
void IO_Event_Selector_URing_Completion_initialize(void *element)
|
213
|
+
{
|
214
|
+
struct IO_Event_Selector_URing_Completion *completion = element;
|
215
|
+
IO_Event_List_initialize(&completion->list);
|
216
|
+
completion->list.type = &IO_Event_Selector_URing_Completion_Type;
|
217
|
+
}
|
218
|
+
|
219
|
+
void IO_Event_Selector_URing_Completion_free(void *element)
|
220
|
+
{
|
221
|
+
struct IO_Event_Selector_URing_Completion *completion = element;
|
222
|
+
IO_Event_Selector_URing_Completion_cancel(completion);
|
223
|
+
}
|
224
|
+
|
90
225
|
VALUE IO_Event_Selector_URing_allocate(VALUE self) {
|
91
|
-
struct IO_Event_Selector_URing *
|
92
|
-
VALUE instance = TypedData_Make_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
226
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
227
|
+
VALUE instance = TypedData_Make_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
228
|
+
|
229
|
+
IO_Event_Selector_initialize(&selector->backend, Qnil);
|
230
|
+
selector->ring.ring_fd = -1;
|
93
231
|
|
94
|
-
|
95
|
-
|
232
|
+
selector->pending = 0;
|
233
|
+
selector->blocked = 0;
|
96
234
|
|
97
|
-
|
98
|
-
|
235
|
+
IO_Event_List_initialize(&selector->free_list);
|
236
|
+
|
237
|
+
selector->completions.element_initialize = IO_Event_Selector_URing_Completion_initialize;
|
238
|
+
selector->completions.element_free = IO_Event_Selector_URing_Completion_free;
|
239
|
+
IO_Event_Array_allocate(&selector->completions, 1024, sizeof(struct IO_Event_Selector_URing_Completion));
|
99
240
|
|
100
241
|
return instance;
|
101
242
|
}
|
@@ -103,100 +244,100 @@ VALUE IO_Event_Selector_URing_allocate(VALUE self) {
|
|
103
244
|
#pragma mark - Methods
|
104
245
|
|
105
246
|
VALUE IO_Event_Selector_URing_initialize(VALUE self, VALUE loop) {
|
106
|
-
struct IO_Event_Selector_URing *
|
107
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
247
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
248
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
108
249
|
|
109
|
-
IO_Event_Selector_initialize(&
|
110
|
-
int result = io_uring_queue_init(URING_ENTRIES, &
|
250
|
+
IO_Event_Selector_initialize(&selector->backend, loop);
|
251
|
+
int result = io_uring_queue_init(URING_ENTRIES, &selector->ring, 0);
|
111
252
|
|
112
253
|
if (result < 0) {
|
113
254
|
rb_syserr_fail(-result, "IO_Event_Selector_URing_initialize:io_uring_queue_init");
|
114
255
|
}
|
115
256
|
|
116
|
-
rb_update_max_fd(
|
257
|
+
rb_update_max_fd(selector->ring.ring_fd);
|
117
258
|
|
118
259
|
return self;
|
119
260
|
}
|
120
261
|
|
121
262
|
VALUE IO_Event_Selector_URing_loop(VALUE self) {
|
122
|
-
struct IO_Event_Selector_URing *
|
123
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
263
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
264
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
124
265
|
|
125
|
-
return
|
266
|
+
return selector->backend.loop;
|
126
267
|
}
|
127
268
|
|
128
269
|
VALUE IO_Event_Selector_URing_close(VALUE self) {
|
129
|
-
struct IO_Event_Selector_URing *
|
130
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
270
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
271
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
131
272
|
|
132
|
-
close_internal(
|
273
|
+
close_internal(selector);
|
133
274
|
|
134
275
|
return Qnil;
|
135
276
|
}
|
136
277
|
|
137
278
|
VALUE IO_Event_Selector_URing_transfer(VALUE self)
|
138
279
|
{
|
139
|
-
struct IO_Event_Selector_URing *
|
140
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
280
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
281
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
141
282
|
|
142
|
-
return IO_Event_Selector_fiber_transfer(
|
283
|
+
return IO_Event_Selector_fiber_transfer(selector->backend.loop, 0, NULL);
|
143
284
|
}
|
144
285
|
|
145
286
|
VALUE IO_Event_Selector_URing_resume(int argc, VALUE *argv, VALUE self)
|
146
287
|
{
|
147
|
-
struct IO_Event_Selector_URing *
|
148
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
288
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
289
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
149
290
|
|
150
|
-
return IO_Event_Selector_resume(&
|
291
|
+
return IO_Event_Selector_resume(&selector->backend, argc, argv);
|
151
292
|
}
|
152
293
|
|
153
294
|
VALUE IO_Event_Selector_URing_yield(VALUE self)
|
154
295
|
{
|
155
|
-
struct IO_Event_Selector_URing *
|
156
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
296
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
297
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
157
298
|
|
158
|
-
return IO_Event_Selector_yield(&
|
299
|
+
return IO_Event_Selector_yield(&selector->backend);
|
159
300
|
}
|
160
301
|
|
161
302
|
VALUE IO_Event_Selector_URing_push(VALUE self, VALUE fiber)
|
162
303
|
{
|
163
|
-
struct IO_Event_Selector_URing *
|
164
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
304
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
305
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
165
306
|
|
166
|
-
IO_Event_Selector_queue_push(&
|
307
|
+
IO_Event_Selector_queue_push(&selector->backend, fiber);
|
167
308
|
|
168
309
|
return Qnil;
|
169
310
|
}
|
170
311
|
|
171
312
|
VALUE IO_Event_Selector_URing_raise(int argc, VALUE *argv, VALUE self)
|
172
313
|
{
|
173
|
-
struct IO_Event_Selector_URing *
|
174
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
314
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
315
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
175
316
|
|
176
|
-
return IO_Event_Selector_raise(&
|
317
|
+
return IO_Event_Selector_raise(&selector->backend, argc, argv);
|
177
318
|
}
|
178
319
|
|
179
320
|
VALUE IO_Event_Selector_URing_ready_p(VALUE self) {
|
180
|
-
struct IO_Event_Selector_URing *
|
181
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
321
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
322
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
182
323
|
|
183
|
-
return
|
324
|
+
return selector->backend.ready ? Qtrue : Qfalse;
|
184
325
|
}
|
185
326
|
|
186
327
|
#pragma mark - Submission Queue
|
187
328
|
|
188
329
|
// Flush the submission queue if pending operations are present.
|
189
330
|
static
|
190
|
-
int io_uring_submit_flush(struct IO_Event_Selector_URing *
|
191
|
-
if (
|
192
|
-
if (DEBUG) fprintf(stderr, "io_uring_submit_flush(pending=%ld)\n",
|
331
|
+
int io_uring_submit_flush(struct IO_Event_Selector_URing *selector) {
|
332
|
+
if (selector->pending) {
|
333
|
+
if (DEBUG) fprintf(stderr, "io_uring_submit_flush(pending=%ld)\n", selector->pending);
|
193
334
|
|
194
335
|
// Try to submit:
|
195
|
-
int result = io_uring_submit(&
|
336
|
+
int result = io_uring_submit(&selector->ring);
|
196
337
|
|
197
338
|
if (result >= 0) {
|
198
339
|
// If it was submitted, reset pending count:
|
199
|
-
|
340
|
+
selector->pending = 0;
|
200
341
|
} else if (result != -EBUSY && result != -EAGAIN) {
|
201
342
|
rb_syserr_fail(-result, "io_uring_submit_flush:io_uring_submit");
|
202
343
|
}
|
@@ -209,41 +350,47 @@ int io_uring_submit_flush(struct IO_Event_Selector_URing *data) {
|
|
209
350
|
|
210
351
|
// Immediately flush the submission queue, yielding to the event loop if it was not successful.
|
211
352
|
static
|
212
|
-
int io_uring_submit_now(struct IO_Event_Selector_URing *
|
213
|
-
if (DEBUG &&
|
353
|
+
int io_uring_submit_now(struct IO_Event_Selector_URing *selector) {
|
354
|
+
if (DEBUG && selector->pending) fprintf(stderr, "io_uring_submit_now(pending=%ld)\n", selector->pending);
|
214
355
|
|
215
356
|
while (true) {
|
216
|
-
int result = io_uring_submit(&
|
357
|
+
int result = io_uring_submit(&selector->ring);
|
217
358
|
|
218
359
|
if (result >= 0) {
|
219
|
-
|
360
|
+
selector->pending = 0;
|
220
361
|
return result;
|
221
362
|
}
|
222
363
|
|
223
364
|
if (result == -EBUSY || result == -EAGAIN) {
|
224
|
-
IO_Event_Selector_yield(&
|
365
|
+
IO_Event_Selector_yield(&selector->backend);
|
225
366
|
} else {
|
226
367
|
rb_syserr_fail(-result, "io_uring_submit_now:io_uring_submit");
|
227
368
|
}
|
228
369
|
}
|
229
370
|
}
|
230
371
|
|
372
|
+
static
|
373
|
+
void IO_Event_Selector_URing_submit_sqe(struct io_uring_sqe *sqe)
|
374
|
+
{
|
375
|
+
if (DEBUG) fprintf(stderr, "IO_Event_Selector_URing_submit_sqe(%p): user_data=%p opcode=%d\n", sqe, (void*)sqe->user_data, sqe->opcode);
|
376
|
+
}
|
377
|
+
|
231
378
|
// Submit a pending operation. This does not submit the operation immediately, but instead defers it to the next call to `io_uring_submit_flush` or `io_uring_submit_now`. This is useful for operations that are not urgent, but should be used with care as it can lead to a deadlock if the submission queue is not flushed.
|
232
379
|
static
|
233
|
-
void io_uring_submit_pending(struct IO_Event_Selector_URing *
|
234
|
-
|
380
|
+
void io_uring_submit_pending(struct IO_Event_Selector_URing *selector) {
|
381
|
+
selector->pending += 1;
|
235
382
|
|
236
|
-
if (DEBUG) fprintf(stderr, "io_uring_submit_pending(ring=%p, pending=%ld)\n", &
|
383
|
+
if (DEBUG) fprintf(stderr, "io_uring_submit_pending(ring=%p, pending=%ld)\n", &selector->ring, selector->pending);
|
237
384
|
}
|
238
385
|
|
239
|
-
struct io_uring_sqe * io_get_sqe(struct IO_Event_Selector_URing *
|
240
|
-
struct io_uring_sqe *sqe = io_uring_get_sqe(&
|
386
|
+
struct io_uring_sqe * io_get_sqe(struct IO_Event_Selector_URing *selector) {
|
387
|
+
struct io_uring_sqe *sqe = io_uring_get_sqe(&selector->ring);
|
241
388
|
|
242
389
|
while (sqe == NULL) {
|
243
390
|
// The submit queue is full, we need to drain it:
|
244
|
-
io_uring_submit_now(
|
391
|
+
io_uring_submit_now(selector);
|
245
392
|
|
246
|
-
sqe = io_uring_get_sqe(&
|
393
|
+
sqe = io_uring_get_sqe(&selector->ring);
|
247
394
|
}
|
248
395
|
|
249
396
|
return sqe;
|
@@ -252,9 +399,10 @@ struct io_uring_sqe * io_get_sqe(struct IO_Event_Selector_URing *data) {
|
|
252
399
|
#pragma mark - Process.wait
|
253
400
|
|
254
401
|
struct process_wait_arguments {
|
255
|
-
struct IO_Event_Selector_URing *
|
402
|
+
struct IO_Event_Selector_URing *selector;
|
403
|
+
struct IO_Event_Selector_URing_Waiting *waiting;
|
404
|
+
|
256
405
|
pid_t pid;
|
257
|
-
int flags;
|
258
406
|
int descriptor;
|
259
407
|
};
|
260
408
|
|
@@ -262,9 +410,13 @@ static
|
|
262
410
|
VALUE process_wait_transfer(VALUE _arguments) {
|
263
411
|
struct process_wait_arguments *arguments = (struct process_wait_arguments *)_arguments;
|
264
412
|
|
265
|
-
IO_Event_Selector_fiber_transfer(arguments->
|
413
|
+
IO_Event_Selector_fiber_transfer(arguments->selector->backend.loop, 0, NULL);
|
266
414
|
|
267
|
-
|
415
|
+
if (arguments->waiting->result) {
|
416
|
+
return IO_Event_Selector_process_status_wait(arguments->pid);
|
417
|
+
} else {
|
418
|
+
return Qfalse;
|
419
|
+
}
|
268
420
|
}
|
269
421
|
|
270
422
|
static
|
@@ -273,29 +425,44 @@ VALUE process_wait_ensure(VALUE _arguments) {
|
|
273
425
|
|
274
426
|
close(arguments->descriptor);
|
275
427
|
|
428
|
+
IO_Event_Selector_URing_Waiting_cancel(arguments->waiting);
|
429
|
+
|
276
430
|
return Qnil;
|
277
431
|
}
|
278
432
|
|
279
|
-
VALUE IO_Event_Selector_URing_process_wait(VALUE self, VALUE fiber, VALUE
|
280
|
-
struct IO_Event_Selector_URing *
|
281
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
433
|
+
VALUE IO_Event_Selector_URing_process_wait(VALUE self, VALUE fiber, VALUE _pid, VALUE _flags) {
|
434
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
435
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
436
|
+
|
437
|
+
pid_t pid = NUM2PIDT(_pid);
|
438
|
+
|
439
|
+
int descriptor = pidfd_open(pid, 0);
|
440
|
+
if (descriptor < 0) {
|
441
|
+
rb_syserr_fail(errno, "IO_Event_Selector_URing_process_wait:pidfd_open");
|
442
|
+
}
|
443
|
+
rb_update_max_fd(descriptor);
|
444
|
+
|
445
|
+
struct IO_Event_Selector_URing_Waiting waiting = {
|
446
|
+
.fiber = fiber,
|
447
|
+
};
|
448
|
+
|
449
|
+
struct IO_Event_Selector_URing_Completion *completion = IO_Event_Selector_URing_Completion_acquire(selector, &waiting);
|
282
450
|
|
283
451
|
struct process_wait_arguments process_wait_arguments = {
|
284
|
-
.
|
285
|
-
.
|
286
|
-
.
|
452
|
+
.selector = selector,
|
453
|
+
.waiting = &waiting,
|
454
|
+
.pid = pid,
|
455
|
+
.descriptor = descriptor,
|
287
456
|
};
|
288
457
|
|
289
|
-
|
290
|
-
rb_update_max_fd(process_wait_arguments.descriptor);
|
458
|
+
struct io_uring_sqe *sqe = io_get_sqe(selector);
|
291
459
|
|
292
|
-
struct io_uring_sqe *sqe = io_get_sqe(data);
|
293
|
-
|
294
460
|
if (DEBUG) fprintf(stderr, "IO_Event_Selector_URing_process_wait:io_uring_prep_poll_add(%p)\n", (void*)fiber);
|
295
|
-
io_uring_prep_poll_add(sqe,
|
296
|
-
io_uring_sqe_set_data(sqe,
|
297
|
-
|
298
|
-
|
461
|
+
io_uring_prep_poll_add(sqe, descriptor, POLLIN|POLLHUP|POLLERR);
|
462
|
+
io_uring_sqe_set_data(sqe, completion);
|
463
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
464
|
+
io_uring_submit_pending(selector);
|
465
|
+
|
299
466
|
return rb_ensure(process_wait_transfer, (VALUE)&process_wait_arguments, process_wait_ensure, (VALUE)&process_wait_arguments);
|
300
467
|
}
|
301
468
|
|
@@ -328,70 +495,81 @@ int events_from_poll_flags(short flags) {
|
|
328
495
|
}
|
329
496
|
|
330
497
|
struct io_wait_arguments {
|
331
|
-
struct IO_Event_Selector_URing *
|
332
|
-
|
498
|
+
struct IO_Event_Selector_URing *selector;
|
499
|
+
struct IO_Event_Selector_URing_Waiting *waiting;
|
333
500
|
short flags;
|
334
501
|
};
|
335
502
|
|
336
503
|
static
|
337
|
-
VALUE
|
504
|
+
VALUE io_wait_ensure(VALUE _arguments) {
|
338
505
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
339
|
-
struct IO_Event_Selector_URing *data = arguments->data;
|
340
506
|
|
341
|
-
|
507
|
+
if (DEBUG) fprintf(stderr, "io_wait_ensure:io_uring_prep_cancel(waiting=%p, completion=%p)\n", (void*)arguments->waiting, (void*)arguments->waiting->completion);
|
342
508
|
|
343
|
-
|
509
|
+
// If the operation is still in progress, cancel it:
|
510
|
+
if (arguments->waiting->completion) {
|
511
|
+
struct io_uring_sqe *sqe = io_get_sqe(arguments->selector);
|
512
|
+
io_uring_prep_cancel(sqe, (void*)arguments->waiting->completion, 0);
|
513
|
+
io_uring_sqe_set_data(sqe, NULL);
|
514
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
515
|
+
io_uring_submit_now(arguments->selector);
|
516
|
+
}
|
344
517
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
rb_exc_raise(exception);
|
518
|
+
IO_Event_Selector_URing_Waiting_cancel(arguments->waiting);
|
519
|
+
|
520
|
+
return Qnil;
|
350
521
|
};
|
351
522
|
|
352
523
|
static
|
353
524
|
VALUE io_wait_transfer(VALUE _arguments) {
|
354
525
|
struct io_wait_arguments *arguments = (struct io_wait_arguments *)_arguments;
|
355
|
-
struct IO_Event_Selector_URing *
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
526
|
+
struct IO_Event_Selector_URing *selector = arguments->selector;
|
527
|
+
|
528
|
+
IO_Event_Selector_fiber_transfer(selector->backend.loop, 0, NULL);
|
529
|
+
|
530
|
+
if (DEBUG) fprintf(stderr, "io_wait_transfer:waiting=%p, result=%d\n", (void*)arguments->waiting, arguments->waiting->result);
|
531
|
+
|
532
|
+
if (arguments->waiting->result) {
|
533
|
+
// We explicitly filter the resulting events based on the requested events.
|
534
|
+
// In some cases, poll will report events we didn't ask for.
|
535
|
+
return RB_INT2NUM(events_from_poll_flags(arguments->waiting->result & arguments->flags));
|
536
|
+
} else {
|
361
537
|
return Qfalse;
|
362
538
|
}
|
363
|
-
|
364
|
-
// We explicitly filter the resulting events based on the requested events.
|
365
|
-
// In some cases, poll will report events we didn't ask for.
|
366
|
-
short flags = arguments->flags & NUM2INT(result);
|
367
|
-
|
368
|
-
return INT2NUM(events_from_poll_flags(flags));
|
369
539
|
};
|
370
540
|
|
371
541
|
VALUE IO_Event_Selector_URing_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE events) {
|
372
|
-
struct IO_Event_Selector_URing *
|
373
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
542
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
543
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
374
544
|
|
375
545
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
376
|
-
struct io_uring_sqe *sqe = io_get_sqe(
|
546
|
+
struct io_uring_sqe *sqe = io_get_sqe(selector);
|
377
547
|
|
378
548
|
short flags = poll_flags_from_events(NUM2INT(events));
|
379
549
|
|
380
550
|
if (DEBUG) fprintf(stderr, "IO_Event_Selector_URing_io_wait:io_uring_prep_poll_add(descriptor=%d, flags=%d, fiber=%p)\n", descriptor, flags, (void*)fiber);
|
381
551
|
|
382
552
|
io_uring_prep_poll_add(sqe, descriptor, flags);
|
383
|
-
|
553
|
+
|
554
|
+
struct IO_Event_Selector_URing_Waiting waiting = {
|
555
|
+
.fiber = fiber,
|
556
|
+
};
|
557
|
+
|
558
|
+
struct IO_Event_Selector_URing_Completion *completion = IO_Event_Selector_URing_Completion_acquire(selector, &waiting);
|
559
|
+
|
560
|
+
io_uring_sqe_set_data(sqe, completion);
|
561
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
384
562
|
|
385
563
|
// If we are going to wait, we assume that we are waiting for a while:
|
386
|
-
io_uring_submit_pending(
|
564
|
+
io_uring_submit_pending(selector);
|
387
565
|
|
388
566
|
struct io_wait_arguments io_wait_arguments = {
|
389
|
-
.
|
390
|
-
.
|
567
|
+
.selector = selector,
|
568
|
+
.waiting = &waiting,
|
391
569
|
.flags = flags
|
392
570
|
};
|
393
571
|
|
394
|
-
return
|
572
|
+
return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
|
395
573
|
}
|
396
574
|
|
397
575
|
#ifdef HAVE_RUBY_IO_BUFFER_H
|
@@ -417,8 +595,8 @@ static inline off_t io_seekable(int descriptor)
|
|
417
595
|
#pragma mark - IO#read
|
418
596
|
|
419
597
|
struct io_read_arguments {
|
420
|
-
struct IO_Event_Selector_URing *
|
421
|
-
|
598
|
+
struct IO_Event_Selector_URing *selector;
|
599
|
+
struct IO_Event_Selector_URing_Waiting *waiting;
|
422
600
|
int descriptor;
|
423
601
|
char *buffer;
|
424
602
|
size_t length;
|
@@ -428,58 +606,69 @@ static VALUE
|
|
428
606
|
io_read_submit(VALUE _arguments)
|
429
607
|
{
|
430
608
|
struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
|
431
|
-
struct IO_Event_Selector_URing *
|
432
|
-
struct io_uring_sqe *sqe = io_get_sqe(
|
609
|
+
struct IO_Event_Selector_URing *selector = arguments->selector;
|
610
|
+
struct io_uring_sqe *sqe = io_get_sqe(selector);
|
433
611
|
|
434
|
-
if (DEBUG) fprintf(stderr, "io_read_submit:io_uring_prep_read(
|
612
|
+
if (DEBUG) fprintf(stderr, "io_read_submit:io_uring_prep_read(waiting=%p, completion=%p, descriptor=%d, buffer=%p, length=%ld)\n", (void*)arguments->waiting, (void*)arguments->waiting->completion, arguments->descriptor, arguments->buffer, arguments->length);
|
435
613
|
|
436
614
|
io_uring_prep_read(sqe, arguments->descriptor, arguments->buffer, arguments->length, io_seekable(arguments->descriptor));
|
437
|
-
io_uring_sqe_set_data(sqe,
|
438
|
-
|
615
|
+
io_uring_sqe_set_data(sqe, arguments->waiting->completion);
|
616
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
617
|
+
io_uring_submit_now(selector);
|
618
|
+
|
619
|
+
IO_Event_Selector_fiber_transfer(selector->backend.loop, 0, NULL);
|
439
620
|
|
440
|
-
return
|
621
|
+
return RB_INT2NUM(arguments->waiting->result);
|
441
622
|
}
|
442
623
|
|
443
624
|
static VALUE
|
444
|
-
|
625
|
+
io_read_ensure(VALUE _arguments)
|
445
626
|
{
|
446
627
|
struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
|
447
|
-
struct IO_Event_Selector_URing *
|
628
|
+
struct IO_Event_Selector_URing *selector = arguments->selector;
|
448
629
|
|
449
|
-
struct io_uring_sqe *sqe = io_get_sqe(
|
630
|
+
struct io_uring_sqe *sqe = io_get_sqe(selector);
|
450
631
|
|
451
|
-
if (DEBUG) fprintf(stderr, "
|
632
|
+
if (DEBUG) fprintf(stderr, "io_read_ensure:io_uring_prep_cancel(waiting=%p, completion=%p)\n", (void*)arguments->waiting, (void*)arguments->waiting->completion);
|
452
633
|
|
453
|
-
|
454
|
-
|
455
|
-
|
634
|
+
// If the operation is still in progress, cancel it:
|
635
|
+
if (arguments->waiting->completion) {
|
636
|
+
io_uring_prep_cancel(sqe, (void*)arguments->waiting->completion, 0);
|
637
|
+
io_uring_sqe_set_data(sqe, NULL);
|
638
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
639
|
+
io_uring_submit_now(selector);
|
640
|
+
}
|
456
641
|
|
457
|
-
|
642
|
+
IO_Event_Selector_URing_Waiting_cancel(arguments->waiting);
|
643
|
+
|
644
|
+
return Qnil;
|
458
645
|
}
|
459
646
|
|
460
647
|
static int
|
461
|
-
io_read(struct IO_Event_Selector_URing *
|
648
|
+
io_read(struct IO_Event_Selector_URing *selector, VALUE fiber, int descriptor, char *buffer, size_t length)
|
462
649
|
{
|
463
|
-
struct
|
464
|
-
.data = data,
|
650
|
+
struct IO_Event_Selector_URing_Waiting waiting = {
|
465
651
|
.fiber = fiber,
|
652
|
+
};
|
653
|
+
|
654
|
+
IO_Event_Selector_URing_Completion_acquire(selector, &waiting);
|
655
|
+
|
656
|
+
struct io_read_arguments io_read_arguments = {
|
657
|
+
.selector = selector,
|
658
|
+
.waiting = &waiting,
|
466
659
|
.descriptor = descriptor,
|
467
660
|
.buffer = buffer,
|
468
661
|
.length = length
|
469
662
|
};
|
470
663
|
|
471
|
-
|
472
|
-
|
664
|
+
return RB_NUM2INT(
|
665
|
+
rb_ensure(io_read_submit, (VALUE)&io_read_arguments, io_read_ensure, (VALUE)&io_read_arguments)
|
473
666
|
);
|
474
|
-
|
475
|
-
if (DEBUG) fprintf(stderr, "io_read:IO_Event_Selector_fiber_transfer -> %d\n", result);
|
476
|
-
|
477
|
-
return result;
|
478
667
|
}
|
479
668
|
|
480
669
|
VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
|
481
|
-
struct IO_Event_Selector_URing *
|
482
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
670
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
671
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
483
672
|
|
484
673
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
485
674
|
|
@@ -489,14 +678,14 @@ VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
|
|
489
678
|
|
490
679
|
size_t length = NUM2SIZET(_length);
|
491
680
|
size_t offset = NUM2SIZET(_offset);
|
681
|
+
size_t total = 0;
|
492
682
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
int result = io_read(data, fiber, descriptor, (char*)base+offset, maximum_size);
|
497
|
-
if (DEBUG_IO_READ) fprintf(stderr, "io_read(%d, +%ld, %ld) -> %d\n", descriptor, offset, maximum_size, result);
|
683
|
+
size_t maximum_size = size - offset;
|
684
|
+
while (maximum_size) {
|
685
|
+
int result = io_read(selector, fiber, descriptor, (char*)base+offset, maximum_size);
|
498
686
|
|
499
687
|
if (result > 0) {
|
688
|
+
total += result;
|
500
689
|
offset += result;
|
501
690
|
if ((size_t)result >= length) break;
|
502
691
|
length -= result;
|
@@ -507,9 +696,11 @@ VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
|
|
507
696
|
} else {
|
508
697
|
return rb_fiber_scheduler_io_result(-1, -result);
|
509
698
|
}
|
699
|
+
|
700
|
+
maximum_size = size - offset;
|
510
701
|
}
|
511
702
|
|
512
|
-
return rb_fiber_scheduler_io_result(
|
703
|
+
return rb_fiber_scheduler_io_result(total, 0);
|
513
704
|
}
|
514
705
|
|
515
706
|
static VALUE IO_Event_Selector_URing_io_read_compatible(int argc, VALUE *argv, VALUE self)
|
@@ -528,8 +719,8 @@ static VALUE IO_Event_Selector_URing_io_read_compatible(int argc, VALUE *argv, V
|
|
528
719
|
#pragma mark - IO#write
|
529
720
|
|
530
721
|
struct io_write_arguments {
|
531
|
-
struct IO_Event_Selector_URing *
|
532
|
-
|
722
|
+
struct IO_Event_Selector_URing *selector;
|
723
|
+
struct IO_Event_Selector_URing_Waiting *waiting;
|
533
724
|
int descriptor;
|
534
725
|
char *buffer;
|
535
726
|
size_t length;
|
@@ -539,59 +730,70 @@ static VALUE
|
|
539
730
|
io_write_submit(VALUE _argument)
|
540
731
|
{
|
541
732
|
struct io_write_arguments *arguments = (struct io_write_arguments*)_argument;
|
542
|
-
struct IO_Event_Selector_URing *
|
733
|
+
struct IO_Event_Selector_URing *selector = arguments->selector;
|
543
734
|
|
544
|
-
struct io_uring_sqe *sqe = io_get_sqe(
|
735
|
+
struct io_uring_sqe *sqe = io_get_sqe(selector);
|
545
736
|
|
546
|
-
if (DEBUG) fprintf(stderr, "io_write_submit:io_uring_prep_write(
|
737
|
+
if (DEBUG) fprintf(stderr, "io_write_submit:io_uring_prep_write(waiting=%p, completion=%p, descriptor=%d, buffer=%p, length=%ld)\n", (void*)arguments->waiting, (void*)arguments->waiting->completion, arguments->descriptor, arguments->buffer, arguments->length);
|
547
738
|
|
548
739
|
io_uring_prep_write(sqe, arguments->descriptor, arguments->buffer, arguments->length, io_seekable(arguments->descriptor));
|
549
|
-
io_uring_sqe_set_data(sqe,
|
550
|
-
|
740
|
+
io_uring_sqe_set_data(sqe, arguments->waiting->completion);
|
741
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
742
|
+
io_uring_submit_pending(selector);
|
551
743
|
|
552
|
-
|
744
|
+
IO_Event_Selector_fiber_transfer(selector->backend.loop, 0, NULL);
|
745
|
+
|
746
|
+
return RB_INT2NUM(arguments->waiting->result);
|
553
747
|
}
|
554
748
|
|
555
749
|
static VALUE
|
556
|
-
|
750
|
+
io_write_ensure(VALUE _argument)
|
557
751
|
{
|
558
752
|
struct io_write_arguments *arguments = (struct io_write_arguments*)_argument;
|
559
|
-
struct IO_Event_Selector_URing *
|
753
|
+
struct IO_Event_Selector_URing *selector = arguments->selector;
|
560
754
|
|
561
|
-
struct io_uring_sqe *sqe = io_get_sqe(
|
755
|
+
struct io_uring_sqe *sqe = io_get_sqe(selector);
|
562
756
|
|
563
|
-
if (DEBUG) fprintf(stderr, "
|
757
|
+
if (DEBUG) fprintf(stderr, "io_write_ensure:io_uring_prep_cancel(waiting=%p, completion=%p)\n", (void*)arguments->waiting, (void*)arguments->waiting->completion);
|
564
758
|
|
565
|
-
|
566
|
-
|
567
|
-
|
759
|
+
// If the operation is still in progress, cancel it:
|
760
|
+
if (arguments->waiting->completion) {
|
761
|
+
io_uring_prep_cancel(sqe, (void*)arguments->waiting->completion, 0);
|
762
|
+
io_uring_sqe_set_data(sqe, NULL);
|
763
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
764
|
+
io_uring_submit_now(selector);
|
765
|
+
}
|
568
766
|
|
569
|
-
|
767
|
+
IO_Event_Selector_URing_Waiting_cancel(arguments->waiting);
|
768
|
+
|
769
|
+
return Qnil;
|
570
770
|
}
|
571
771
|
|
572
772
|
static int
|
573
|
-
io_write(struct IO_Event_Selector_URing *
|
773
|
+
io_write(struct IO_Event_Selector_URing *selector, VALUE fiber, int descriptor, char *buffer, size_t length)
|
574
774
|
{
|
575
|
-
struct
|
576
|
-
.data = data,
|
775
|
+
struct IO_Event_Selector_URing_Waiting waiting = {
|
577
776
|
.fiber = fiber,
|
777
|
+
};
|
778
|
+
|
779
|
+
IO_Event_Selector_URing_Completion_acquire(selector, &waiting);
|
780
|
+
|
781
|
+
struct io_write_arguments arguments = {
|
782
|
+
.selector = selector,
|
783
|
+
.waiting = &waiting,
|
578
784
|
.descriptor = descriptor,
|
579
785
|
.buffer = buffer,
|
580
786
|
.length = length,
|
581
787
|
};
|
582
788
|
|
583
|
-
|
584
|
-
|
789
|
+
return RB_NUM2INT(
|
790
|
+
rb_ensure(io_write_submit, (VALUE)&arguments, io_write_ensure, (VALUE)&arguments)
|
585
791
|
);
|
586
|
-
|
587
|
-
if (DEBUG) fprintf(stderr, "io_write:IO_Event_Selector_fiber_transfer -> %d\n", result);
|
588
|
-
|
589
|
-
return result;
|
590
792
|
}
|
591
793
|
|
592
794
|
VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
|
593
|
-
struct IO_Event_Selector_URing *
|
594
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
795
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
796
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
595
797
|
|
596
798
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
597
799
|
|
@@ -601,16 +803,18 @@ VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
601
803
|
|
602
804
|
size_t length = NUM2SIZET(_length);
|
603
805
|
size_t offset = NUM2SIZET(_offset);
|
806
|
+
size_t total = 0;
|
604
807
|
|
605
808
|
if (length > size) {
|
606
809
|
rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
|
607
810
|
}
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
int result = io_write(
|
811
|
+
|
812
|
+
size_t maximum_size = size - offset;
|
813
|
+
while (maximum_size) {
|
814
|
+
int result = io_write(selector, fiber, descriptor, (char*)base+offset, maximum_size);
|
612
815
|
|
613
816
|
if (result > 0) {
|
817
|
+
total += result;
|
614
818
|
offset += result;
|
615
819
|
if ((size_t)result >= length) break;
|
616
820
|
length -= result;
|
@@ -621,9 +825,11 @@ VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
621
825
|
} else {
|
622
826
|
return rb_fiber_scheduler_io_result(-1, -result);
|
623
827
|
}
|
828
|
+
|
829
|
+
maximum_size = size - offset;
|
624
830
|
}
|
625
831
|
|
626
|
-
return rb_fiber_scheduler_io_result(
|
832
|
+
return rb_fiber_scheduler_io_result(total, 0);
|
627
833
|
}
|
628
834
|
|
629
835
|
static VALUE IO_Event_Selector_URing_io_write_compatible(int argc, VALUE *argv, VALUE self)
|
@@ -646,17 +852,18 @@ static VALUE IO_Event_Selector_URing_io_write_compatible(int argc, VALUE *argv,
|
|
646
852
|
static const int ASYNC_CLOSE = 1;
|
647
853
|
|
648
854
|
VALUE IO_Event_Selector_URing_io_close(VALUE self, VALUE io) {
|
649
|
-
struct IO_Event_Selector_URing *
|
650
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
855
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
856
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
651
857
|
|
652
858
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
653
859
|
|
654
860
|
if (ASYNC_CLOSE) {
|
655
|
-
struct io_uring_sqe *sqe = io_get_sqe(
|
861
|
+
struct io_uring_sqe *sqe = io_get_sqe(selector);
|
656
862
|
|
657
863
|
io_uring_prep_close(sqe, descriptor);
|
658
864
|
io_uring_sqe_set_data(sqe, NULL);
|
659
|
-
|
865
|
+
IO_Event_Selector_URing_submit_sqe(sqe);
|
866
|
+
io_uring_submit_now(selector);
|
660
867
|
} else {
|
661
868
|
close(descriptor);
|
662
869
|
}
|
@@ -699,7 +906,7 @@ int timeout_nonblocking(struct __kernel_timespec *timespec) {
|
|
699
906
|
}
|
700
907
|
|
701
908
|
struct select_arguments {
|
702
|
-
struct IO_Event_Selector_URing *
|
909
|
+
struct IO_Event_Selector_URing *selector;
|
703
910
|
|
704
911
|
int result;
|
705
912
|
|
@@ -712,18 +919,18 @@ void * select_internal(void *_arguments) {
|
|
712
919
|
struct select_arguments * arguments = (struct select_arguments *)_arguments;
|
713
920
|
struct io_uring_cqe *cqe = NULL;
|
714
921
|
|
715
|
-
arguments->result = io_uring_wait_cqe_timeout(&arguments->
|
922
|
+
arguments->result = io_uring_wait_cqe_timeout(&arguments->selector->ring, &cqe, arguments->timeout);
|
716
923
|
|
717
924
|
return NULL;
|
718
925
|
}
|
719
926
|
|
720
927
|
static
|
721
928
|
int select_internal_without_gvl(struct select_arguments *arguments) {
|
722
|
-
io_uring_submit_flush(arguments->
|
929
|
+
io_uring_submit_flush(arguments->selector);
|
723
930
|
|
724
|
-
arguments->
|
931
|
+
arguments->selector->blocked = 1;
|
725
932
|
rb_thread_call_without_gvl(select_internal, (void *)arguments, RUBY_UBF_IO, 0);
|
726
|
-
arguments->
|
933
|
+
arguments->selector->blocked = 0;
|
727
934
|
|
728
935
|
if (arguments->result == -ETIME) {
|
729
936
|
arguments->result = 0;
|
@@ -740,96 +947,112 @@ int select_internal_without_gvl(struct select_arguments *arguments) {
|
|
740
947
|
}
|
741
948
|
|
742
949
|
static inline
|
743
|
-
unsigned select_process_completions(struct
|
950
|
+
unsigned select_process_completions(struct IO_Event_Selector_URing *selector) {
|
951
|
+
struct io_uring *ring = &selector->ring;
|
744
952
|
unsigned completed = 0;
|
745
953
|
unsigned head;
|
746
954
|
struct io_uring_cqe *cqe;
|
747
955
|
|
956
|
+
if (DEBUG) fprintf(stderr, "select_process_completions...\n");
|
957
|
+
|
748
958
|
io_uring_for_each_cqe(ring, head, cqe) {
|
959
|
+
if (DEBUG) fprintf(stderr, "select_process_completions: cqe res=%d user_data=%p\n", cqe->res, (void*)cqe->user_data);
|
960
|
+
|
749
961
|
++completed;
|
750
962
|
|
751
|
-
// If the operation was cancelled, or the operation has no user data
|
752
|
-
if (cqe->
|
963
|
+
// If the operation was cancelled, or the operation has no user data:
|
964
|
+
if (cqe->user_data == 0 || cqe->user_data == LIBURING_UDATA_TIMEOUT) {
|
753
965
|
io_uring_cq_advance(ring, 1);
|
754
966
|
continue;
|
755
967
|
}
|
756
968
|
|
757
|
-
|
758
|
-
|
969
|
+
struct IO_Event_Selector_URing_Completion *completion = (void*)cqe->user_data;
|
970
|
+
struct IO_Event_Selector_URing_Waiting *waiting = completion->waiting;
|
759
971
|
|
760
|
-
if (DEBUG) fprintf(stderr, "
|
972
|
+
if (DEBUG) fprintf(stderr, "select_process_completions: completion=%p waiting=%p\n", (void*)completion, (void*)waiting);
|
761
973
|
|
762
|
-
|
974
|
+
if (waiting) {
|
975
|
+
waiting->result = cqe->res;
|
976
|
+
waiting->flags = cqe->flags;
|
977
|
+
}
|
978
|
+
|
979
|
+
if (waiting && waiting->fiber) {
|
980
|
+
assert(waiting->result != -ECANCELED);
|
981
|
+
|
982
|
+
IO_Event_Selector_fiber_transfer(waiting->fiber, 0, NULL);
|
983
|
+
}
|
763
984
|
|
764
|
-
|
985
|
+
// This marks the waiting operation as "complete":
|
986
|
+
IO_Event_Selector_URing_Completion_release(selector, completion);
|
987
|
+
io_uring_cq_advance(ring, 1);
|
765
988
|
}
|
766
989
|
|
767
|
-
// io_uring_cq_advance(ring, completed);
|
768
|
-
|
769
990
|
if (DEBUG && completed > 0) fprintf(stderr, "select_process_completions(completed=%d)\n", completed);
|
770
991
|
|
771
992
|
return completed;
|
772
993
|
}
|
773
994
|
|
774
995
|
VALUE IO_Event_Selector_URing_select(VALUE self, VALUE duration) {
|
775
|
-
struct IO_Event_Selector_URing *
|
776
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
996
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
997
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
777
998
|
|
778
999
|
// Flush any pending events:
|
779
|
-
io_uring_submit_flush(
|
1000
|
+
io_uring_submit_flush(selector);
|
780
1001
|
|
781
|
-
int ready = IO_Event_Selector_queue_flush(&
|
1002
|
+
int ready = IO_Event_Selector_queue_flush(&selector->backend);
|
782
1003
|
|
783
|
-
int result = select_process_completions(
|
1004
|
+
int result = select_process_completions(selector);
|
784
1005
|
|
785
1006
|
// If we:
|
786
1007
|
// 1. Didn't process any ready fibers, and
|
787
1008
|
// 2. Didn't process any events from non-blocking select (above), and
|
788
1009
|
// 3. There are no items in the ready list,
|
789
1010
|
// then we can perform a blocking select.
|
790
|
-
if (!ready && !result && !
|
1011
|
+
if (!ready && !result && !selector->backend.ready) {
|
791
1012
|
// We might need to wait for events:
|
792
1013
|
struct select_arguments arguments = {
|
793
|
-
.
|
1014
|
+
.selector = selector,
|
794
1015
|
.timeout = NULL,
|
795
1016
|
};
|
796
1017
|
|
797
1018
|
arguments.timeout = make_timeout(duration, &arguments.storage);
|
798
1019
|
|
799
|
-
if (!
|
1020
|
+
if (!selector->backend.ready && !timeout_nonblocking(arguments.timeout)) {
|
800
1021
|
// This is a blocking operation, we wait for events:
|
801
1022
|
result = select_internal_without_gvl(&arguments);
|
1023
|
+
|
1024
|
+
// After waiting/flushing the SQ, check if there are any completions:
|
1025
|
+
if (result > 0) {
|
1026
|
+
result = select_process_completions(selector);
|
1027
|
+
}
|
802
1028
|
}
|
803
|
-
|
804
|
-
// After waiting/flushing the SQ, check if there are any completions:
|
805
|
-
result = select_process_completions(&data->ring);
|
806
1029
|
}
|
807
1030
|
|
808
1031
|
return RB_INT2NUM(result);
|
809
1032
|
}
|
810
1033
|
|
811
1034
|
VALUE IO_Event_Selector_URing_wakeup(VALUE self) {
|
812
|
-
struct IO_Event_Selector_URing *
|
813
|
-
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type,
|
1035
|
+
struct IO_Event_Selector_URing *selector = NULL;
|
1036
|
+
TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, selector);
|
814
1037
|
|
815
1038
|
// If we are blocking, we can schedule a nop event to wake up the selector:
|
816
|
-
if (
|
1039
|
+
if (selector->blocked) {
|
817
1040
|
struct io_uring_sqe *sqe = NULL;
|
818
1041
|
|
819
1042
|
while (true) {
|
820
|
-
sqe = io_uring_get_sqe(&
|
1043
|
+
sqe = io_uring_get_sqe(&selector->ring);
|
821
1044
|
if (sqe) break;
|
822
1045
|
|
823
1046
|
rb_thread_schedule();
|
824
1047
|
|
825
1048
|
// It's possible we became unblocked already, so we can assume the selector has already cycled at least once:
|
826
|
-
if (!
|
1049
|
+
if (!selector->blocked) return Qfalse;
|
827
1050
|
}
|
828
1051
|
|
829
1052
|
io_uring_prep_nop(sqe);
|
830
|
-
// If you don't set this line, the SQE will eventually be recycled and have valid user
|
1053
|
+
// If you don't set this line, the SQE will eventually be recycled and have valid user selector which can cause odd behaviour:
|
831
1054
|
io_uring_sqe_set_data(sqe, NULL);
|
832
|
-
io_uring_submit(&
|
1055
|
+
io_uring_submit(&selector->ring);
|
833
1056
|
|
834
1057
|
return Qtrue;
|
835
1058
|
}
|