polyphony 0.63 → 0.67
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/CHANGELOG.md +19 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +10 -40
- data/bin/pdbg +30 -0
- data/examples/core/await.rb +9 -1
- data/ext/polyphony/backend_common.c +14 -1
- data/ext/polyphony/backend_common.h +3 -1
- data/ext/polyphony/backend_io_uring.c +84 -24
- data/ext/polyphony/backend_io_uring_context.c +42 -0
- data/ext/polyphony/backend_io_uring_context.h +6 -9
- data/ext/polyphony/backend_libev.c +85 -39
- data/ext/polyphony/fiber.c +20 -0
- data/ext/polyphony/polyphony.c +2 -0
- data/ext/polyphony/polyphony.h +5 -2
- data/ext/polyphony/queue.c +1 -1
- data/ext/polyphony/runqueue.c +7 -3
- data/ext/polyphony/runqueue.h +4 -3
- data/ext/polyphony/runqueue_ring_buffer.c +25 -14
- data/ext/polyphony/runqueue_ring_buffer.h +2 -0
- data/ext/polyphony/thread.c +2 -8
- data/lib/polyphony.rb +6 -0
- data/lib/polyphony/debugger/server.rb +137 -0
- data/lib/polyphony/extensions/debug.rb +1 -1
- data/lib/polyphony/extensions/fiber.rb +40 -33
- data/lib/polyphony/extensions/io.rb +6 -2
- data/lib/polyphony/extensions/openssl.rb +8 -2
- data/lib/polyphony/extensions/socket.rb +15 -10
- data/lib/polyphony/version.rb +1 -1
- data/test/helper.rb +6 -4
- data/test/stress.rb +6 -2
- data/test/test_backend.rb +13 -4
- data/test/test_fiber.rb +33 -9
- data/test/test_global_api.rb +9 -4
- data/test/test_io.rb +2 -0
- data/test/test_socket.rb +14 -11
- data/test/test_thread.rb +3 -0
- data/test/test_thread_pool.rb +1 -1
- data/test/test_throttler.rb +2 -2
- data/test/test_timer.rb +5 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b8553a2f84e79520ce53412ee6891873c9a9d25e0789e82b26a7153d3d7ae67
|
4
|
+
data.tar.gz: 6889ef71f11d79d6fbb82adc77447f9b3526a29858f2aa3c9e51ee9098add2c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91814f767f74c673681a2215f82a302f3aab5ced6ae7197720e474b8c1ad6846eb10001580c1f11d5b62bd0ed7563422fd71f0fb5728eb0b3fcb4ebd36d2038c
|
7
|
+
data.tar.gz: 74e1c7ed34b4f212ca1ffd5881da3e9f689c3934d0f3680da2396d7444b5a214a610ccc779c1ef59713116f0a8240491dc60f32b5d5e30de5092ddc41b8c9f18
|
data/.github/workflows/test.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
## 0.67 2021-08-06
|
2
|
+
|
3
|
+
- Improve fiber monitoring
|
4
|
+
- Add fiber parking (a parked fiber is prevented from running). This is in
|
5
|
+
preparation for the upcoming work on an integrated debugger.
|
6
|
+
|
7
|
+
## 0.66 2021-08-01
|
8
|
+
|
9
|
+
- Fix all splicing APIs on non-linux OSes (#63)
|
10
|
+
- Add GC marking of buffers when cancelling read/write ops in io_uring backend
|
11
|
+
|
12
|
+
## 0.65 2021-07-29
|
13
|
+
|
14
|
+
- Add `#__polyphony_read_method__` method for read method detection
|
15
|
+
|
16
|
+
## 0.64 2021-07-26
|
17
|
+
|
18
|
+
- Add optional raise_on_eof argument to `#readpartial`
|
19
|
+
|
1
20
|
## 0.63 2021-07-26
|
2
21
|
|
3
22
|
- Add support for specifying buf and buf_pos in `IO#read`
|
data/Gemfile.lock
CHANGED
data/TODO.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
- io_uring backend:
|
2
|
+
- if `io_uring_get_sqe` returns null, call `io_uring_submit`, (snooze fiber)?
|
3
|
+
and try again
|
4
|
+
|
5
|
+
- Tracing:
|
6
|
+
- Emit events on I/O ops, e.g.:
|
7
|
+
- [:op_read_submit, id, io, len]
|
8
|
+
- [:op_read_complete, id, io, len, buffer]
|
9
|
+
- Prevent tracing while an event is being emitted (to allow the trace proc to perform I/O)
|
10
|
+
|
1
11
|
- Add support for IPv6:
|
2
12
|
https://www.reddit.com/r/ruby/comments/lyen23/understanding_ipv6_and_why_its_important_to_you/
|
3
13
|
|
@@ -14,47 +24,8 @@
|
|
14
24
|
- `IO#gets_loop`, `Socket#gets_loop`, `OpenSSL::Socket#gets_loop` (medium effort)
|
15
25
|
- `Fiber#receive_loop` (very little effort, should be implemented in C)
|
16
26
|
|
17
|
-
|
18
|
-
- Add `Backend#splice`, `Backend#splice_to_eof` for implementing stuff like proxying:
|
19
|
-
|
20
|
-
```ruby
|
21
|
-
def two_way_proxy(socket1, socket2)
|
22
|
-
backend = Thread.current.backend
|
23
|
-
f1 = spin { backend.splice_to_eof(socket1, socket2) }
|
24
|
-
f2 = spin { backend.splice_to_eof(socket2, socket1) }
|
25
|
-
Fiber.await(f1, f2)
|
26
|
-
end
|
27
|
-
```
|
28
|
-
|
29
27
|
- Add support for `close` to io_uring backend
|
30
28
|
|
31
|
-
- Add support for submission of multiple requests to io_uring backend:
|
32
|
-
|
33
|
-
```ruby
|
34
|
-
Thread.current.backend.submit(
|
35
|
-
[:send, sock, chunk_header(len)],
|
36
|
-
[:splice, file, sock, len]
|
37
|
-
)
|
38
|
-
```
|
39
|
-
|
40
|
-
Full example (for writing chunks from a file to an HTTP response):
|
41
|
-
|
42
|
-
```ruby
|
43
|
-
def serve_io(io)
|
44
|
-
i, o = IO.pipe
|
45
|
-
backend = Thread.current.backend
|
46
|
-
while true
|
47
|
-
len = o.splice(io, 8192)
|
48
|
-
break if len == 0
|
49
|
-
|
50
|
-
backend.submit(
|
51
|
-
[:write, sock, chunk_header(len)],
|
52
|
-
[:splice, i, sock, len]
|
53
|
-
)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
```
|
57
|
-
|
58
29
|
- Graceful shutdown again:
|
59
30
|
- What happens to children when doing a graceful shutdown?
|
60
31
|
- What are the implications of passing graceful shutdown flag to children?
|
@@ -92,7 +63,6 @@
|
|
92
63
|
|
93
64
|
-----------------------------------------------------
|
94
65
|
|
95
|
-
- Add `Backend#splice(in, out, nbytes)` API
|
96
66
|
- Adapter for io/console (what does `IO#raw` do?)
|
97
67
|
- Adapter for Pry and IRB (Which fixes #5 and #6)
|
98
68
|
- allow backend selection at runtime
|
data/bin/pdbg
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'polyphony'
|
6
|
+
|
7
|
+
UNIX_SOCKET_PATH = '/tmp/pdbg.sock'
|
8
|
+
|
9
|
+
cmd = ARGV.join(' ')
|
10
|
+
injected_lib_path = File.expand_path('../lib/polyphony/debugger/server_inject.rb', __dir__)
|
11
|
+
p cmd
|
12
|
+
pid = fork { exec("env POLYPHONY_DEBUG_SOCKET_PATH=#{UNIX_SOCKET_PATH} ruby #{cmd}") }
|
13
|
+
puts "Started debugged process (#{pid})"
|
14
|
+
|
15
|
+
sleep 3
|
16
|
+
socket = UNIXSocket.new(UNIX_SOCKET_PATH)
|
17
|
+
socket.puts 'pdbg'
|
18
|
+
response = socket.gets
|
19
|
+
if response.chomp == 'pdbg'
|
20
|
+
puts 'Connected to process'
|
21
|
+
end
|
22
|
+
loop do
|
23
|
+
status = socket.gets
|
24
|
+
puts status
|
25
|
+
|
26
|
+
STDOUT << "> "
|
27
|
+
cmd = STDIN.gets
|
28
|
+
puts '-' * 40
|
29
|
+
socket.puts cmd
|
30
|
+
end
|
data/examples/core/await.rb
CHANGED
@@ -2,7 +2,11 @@
|
|
2
2
|
|
3
3
|
require 'bundler/setup'
|
4
4
|
require 'polyphony'
|
5
|
+
require 'polyphony/extensions/debug'
|
5
6
|
|
7
|
+
Exception.__disable_sanitized_backtrace__ = true
|
8
|
+
|
9
|
+
puts '----- start await example ------'
|
6
10
|
sleeper = spin do
|
7
11
|
puts 'going to sleep'
|
8
12
|
sleep 1
|
@@ -17,4 +21,8 @@ waiter = spin do
|
|
17
21
|
puts 'done waiting'
|
18
22
|
end
|
19
23
|
|
20
|
-
|
24
|
+
trace :before_await
|
25
|
+
|
26
|
+
sleep 2
|
27
|
+
waiter.await
|
28
|
+
trace :after_await
|
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
inline void backend_base_initialize(struct Backend_base *base) {
|
9
9
|
runqueue_initialize(&base->runqueue);
|
10
|
+
runqueue_initialize(&base->parked_runqueue);
|
10
11
|
base->currently_polling = 0;
|
11
12
|
base->op_count = 0;
|
12
13
|
base->switch_count = 0;
|
@@ -20,12 +21,14 @@ inline void backend_base_initialize(struct Backend_base *base) {
|
|
20
21
|
|
21
22
|
inline void backend_base_finalize(struct Backend_base *base) {
|
22
23
|
runqueue_finalize(&base->runqueue);
|
24
|
+
runqueue_finalize(&base->parked_runqueue);
|
23
25
|
}
|
24
26
|
|
25
27
|
inline void backend_base_mark(struct Backend_base *base) {
|
26
28
|
if (base->idle_proc != Qnil) rb_gc_mark(base->idle_proc);
|
27
29
|
if (base->trace_proc != Qnil) rb_gc_mark(base->trace_proc);
|
28
30
|
runqueue_mark(&base->runqueue);
|
31
|
+
runqueue_mark(&base->parked_runqueue);
|
29
32
|
}
|
30
33
|
|
31
34
|
const unsigned int ANTI_STARVE_SWITCH_COUNT_THRESHOLD = 64;
|
@@ -91,7 +94,10 @@ void backend_base_schedule_fiber(VALUE thread, VALUE backend, struct Backend_bas
|
|
91
94
|
|
92
95
|
COND_TRACE(base, 4, SYM_fiber_schedule, fiber, value, prioritize ? Qtrue : Qfalse);
|
93
96
|
|
94
|
-
|
97
|
+
runqueue_t *runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ?
|
98
|
+
&base->parked_runqueue : &base->runqueue;
|
99
|
+
|
100
|
+
(prioritize ? runqueue_unshift : runqueue_push)(runqueue, fiber, value, already_runnable);
|
95
101
|
if (!already_runnable) {
|
96
102
|
rb_ivar_set(fiber, ID_ivar_runnable, Qtrue);
|
97
103
|
if (rb_thread_current() != thread) {
|
@@ -105,6 +111,13 @@ void backend_base_schedule_fiber(VALUE thread, VALUE backend, struct Backend_bas
|
|
105
111
|
}
|
106
112
|
}
|
107
113
|
|
114
|
+
inline void backend_base_park_fiber(struct Backend_base *base, VALUE fiber) {
|
115
|
+
runqueue_migrate(&base->runqueue, &base->parked_runqueue, fiber);
|
116
|
+
}
|
117
|
+
|
118
|
+
inline void backend_base_unpark_fiber(struct Backend_base *base, VALUE fiber) {
|
119
|
+
runqueue_migrate(&base->parked_runqueue, &base->runqueue, fiber);
|
120
|
+
}
|
108
121
|
|
109
122
|
inline void backend_trace(struct Backend_base *base, int argc, VALUE *argv) {
|
110
123
|
if (base->trace_proc == Qnil) return;
|
@@ -17,6 +17,7 @@ struct backend_stats {
|
|
17
17
|
|
18
18
|
struct Backend_base {
|
19
19
|
runqueue_t runqueue;
|
20
|
+
runqueue_t parked_runqueue;
|
20
21
|
unsigned int currently_polling;
|
21
22
|
unsigned int op_count;
|
22
23
|
unsigned int switch_count;
|
@@ -33,6 +34,8 @@ void backend_base_finalize(struct Backend_base *base);
|
|
33
34
|
void backend_base_mark(struct Backend_base *base);
|
34
35
|
VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base);
|
35
36
|
void backend_base_schedule_fiber(VALUE thread, VALUE backend, struct Backend_base *base, VALUE fiber, VALUE value, int prioritize);
|
37
|
+
void backend_base_park_fiber(struct Backend_base *base, VALUE fiber);
|
38
|
+
void backend_base_unpark_fiber(struct Backend_base *base, VALUE fiber);
|
36
39
|
void backend_trace(struct Backend_base *base, int argc, VALUE *argv);
|
37
40
|
struct backend_stats backend_base_stats(struct Backend_base *base);
|
38
41
|
|
@@ -104,7 +107,6 @@ VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
|
|
104
107
|
VALUE Backend_stats(VALUE self);
|
105
108
|
void backend_run_idle_tasks(struct Backend_base *base);
|
106
109
|
void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking);
|
107
|
-
|
108
110
|
void backend_setup_stats_symbols();
|
109
111
|
|
110
112
|
#endif /* BACKEND_COMMON_H */
|
@@ -25,6 +25,8 @@ VALUE SYM_send;
|
|
25
25
|
VALUE SYM_splice;
|
26
26
|
VALUE SYM_write;
|
27
27
|
|
28
|
+
VALUE eArgumentError;
|
29
|
+
|
28
30
|
#ifdef POLYPHONY_UNSET_NONBLOCK
|
29
31
|
#define io_unset_nonblock(fptr, io) io_verify_blocking_mode(fptr, io, Qtrue)
|
30
32
|
#else
|
@@ -45,6 +47,7 @@ typedef struct Backend_t {
|
|
45
47
|
static void Backend_mark(void *ptr) {
|
46
48
|
Backend_t *backend = ptr;
|
47
49
|
backend_base_mark(&backend->base);
|
50
|
+
context_store_mark_taken_buffers(&backend->store);
|
48
51
|
}
|
49
52
|
|
50
53
|
static void Backend_free(void *ptr) {
|
@@ -226,7 +229,7 @@ inline void Backend_unschedule_fiber(VALUE self, VALUE fiber) {
|
|
226
229
|
Backend_t *backend;
|
227
230
|
GetBackend(self, backend);
|
228
231
|
|
229
|
-
runqueue_delete(&backend->base.runqueue, fiber);
|
232
|
+
runqueue_delete(&backend->base.runqueue, fiber);
|
230
233
|
}
|
231
234
|
|
232
235
|
inline VALUE Backend_switch_fiber(VALUE self) {
|
@@ -349,8 +352,11 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
349
352
|
|
350
353
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
351
354
|
int completed = context_store_release(&backend->store, ctx);
|
352
|
-
|
353
|
-
|
355
|
+
if (!completed) {
|
356
|
+
context_attach_buffers(ctx, 1, &str);
|
357
|
+
RAISE_IF_EXCEPTION(resume_value);
|
358
|
+
return resume_value;
|
359
|
+
}
|
354
360
|
RB_GC_GUARD(resume_value);
|
355
361
|
|
356
362
|
if (result < 0)
|
@@ -410,8 +416,11 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
410
416
|
|
411
417
|
ssize_t result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
412
418
|
int completed = context_store_release(&backend->store, ctx);
|
413
|
-
|
414
|
-
|
419
|
+
if (!completed) {
|
420
|
+
context_attach_buffers(ctx, 1, &str);
|
421
|
+
RAISE_IF_EXCEPTION(resume_value);
|
422
|
+
return resume_value;
|
423
|
+
}
|
415
424
|
RB_GC_GUARD(resume_value);
|
416
425
|
|
417
426
|
if (result < 0)
|
@@ -457,8 +466,11 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
457
466
|
|
458
467
|
ssize_t result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
459
468
|
int completed = context_store_release(&backend->store, ctx);
|
460
|
-
|
461
|
-
|
469
|
+
if (!completed) {
|
470
|
+
context_attach_buffers(ctx, 1, &str);
|
471
|
+
RAISE_IF_EXCEPTION(resume_value);
|
472
|
+
return resume_value;
|
473
|
+
}
|
462
474
|
RB_GC_GUARD(resume_value);
|
463
475
|
|
464
476
|
if (result < 0)
|
@@ -500,8 +512,11 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
500
512
|
|
501
513
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
502
514
|
int completed = context_store_release(&backend->store, ctx);
|
503
|
-
|
504
|
-
|
515
|
+
if (!completed) {
|
516
|
+
context_attach_buffers(ctx, 1, &str);
|
517
|
+
RAISE_IF_EXCEPTION(resume_value);
|
518
|
+
return resume_value;
|
519
|
+
}
|
505
520
|
RB_GC_GUARD(resume_value);
|
506
521
|
|
507
522
|
if (result < 0)
|
@@ -549,12 +564,10 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
549
564
|
|
550
565
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
551
566
|
int completed = context_store_release(&backend->store, ctx);
|
552
|
-
if (TEST_EXCEPTION(resume_value)) {
|
553
|
-
free(iov);
|
554
|
-
RAISE_EXCEPTION(resume_value);
|
555
|
-
}
|
556
567
|
if (!completed) {
|
557
568
|
free(iov);
|
569
|
+
context_attach_buffers(ctx, argc, argv);
|
570
|
+
RAISE_IF_EXCEPTION(resume_value);
|
558
571
|
return resume_value;
|
559
572
|
}
|
560
573
|
RB_GC_GUARD(resume_value);
|
@@ -588,8 +601,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
588
601
|
|
589
602
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
590
603
|
if (argc < 2)
|
591
|
-
|
592
|
-
rb_raise(rb_eRuntimeError, "(wrong number of arguments (expected 2 or more))");
|
604
|
+
rb_raise(eArgumentError, "(wrong number of arguments (expected 2 or more))");
|
593
605
|
|
594
606
|
return (argc == 2) ?
|
595
607
|
Backend_write(self, argv[0], argv[1]) :
|
@@ -628,8 +640,11 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
628
640
|
|
629
641
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
630
642
|
int completed = context_store_release(&backend->store, ctx);
|
631
|
-
|
632
|
-
|
643
|
+
if (!completed) {
|
644
|
+
context_attach_buffers(ctx, 1, &str);
|
645
|
+
RAISE_IF_EXCEPTION(resume_value);
|
646
|
+
return resume_value;
|
647
|
+
}
|
633
648
|
RB_GC_GUARD(resume_value);
|
634
649
|
|
635
650
|
if (result < 0)
|
@@ -675,8 +690,11 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
675
690
|
|
676
691
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
677
692
|
int completed = context_store_release(&backend->store, ctx);
|
678
|
-
|
679
|
-
|
693
|
+
if (!completed) {
|
694
|
+
context_attach_buffers(ctx, 1, &str);
|
695
|
+
RAISE_IF_EXCEPTION(resume_value);
|
696
|
+
return resume_value;
|
697
|
+
}
|
680
698
|
RB_GC_GUARD(resume_value);
|
681
699
|
|
682
700
|
if (result < 0)
|
@@ -721,8 +739,11 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
|
|
721
739
|
|
722
740
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
723
741
|
int completed = context_store_release(&backend->store, ctx);
|
724
|
-
|
725
|
-
|
742
|
+
if (!completed) {
|
743
|
+
context_attach_buffers(ctx, 1, &str);
|
744
|
+
RAISE_IF_EXCEPTION(resume_value);
|
745
|
+
return resume_value;
|
746
|
+
}
|
726
747
|
RB_GC_GUARD(resume_value);
|
727
748
|
|
728
749
|
if (result < 0)
|
@@ -764,8 +785,11 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
764
785
|
|
765
786
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
766
787
|
int completed = context_store_release(&backend->store, ctx);
|
767
|
-
|
768
|
-
|
788
|
+
if (!completed) {
|
789
|
+
context_attach_buffers(ctx, 1, &str);
|
790
|
+
RAISE_IF_EXCEPTION(resume_value);
|
791
|
+
return resume_value;
|
792
|
+
}
|
769
793
|
RB_GC_GUARD(resume_value);
|
770
794
|
|
771
795
|
if (result < 0)
|
@@ -1165,6 +1189,24 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src,
|
|
1165
1189
|
return sqe;
|
1166
1190
|
}
|
1167
1191
|
|
1192
|
+
void Backend_chain_ctx_attach_buffers(op_context_t *ctx, int argc, VALUE *argv) {
|
1193
|
+
int count = 0;
|
1194
|
+
if (argc > 1) ctx->buffers = malloc(sizeof(VALUE) * (argc - 1));
|
1195
|
+
|
1196
|
+
for (int i = 0; i < argc; i++) {
|
1197
|
+
VALUE op = argv[i];
|
1198
|
+
VALUE op_type = RARRAY_AREF(op, 0);
|
1199
|
+
|
1200
|
+
if (op_type == SYM_write || op_type == SYM_send) {
|
1201
|
+
if (!count) ctx->buffer0 = RARRAY_AREF(op, 2);
|
1202
|
+
else ctx->buffers[count - 1] = RARRAY_AREF(op, 2);
|
1203
|
+
count++;
|
1204
|
+
}
|
1205
|
+
}
|
1206
|
+
ctx->buffer_count = count;
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
|
1168
1210
|
VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
1169
1211
|
VALUE resume_value = Qnil;
|
1170
1212
|
unsigned int sqe_count = 0;
|
@@ -1218,6 +1260,8 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1218
1260
|
int result = ctx->result;
|
1219
1261
|
int completed = context_store_release(&backend->store, ctx);
|
1220
1262
|
if (!completed) {
|
1263
|
+
Backend_chain_ctx_attach_buffers(ctx, argc, argv);
|
1264
|
+
|
1221
1265
|
// op was not completed (an exception was raised), so we need to cancel it
|
1222
1266
|
ctx->result = -ECANCELED;
|
1223
1267
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
@@ -1409,6 +1453,7 @@ syscallerror:
|
|
1409
1453
|
if (pipefd[1] != -1) close(pipefd[1]);
|
1410
1454
|
rb_syserr_fail(err, strerror(err));
|
1411
1455
|
error:
|
1456
|
+
context_attach_buffers_v(ctx, 4, prefix, postfix, chunk_prefix, chunk_postfix);
|
1412
1457
|
if (pipefd[0] != -1) close(pipefd[0]);
|
1413
1458
|
if (pipefd[1] != -1) close(pipefd[1]);
|
1414
1459
|
return RAISE_EXCEPTION(switchpoint_result);
|
@@ -1429,6 +1474,20 @@ VALUE Backend_trace_proc_set(VALUE self, VALUE block) {
|
|
1429
1474
|
return self;
|
1430
1475
|
}
|
1431
1476
|
|
1477
|
+
void Backend_park_fiber(VALUE self, VALUE fiber) {
|
1478
|
+
Backend_t *backend;
|
1479
|
+
GetBackend(self, backend);
|
1480
|
+
|
1481
|
+
backend_base_park_fiber(&backend->base, fiber);
|
1482
|
+
}
|
1483
|
+
|
1484
|
+
void Backend_unpark_fiber(VALUE self, VALUE fiber) {
|
1485
|
+
Backend_t *backend;
|
1486
|
+
GetBackend(self, backend);
|
1487
|
+
|
1488
|
+
backend_base_unpark_fiber(&backend->base, fiber);
|
1489
|
+
}
|
1490
|
+
|
1432
1491
|
void Init_Backend() {
|
1433
1492
|
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
|
1434
1493
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
@@ -1469,7 +1528,6 @@ void Init_Backend() {
|
|
1469
1528
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1470
1529
|
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1471
1530
|
|
1472
|
-
|
1473
1531
|
#ifdef POLYPHONY_UNSET_NONBLOCK
|
1474
1532
|
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
1475
1533
|
#endif
|
@@ -1480,6 +1538,8 @@ void Init_Backend() {
|
|
1480
1538
|
SYM_write = ID2SYM(rb_intern("write"));
|
1481
1539
|
|
1482
1540
|
backend_setup_stats_symbols();
|
1541
|
+
|
1542
|
+
eArgumentError = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
|
1483
1543
|
}
|
1484
1544
|
|
1485
1545
|
#endif // POLYPHONY_BACKEND_LIBURING
|