polyphony 0.73 → 0.76
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 +14 -10
- data/.github/workflows/test_io_uring.yml +32 -0
- data/CHANGELOG.md +22 -0
- data/Gemfile.lock +16 -13
- data/bin/pdbg +0 -0
- data/bin/polyphony-debug +0 -0
- data/bin/stress.rb +0 -0
- data/bin/test +0 -0
- data/ext/polyphony/backend_common.c +84 -12
- data/ext/polyphony/backend_common.h +8 -0
- data/ext/polyphony/backend_io_uring.c +226 -106
- 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 +7 -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/lib/polyphony/extensions/fiber.rb +85 -3
- 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 +0 -5
- data/test/test_backend.rb +3 -5
- 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_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 +1 -1
- data/test/test_trace.rb +7 -1
- metadata +4 -3
@@ -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;
|
@@ -282,9 +295,11 @@ int io_uring_backend_defer_submit_and_await(
|
|
282
295
|
switchpoint_result = backend_await((struct Backend_base *)backend);
|
283
296
|
|
284
297
|
if (ctx->ref_count > 1) {
|
298
|
+
struct io_uring_sqe *sqe;
|
299
|
+
|
285
300
|
// op was not completed (an exception was raised), so we need to cancel it
|
286
301
|
ctx->result = -ECANCELED;
|
287
|
-
|
302
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
288
303
|
io_uring_prep_cancel(sqe, ctx, 0);
|
289
304
|
backend->pending_sqes = 0;
|
290
305
|
io_uring_submit(&backend->ring);
|
@@ -316,16 +331,20 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
316
331
|
long dynamic_len = length == Qnil;
|
317
332
|
long buffer_size = dynamic_len ? 4096 : NUM2INT(length);
|
318
333
|
long buf_pos = NUM2INT(pos);
|
334
|
+
int shrinkable;
|
335
|
+
char *buf;
|
336
|
+
long total = 0;
|
337
|
+
int read_to_eof = RTEST(to_eof);
|
338
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
339
|
+
|
340
|
+
|
319
341
|
if (str != Qnil) {
|
320
342
|
int current_len = RSTRING_LEN(str);
|
321
343
|
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
322
344
|
}
|
323
345
|
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);
|
346
|
+
shrinkable = io_setstrbuf(&str, buf_pos + buffer_size);
|
347
|
+
buf = RSTRING_PTR(str) + buf_pos;
|
329
348
|
|
330
349
|
GetBackend(self, backend);
|
331
350
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -338,10 +357,13 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
338
357
|
VALUE resume_value = Qnil;
|
339
358
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
340
359
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
360
|
+
int result;
|
361
|
+
int completed;
|
362
|
+
|
341
363
|
io_uring_prep_read(sqe, fptr->fd, buf, buffer_size - total, -1);
|
342
364
|
|
343
|
-
|
344
|
-
|
365
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
366
|
+
completed = context_store_release(&backend->store, ctx);
|
345
367
|
if (!completed) {
|
346
368
|
context_attach_buffers(ctx, 1, &str);
|
347
369
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -402,10 +424,13 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
402
424
|
VALUE resume_value = Qnil;
|
403
425
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
404
426
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
427
|
+
ssize_t result;
|
428
|
+
int completed;
|
429
|
+
|
405
430
|
io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
|
406
431
|
|
407
|
-
|
408
|
-
|
432
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
433
|
+
completed = context_store_release(&backend->store, ctx);
|
409
434
|
if (!completed) {
|
410
435
|
context_attach_buffers(ctx, 1, &str);
|
411
436
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -452,10 +477,13 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
452
477
|
VALUE resume_value = Qnil;
|
453
478
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
454
479
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
480
|
+
ssize_t result;
|
481
|
+
int completed;
|
482
|
+
|
455
483
|
io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
|
456
484
|
|
457
|
-
|
458
|
-
|
485
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
486
|
+
completed = context_store_release(&backend->store, ctx);
|
459
487
|
if (!completed) {
|
460
488
|
context_attach_buffers(ctx, 1, &str);
|
461
489
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -482,6 +510,9 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
482
510
|
Backend_t *backend;
|
483
511
|
rb_io_t *fptr;
|
484
512
|
VALUE underlying_io;
|
513
|
+
char *buf = StringValuePtr(str);
|
514
|
+
long len = RSTRING_LEN(str);
|
515
|
+
long left = len;
|
485
516
|
|
486
517
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
487
518
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -490,18 +521,17 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
490
521
|
GetOpenFile(io, fptr);
|
491
522
|
io_unset_nonblock(fptr, io);
|
492
523
|
|
493
|
-
char *buf = StringValuePtr(str);
|
494
|
-
long len = RSTRING_LEN(str);
|
495
|
-
long left = len;
|
496
|
-
|
497
524
|
while (left > 0) {
|
498
525
|
VALUE resume_value = Qnil;
|
499
526
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITE);
|
500
527
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
528
|
+
int result;
|
529
|
+
int completed;
|
530
|
+
|
501
531
|
io_uring_prep_write(sqe, fptr->fd, buf, left, 0);
|
502
532
|
|
503
|
-
|
504
|
-
|
533
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
534
|
+
completed = context_store_release(&backend->store, ctx);
|
505
535
|
if (!completed) {
|
506
536
|
context_attach_buffers(ctx, 1, &str);
|
507
537
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -550,10 +580,13 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
550
580
|
VALUE resume_value = Qnil;
|
551
581
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITEV);
|
552
582
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
583
|
+
int result;
|
584
|
+
int completed;
|
585
|
+
|
553
586
|
io_uring_prep_writev(sqe, fptr->fd, iov_ptr, iov_count, -1);
|
554
587
|
|
555
|
-
|
556
|
-
|
588
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
589
|
+
completed = context_store_release(&backend->store, ctx);
|
557
590
|
if (!completed) {
|
558
591
|
free(iov);
|
559
592
|
context_attach_buffers(ctx, argc, argv);
|
@@ -604,15 +637,18 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
604
637
|
long dynamic_len = length == Qnil;
|
605
638
|
long len = dynamic_len ? 4096 : NUM2INT(length);
|
606
639
|
long buf_pos = NUM2INT(pos);
|
640
|
+
int shrinkable;
|
641
|
+
char *buf;
|
642
|
+
long total = 0;
|
643
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);;
|
644
|
+
|
607
645
|
if (str != Qnil) {
|
608
646
|
int current_len = RSTRING_LEN(str);
|
609
647
|
if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
|
610
648
|
}
|
611
649
|
else buf_pos = 0;
|
612
|
-
|
613
|
-
|
614
|
-
long total = 0;
|
615
|
-
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
650
|
+
shrinkable = io_setstrbuf(&str, buf_pos + len);
|
651
|
+
buf = RSTRING_PTR(str) + buf_pos;
|
616
652
|
|
617
653
|
GetBackend(self, backend);
|
618
654
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -625,10 +661,13 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
625
661
|
VALUE resume_value = Qnil;
|
626
662
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
627
663
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
664
|
+
int result;
|
665
|
+
int completed;
|
666
|
+
|
628
667
|
io_uring_prep_recv(sqe, fptr->fd, buf, len - total, 0);
|
629
668
|
|
630
|
-
|
631
|
-
|
669
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
670
|
+
completed = context_store_release(&backend->store, ctx);
|
632
671
|
if (!completed) {
|
633
672
|
context_attach_buffers(ctx, 1, &str);
|
634
673
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -675,10 +714,13 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
675
714
|
VALUE resume_value = Qnil;
|
676
715
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
677
716
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
717
|
+
int result;
|
718
|
+
int completed;
|
719
|
+
|
678
720
|
io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
|
679
721
|
|
680
|
-
|
681
|
-
|
722
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
723
|
+
completed = context_store_release(&backend->store, ctx);
|
682
724
|
if (!completed) {
|
683
725
|
context_attach_buffers(ctx, 1, &str);
|
684
726
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -724,10 +766,13 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
|
|
724
766
|
VALUE resume_value = Qnil;
|
725
767
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
726
768
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
769
|
+
int result;
|
770
|
+
int completed;
|
771
|
+
|
727
772
|
io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
|
728
773
|
|
729
|
-
|
730
|
-
|
774
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
775
|
+
completed = context_store_release(&backend->store, ctx);
|
731
776
|
if (!completed) {
|
732
777
|
context_attach_buffers(ctx, 1, &str);
|
733
778
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -753,6 +798,10 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
753
798
|
Backend_t *backend;
|
754
799
|
rb_io_t *fptr;
|
755
800
|
VALUE underlying_io;
|
801
|
+
char *buf;
|
802
|
+
long len;
|
803
|
+
long left;
|
804
|
+
int flags_int;
|
756
805
|
|
757
806
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
758
807
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -761,19 +810,22 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
761
810
|
GetOpenFile(io, fptr);
|
762
811
|
io_unset_nonblock(fptr, io);
|
763
812
|
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
813
|
+
buf = StringValuePtr(str);
|
814
|
+
len = RSTRING_LEN(str);
|
815
|
+
left = len;
|
816
|
+
flags_int = NUM2INT(flags);
|
768
817
|
|
769
818
|
while (left > 0) {
|
770
819
|
VALUE resume_value = Qnil;
|
771
820
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SEND);
|
772
821
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
822
|
+
int result;
|
823
|
+
int completed;
|
824
|
+
|
773
825
|
io_uring_prep_send(sqe, fptr->fd, buf, left, flags_int);
|
774
826
|
|
775
|
-
|
776
|
-
|
827
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
828
|
+
completed = context_store_release(&backend->store, ctx);
|
777
829
|
if (!completed) {
|
778
830
|
context_attach_buffers(ctx, 1, &str);
|
779
831
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -807,10 +859,13 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc
|
|
807
859
|
VALUE resume_value = Qnil;
|
808
860
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_ACCEPT);
|
809
861
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
862
|
+
int fd;
|
863
|
+
int completed;
|
864
|
+
|
810
865
|
io_uring_prep_accept(sqe, fptr->fd, &addr, &len, 0);
|
811
866
|
|
812
|
-
|
813
|
-
|
867
|
+
fd = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
868
|
+
completed = context_store_release(&backend->store, ctx);
|
814
869
|
RAISE_IF_EXCEPTION(resume_value);
|
815
870
|
if (!completed) return resume_value;
|
816
871
|
RB_GC_GUARD(resume_value);
|
@@ -861,6 +916,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
861
916
|
rb_io_t *dest_fptr;
|
862
917
|
VALUE underlying_io;
|
863
918
|
int total = 0;
|
919
|
+
VALUE resume_value = Qnil;
|
864
920
|
|
865
921
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
866
922
|
if (underlying_io != Qnil) src = underlying_io;
|
@@ -873,15 +929,16 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
873
929
|
GetOpenFile(dest, dest_fptr);
|
874
930
|
io_unset_nonblock(dest_fptr, dest);
|
875
931
|
|
876
|
-
VALUE resume_value = Qnil;
|
877
|
-
|
878
932
|
while (1) {
|
879
933
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
|
880
934
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
935
|
+
int result;
|
936
|
+
int completed;
|
937
|
+
|
881
938
|
io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
|
882
939
|
|
883
|
-
|
884
|
-
|
940
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
941
|
+
completed = context_store_release(&backend->store, ctx);
|
885
942
|
RAISE_IF_EXCEPTION(resume_value);
|
886
943
|
if (!completed) return resume_value;
|
887
944
|
|
@@ -909,29 +966,31 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize)
|
|
909
966
|
return io_uring_backend_splice(backend, src, dest, chunksize, 1);
|
910
967
|
}
|
911
968
|
|
912
|
-
|
913
969
|
VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
914
970
|
Backend_t *backend;
|
915
971
|
rb_io_t *fptr;
|
916
|
-
struct
|
917
|
-
|
972
|
+
struct sockaddr *ai_addr;
|
973
|
+
int ai_addrlen;
|
918
974
|
VALUE underlying_sock = rb_ivar_get(sock, ID_ivar_io);
|
975
|
+
VALUE resume_value = Qnil;
|
976
|
+
op_context_t *ctx;
|
977
|
+
struct io_uring_sqe *sqe;
|
978
|
+
int result;
|
979
|
+
int completed;
|
980
|
+
|
981
|
+
ai_addrlen = backend_getaddrinfo(host, port, &ai_addr);
|
982
|
+
|
919
983
|
if (underlying_sock != Qnil) sock = underlying_sock;
|
920
984
|
|
921
985
|
GetBackend(self, backend);
|
922
986
|
GetOpenFile(sock, fptr);
|
923
987
|
io_unset_nonblock(fptr, sock);
|
924
988
|
|
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);
|
989
|
+
ctx = context_store_acquire(&backend->store, OP_CONNECT);
|
990
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
991
|
+
io_uring_prep_connect(sqe, fptr->fd, ai_addr, ai_addrlen);
|
992
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
993
|
+
completed = context_store_release(&backend->store, ctx);
|
935
994
|
RAISE_IF_EXCEPTION(resume_value);
|
936
995
|
if (!completed) return resume_value;
|
937
996
|
RB_GC_GUARD(resume_value);
|
@@ -944,17 +1003,54 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
944
1003
|
Backend_t *backend;
|
945
1004
|
rb_io_t *fptr;
|
946
1005
|
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1006
|
+
VALUE resume_value;
|
1007
|
+
|
947
1008
|
if (underlying_io != Qnil) io = underlying_io;
|
948
1009
|
GetBackend(self, backend);
|
949
1010
|
GetOpenFile(io, fptr);
|
950
1011
|
io_unset_nonblock(fptr, io);
|
951
1012
|
|
952
|
-
|
1013
|
+
resume_value = io_uring_backend_wait_fd(backend, fptr->fd, RTEST(write));
|
1014
|
+
|
953
1015
|
RAISE_IF_EXCEPTION(resume_value);
|
954
1016
|
RB_GC_GUARD(resume_value);
|
955
1017
|
return self;
|
956
1018
|
}
|
957
1019
|
|
1020
|
+
// VALUE Backend_close(VALUE self, VALUE io) {
|
1021
|
+
// Backend_t *backend;
|
1022
|
+
// rb_io_t *fptr;
|
1023
|
+
// VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1024
|
+
// VALUE resume_value = Qnil;
|
1025
|
+
// op_context_t *ctx;
|
1026
|
+
// struct io_uring_sqe *sqe;
|
1027
|
+
// int result;
|
1028
|
+
// int completed;
|
1029
|
+
|
1030
|
+
// if (underlying_io != Qnil) io = underlying_io;
|
1031
|
+
// GetBackend(self, backend);
|
1032
|
+
// GetOpenFile(io, fptr);
|
1033
|
+
|
1034
|
+
// if (fptr->fd < 0) return Qnil;
|
1035
|
+
|
1036
|
+
// io_unset_nonblock(fptr, io);
|
1037
|
+
|
1038
|
+
// ctx = context_store_acquire(&backend->store, OP_CLOSE);
|
1039
|
+
// sqe = io_uring_get_sqe(&backend->ring);
|
1040
|
+
// io_uring_prep_close(sqe, fptr->fd);
|
1041
|
+
// result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
1042
|
+
// completed = context_store_release(&backend->store, ctx);
|
1043
|
+
// RAISE_IF_EXCEPTION(resume_value);
|
1044
|
+
// if (!completed) return resume_value;
|
1045
|
+
// RB_GC_GUARD(resume_value);
|
1046
|
+
|
1047
|
+
// if (result < 0) rb_syserr_fail(-result, strerror(-result));
|
1048
|
+
|
1049
|
+
// fptr_finalize(fptr);
|
1050
|
+
// // fptr->fd = -1;
|
1051
|
+
// return io;
|
1052
|
+
// }
|
1053
|
+
|
958
1054
|
inline struct __kernel_timespec double_to_timespec(double duration) {
|
959
1055
|
double duration_integral;
|
960
1056
|
double duration_fraction = modf(duration, &duration_integral);
|
@@ -972,18 +1068,18 @@ inline struct __kernel_timespec duration_to_timespec(VALUE duration) {
|
|
972
1068
|
int io_uring_backend_submit_timeout_and_await(Backend_t *backend, double duration, VALUE *resume_value) {
|
973
1069
|
struct __kernel_timespec ts = double_to_timespec(duration);
|
974
1070
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
975
|
-
|
976
1071
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
1072
|
+
|
977
1073
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
978
1074
|
io_uring_backend_defer_submit_and_await(backend, sqe, ctx, resume_value);
|
979
1075
|
return context_store_release(&backend->store, ctx);
|
980
1076
|
}
|
981
1077
|
|
982
1078
|
VALUE Backend_sleep(VALUE self, VALUE duration) {
|
1079
|
+
VALUE resume_value = Qnil;
|
983
1080
|
Backend_t *backend;
|
984
1081
|
GetBackend(self, backend);
|
985
1082
|
|
986
|
-
VALUE resume_value = Qnil;
|
987
1083
|
io_uring_backend_submit_timeout_and_await(backend, NUM2DBL(duration), &resume_value);
|
988
1084
|
RAISE_IF_EXCEPTION(resume_value);
|
989
1085
|
RB_GC_GUARD(resume_value);
|
@@ -1028,12 +1124,13 @@ struct Backend_timeout_ctx {
|
|
1028
1124
|
};
|
1029
1125
|
|
1030
1126
|
VALUE Backend_timeout_ensure(VALUE arg) {
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1127
|
+
struct Backend_timeout_ctx *timeout_ctx = (struct Backend_timeout_ctx *)arg;
|
1128
|
+
if (timeout_ctx->ctx->ref_count) {
|
1129
|
+
struct io_uring_sqe *sqe;
|
1034
1130
|
|
1131
|
+
timeout_ctx->ctx->result = -ECANCELED;
|
1035
1132
|
// op was not completed, so we need to cancel it
|
1036
|
-
|
1133
|
+
sqe = io_uring_get_sqe(&timeout_ctx->backend->ring);
|
1037
1134
|
io_uring_prep_cancel(sqe, timeout_ctx->ctx, 0);
|
1038
1135
|
timeout_ctx->backend->pending_sqes = 0;
|
1039
1136
|
io_uring_submit(&timeout_ctx->backend->ring);
|
@@ -1046,24 +1143,30 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1046
1143
|
VALUE duration;
|
1047
1144
|
VALUE exception;
|
1048
1145
|
VALUE move_on_value = Qnil;
|
1049
|
-
|
1050
|
-
|
1051
|
-
struct
|
1146
|
+
struct Backend_timeout_ctx timeout_ctx;
|
1147
|
+
op_context_t *ctx;
|
1148
|
+
struct io_uring_sqe *sqe;
|
1052
1149
|
Backend_t *backend;
|
1053
|
-
|
1150
|
+
struct __kernel_timespec ts;
|
1054
1151
|
VALUE result = Qnil;
|
1055
|
-
VALUE timeout
|
1152
|
+
VALUE timeout;
|
1056
1153
|
|
1057
|
-
|
1154
|
+
rb_scan_args(argc, argv, "21", &duration, &exception, &move_on_value);
|
1058
1155
|
|
1059
|
-
|
1156
|
+
ts = duration_to_timespec(duration);
|
1157
|
+
GetBackend(self, backend);
|
1158
|
+
timeout = rb_funcall(cTimeoutException, ID_new, 0);
|
1159
|
+
|
1160
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1161
|
+
ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
1060
1162
|
ctx->resume_value = timeout;
|
1061
1163
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
1062
1164
|
io_uring_sqe_set_data(sqe, ctx);
|
1063
1165
|
io_uring_backend_defer_submit(backend);
|
1064
1166
|
backend->base.op_count++;
|
1065
1167
|
|
1066
|
-
|
1168
|
+
timeout_ctx.backend = backend;
|
1169
|
+
timeout_ctx.ctx = ctx;
|
1067
1170
|
result = rb_ensure(Backend_timeout_ensure_safe, Qnil, Backend_timeout_ensure, (VALUE)&timeout_ctx);
|
1068
1171
|
|
1069
1172
|
if (result == timeout) {
|
@@ -1080,19 +1183,21 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1080
1183
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1081
1184
|
int pid_int = NUM2INT(pid);
|
1082
1185
|
int fd = pidfd_open(pid_int, 0);
|
1186
|
+
int status;
|
1187
|
+
pid_t ret;
|
1083
1188
|
|
1084
1189
|
if (fd >= 0) {
|
1190
|
+
VALUE resume_value;
|
1085
1191
|
Backend_t *backend;
|
1086
1192
|
GetBackend(self, backend);
|
1087
1193
|
|
1088
|
-
|
1194
|
+
resume_value = io_uring_backend_wait_fd(backend, fd, 0);
|
1089
1195
|
close(fd);
|
1090
1196
|
RAISE_IF_EXCEPTION(resume_value);
|
1091
1197
|
RB_GC_GUARD(resume_value);
|
1092
1198
|
}
|
1093
1199
|
|
1094
|
-
|
1095
|
-
pid_t ret = waitpid(pid_int, &status, WNOHANG);
|
1200
|
+
ret = waitpid(pid_int, &status, WNOHANG);
|
1096
1201
|
if (ret < 0) {
|
1097
1202
|
int e = errno;
|
1098
1203
|
if (e == ECHILD)
|
@@ -1105,6 +1210,8 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1105
1210
|
|
1106
1211
|
VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
1107
1212
|
Backend_t *backend;
|
1213
|
+
VALUE resume_value;
|
1214
|
+
|
1108
1215
|
GetBackend(self, backend);
|
1109
1216
|
|
1110
1217
|
if (backend->event_fd == -1) {
|
@@ -1115,7 +1222,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1115
1222
|
}
|
1116
1223
|
}
|
1117
1224
|
|
1118
|
-
|
1225
|
+
resume_value = io_uring_backend_wait_fd(backend, backend->event_fd, 0);
|
1119
1226
|
if (RTEST(raise)) RAISE_IF_EXCEPTION(resume_value);
|
1120
1227
|
RB_GC_GUARD(resume_value);
|
1121
1228
|
return resume_value;
|
@@ -1128,6 +1235,7 @@ VALUE Backend_kind(VALUE self) {
|
|
1128
1235
|
struct io_uring_sqe *Backend_chain_prepare_write(Backend_t *backend, VALUE io, VALUE str) {
|
1129
1236
|
rb_io_t *fptr;
|
1130
1237
|
VALUE underlying_io;
|
1238
|
+
struct io_uring_sqe *sqe;
|
1131
1239
|
|
1132
1240
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1133
1241
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -1135,17 +1243,15 @@ struct io_uring_sqe *Backend_chain_prepare_write(Backend_t *backend, VALUE io, V
|
|
1135
1243
|
GetOpenFile(io, fptr);
|
1136
1244
|
io_unset_nonblock(fptr, io);
|
1137
1245
|
|
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);
|
1246
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1247
|
+
io_uring_prep_write(sqe, fptr->fd, StringValuePtr(str), RSTRING_LEN(str), 0);
|
1143
1248
|
return sqe;
|
1144
1249
|
}
|
1145
1250
|
|
1146
1251
|
struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VALUE str, VALUE flags) {
|
1147
1252
|
rb_io_t *fptr;
|
1148
1253
|
VALUE underlying_io;
|
1254
|
+
struct io_uring_sqe *sqe;
|
1149
1255
|
|
1150
1256
|
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
1151
1257
|
if (underlying_io != Qnil) io = underlying_io;
|
@@ -1153,12 +1259,8 @@ struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VA
|
|
1153
1259
|
GetOpenFile(io, fptr);
|
1154
1260
|
io_unset_nonblock(fptr, io);
|
1155
1261
|
|
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);
|
1262
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1263
|
+
io_uring_prep_send(sqe, fptr->fd, StringValuePtr(str), RSTRING_LEN(str), NUM2INT(flags));
|
1162
1264
|
return sqe;
|
1163
1265
|
}
|
1164
1266
|
|
@@ -1166,6 +1268,7 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src,
|
|
1166
1268
|
rb_io_t *src_fptr;
|
1167
1269
|
rb_io_t *dest_fptr;
|
1168
1270
|
VALUE underlying_io;
|
1271
|
+
struct io_uring_sqe *sqe;
|
1169
1272
|
|
1170
1273
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
1171
1274
|
if (underlying_io != Qnil) src = underlying_io;
|
@@ -1178,7 +1281,7 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src,
|
|
1178
1281
|
GetOpenFile(dest, dest_fptr);
|
1179
1282
|
io_unset_nonblock(dest_fptr, dest);
|
1180
1283
|
|
1181
|
-
|
1284
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1182
1285
|
io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
|
1183
1286
|
return sqe;
|
1184
1287
|
}
|
@@ -1206,14 +1309,19 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1206
1309
|
unsigned int sqe_count = 0;
|
1207
1310
|
struct io_uring_sqe *last_sqe = 0;
|
1208
1311
|
Backend_t *backend;
|
1312
|
+
int result;
|
1313
|
+
int completed;
|
1314
|
+
op_context_t *ctx;
|
1315
|
+
|
1209
1316
|
GetBackend(self, backend);
|
1210
1317
|
if (argc == 0) return resume_value;
|
1211
1318
|
|
1212
|
-
|
1319
|
+
ctx = context_store_acquire(&backend->store, OP_CHAIN);
|
1213
1320
|
for (int i = 0; i < argc; i++) {
|
1214
1321
|
VALUE op = argv[i];
|
1215
1322
|
VALUE op_type = RARRAY_AREF(op, 0);
|
1216
1323
|
VALUE op_len = RARRAY_LEN(op);
|
1324
|
+
unsigned int flags;
|
1217
1325
|
|
1218
1326
|
if (op_type == SYM_write && op_len == 3) {
|
1219
1327
|
last_sqe = Backend_chain_prepare_write(backend, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2));
|
@@ -1223,13 +1331,16 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1223
1331
|
else if (op_type == SYM_splice && op_len == 4)
|
1224
1332
|
last_sqe = Backend_chain_prepare_splice(backend, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1225
1333
|
else {
|
1334
|
+
|
1226
1335
|
if (sqe_count) {
|
1336
|
+
struct io_uring_sqe *sqe;
|
1337
|
+
|
1227
1338
|
io_uring_sqe_set_data(last_sqe, ctx);
|
1228
1339
|
io_uring_sqe_set_flags(last_sqe, IOSQE_ASYNC);
|
1229
1340
|
|
1230
1341
|
ctx->ref_count = sqe_count;
|
1231
1342
|
ctx->result = -ECANCELED;
|
1232
|
-
|
1343
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1233
1344
|
io_uring_prep_cancel(sqe, ctx, 0);
|
1234
1345
|
backend->pending_sqes = 0;
|
1235
1346
|
io_uring_submit(&backend->ring);
|
@@ -1242,7 +1353,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1242
1353
|
}
|
1243
1354
|
|
1244
1355
|
io_uring_sqe_set_data(last_sqe, ctx);
|
1245
|
-
|
1356
|
+
flags = (i == (argc - 1)) ? IOSQE_ASYNC : IOSQE_ASYNC | IOSQE_IO_LINK;
|
1246
1357
|
io_uring_sqe_set_flags(last_sqe, flags);
|
1247
1358
|
sqe_count++;
|
1248
1359
|
}
|
@@ -1251,14 +1362,16 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1251
1362
|
ctx->ref_count = sqe_count + 1;
|
1252
1363
|
io_uring_backend_defer_submit(backend);
|
1253
1364
|
resume_value = backend_await((struct Backend_base *)backend);
|
1254
|
-
|
1255
|
-
|
1365
|
+
result = ctx->result;
|
1366
|
+
completed = context_store_release(&backend->store, ctx);
|
1256
1367
|
if (!completed) {
|
1368
|
+
struct io_uring_sqe *sqe;
|
1369
|
+
|
1257
1370
|
Backend_chain_ctx_attach_buffers(ctx, argc, argv);
|
1258
1371
|
|
1259
1372
|
// op was not completed (an exception was raised), so we need to cancel it
|
1260
1373
|
ctx->result = -ECANCELED;
|
1261
|
-
|
1374
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1262
1375
|
io_uring_prep_cancel(sqe, ctx, 0);
|
1263
1376
|
backend->pending_sqes = 0;
|
1264
1377
|
io_uring_submit(&backend->ring);
|
@@ -1322,8 +1435,10 @@ static inline void splice_chunks_get_sqe(
|
|
1322
1435
|
}
|
1323
1436
|
|
1324
1437
|
static inline void splice_chunks_cancel(Backend_t *backend, op_context_t *ctx) {
|
1438
|
+
struct io_uring_sqe *sqe;
|
1439
|
+
|
1325
1440
|
ctx->result = -ECANCELED;
|
1326
|
-
|
1441
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1327
1442
|
io_uring_prep_cancel(sqe, ctx, 0);
|
1328
1443
|
backend->pending_sqes = 0;
|
1329
1444
|
io_uring_submit(&backend->ring);
|
@@ -1336,9 +1451,11 @@ static inline int splice_chunks_await_ops(
|
|
1336
1451
|
VALUE *switchpoint_result
|
1337
1452
|
)
|
1338
1453
|
{
|
1454
|
+
int completed;
|
1339
1455
|
int res = io_uring_backend_defer_submit_and_await(backend, 0, *ctx, switchpoint_result);
|
1456
|
+
|
1340
1457
|
if (result) (*result) = res;
|
1341
|
-
|
1458
|
+
completed = context_store_release(&backend->store, *ctx);
|
1342
1459
|
if (!completed) {
|
1343
1460
|
splice_chunks_cancel(backend, *ctx);
|
1344
1461
|
if (TEST_EXCEPTION(*switchpoint_result)) return 1;
|
@@ -1352,17 +1469,22 @@ static inline int splice_chunks_await_ops(
|
|
1352
1469
|
|
1353
1470
|
VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VALUE postfix, VALUE chunk_prefix, VALUE chunk_postfix, VALUE chunk_size) {
|
1354
1471
|
Backend_t *backend;
|
1355
|
-
GetBackend(self, backend);
|
1356
1472
|
int total = 0;
|
1357
1473
|
int err = 0;
|
1358
1474
|
VALUE switchpoint_result = Qnil;
|
1359
1475
|
op_context_t *ctx = 0;
|
1360
1476
|
struct io_uring_sqe *sqe = 0;
|
1361
|
-
|
1477
|
+
int maxlen;
|
1478
|
+
VALUE underlying_io;
|
1479
|
+
VALUE str = Qnil;
|
1480
|
+
VALUE chunk_len_value = Qnil;
|
1362
1481
|
rb_io_t *src_fptr;
|
1363
1482
|
rb_io_t *dest_fptr;
|
1483
|
+
int pipefd[2] = { -1, -1 };
|
1484
|
+
|
1485
|
+
GetBackend(self, backend);
|
1364
1486
|
|
1365
|
-
|
1487
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
1366
1488
|
if (underlying_io != Qnil) src = underlying_io;
|
1367
1489
|
GetOpenFile(src, src_fptr);
|
1368
1490
|
io_verify_blocking_mode(src_fptr, src, Qtrue);
|
@@ -1373,11 +1495,8 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1373
1495
|
GetOpenFile(dest, dest_fptr);
|
1374
1496
|
io_verify_blocking_mode(dest_fptr, dest, Qtrue);
|
1375
1497
|
|
1376
|
-
|
1377
|
-
VALUE str = Qnil;
|
1378
|
-
VALUE chunk_len_value = Qnil;
|
1498
|
+
maxlen = NUM2INT(chunk_size);
|
1379
1499
|
|
1380
|
-
int pipefd[2] = { -1, -1 };
|
1381
1500
|
if (pipe(pipefd) == -1) {
|
1382
1501
|
err = errno;
|
1383
1502
|
goto syscallerror;
|
@@ -1521,6 +1640,7 @@ void Init_Backend() {
|
|
1521
1640
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1522
1641
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1523
1642
|
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1643
|
+
// rb_define_method(cBackend, "close", Backend_close, 1);
|
1524
1644
|
|
1525
1645
|
SYM_io_uring = ID2SYM(rb_intern("io_uring"));
|
1526
1646
|
SYM_send = ID2SYM(rb_intern("send"));
|