polyphony 0.87 → 0.91
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_io_uring.yml +8 -4
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +1 -1
- data/examples/pipes/echo_server.rb +17 -0
- data/examples/pipes/gunzip.rb +6 -0
- data/examples/pipes/gzip.rb +6 -0
- data/examples/pipes/gzip_http_server.rb +49 -0
- data/examples/pipes/tcp_proxy.rb +28 -0
- data/examples/pipes/tee.rb +15 -0
- data/ext/polyphony/backend_common.c +10 -10
- data/ext/polyphony/backend_io_uring.c +175 -51
- data/ext/polyphony/backend_libev.c +25 -25
- data/ext/polyphony/extconf.rb +4 -2
- data/ext/polyphony/io_extensions.c +132 -57
- data/ext/polyphony/polyphony.c +12 -9
- data/ext/polyphony/polyphony.h +7 -0
- data/ext/polyphony/queue.c +3 -3
- data/ext/polyphony/socket_extensions.c +2 -2
- data/lib/polyphony/extensions/io.rb +4 -0
- data/lib/polyphony/version.rb +1 -1
- data/test/stress.rb +1 -1
- data/test/test_io.rb +229 -9
- data/test/test_signal.rb +6 -2
- metadata +8 -2
@@ -262,6 +262,21 @@ inline struct backend_stats backend_get_stats(VALUE self) {
|
|
262
262
|
return backend_base_stats(&backend->base);
|
263
263
|
}
|
264
264
|
|
265
|
+
static inline struct io_uring_sqe *io_uring_backend_get_sqe(Backend_t *backend) {
|
266
|
+
struct io_uring_sqe *sqe;
|
267
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
268
|
+
if (sqe) goto done;
|
269
|
+
|
270
|
+
if (backend->pending_sqes)
|
271
|
+
io_uring_backend_immediate_submit(backend);
|
272
|
+
else {
|
273
|
+
VALUE resume_value = backend_snooze(&backend->base);
|
274
|
+
RAISE_IF_EXCEPTION(resume_value);
|
275
|
+
}
|
276
|
+
done:
|
277
|
+
return sqe;
|
278
|
+
}
|
279
|
+
|
265
280
|
VALUE Backend_wakeup(VALUE self) {
|
266
281
|
Backend_t *backend;
|
267
282
|
GetBackend(self, backend);
|
@@ -269,7 +284,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
269
284
|
if (backend->base.currently_polling) {
|
270
285
|
// Since we're currently blocking while waiting for a completion, we add a
|
271
286
|
// NOP which would cause the io_uring_enter syscall to return
|
272
|
-
struct io_uring_sqe *sqe =
|
287
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
273
288
|
io_uring_prep_nop(sqe);
|
274
289
|
io_uring_backend_immediate_submit(backend);
|
275
290
|
|
@@ -302,7 +317,7 @@ int io_uring_backend_defer_submit_and_await(
|
|
302
317
|
|
303
318
|
// op was not completed (an exception was raised), so we need to cancel it
|
304
319
|
ctx->result = -ECANCELED;
|
305
|
-
sqe =
|
320
|
+
sqe = io_uring_backend_get_sqe(backend);
|
306
321
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
307
322
|
io_uring_backend_immediate_submit(backend);
|
308
323
|
}
|
@@ -317,7 +332,7 @@ VALUE io_uring_backend_wait_fd(Backend_t *backend, int fd, int write) {
|
|
317
332
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_POLL);
|
318
333
|
VALUE resumed_value = Qnil;
|
319
334
|
|
320
|
-
struct io_uring_sqe *sqe =
|
335
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
321
336
|
io_uring_prep_poll_add(sqe, fd, write ? POLLOUT : POLLIN);
|
322
337
|
|
323
338
|
io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resumed_value);
|
@@ -349,7 +364,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
349
364
|
int fd;
|
350
365
|
rb_io_t *fptr;
|
351
366
|
struct io_buffer buffer = get_io_buffer(str);
|
352
|
-
long buf_pos =
|
367
|
+
long buf_pos = FIX2INT(pos);
|
353
368
|
int shrinkable_string = 0;
|
354
369
|
int expandable_buffer = 0;
|
355
370
|
long total = 0;
|
@@ -368,7 +383,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
368
383
|
|
369
384
|
if (string_cap < expected_read_length + buf_pos) {
|
370
385
|
shrinkable_string = io_setstrbuf(&str, expected_read_length + buf_pos);
|
371
|
-
buffer.ptr = RSTRING_PTR(str) + buf_pos;
|
386
|
+
buffer.ptr = (unsigned char *)RSTRING_PTR(str) + buf_pos;
|
372
387
|
buffer.len = expected_read_length;
|
373
388
|
}
|
374
389
|
else {
|
@@ -385,7 +400,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
385
400
|
while (1) {
|
386
401
|
VALUE resume_value = Qnil;
|
387
402
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
388
|
-
struct io_uring_sqe *sqe =
|
403
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
389
404
|
int result;
|
390
405
|
int completed;
|
391
406
|
|
@@ -415,7 +430,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
415
430
|
rb_str_resize(str, total + buf_pos);
|
416
431
|
rb_str_modify_expand(str, rb_str_capacity(str));
|
417
432
|
shrinkable_string = 0;
|
418
|
-
buffer.ptr = RSTRING_PTR(str) + total + buf_pos;
|
433
|
+
buffer.ptr = (unsigned char *)RSTRING_PTR(str) + total + buf_pos;
|
419
434
|
buffer.len = rb_str_capacity(str) - total - buf_pos;
|
420
435
|
}
|
421
436
|
else {
|
@@ -441,7 +456,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
441
456
|
rb_io_t *fptr;
|
442
457
|
VALUE str;
|
443
458
|
long total;
|
444
|
-
long len =
|
459
|
+
long len = FIX2INT(maxlen);
|
445
460
|
int shrinkable;
|
446
461
|
char *buf;
|
447
462
|
|
@@ -453,7 +468,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
453
468
|
while (1) {
|
454
469
|
VALUE resume_value = Qnil;
|
455
470
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
456
|
-
struct io_uring_sqe *sqe =
|
471
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
457
472
|
ssize_t result;
|
458
473
|
int completed;
|
459
474
|
|
@@ -502,7 +517,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
502
517
|
while (1) {
|
503
518
|
VALUE resume_value = Qnil;
|
504
519
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
|
505
|
-
struct io_uring_sqe *sqe =
|
520
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
506
521
|
ssize_t result;
|
507
522
|
int completed;
|
508
523
|
|
@@ -546,7 +561,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
546
561
|
while (left > 0) {
|
547
562
|
VALUE resume_value = Qnil;
|
548
563
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITE);
|
549
|
-
struct io_uring_sqe *sqe =
|
564
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
550
565
|
int result;
|
551
566
|
int completed;
|
552
567
|
|
@@ -569,7 +584,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
569
584
|
}
|
570
585
|
}
|
571
586
|
|
572
|
-
return
|
587
|
+
return INT2FIX(buffer.len);
|
573
588
|
}
|
574
589
|
|
575
590
|
VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
@@ -597,7 +612,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
597
612
|
while (1) {
|
598
613
|
VALUE resume_value = Qnil;
|
599
614
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITEV);
|
600
|
-
struct io_uring_sqe *sqe =
|
615
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
601
616
|
int result;
|
602
617
|
int completed;
|
603
618
|
|
@@ -637,7 +652,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
637
652
|
}
|
638
653
|
|
639
654
|
free(iov);
|
640
|
-
return
|
655
|
+
return INT2FIX(total_written);
|
641
656
|
}
|
642
657
|
|
643
658
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
@@ -654,7 +669,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
654
669
|
int fd;
|
655
670
|
rb_io_t *fptr;
|
656
671
|
struct io_buffer buffer = get_io_buffer(str);
|
657
|
-
long buf_pos =
|
672
|
+
long buf_pos = FIX2INT(pos);
|
658
673
|
int shrinkable_string = 0;
|
659
674
|
int expandable_buffer = 0;
|
660
675
|
long total = 0;
|
@@ -672,7 +687,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
672
687
|
|
673
688
|
if (string_cap < expected_read_length + buf_pos) {
|
674
689
|
shrinkable_string = io_setstrbuf(&str, expected_read_length + buf_pos);
|
675
|
-
buffer.ptr = RSTRING_PTR(str) + buf_pos;
|
690
|
+
buffer.ptr = (unsigned char *)RSTRING_PTR(str) + buf_pos;
|
676
691
|
buffer.len = expected_read_length;
|
677
692
|
}
|
678
693
|
else {
|
@@ -689,7 +704,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
689
704
|
while (1) {
|
690
705
|
VALUE resume_value = Qnil;
|
691
706
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
692
|
-
struct io_uring_sqe *sqe =
|
707
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
693
708
|
int result;
|
694
709
|
int completed;
|
695
710
|
|
@@ -727,7 +742,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
727
742
|
rb_io_t *fptr;
|
728
743
|
VALUE str;
|
729
744
|
long total;
|
730
|
-
long len =
|
745
|
+
long len = FIX2INT(maxlen);
|
731
746
|
int shrinkable;
|
732
747
|
char *buf;
|
733
748
|
|
@@ -739,7 +754,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
739
754
|
while (1) {
|
740
755
|
VALUE resume_value = Qnil;
|
741
756
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
742
|
-
struct io_uring_sqe *sqe =
|
757
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
743
758
|
int result;
|
744
759
|
int completed;
|
745
760
|
|
@@ -787,7 +802,7 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
|
|
787
802
|
while (1) {
|
788
803
|
VALUE resume_value = Qnil;
|
789
804
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
790
|
-
struct io_uring_sqe *sqe =
|
805
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
791
806
|
int result;
|
792
807
|
int completed;
|
793
808
|
|
@@ -823,7 +838,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
823
838
|
|
824
839
|
struct io_buffer buffer = get_io_buffer(str);
|
825
840
|
long left = buffer.len;
|
826
|
-
int flags_int =
|
841
|
+
int flags_int = FIX2INT(flags);
|
827
842
|
|
828
843
|
GetBackend(self, backend);
|
829
844
|
fd = fd_from_io(io, &fptr, 1, 0);
|
@@ -831,7 +846,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
831
846
|
while (left > 0) {
|
832
847
|
VALUE resume_value = Qnil;
|
833
848
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SEND);
|
834
|
-
struct io_uring_sqe *sqe =
|
849
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
835
850
|
int result;
|
836
851
|
int completed;
|
837
852
|
|
@@ -854,7 +869,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
854
869
|
}
|
855
870
|
}
|
856
871
|
|
857
|
-
return
|
872
|
+
return INT2FIX(buffer.len);
|
858
873
|
}
|
859
874
|
|
860
875
|
VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE socket_class, int loop) {
|
@@ -869,7 +884,7 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc
|
|
869
884
|
while (1) {
|
870
885
|
VALUE resume_value = Qnil;
|
871
886
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_ACCEPT);
|
872
|
-
struct io_uring_sqe *sqe =
|
887
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
873
888
|
int fd;
|
874
889
|
int completed;
|
875
890
|
|
@@ -935,11 +950,11 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
935
950
|
|
936
951
|
while (1) {
|
937
952
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
|
938
|
-
struct io_uring_sqe *sqe =
|
953
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
939
954
|
int result;
|
940
955
|
int completed;
|
941
956
|
|
942
|
-
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1,
|
957
|
+
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, FIX2INT(maxlen), 0);
|
943
958
|
|
944
959
|
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
945
960
|
completed = context_store_release(&backend->store, ctx);
|
@@ -950,7 +965,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
950
965
|
rb_syserr_fail(-result, strerror(-result));
|
951
966
|
|
952
967
|
total += result;
|
953
|
-
if (result == 0 || !loop) return
|
968
|
+
if (result == 0 || !loop) return INT2FIX(total);
|
954
969
|
}
|
955
970
|
|
956
971
|
RB_GC_GUARD(resume_value);
|
@@ -969,6 +984,112 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize)
|
|
969
984
|
return io_uring_backend_splice(backend, src, dest, chunksize, 1);
|
970
985
|
}
|
971
986
|
|
987
|
+
struct double_splice_ctx {
|
988
|
+
Backend_t *backend;
|
989
|
+
VALUE src;
|
990
|
+
VALUE dest;
|
991
|
+
int pipefd[2];
|
992
|
+
};
|
993
|
+
|
994
|
+
#define DOUBLE_SPLICE_MAXLEN (1 << 16)
|
995
|
+
|
996
|
+
static inline op_context_t *prepare_double_splice_ctx(Backend_t *backend, int src_fd, int dest_fd) {
|
997
|
+
op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
|
998
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
999
|
+
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, DOUBLE_SPLICE_MAXLEN, 0);
|
1000
|
+
io_uring_sqe_set_data(sqe, ctx);
|
1001
|
+
io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
1002
|
+
backend->base.op_count += 1;
|
1003
|
+
backend->pending_sqes += 1;
|
1004
|
+
|
1005
|
+
return ctx;
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
static inline void io_uring_backend_cancel(Backend_t *backend, op_context_t *ctx) {
|
1009
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
1010
|
+
ctx->result = -ECANCELED;
|
1011
|
+
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1012
|
+
}
|
1013
|
+
|
1014
|
+
VALUE double_splice_to_eof_safe(struct double_splice_ctx *ctx) {
|
1015
|
+
int src_fd;
|
1016
|
+
int dest_fd;
|
1017
|
+
rb_io_t *src_fptr;
|
1018
|
+
rb_io_t *dest_fptr;
|
1019
|
+
int total = 0;
|
1020
|
+
VALUE resume_value = Qnil;
|
1021
|
+
|
1022
|
+
src_fd = fd_from_io(ctx->src, &src_fptr, 0, 0);
|
1023
|
+
dest_fd = fd_from_io(ctx->dest, &dest_fptr, 1, 0);
|
1024
|
+
|
1025
|
+
op_context_t *ctx_src = prepare_double_splice_ctx(ctx->backend, src_fd, ctx->pipefd[1]);
|
1026
|
+
op_context_t *ctx_dest = prepare_double_splice_ctx(ctx->backend, ctx->pipefd[0], dest_fd);
|
1027
|
+
|
1028
|
+
if (ctx->backend->pending_sqes >= ctx->backend->prepared_limit)
|
1029
|
+
io_uring_backend_immediate_submit(ctx->backend);
|
1030
|
+
|
1031
|
+
while (1) {
|
1032
|
+
resume_value = backend_await((struct Backend_base *)ctx->backend);
|
1033
|
+
|
1034
|
+
if ((ctx_src && ctx_src->ref_count == 2 && ctx_dest && ctx_dest->ref_count == 2) || TEST_EXCEPTION(resume_value)) {
|
1035
|
+
if (ctx_src) {
|
1036
|
+
context_store_release(&ctx->backend->store, ctx_src);
|
1037
|
+
io_uring_backend_cancel(ctx->backend, ctx_src);
|
1038
|
+
}
|
1039
|
+
if (ctx_dest) {
|
1040
|
+
context_store_release(&ctx->backend->store, ctx_dest);
|
1041
|
+
io_uring_backend_cancel(ctx->backend, ctx_dest);
|
1042
|
+
}
|
1043
|
+
io_uring_backend_immediate_submit(ctx->backend);
|
1044
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1045
|
+
return resume_value;
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
if (ctx_src && ctx_src->ref_count == 1) {
|
1049
|
+
context_store_release(&ctx->backend->store, ctx_src);
|
1050
|
+
if (ctx_src->result == 0) {
|
1051
|
+
// close write end of pipe
|
1052
|
+
close(ctx->pipefd[1]);
|
1053
|
+
ctx_src = NULL;
|
1054
|
+
}
|
1055
|
+
else {
|
1056
|
+
ctx_src = prepare_double_splice_ctx(ctx->backend, src_fd, ctx->pipefd[1]);
|
1057
|
+
}
|
1058
|
+
}
|
1059
|
+
if (ctx_dest && ctx_dest->ref_count == 1) {
|
1060
|
+
context_store_release(&ctx->backend->store, ctx_dest);
|
1061
|
+
if (ctx_dest->result == 0)
|
1062
|
+
break;
|
1063
|
+
else {
|
1064
|
+
total += ctx_dest->result;
|
1065
|
+
ctx_dest = prepare_double_splice_ctx(ctx->backend, ctx->pipefd[0], dest_fd);
|
1066
|
+
}
|
1067
|
+
}
|
1068
|
+
|
1069
|
+
if (ctx->backend->pending_sqes >= ctx->backend->prepared_limit)
|
1070
|
+
io_uring_backend_immediate_submit(ctx->backend);
|
1071
|
+
}
|
1072
|
+
RB_GC_GUARD(resume_value);
|
1073
|
+
return INT2FIX(total);
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
VALUE double_splice_to_eof_cleanup(struct double_splice_ctx *ctx) {
|
1077
|
+
if (ctx->pipefd[0]) close(ctx->pipefd[0]);
|
1078
|
+
if (ctx->pipefd[1]) close(ctx->pipefd[1]);
|
1079
|
+
return Qnil;
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
VALUE Backend_double_splice_to_eof(VALUE self, VALUE src, VALUE dest) {
|
1083
|
+
struct double_splice_ctx ctx = { NULL, src, dest, 0, 0 };
|
1084
|
+
GetBackend(self, ctx.backend);
|
1085
|
+
if (pipe(ctx.pipefd) == -1) rb_syserr_fail(errno, strerror(errno));
|
1086
|
+
|
1087
|
+
return rb_ensure(
|
1088
|
+
SAFE(double_splice_to_eof_safe), (VALUE)&ctx,
|
1089
|
+
SAFE(double_splice_to_eof_cleanup), (VALUE)&ctx
|
1090
|
+
);
|
1091
|
+
}
|
1092
|
+
|
972
1093
|
VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
973
1094
|
Backend_t *backend;
|
974
1095
|
GetBackend(self, backend);
|
@@ -984,11 +1105,11 @@ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
984
1105
|
|
985
1106
|
while (1) {
|
986
1107
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
|
987
|
-
struct io_uring_sqe *sqe =
|
1108
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
988
1109
|
int result;
|
989
1110
|
int completed;
|
990
1111
|
|
991
|
-
io_uring_prep_tee(sqe, src_fd, dest_fd,
|
1112
|
+
io_uring_prep_tee(sqe, src_fd, dest_fd, FIX2INT(maxlen), 0);
|
992
1113
|
|
993
1114
|
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
994
1115
|
completed = context_store_release(&backend->store, ctx);
|
@@ -998,7 +1119,7 @@ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
998
1119
|
if (result < 0)
|
999
1120
|
rb_syserr_fail(-result, strerror(-result));
|
1000
1121
|
|
1001
|
-
return
|
1122
|
+
return INT2FIX(result);
|
1002
1123
|
}
|
1003
1124
|
|
1004
1125
|
RB_GC_GUARD(resume_value);
|
@@ -1021,7 +1142,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
1021
1142
|
GetBackend(self, backend);
|
1022
1143
|
fd = fd_from_io(sock, &fptr, 1, 0);
|
1023
1144
|
ctx = context_store_acquire(&backend->store, OP_CONNECT);
|
1024
|
-
sqe =
|
1145
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1025
1146
|
io_uring_prep_connect(sqe, fd, ai_addr, ai_addrlen);
|
1026
1147
|
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
1027
1148
|
completed = context_store_release(&backend->store, ctx);
|
@@ -1063,7 +1184,7 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
1063
1184
|
// io_unset_nonblock(fptr, io);
|
1064
1185
|
|
1065
1186
|
// ctx = context_store_acquire(&backend->store, OP_CLOSE);
|
1066
|
-
// sqe =
|
1187
|
+
// sqe = io_uring_backend_get_sqe(backend);
|
1067
1188
|
// io_uring_prep_close(sqe, fd);
|
1068
1189
|
// result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
1069
1190
|
// completed = context_store_release(&backend->store, ctx);
|
@@ -1094,7 +1215,7 @@ inline struct __kernel_timespec duration_to_timespec(VALUE duration) {
|
|
1094
1215
|
// returns true if completed, 0 otherwise
|
1095
1216
|
int io_uring_backend_submit_timeout_and_await(Backend_t *backend, double duration, VALUE *resume_value) {
|
1096
1217
|
struct __kernel_timespec ts = double_to_timespec(duration);
|
1097
|
-
struct io_uring_sqe *sqe =
|
1218
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
1098
1219
|
op_context_t *ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
1099
1220
|
|
1100
1221
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
@@ -1183,7 +1304,7 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1183
1304
|
GetBackend(self, backend);
|
1184
1305
|
timeout = rb_funcall(cTimeoutException, ID_new, 0);
|
1185
1306
|
|
1186
|
-
sqe =
|
1307
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1187
1308
|
ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
|
1188
1309
|
ctx->resume_value = timeout;
|
1189
1310
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
@@ -1207,7 +1328,7 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1207
1328
|
}
|
1208
1329
|
|
1209
1330
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1210
|
-
int pid_int =
|
1331
|
+
int pid_int = FIX2INT(pid);
|
1211
1332
|
int fd = pidfd_open(pid_int, 0);
|
1212
1333
|
int status;
|
1213
1334
|
pid_t ret;
|
@@ -1231,7 +1352,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1231
1352
|
else
|
1232
1353
|
rb_syserr_fail(e, strerror(e));
|
1233
1354
|
}
|
1234
|
-
return rb_ary_new_from_args(2,
|
1355
|
+
return rb_ary_new_from_args(2, INT2FIX(ret), INT2FIX(WEXITSTATUS(status)));
|
1235
1356
|
}
|
1236
1357
|
|
1237
1358
|
/*
|
@@ -1259,7 +1380,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1259
1380
|
struct io_uring_sqe *sqe;
|
1260
1381
|
|
1261
1382
|
backend->event_fd_ctx = context_store_acquire(&backend->store, OP_POLL);
|
1262
|
-
sqe =
|
1383
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1263
1384
|
io_uring_prep_poll_add(sqe, backend->event_fd, POLLIN);
|
1264
1385
|
backend->base.op_count++;
|
1265
1386
|
io_uring_sqe_set_data(sqe, backend->event_fd_ctx);
|
@@ -1275,7 +1396,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1275
1396
|
|
1276
1397
|
// last fiber to use the eventfd, so we cancel the ongoing poll
|
1277
1398
|
struct io_uring_sqe *sqe;
|
1278
|
-
sqe =
|
1399
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1279
1400
|
io_uring_prep_cancel(sqe, (__u64)backend->event_fd_ctx, 0);
|
1280
1401
|
io_uring_backend_immediate_submit(backend);
|
1281
1402
|
backend->event_fd_ctx = NULL;
|
@@ -1296,7 +1417,7 @@ struct io_uring_sqe *Backend_chain_prepare_write(Backend_t *backend, VALUE io, V
|
|
1296
1417
|
struct io_uring_sqe *sqe;
|
1297
1418
|
|
1298
1419
|
fd = fd_from_io(io, &fptr, 1, 0);
|
1299
|
-
sqe =
|
1420
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1300
1421
|
io_uring_prep_write(sqe, fd, StringValuePtr(str), RSTRING_LEN(str), 0);
|
1301
1422
|
return sqe;
|
1302
1423
|
}
|
@@ -1308,8 +1429,8 @@ struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VA
|
|
1308
1429
|
|
1309
1430
|
fd = fd_from_io(io, &fptr, 1, 0);
|
1310
1431
|
|
1311
|
-
sqe =
|
1312
|
-
io_uring_prep_send(sqe, fd, StringValuePtr(str), RSTRING_LEN(str),
|
1432
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1433
|
+
io_uring_prep_send(sqe, fd, StringValuePtr(str), RSTRING_LEN(str), FIX2INT(flags));
|
1313
1434
|
return sqe;
|
1314
1435
|
}
|
1315
1436
|
|
@@ -1322,8 +1443,8 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src,
|
|
1322
1443
|
|
1323
1444
|
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
1324
1445
|
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
1325
|
-
sqe =
|
1326
|
-
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1,
|
1446
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1447
|
+
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, FIX2INT(maxlen), 0);
|
1327
1448
|
return sqe;
|
1328
1449
|
}
|
1329
1450
|
|
@@ -1381,7 +1502,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1381
1502
|
|
1382
1503
|
ctx->ref_count = sqe_count;
|
1383
1504
|
ctx->result = -ECANCELED;
|
1384
|
-
sqe =
|
1505
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1385
1506
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1386
1507
|
io_uring_backend_immediate_submit(backend);
|
1387
1508
|
}
|
@@ -1411,7 +1532,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1411
1532
|
|
1412
1533
|
// op was not completed (an exception was raised), so we need to cancel it
|
1413
1534
|
ctx->result = -ECANCELED;
|
1414
|
-
sqe =
|
1535
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1415
1536
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1416
1537
|
io_uring_backend_immediate_submit(backend);
|
1417
1538
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -1419,7 +1540,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1419
1540
|
}
|
1420
1541
|
|
1421
1542
|
RB_GC_GUARD(resume_value);
|
1422
|
-
return
|
1543
|
+
return INT2FIX(result);
|
1423
1544
|
}
|
1424
1545
|
|
1425
1546
|
VALUE Backend_idle_gc_period_set(VALUE self, VALUE period) {
|
@@ -1470,14 +1591,14 @@ static inline void splice_chunks_get_sqe(
|
|
1470
1591
|
}
|
1471
1592
|
else
|
1472
1593
|
*ctx = context_store_acquire(&backend->store, type);
|
1473
|
-
(*sqe) =
|
1594
|
+
(*sqe) = io_uring_backend_get_sqe(backend);
|
1474
1595
|
}
|
1475
1596
|
|
1476
1597
|
static inline void splice_chunks_cancel(Backend_t *backend, op_context_t *ctx) {
|
1477
1598
|
struct io_uring_sqe *sqe;
|
1478
1599
|
|
1479
1600
|
ctx->result = -ECANCELED;
|
1480
|
-
sqe =
|
1601
|
+
sqe = io_uring_backend_get_sqe(backend);
|
1481
1602
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1482
1603
|
io_uring_backend_immediate_submit(backend);
|
1483
1604
|
}
|
@@ -1525,7 +1646,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1525
1646
|
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
1526
1647
|
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
1527
1648
|
|
1528
|
-
maxlen =
|
1649
|
+
maxlen = FIX2INT(chunk_size);
|
1529
1650
|
|
1530
1651
|
if (pipe(pipefd) == -1) {
|
1531
1652
|
err = errno;
|
@@ -1551,7 +1672,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1551
1672
|
if (chunk_len == 0) break;
|
1552
1673
|
|
1553
1674
|
total += chunk_len;
|
1554
|
-
chunk_len_value =
|
1675
|
+
chunk_len_value = INT2FIX(chunk_len);
|
1555
1676
|
|
1556
1677
|
|
1557
1678
|
if (chunk_prefix != Qnil) {
|
@@ -1590,7 +1711,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1590
1711
|
RB_GC_GUARD(switchpoint_result);
|
1591
1712
|
if (pipefd[0] != -1) close(pipefd[0]);
|
1592
1713
|
if (pipefd[1] != -1) close(pipefd[1]);
|
1593
|
-
return
|
1714
|
+
return INT2FIX(total);
|
1594
1715
|
syscallerror:
|
1595
1716
|
if (pipefd[0] != -1) close(pipefd[0]);
|
1596
1717
|
if (pipefd[1] != -1) close(pipefd[1]);
|
@@ -1678,9 +1799,12 @@ void Init_Backend() {
|
|
1678
1799
|
rb_define_method(cBackend, "send", Backend_send, 3);
|
1679
1800
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
1680
1801
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
1802
|
+
|
1681
1803
|
rb_define_method(cBackend, "splice", Backend_splice, 3);
|
1682
1804
|
rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
|
1805
|
+
rb_define_method(cBackend, "double_splice_to_eof", Backend_double_splice_to_eof, 2);
|
1683
1806
|
rb_define_method(cBackend, "tee", Backend_tee, 3);
|
1807
|
+
|
1684
1808
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
1685
1809
|
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
1686
1810
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|