1 #include "sleepy_penguin.h"
3 #include <sys/socket.h>
6 #if defined(HAVE_SYS_SENDFILE_H) && !defined(HAVE_BSD_SENDFILE)
7 # include <sys/sendfile.h>
10 #if defined(__linux__) && defined(HAVE_SENDFILE)
11 # define linux_sendfile(in_fd, out_fd, offset, count) \
12 sendfile((in_fd),(out_fd),(offset),(count))
15 #elif defined(HAVE_SENDFILE) && \
16 (defined(__FreeBSD__) || defined(__DragonFly__))
18 * make BSD sendfile look like Linux for now...
19 * we can support SF_NODISKIO later
21 static ssize_t
linux_sendfile(int sockfd
, int filefd
, off_t
*off
, size_t count
)
24 off_t offset
= off
? *off
: lseek(filefd
, 0, SEEK_CUR
);
26 int rc
= sendfile(filefd
, sockfd
, offset
, count
, NULL
, &sbytes
, 0);
31 lseek(filefd
, sbytes
, SEEK_CUR
);
32 return (ssize_t
)sbytes
;
37 #else /* emulate sendfile using (read|pread) + write */
38 static ssize_t
pread_sendfile(int sockfd
, int filefd
, off_t
*off
, size_t count
)
40 size_t max_read
= 16384;
45 max_read
= count
> max_read
? max_read
: count
;
46 buf
= xmalloc(max_read
);
49 r
= off
? pread(filefd
, buf
, max_read
, *off
) :
50 read(filefd
, buf
, max_read
);
51 } while (r
< 0 && errno
== EINTR
);
59 w
= write(sockfd
, buf
, r
);
65 # define linux_sendfile(out_fd, in_fd, offset, count) \
66 pread_sendfile((out_fd),(in_fd),(offset),(count))
76 static VALUE sym_wait_writable
;
78 static VALUE
nogvl_sf(void *ptr
)
80 struct sf_args
*a
= ptr
;
82 return (VALUE
)linux_sendfile(a
->dst_fd
, a
->src_fd
, a
->off
, a
->count
);
85 static VALUE
lsf(VALUE mod
, VALUE dst
, VALUE src
, VALUE src_off
, VALUE count
)
92 a
.off
= NIL_P(src_off
) ? NULL
: (off
= NUM2OFFT(src_off
), &off
);
93 a
.count
= NUM2SIZET(count
);
95 a
.src_fd
= rb_sp_fileno(src
);
96 a
.dst_fd
= rb_sp_fileno(dst
);
97 bytes
= (ssize_t
)rb_sp_fd_region(nogvl_sf
, &a
, a
.dst_fd
);
101 return sym_wait_writable
;
110 rb_sys_fail("sendfile");
112 return SSIZET2NUM(bytes
);
115 void sleepy_penguin_init_sendfile(void)
117 VALUE m
= rb_define_module("SleepyPenguin");
118 rb_define_singleton_method(m
, "__lsf", lsf
, 4);
119 sym_wait_writable
= ID2SYM(rb_intern("wait_writable"));