13 #ifdef HAVE_RB_THREAD_BLOCKING_REGION
14 # define RUBY_1_8_TRAP_BEG for(;0;)
15 # define RUBY_1_8_TRAP_END for(;0;)
17 /* partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */
19 # define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
20 typedef void rb_unblock_function_t(void *);
21 typedef VALUE
rb_blocking_function_t(void *);
23 rb_thread_blocking_region(
24 rb_blocking_function_t
*fn
, void *data1
,
25 rb_unblock_function_t
*ubf
, void *data2
)
29 assert(RUBY_UBF_IO
== ubf
&& "RUBY_UBF_IO required for emulation");
37 # define RUBY_1_8_TRAP_BEG TRAP_BEG
38 # define RUBY_1_8_TRAP_END TRAP_END
39 #endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
42 # define RSTRING_PTR(s) (RSTRING(s)->ptr)
45 # define RSTRING_LEN(s) (RSTRING(s)->len)
48 # define RARRAY_PTR(s) (RARRAY(s)->ptr)
51 # define RARRAY_LEN(s) (RARRAY(s)->len)
55 * Releases GVL only iff blocking I/O is used.
56 * We'll trust programmers who use non-blocking I/O explicitly to
57 * want the fastest possible performance without resorting to threads,
58 * so releasing and them immediately reacquiring the GVL would be
61 static VALUE
nb_io_run(rb_blocking_function_t
*fn
, void *data
, unsigned flags
)
63 if (flags
& SPLICE_F_NONBLOCK
)
65 return rb_thread_blocking_region(fn
, data
, RUBY_UBF_IO
, 0);
77 static VALUE
nogvl_splice(void *ptr
)
79 struct splice_args
*a
= ptr
;
83 * it's still possible to block because the SPLICE_F_NONBLOCK flag
84 * only affects the pipe descriptor, not the non-pipe descriptor.
85 * So use TRAP_BEG/TRAP_END (only) to make Ruby 1.8 happy. We also
86 * don't want the TRAP_BEG/TRAP_END compatibility layer in 1.9,
87 * so we use the 1.8-only versions
90 n
= splice(a
->fd_in
, a
->off_in
, a
->fd_out
, a
->off_out
,
99 * IO.splice(fd_in, off_in, fd_out, off_out, len, flags) => integer
101 * Splice +len+ bytes from/to a pipe. Either +fd_in+ or +fd_out+
102 * MUST be a pipe. +fd_in+ and +fd_out+ may BOTH be pipes as of
103 * Linux 2.6.31 or later.
105 * +off_in+ and +off_out+ if non-nil may be used to
106 * specify an offset for the non-pipe file descriptor.
108 * +flags+ may be a bitmask of the following flags:
110 * IO::Splice::F_MOVE, IO::Splice::F_NONBLOCK, IO::Splice::F_MORE
112 * Returns the number of bytes spliced.
113 * Raises EOFError when +fd_in+ has reached end of file.
114 * Raises Errno::EAGAIN if the IO::Splice::F_NONBLOCK flag is set
115 * and the pipe has no data to read from or space to write to. May
116 * also raise Errno::EAGAIN if the non-pipe descriptor has no data
117 * to read from or space to write to.
119 * rd, wr = (pipe = IO.pipe).map { |io| io.fileno }
120 * src_io, dst_io = File.open("/path/to/src"), File.open("/path/to/dst")
121 * src, dst = src_io.fileno, dst_io.fileno
123 * nr = IO.splice(src, nil, wr, nil, IO::Splice::PIPE_CAPA, 0)
124 * IO.splice(rd, nil, dst, nil, nr, 0)
126 * As splice never exposes buffers to userspace, it will not take
127 * into account userspace buffering done by Ruby or stdio. It is
128 * also not subject to encoding/decoding filters under Ruby 1.9.
130 * See manpage for full documentation:
131 * http://kernel.org/doc/man-pages/online/pages/man2/splice.2.html
133 static VALUE
my_splice(VALUE self
,
134 VALUE fd_in
, VALUE off_in
,
135 VALUE fd_out
, VALUE off_out
,
136 VALUE len
, VALUE flags
)
140 struct splice_args a
= {
141 .off_in
= NIL_P(off_in
) ? NULL
: (i
= NUM2OFFT(off_in
), &i
),
142 .off_out
= NIL_P(off_out
) ? NULL
: (o
= NUM2OFFT(off_out
), &o
),
143 .fd_in
= NUM2INT(fd_in
),
144 .fd_out
= NUM2INT(fd_out
),
145 .len
= (size_t)NUM2ULONG(len
),
146 .flags
= NUM2UINT(flags
),
149 n
= (long)nb_io_run(nogvl_splice
, &a
, a
.flags
);
153 rb_sys_fail("splice");
164 /* runs without GVL */
165 static VALUE
nogvl_tee(void *ptr
)
167 struct tee_args
*a
= ptr
;
169 return (VALUE
)tee(a
->fd_in
, a
->fd_out
, a
->len
, a
->flags
);
174 * IO.tee(fd_in, fd_out, len, flags) => integer
176 * Copies up to +len+ bytes of data from +fd_in+ to +fd_out+. +fd_in+
177 * and +fd_out+ must both refer to pipe descriptors. +fd_in+ and +fd_out+
178 * may not be endpoints of the same pipe.
180 * +flags+ may be zero or IO::Splice::F_NONBLOCK
181 * Other IO::Splice flags are currently unimplemented or have no effect.
183 * Returns the number of bytes duplicated if successful.
184 * Raises EOFError when +fd_in+ is closed and emptied.
185 * Raises Errno::EAGAIN when +fd_in+ is empty and/or +fd_out+ is full
186 * and +flags+ contains IO::Splice::F_NONBLOCK
188 * See manpage for full documentation:
189 * http://kernel.org/doc/man-pages/online/pages/man2/tee.2.html
191 static VALUE
my_tee(VALUE self
,
192 VALUE fd_in
, VALUE fd_out
,
193 VALUE len
, VALUE flags
)
196 struct tee_args a
= {
197 .fd_in
= NUM2INT(fd_in
),
198 .fd_out
= NUM2INT(fd_out
),
199 .len
= (size_t)NUM2ULONG(len
),
200 .flags
= NUM2UINT(flags
),
203 n
= (long)nb_io_run(nogvl_tee
, &a
, a
.flags
);
212 struct vmsplice_args
{
215 unsigned long nr_segs
;
219 static VALUE
nogvl_vmsplice(void *ptr
)
221 struct vmsplice_args
*a
= ptr
;
223 return (VALUE
)vmsplice(a
->fd
, a
->iov
, a
->nr_segs
, a
->flags
);
228 * IO.vmsplice(fd, string_array, flags) => integer
230 * Transfers an array of strings into the pipe descriptor given by fd.
231 * +fd+ must be the writable end of a pipe.
233 * This may allow the kernel to avoid data copies in some cases.
234 * but is (probably) of limited usefulness in Ruby.
236 * See manpage for full documentation:
237 * http://kernel.org/doc/man-pages/online/pages/man2/vmsplice.2.html
239 static VALUE
my_vmsplice(VALUE self
, VALUE fd
, VALUE data
, VALUE flags
)
242 struct vmsplice_args a
;
246 switch (TYPE(data
)) {
248 ary
= RARRAY_PTR(data
);
249 a
.nr_segs
= RARRAY_LEN(data
);
251 if (a
.nr_segs
> IOV_MAX
)
252 rb_raise(rb_eArgError
, "array larger than IOV_MAX");
254 a
.iov
= tmp
= alloca(sizeof(struct iovec
) * a
.nr_segs
);
256 for (n
= (long)a
.nr_segs
; --n
>= 0; tmp
++, ary
++) {
257 if (TYPE(*ary
) != T_STRING
)
258 rb_raise(rb_eArgError
,
259 "must be an array of strings");
260 tmp
->iov_base
= RSTRING_PTR(*ary
);
261 tmp
->iov_len
= RSTRING_LEN(*ary
);
265 rb_raise(rb_eArgError
, "must be an array of strings");
269 a
.flags
= NUM2UINT(flags
);
271 n
= (long)nb_io_run(nogvl_vmsplice
, &a
, a
.flags
);
273 rb_sys_fail("vmsplice");
278 void Init_io_splice_ext(void)
280 VALUE cSplice
= rb_define_class_under(rb_cIO
, "Splice", rb_cObject
);
282 rb_define_singleton_method(rb_cIO
, "splice", my_splice
, 6);
283 rb_define_singleton_method(rb_cIO
, "tee", my_tee
, 4);
284 rb_define_singleton_method(rb_cIO
, "vmsplice", my_vmsplice
, 3);
287 * Attempt to move pages instead of copying. This is only a hint
288 * and support for it was removed in Linux 2.6.21 and has not been
289 * readded as of 2.6.30.
291 rb_define_const(cSplice
, "F_MOVE", UINT2NUM(SPLICE_F_MOVE
));
294 * Do not block on I/O. This flag only affects the pipe(s) being
295 * spliced from/to and has no effect on the non-pipe descriptor
296 * (which requires non-blocking operation to be set explicitly).
298 rb_define_const(cSplice
, "F_NONBLOCK", UINT2NUM(SPLICE_F_NONBLOCK
));
301 * Indicate that there may be more data coming into the outbound
302 * descriptor. This can allow the kernel to avoid sending partial
303 * frames from sockets. Currently only used with splice.
305 rb_define_const(cSplice
, "F_MORE", UINT2NUM(SPLICE_F_MORE
));
308 * Only usable by vmsplice. This flag probably not useful in the
309 * context of Ruby applications which cannot control alignment.
311 rb_define_const(cSplice
, "F_GIFT", UINT2NUM(SPLICE_F_GIFT
));
314 * The maximum size of an atomic write to a pipe
315 * POSIX requires this to be at least 512 bytes.
316 * Under Linux, this is 4096 bytes.
318 rb_define_const(cSplice
, "PIPE_BUF", UINT2NUM(PIPE_BUF
));