1 #include "sleepy_penguin.h"
10 static VALUE sym_EAGAIN
;
12 #ifndef F_LINUX_SPECIFIC_BASE
13 # define F_LINUX_SPECIFIC_BASE 1024
17 # define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
18 # define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
21 static int check_fileno(VALUE io
)
23 int saved_errno
= errno
;
24 int fd
= rb_sp_fileno(io
);
29 static void *nogvl_splice(void *ptr
)
31 struct copy_args
*a
= ptr
;
33 return (void *)splice(a
->fd_in
, a
->off_in
, a
->fd_out
, a
->off_out
,
38 static VALUE
my_splice(VALUE mod
, VALUE io_in
, VALUE off_in
,
39 VALUE io_out
, VALUE off_out
,
40 VALUE len
, VALUE flags
)
46 a
.off_in
= NIL_P(off_in
) ? NULL
: (i
= NUM2OFFT(off_in
), &i
);
47 a
.off_out
= NIL_P(off_out
) ? NULL
: (o
= NUM2OFFT(off_out
), &o
);
48 a
.len
= NUM2SIZET(len
);
49 a
.flags
= NUM2UINT(flags
);
52 a
.fd_in
= check_fileno(io_in
);
53 a
.fd_out
= check_fileno(io_out
);
54 bytes
= (ssize_t
)IO_RUN(nogvl_splice
, &a
);
55 if (bytes
== 0) return Qnil
;
59 case EAGAIN
: return sym_EAGAIN
;
60 default: rb_sys_fail("splice");
63 return SSIZET2NUM(bytes
);
74 /* runs without GVL */
75 static void *nogvl_tee(void *ptr
)
77 struct tee_args
*a
= ptr
;
79 return (void *)tee(a
->fd_in
, a
->fd_out
, a
->len
, a
->flags
);
83 static VALUE
my_tee(VALUE mod
, VALUE io_in
, VALUE io_out
,
84 VALUE len
, VALUE flags
)
89 a
.len
= (size_t)NUM2SIZET(len
);
90 a
.flags
= NUM2UINT(flags
);
93 a
.fd_in
= check_fileno(io_in
);
94 a
.fd_out
= check_fileno(io_out
);
95 bytes
= (ssize_t
)IO_RUN(nogvl_tee
, &a
);
96 if (bytes
== 0) return Qnil
;
100 case EAGAIN
: return sym_EAGAIN
;
101 default: rb_sys_fail("tee");
104 return SSIZET2NUM(bytes
);
108 void sleepy_penguin_init_splice(void)
110 VALUE mod
= rb_define_module("SleepyPenguin");
111 rb_define_singleton_method(mod
, "__splice", my_splice
, 6);
112 rb_define_singleton_method(mod
, "__tee", my_tee
, 4);
115 * Attempt to move pages instead of copying. This is only a hint
116 * and support for it was removed in Linux 2.6.21. It will be
117 * re-added for FUSE filesystems only in Linux 2.6.35.
119 rb_define_const(mod
, "F_MOVE", UINT2NUM(SPLICE_F_MOVE
));
122 * Do not block on pipe I/O. This flag only affects the pipe(s)
123 * being spliced from/to and has no effect on the non-pipe
124 * descriptor (which requires non-blocking operation to be set
127 * The non-blocking flag (O_NONBLOCK) on the pipe descriptors
128 * themselves are ignored by this family of functions, and
129 * using this flag is the only way to get non-blocking operation
132 * It is highly recommended this flag be set
133 * (or SleepyPenguin.trysplice used)
134 * whenever splicing from a socket into a pipe unless there is
135 * another (native) thread or process doing a blocking read on that
136 * pipe. Otherwise it is possible to block a single-threaded process
137 * if the socket buffers are larger than the pipe buffers.
139 rb_define_const(mod
, "F_NONBLOCK", UINT2NUM(SPLICE_F_NONBLOCK
));
142 * Indicate that there may be more data coming into the outbound
143 * descriptor. This can allow the kernel to avoid sending partial
144 * frames from sockets. Currently only used with splice.
146 rb_define_const(mod
, "F_MORE", UINT2NUM(SPLICE_F_MORE
));
149 * fcntl() command constant used to return the size of a pipe.
150 * This constant is only defined when running Linux 2.6.35
155 * r.fcntl(SleepyPenguin::F_GETPIPE_SZ) => Integer
157 rb_define_const(mod
, "F_GETPIPE_SZ", UINT2NUM(F_GETPIPE_SZ
));
160 * fcntl() command constant used to set the size of a pipe.
161 * This constant is only defined when running Linux 2.6.35
168 * r.fcntl(SleepyPenguin::F_SETPIPE_SZ, 131072)
170 rb_define_const(mod
, "F_SETPIPE_SZ", UINT2NUM(F_SETPIPE_SZ
));
172 sym_EAGAIN
= ID2SYM(rb_intern("EAGAIN"));