polyphony 0.73.1 → 0.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +13 -10
- data/.github/workflows/test_io_uring.yml +32 -0
- data/CHANGELOG.md +22 -0
- data/Gemfile.lock +10 -7
- data/bin/pdbg +0 -0
- data/bin/polyphony-debug +0 -0
- data/bin/stress.rb +0 -0
- data/bin/test +0 -0
- data/examples/core/trap1.rb +21 -0
- data/examples/core/trap2.rb +14 -0
- data/ext/polyphony/backend_common.c +84 -12
- data/ext/polyphony/backend_common.h +8 -0
- data/ext/polyphony/backend_io_uring.c +231 -107
- data/ext/polyphony/backend_io_uring_context.c +1 -0
- data/ext/polyphony/backend_io_uring_context.h +2 -1
- data/ext/polyphony/backend_libev.c +12 -9
- data/ext/polyphony/event.c +5 -2
- data/ext/polyphony/polyphony.c +11 -1
- data/ext/polyphony/polyphony.h +4 -1
- data/ext/polyphony/queue.c +10 -5
- data/ext/polyphony/runqueue_ring_buffer.c +3 -1
- data/ext/polyphony/socket_extensions.c +5 -2
- data/ext/test_eintr.c +50 -0
- data/lib/polyphony/extensions/fiber.rb +85 -5
- data/lib/polyphony/extensions/openssl.rb +5 -1
- data/lib/polyphony/extensions/socket.rb +12 -6
- data/lib/polyphony/extensions/thread.rb +9 -3
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +4 -1
- data/test/helper.rb +2 -6
- data/test/stress.rb +1 -1
- data/test/test_backend.rb +3 -5
- data/test/test_fiber.rb +6 -4
- data/test/test_global_api.rb +10 -14
- data/test/test_io.rb +2 -2
- data/test/test_kernel.rb +2 -2
- data/test/test_signal.rb +57 -0
- data/test/test_socket.rb +35 -2
- data/test/test_thread.rb +1 -1
- data/test/test_thread_pool.rb +1 -1
- data/test/test_throttler.rb +3 -3
- data/test/test_timer.rb +2 -2
- data/test/test_trace.rb +7 -1
- metadata +11 -7
@@ -42,6 +42,7 @@ typedef struct Backend_t {
|
|
42
42
|
unsigned int pending_sqes;
|
43
43
|
unsigned int prepared_limit;
|
44
44
|
int event_fd;
|
45
|
+
int ring_initialized;
|
45
46
|
} Backend_t;
|
46
47
|
|
47
48
|
static void Backend_mark(void *ptr) {
|
@@ -80,20 +81,32 @@ static VALUE Backend_initialize(VALUE self) {
|
|
80
81
|
|
81
82
|
backend_base_initialize(&backend->base);
|
82
83
|
backend->pending_sqes = 0;
|
83
|
-
backend->
|
84
|
+
backend->ring_initialized = 0;
|
85
|
+
backend->event_fd = -1;
|
84
86
|
|
85
87
|
context_store_initialize(&backend->store);
|
86
|
-
io_uring_queue_init(backend->prepared_limit, &backend->ring, 0);
|
87
|
-
backend->event_fd = -1;
|
88
88
|
|
89
|
-
|
89
|
+
backend->prepared_limit = 1024;
|
90
|
+
while (1) {
|
91
|
+
int ret = io_uring_queue_init(backend->prepared_limit, &backend->ring, 0);
|
92
|
+
if (!ret) break;
|
93
|
+
|
94
|
+
// if ENOMEM is returned, use a smaller limit
|
95
|
+
if (ret == -ENOMEM && backend->prepared_limit > 64)
|
96
|
+
backend->prepared_limit = backend->prepared_limit / 2;
|
97
|
+
else
|
98
|
+
rb_syserr_fail(-ret, strerror(-ret));
|
99
|
+
}
|
100
|
+
backend->ring_initialized = 1;
|
101
|
+
|
102
|
+
return self;
|
90
103
|
}
|
91
104
|
|
92
105
|
VALUE Backend_finalize(VALUE self) {
|
93
106
|
Backend_t *backend;
|
94
107
|
GetBackend(self, backend);
|
95
108
|
|
96
|
-
io_uring_queue_exit(&backend->ring);
|
109
|
+
if (backend->ring_initialized) io_uring_queue_exit(&backend->ring);
|
97
110
|
if (backend->event_fd != -1) close(backend->event_fd);
|
98
111
|
context_store_free(&backend->store);
|
99
112
|
return self;
|
@@ -178,10 +191,14 @@ void io_uring_backend_poll(Backend_t *backend) {
|
|
178
191
|
io_uring_submit(&backend->ring);
|
179
192
|
}
|
180
193
|
|
194
|
+
wait_cqe:
|
181
195
|
backend->base.currently_polling = 1;
|
182
196
|
rb_thread_call_without_gvl(io_uring_backend_poll_without_gvl, (void *)&poll_ctx, RUBY_UBF_IO, 0);
|
183
197
|
backend->base.currently_polling = 0;
|
184
|
-
if (poll_ctx.result < 0)
|
198
|
+
if (poll_ctx.result < 0) {
|
199
|
+
if (poll_ctx.result == -EINTR && runqueue_empty_p(&backend->base.runqueue)) goto wait_cqe;
|
200
|
+
return;
|
201
|
+
}
|
185
202
|
|
186
203
|
io_uring_backend_handle_completion(poll_ctx.cqe, backend);
|
187
204
|
io_uring_cqe_seen(&backend->ring, poll_ctx.cqe);
|
@@ -282,9 +299,11 @@ int io_uring_backend_defer_submit_and_await(
|
|
282
299
|
switchpoint_result = backend_await((struct Backend_base *)backend);
|
283
300
|
|
284
301
|
if (ctx->ref_count > 1) {
|
302
|
+
struct io_uring_sqe *sqe;
|
303
|
+
|
285
304
|
// op was not completed (an exception was raised), so we need to cancel it
|
286
305
|
ctx->result = -ECANCELED;
|
287
|
-
|
306
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
288
307
|
io_uring_prep_cancel(sqe, ctx, 0);
|
289
308
|
backend->pending_sqes = 0;
|
290
309
|
io_uring_submit(&backend->ring);
|
@@ -316,16 +335,20 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
316
335
|
long dynamic_len = length == Qnil;
|
317
336
|
long buffer_size = dynamic_len ? 4096 : NUM2INT(length);
|
318
337
|
long buf_pos = NUM2INT(pos);
|
338
|
+
int shrinkable;
|
339
|
+
char *buf;
|
340
|
+
long total = 0;
|
341
|
+
int read_to_eof = RTEST(to_eof);
|
342
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
343
|
+
|
344
|
+
|
319
345
|
if (str != Qnil) {
|
320
346
|
int current_len = RSTRING_LEN(str);
|
321
347
|
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
322
348
|
}
|
323
349
|
else buf_pos = 0;
|
324
|
-
|
325
|
-
|
326
|
-
long total = 0;
|
327
|
-
int read_to_eof = RTEST(to_eof);
|
328
|
-
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
350
|
+
shrinkable = io_setstrbuf(&str, buf_pos + buffer_size);
|
351
|
+
buf = RSTRING_PTR(str) + buf_pos;
|
329
352
|
|
330
353
|
GetBackend(self, backend);
|
331
354
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -338,10 +361,13 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
338
361
|
VALUE resume_value = Qnil;
|
339
362
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
340
363
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
364
|
+
int result;
|
365
|
+
int completed;
|
366
|
+
|
341
367
|
io_uring_prep_read(sqe, fptr->fd, buf, buffer_size - total, -1);
|
342
368
|
|
343
|
-
|
344
|
-
|
369
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
370
|
+
completed = context_store_release(&backend->store, ctx);
|
345
371
|
if (!completed) {
|
346
372
|
context_attach_buffers(ctx, 1, &str);
|
347
373
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -402,10 +428,13 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
402
428
|
VALUE resume_value = Qnil;
|
403
429
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
404
430
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
431
|
+
ssize_t result;
|
432
|
+
int completed;
|
433
|
+
|
405
434
|
io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
|
406
435
|
|
407
|
-
|
408
|
-
|
436
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
437
|
+
completed = context_store_release(&backend->store, ctx);
|
409
438
|
if (!completed) {
|
410
439
|
context_attach_buffers(ctx, 1, &str);
|
411
440
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -452,10 +481,13 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
452
481
|
VALUE resume_value = Qnil;
|
453
482
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
454
483
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
484
|
+
ssize_t result;
|
485
|
+
int completed;
|
486
|
+
|
455
487
|
io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
|
456
488
|
|
457
|
-
|
458
|
-
|
489
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
490
|
+
completed = context_store_release(&backend->store, ctx);
|
459
491
|
if (!completed) {
|
460
492
|
context_attach_buffers(ctx, 1, &str);
|
461
493
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -482,6 +514,9 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
482
514
|
Backend_t *backend;
|
483
515
|
rb_io_t *fptr;
|
484
516
|
VALUE underlying_io;
|
517
|
+
char *buf = StringValuePtr(str);
|
518
|
+
long len = RSTRING_LEN(str);
|
519
|
+
long left = len;
|
485
520
|
|
486
521
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
487
522
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -490,18 +525,17 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
490
525
|
GetOpenFile(io, fptr);
|
491
526
|
io_unset_nonblock(fptr, io);
|
492
527
|
|
493
|
-
char *buf = StringValuePtr(str);
|
494
|
-
long len = RSTRING_LEN(str);
|
495
|
-
long left = len;
|
496
|
-
|
497
528
|
while (left > 0) {
|
498
529
|
VALUE resume_value = Qnil;
|
499
530
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITE);
|
500
531
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
532
|
+
int result;
|
533
|
+
int completed;
|
534
|
+
|
501
535
|
io_uring_prep_write(sqe, fptr->fd, buf, left, 0);
|
502
536
|
|
503
|
-
|
504
|
-
|
537
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
538
|
+
completed = context_store_release(&backend->store, ctx);
|
505
539
|
if (!completed) {
|
506
540
|
context_attach_buffers(ctx, 1, &str);
|
507
541
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -550,10 +584,13 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
550
584
|
VALUE resume_value = Qnil;
|
551
585
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITEV);
|
552
586
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
587
|
+
int result;
|
588
|
+
int completed;
|
589
|
+
|
553
590
|
io_uring_prep_writev(sqe, fptr->fd, iov_ptr, iov_count, -1);
|
554
591
|
|
555
|
-
|
556
|
-
|
592
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
593
|
+
completed = context_store_release(&backend->store, ctx);
|
557
594
|
if (!completed) {
|
558
595
|
free(iov);
|
559
596
|
context_attach_buffers(ctx, argc, argv);
|
@@ -604,15 +641,18 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
604
641
|
long dynamic_len = length == Qnil;
|
605
642
|
long len = dynamic_len ? 4096 : NUM2INT(length);
|
606
643
|
long buf_pos = NUM2INT(pos);
|
644
|
+
int shrinkable;
|
645
|
+
char *buf;
|
646
|
+
long total = 0;
|
647
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);;
|
648
|
+
|
607
649
|
if (str != Qnil) {
|
608
650
|
int current_len = RSTRING_LEN(str);
|
609
651
|
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
610
652
|
}
|
611
653
|
else buf_pos = 0;
|
612
|
-
|
613
|
-
|
614
|
-
long total = 0;
|
615
|
-
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
654
|
+
shrinkable = io_setstrbuf(&str, buf_pos + len);
|
655
|
+
buf = RSTRING_PTR(str) + buf_pos;
|
616
656
|
|
617
657
|
GetBackend(self, backend);
|
618
658
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -625,10 +665,13 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
625
665
|
VALUE resume_value = Qnil;
|
626
666
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
627
667
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
668
|
+
int result;
|
669
|
+
int completed;
|
670
|
+
|
628
671
|
io_uring_prep_recv(sqe, fptr->fd, buf, len - total, 0);
|
629
672
|
|
630
|
-
|
631
|
-
|
673
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
674
|
+
completed = context_store_release(&backend->store, ctx);
|
632
675
|
if (!completed) {
|
633
676
|
context_attach_buffers(ctx, 1, &str);
|
634
677
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -675,10 +718,13 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
675
718
|
VALUE resume_value = Qnil;
|
676
719
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
677
720
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
721
|
+
int result;
|
722
|
+
int completed;
|
723
|
+
|
678
724
|
io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
|
679
725
|
|
680
|
-
|
681
|
-
|
726
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
727
|
+
completed = context_store_release(&backend->store, ctx);
|
682
728
|
if (!completed) {
|
683
729
|
context_attach_buffers(ctx, 1, &str);
|
684
730
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -724,10 +770,13 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
|
|
724
770
|
VALUE resume_value = Qnil;
|
725
771
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
726
772
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
773
|
+
int result;
|
774
|
+
int completed;
|
775
|
+
|
727
776
|
io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
|
728
777
|
|
729
|
-
|
730
|
-
|
778
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
779
|
+
completed = context_store_release(&backend->store, ctx);
|
731
780
|
if (!completed) {
|
732
781
|
context_attach_buffers(ctx, 1, &str);
|
733
782
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -753,6 +802,10 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
753
802
|
Backend_t *backend;
|
754
803
|
rb_io_t *fptr;
|
755
804
|
VALUE underlying_io;
|
805
|
+
char *buf;
|
806
|
+
long len;
|
807
|
+
long left;
|
808
|
+
int flags_int;
|
756
809
|
|
757
810
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
758
811
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -761,19 +814,22 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
761
814
|
GetOpenFile(io, fptr);
|
762
815
|
io_unset_nonblock(fptr, io);
|
763
816
|
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
817
|
+
buf = StringValuePtr(str);
|
818
|
+
len = RSTRING_LEN(str);
|
819
|
+
left = len;
|
820
|
+
flags_int = NUM2INT(flags);
|
768
821
|
|
769
822
|
while (left > 0) {
|
770
823
|
VALUE resume_value = Qnil;
|
771
824
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SEND);
|
772
825
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
826
|
+
int result;
|
827
|
+
int completed;
|
828
|
+
|
773
829
|
io_uring_prep_send(sqe, fptr->fd, buf, left, flags_int);
|
774
830
|
|
775
|
-
|
776
|
-
|
831
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
832
|
+
completed = context_store_release(&backend->store, ctx);
|
777
833
|
if (!completed) {
|
778
834
|
context_attach_buffers(ctx, 1, &str);
|
779
835
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -807,10 +863,13 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc
|
|
807
863
|
VALUE resume_value = Qnil;
|
808
864
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_ACCEPT);
|
809
865
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
866
|
+
int fd;
|
867
|
+
int completed;
|
868
|
+
|
810
869
|
io_uring_prep_accept(sqe, fptr->fd, &addr, &len, 0);
|
811
870
|
|
812
|
-
|
813
|
-
|
871
|
+
fd = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
872
|
+
completed = context_store_release(&backend->store, ctx);
|
814
873
|
RAISE_IF_EXCEPTION(resume_value);
|
815
874
|
if (!completed) return resume_value;
|
816
875
|
RB_GC_GUARD(resume_value);
|
@@ -861,6 +920,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
861
920
|
rb_io_t *dest_fptr;
|
862
921
|
VALUE underlying_io;
|
863
922
|
int total = 0;
|
923
|
+
VALUE resume_value = Qnil;
|
864
924
|
|
865
925
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
866
926
|
if (underlying_io != Qnil) src = underlying_io;
|
@@ -873,15 +933,16 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
873
933
|
GetOpenFile(dest, dest_fptr);
|
874
934
|
io_unset_nonblock(dest_fptr, dest);
|
875
935
|
|
876
|
-
VALUE resume_value = Qnil;
|
877
|
-
|
878
936
|
while (1) {
|
879
937
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
|
880
938
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
939
|
+
int result;
|
940
|
+
int completed;
|
941
|
+
|
881
942
|
io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
|
882
943
|
|
883
|
-
|
884
|
-
|
944
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
945
|
+
completed = context_store_release(&backend->store, ctx);
|
885
946
|
RAISE_IF_EXCEPTION(resume_value);
|
886
947
|
if (!completed) return resume_value;
|
887
948
|
|
@@ -909,29 +970,31 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize)
|
|
909
970
|
return io_uring_backend_splice(backend, src, dest, chunksize, 1);
|
910
971
|
}
|
911
972
|
|
912
|
-
|
913
973
|
VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
914
974
|
Backend_t *backend;
|
915
975
|
rb_io_t *fptr;
|
916
|
-
struct
|
917
|
-
|
976
|
+
struct sockaddr *ai_addr;
|
977
|
+
int ai_addrlen;
|
918
978
|
VALUE underlying_sock = rb_ivar_get(sock, ID_ivar_io);
|
979
|
+
VALUE resume_value = Qnil;
|
980
|
+
op_context_t *ctx;
|
981
|
+
struct io_uring_sqe *sqe;
|
982
|
+
int result;
|
983
|
+
int completed;
|
984
|
+
|
985
|
+
ai_addrlen = backend_getaddrinfo(host, port, &ai_addr);
|
986
|
+
|
919
987
|
if (underlying_sock != Qnil) sock = underlying_sock;
|
920
988
|
|
921
989
|
GetBackend(self, backend);
|
922
990
|
GetOpenFile(sock, fptr);
|
923
991
|
io_unset_nonblock(fptr, sock);
|
924
992
|
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
op_context_t *ctx = context_store_acquire(&backend->store, OP_CONNECT);
|
931
|
-
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
932
|
-
io_uring_prep_connect(sqe, fptr->fd, (struct sockaddr *)&addr, sizeof(addr));
|
933
|
-
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
934
|
-
int completed = context_store_release(&backend->store, ctx);
|
993
|
+
ctx = context_store_acquire(&backend->store, OP_CONNECT);
|
994
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
995
|
+
io_uring_prep_connect(sqe, fptr->fd, ai_addr, ai_addrlen);
|
996
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
997
|
+
completed = context_store_release(&backend->store, ctx);
|
935
998
|
RAISE_IF_EXCEPTION(resume_value);
|
936
999
|
if (!completed) return resume_value;
|
937
1000
|
RB_GC_GUARD(resume_value);
|
@@ -944,17 +1007,54 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
944
1007
|
Backend_t *backend;
|
945
1008
|
rb_io_t *fptr;
|
946
1009
|
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1010
|
+
VALUE resume_value;
|
1011
|
+
|
947
1012
|
if (underlying_io != Qnil) io = underlying_io;
|
948
1013
|
GetBackend(self, backend);
|
949
1014
|
GetOpenFile(io, fptr);
|
950
1015
|
io_unset_nonblock(fptr, io);
|
951
1016
|
|
952
|
-
|
1017
|
+
resume_value = io_uring_backend_wait_fd(backend, fptr->fd, RTEST(write));
|
1018
|
+
|
953
1019
|
RAISE_IF_EXCEPTION(resume_value);
|
954
1020
|
RB_GC_GUARD(resume_value);
|
955
1021
|
return self;
|
956
1022
|
}
|
957
1023
|
|
1024
|
+
// VALUE Backend_close(VALUE self, VALUE io) {
|
1025
|
+
// Backend_t *backend;
|
1026
|
+
// rb_io_t *fptr;
|
1027
|
+
// VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1028
|
+
// VALUE resume_value = Qnil;
|
1029
|
+
// op_context_t *ctx;
|
1030
|
+
// struct io_uring_sqe *sqe;
|
1031
|
+
// int result;
|
1032
|
+
// int completed;
|
1033
|
+
|
1034
|
+
// if (underlying_io != Qnil) io = underlying_io;
|
1035
|
+
// GetBackend(self, backend);
|
1036
|
+
// GetOpenFile(io, fptr);
|
1037
|
+
|
1038
|
+
// if (fptr->fd < 0) return Qnil;
|
1039
|
+
|
1040
|
+
// io_unset_nonblock(fptr, io);
|
1041
|
+
|
1042
|
+
// ctx = context_store_acquire(&backend->store, OP_CLOSE);
|
1043
|
+
// sqe = io_uring_get_sqe(&backend->ring);
|
1044
|
+
// io_uring_prep_close(sqe, fptr->fd);
|
1045
|
+
// result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
1046
|
+
// completed = context_store_release(&backend->store, ctx);
|
1047
|
+
// RAISE_IF_EXCEPTION(resume_value);
|
1048
|
+
// if (!completed) return resume_value;
|
1049
|
+
// RB_GC_GUARD(resume_value);
|
1050
|
+
|
1051
|
+
// if (result < 0) rb_syserr_fail(-result, strerror(-result));
|
1052
|
+
|
1053
|
+
// fptr_finalize(fptr);
|
1054
|
+
// // fptr->fd = -1;
|
1055
|
+
// return io;
|
1056
|
+
// }
|
1057
|
+
|
958
1058
|
inline struct __kernel_timespec double_to_timespec(double duration) {
|
959
1059
|
double duration_integral;
|
960
1060
|
double duration_fraction = modf(duration, &duration_integral);
|
@@ -972,18 +1072,18 @@ inline struct __kernel_timespec duration_to_timespec(VALUE duration) {
|
|
972
1072
|
int io_uring_backend_submit_timeout_and_await(Backend_t *backend, double duration, VALUE *resume_value) {
|
973
1073
|
struct __kernel_timespec ts = double_to_timespec(duration);
|
974
1074
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
975
|
-
|
976
1075
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
1076
|
+
|
977
1077
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
978
1078
|
io_uring_backend_defer_submit_and_await(backend, sqe, ctx, resume_value);
|
979
1079
|
return context_store_release(&backend->store, ctx);
|
980
1080
|
}
|
981
1081
|
|
982
1082
|
VALUE Backend_sleep(VALUE self, VALUE duration) {
|
1083
|
+
VALUE resume_value = Qnil;
|
983
1084
|
Backend_t *backend;
|
984
1085
|
GetBackend(self, backend);
|
985
1086
|
|
986
|
-
VALUE resume_value = Qnil;
|
987
1087
|
io_uring_backend_submit_timeout_and_await(backend, NUM2DBL(duration), &resume_value);
|
988
1088
|
RAISE_IF_EXCEPTION(resume_value);
|
989
1089
|
RB_GC_GUARD(resume_value);
|
@@ -1028,12 +1128,13 @@ struct Backend_timeout_ctx {
|
|
1028
1128
|
};
|
1029
1129
|
|
1030
1130
|
VALUE Backend_timeout_ensure(VALUE arg) {
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1131
|
+
struct Backend_timeout_ctx *timeout_ctx = (struct Backend_timeout_ctx *)arg;
|
1132
|
+
if (timeout_ctx->ctx->ref_count) {
|
1133
|
+
struct io_uring_sqe *sqe;
|
1034
1134
|
|
1135
|
+
timeout_ctx->ctx->result = -ECANCELED;
|
1035
1136
|
// op was not completed, so we need to cancel it
|
1036
|
-
|
1137
|
+
sqe = io_uring_get_sqe(&timeout_ctx->backend->ring);
|
1037
1138
|
io_uring_prep_cancel(sqe, timeout_ctx->ctx, 0);
|
1038
1139
|
timeout_ctx->backend->pending_sqes = 0;
|
1039
1140
|
io_uring_submit(&timeout_ctx->backend->ring);
|
@@ -1046,24 +1147,30 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1046
1147
|
VALUE duration;
|
1047
1148
|
VALUE exception;
|
1048
1149
|
VALUE move_on_value = Qnil;
|
1049
|
-
|
1050
|
-
|
1051
|
-
struct
|
1150
|
+
struct Backend_timeout_ctx timeout_ctx;
|
1151
|
+
op_context_t *ctx;
|
1152
|
+
struct io_uring_sqe *sqe;
|
1052
1153
|
Backend_t *backend;
|
1053
|
-
|
1154
|
+
struct __kernel_timespec ts;
|
1054
1155
|
VALUE result = Qnil;
|
1055
|
-
VALUE timeout
|
1156
|
+
VALUE timeout;
|
1056
1157
|
|
1057
|
-
|
1158
|
+
rb_scan_args(argc, argv, "21", &duration, &exception, &move_on_value);
|
1058
1159
|
|
1059
|
-
|
1160
|
+
ts = duration_to_timespec(duration);
|
1161
|
+
GetBackend(self, backend);
|
1162
|
+
timeout = rb_funcall(cTimeoutException, ID_new, 0);
|
1163
|
+
|
1164
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1165
|
+
ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
1060
1166
|
ctx->resume_value = timeout;
|
1061
1167
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
1062
1168
|
io_uring_sqe_set_data(sqe, ctx);
|
1063
1169
|
io_uring_backend_defer_submit(backend);
|
1064
1170
|
backend->base.op_count++;
|
1065
1171
|
|
1066
|
-
|
1172
|
+
timeout_ctx.backend = backend;
|
1173
|
+
timeout_ctx.ctx = ctx;
|
1067
1174
|
result = rb_ensure(Backend_timeout_ensure_safe, Qnil, Backend_timeout_ensure, (VALUE)&timeout_ctx);
|
1068
1175
|
|
1069
1176
|
if (result == timeout) {
|
@@ -1080,19 +1187,21 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1080
1187
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1081
1188
|
int pid_int = NUM2INT(pid);
|
1082
1189
|
int fd = pidfd_open(pid_int, 0);
|
1190
|
+
int status;
|
1191
|
+
pid_t ret;
|
1083
1192
|
|
1084
1193
|
if (fd >= 0) {
|
1194
|
+
VALUE resume_value;
|
1085
1195
|
Backend_t *backend;
|
1086
1196
|
GetBackend(self, backend);
|
1087
1197
|
|
1088
|
-
|
1198
|
+
resume_value = io_uring_backend_wait_fd(backend, fd, 0);
|
1089
1199
|
close(fd);
|
1090
1200
|
RAISE_IF_EXCEPTION(resume_value);
|
1091
1201
|
RB_GC_GUARD(resume_value);
|
1092
1202
|
}
|
1093
1203
|
|
1094
|
-
|
1095
|
-
pid_t ret = waitpid(pid_int, &status, WNOHANG);
|
1204
|
+
ret = waitpid(pid_int, &status, WNOHANG);
|
1096
1205
|
if (ret < 0) {
|
1097
1206
|
int e = errno;
|
1098
1207
|
if (e == ECHILD)
|
@@ -1105,6 +1214,8 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1105
1214
|
|
1106
1215
|
VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
1107
1216
|
Backend_t *backend;
|
1217
|
+
VALUE resume_value;
|
1218
|
+
|
1108
1219
|
GetBackend(self, backend);
|
1109
1220
|
|
1110
1221
|
if (backend->event_fd == -1) {
|
@@ -1115,7 +1226,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1115
1226
|
}
|
1116
1227
|
}
|
1117
1228
|
|
1118
|
-
|
1229
|
+
resume_value = io_uring_backend_wait_fd(backend, backend->event_fd, 0);
|
1119
1230
|
if (RTEST(raise)) RAISE_IF_EXCEPTION(resume_value);
|
1120
1231
|
RB_GC_GUARD(resume_value);
|
1121
1232
|
return resume_value;
|
@@ -1128,6 +1239,7 @@ VALUE Backend_kind(VALUE self) {
|
|
1128
1239
|
struct io_uring_sqe *Backend_chain_prepare_write(Backend_t *backend, VALUE io, VALUE str) {
|
1129
1240
|
rb_io_t *fptr;
|
1130
1241
|
VALUE underlying_io;
|
1242
|
+
struct io_uring_sqe *sqe;
|
1131
1243
|
|
1132
1244
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1133
1245
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -1135,17 +1247,15 @@ struct io_uring_sqe *Backend_chain_prepare_write(Backend_t *backend, VALUE io, V
|
|
1135
1247
|
GetOpenFile(io, fptr);
|
1136
1248
|
io_unset_nonblock(fptr, io);
|
1137
1249
|
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
1142
|
-
io_uring_prep_write(sqe, fptr->fd, buf, len, 0);
|
1250
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1251
|
+
io_uring_prep_write(sqe, fptr->fd, StringValuePtr(str), RSTRING_LEN(str), 0);
|
1143
1252
|
return sqe;
|
1144
1253
|
}
|
1145
1254
|
|
1146
1255
|
struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VALUE str, VALUE flags) {
|
1147
1256
|
rb_io_t *fptr;
|
1148
1257
|
VALUE underlying_io;
|
1258
|
+
struct io_uring_sqe *sqe;
|
1149
1259
|
|
1150
1260
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1151
1261
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -1153,12 +1263,8 @@ struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VA
|
|
1153
1263
|
GetOpenFile(io, fptr);
|
1154
1264
|
io_unset_nonblock(fptr, io);
|
1155
1265
|
|
1156
|
-
|
1157
|
-
|
1158
|
-
int flags_int = NUM2INT(flags);
|
1159
|
-
|
1160
|
-
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
1161
|
-
io_uring_prep_send(sqe, fptr->fd, buf, len, flags_int);
|
1266
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1267
|
+
io_uring_prep_send(sqe, fptr->fd, StringValuePtr(str), RSTRING_LEN(str), NUM2INT(flags));
|
1162
1268
|
return sqe;
|
1163
1269
|
}
|
1164
1270
|
|
@@ -1166,6 +1272,7 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src,
|
|
1166
1272
|
rb_io_t *src_fptr;
|
1167
1273
|
rb_io_t *dest_fptr;
|
1168
1274
|
VALUE underlying_io;
|
1275
|
+
struct io_uring_sqe *sqe;
|
1169
1276
|
|
1170
1277
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
1171
1278
|
if (underlying_io != Qnil) src = underlying_io;
|
@@ -1178,7 +1285,7 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src,
|
|
1178
1285
|
GetOpenFile(dest, dest_fptr);
|
1179
1286
|
io_unset_nonblock(dest_fptr, dest);
|
1180
1287
|
|
1181
|
-
|
1288
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1182
1289
|
io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
|
1183
1290
|
return sqe;
|
1184
1291
|
}
|
@@ -1206,14 +1313,19 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1206
1313
|
unsigned int sqe_count = 0;
|
1207
1314
|
struct io_uring_sqe *last_sqe = 0;
|
1208
1315
|
Backend_t *backend;
|
1316
|
+
int result;
|
1317
|
+
int completed;
|
1318
|
+
op_context_t *ctx;
|
1319
|
+
|
1209
1320
|
GetBackend(self, backend);
|
1210
1321
|
if (argc == 0) return resume_value;
|
1211
1322
|
|
1212
|
-
|
1323
|
+
ctx = context_store_acquire(&backend->store, OP_CHAIN);
|
1213
1324
|
for (int i = 0; i < argc; i++) {
|
1214
1325
|
VALUE op = argv[i];
|
1215
1326
|
VALUE op_type = RARRAY_AREF(op, 0);
|
1216
1327
|
VALUE op_len = RARRAY_LEN(op);
|
1328
|
+
unsigned int flags;
|
1217
1329
|
|
1218
1330
|
if (op_type == SYM_write && op_len == 3) {
|
1219
1331
|
last_sqe = Backend_chain_prepare_write(backend, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2));
|
@@ -1223,13 +1335,16 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1223
1335
|
else if (op_type == SYM_splice && op_len == 4)
|
1224
1336
|
last_sqe = Backend_chain_prepare_splice(backend, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1225
1337
|
else {
|
1338
|
+
|
1226
1339
|
if (sqe_count) {
|
1340
|
+
struct io_uring_sqe *sqe;
|
1341
|
+
|
1227
1342
|
io_uring_sqe_set_data(last_sqe, ctx);
|
1228
1343
|
io_uring_sqe_set_flags(last_sqe, IOSQE_ASYNC);
|
1229
1344
|
|
1230
1345
|
ctx->ref_count = sqe_count;
|
1231
1346
|
ctx->result = -ECANCELED;
|
1232
|
-
|
1347
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1233
1348
|
io_uring_prep_cancel(sqe, ctx, 0);
|
1234
1349
|
backend->pending_sqes = 0;
|
1235
1350
|
io_uring_submit(&backend->ring);
|
@@ -1242,7 +1357,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1242
1357
|
}
|
1243
1358
|
|
1244
1359
|
io_uring_sqe_set_data(last_sqe, ctx);
|
1245
|
-
|
1360
|
+
flags = (i == (argc - 1)) ? IOSQE_ASYNC : IOSQE_ASYNC | IOSQE_IO_LINK;
|
1246
1361
|
io_uring_sqe_set_flags(last_sqe, flags);
|
1247
1362
|
sqe_count++;
|
1248
1363
|
}
|
@@ -1251,14 +1366,16 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1251
1366
|
ctx->ref_count = sqe_count + 1;
|
1252
1367
|
io_uring_backend_defer_submit(backend);
|
1253
1368
|
resume_value = backend_await((struct Backend_base *)backend);
|
1254
|
-
|
1255
|
-
|
1369
|
+
result = ctx->result;
|
1370
|
+
completed = context_store_release(&backend->store, ctx);
|
1256
1371
|
if (!completed) {
|
1372
|
+
struct io_uring_sqe *sqe;
|
1373
|
+
|
1257
1374
|
Backend_chain_ctx_attach_buffers(ctx, argc, argv);
|
1258
1375
|
|
1259
1376
|
// op was not completed (an exception was raised), so we need to cancel it
|
1260
1377
|
ctx->result = -ECANCELED;
|
1261
|
-
|
1378
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1262
1379
|
io_uring_prep_cancel(sqe, ctx, 0);
|
1263
1380
|
backend->pending_sqes = 0;
|
1264
1381
|
io_uring_submit(&backend->ring);
|
@@ -1322,8 +1439,10 @@ static inline void splice_chunks_get_sqe(
|
|
1322
1439
|
}
|
1323
1440
|
|
1324
1441
|
static inline void splice_chunks_cancel(Backend_t *backend, op_context_t *ctx) {
|
1442
|
+
struct io_uring_sqe *sqe;
|
1443
|
+
|
1325
1444
|
ctx->result = -ECANCELED;
|
1326
|
-
|
1445
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1327
1446
|
io_uring_prep_cancel(sqe, ctx, 0);
|
1328
1447
|
backend->pending_sqes = 0;
|
1329
1448
|
io_uring_submit(&backend->ring);
|
@@ -1336,9 +1455,11 @@ static inline int splice_chunks_await_ops(
|
|
1336
1455
|
VALUE *switchpoint_result
|
1337
1456
|
)
|
1338
1457
|
{
|
1458
|
+
int completed;
|
1339
1459
|
int res = io_uring_backend_defer_submit_and_await(backend, 0, *ctx, switchpoint_result);
|
1460
|
+
|
1340
1461
|
if (result) (*result) = res;
|
1341
|
-
|
1462
|
+
completed = context_store_release(&backend->store, *ctx);
|
1342
1463
|
if (!completed) {
|
1343
1464
|
splice_chunks_cancel(backend, *ctx);
|
1344
1465
|
if (TEST_EXCEPTION(*switchpoint_result)) return 1;
|
@@ -1352,17 +1473,22 @@ static inline int splice_chunks_await_ops(
|
|
1352
1473
|
|
1353
1474
|
VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VALUE postfix, VALUE chunk_prefix, VALUE chunk_postfix, VALUE chunk_size) {
|
1354
1475
|
Backend_t *backend;
|
1355
|
-
GetBackend(self, backend);
|
1356
1476
|
int total = 0;
|
1357
1477
|
int err = 0;
|
1358
1478
|
VALUE switchpoint_result = Qnil;
|
1359
1479
|
op_context_t *ctx = 0;
|
1360
1480
|
struct io_uring_sqe *sqe = 0;
|
1361
|
-
|
1481
|
+
int maxlen;
|
1482
|
+
VALUE underlying_io;
|
1483
|
+
VALUE str = Qnil;
|
1484
|
+
VALUE chunk_len_value = Qnil;
|
1362
1485
|
rb_io_t *src_fptr;
|
1363
1486
|
rb_io_t *dest_fptr;
|
1487
|
+
int pipefd[2] = { -1, -1 };
|
1488
|
+
|
1489
|
+
GetBackend(self, backend);
|
1364
1490
|
|
1365
|
-
|
1491
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
1366
1492
|
if (underlying_io != Qnil) src = underlying_io;
|
1367
1493
|
GetOpenFile(src, src_fptr);
|
1368
1494
|
io_verify_blocking_mode(src_fptr, src, Qtrue);
|
@@ -1373,11 +1499,8 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1373
1499
|
GetOpenFile(dest, dest_fptr);
|
1374
1500
|
io_verify_blocking_mode(dest_fptr, dest, Qtrue);
|
1375
1501
|
|
1376
|
-
|
1377
|
-
VALUE str = Qnil;
|
1378
|
-
VALUE chunk_len_value = Qnil;
|
1502
|
+
maxlen = NUM2INT(chunk_size);
|
1379
1503
|
|
1380
|
-
int pipefd[2] = { -1, -1 };
|
1381
1504
|
if (pipe(pipefd) == -1) {
|
1382
1505
|
err = errno;
|
1383
1506
|
goto syscallerror;
|
@@ -1521,6 +1644,7 @@ void Init_Backend() {
|
|
1521
1644
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1522
1645
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1523
1646
|
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1647
|
+
// rb_define_method(cBackend, "close", Backend_close, 1);
|
1524
1648
|
|
1525
1649
|
SYM_io_uring = ID2SYM(rb_intern("io_uring"));
|
1526
1650
|
SYM_send = ID2SYM(rb_intern("send"));
|