Feature #9323 » patch.diff
configure.in | ||
---|---|---|
sys/socket.h \
|
||
process.h \
|
||
sys/prctl.h \
|
||
sys/uio.h \
|
||
atomic.h \
|
||
malloc.h \
|
||
malloc_np.h \
|
||
... | ... | |
AC_CHECK_FUNCS(malloc_size)
|
||
AC_CHECK_FUNCS(mblen)
|
||
AC_CHECK_FUNCS(memalign)
|
||
AC_CHECK_FUNCS(writev)
|
||
AC_CHECK_FUNCS(memrchr)
|
||
AC_CHECK_FUNCS(mktime)
|
||
AC_CHECK_FUNCS(pipe2)
|
include/ruby/intern.h | ||
---|---|---|
RUBY_EXTERN VALUE rb_default_rs;
|
||
RUBY_EXTERN VALUE rb_output_rs;
|
||
VALUE rb_io_write(VALUE, VALUE);
|
||
VALUE rb_io_writev(VALUE, VALUE);
|
||
VALUE rb_io_gets(VALUE);
|
||
VALUE rb_io_getbyte(VALUE);
|
||
VALUE rb_io_ungetc(VALUE, VALUE);
|
io.c | ||
---|---|---|
#include <sys/syscall.h>
|
||
#endif
|
||
#ifdef HAVE_SYS_UIO_H
|
||
#include <sys/uio.h>
|
||
#endif
|
||
#if defined(__BEOS__) || defined(__HAIKU__)
|
||
# ifndef NOFILE
|
||
# define NOFILE (OPEN_MAX)
|
||
... | ... | |
static VALUE argf;
|
||
static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
|
||
static ID id_write, id_writev, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
|
||
static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
|
||
static VALUE sym_textmode, sym_binmode, sym_autoclose, sym_exception;
|
||
static VALUE sym_SET, sym_CUR, sym_END;
|
||
... | ... | |
size_t capa;
|
||
};
|
||
#ifdef HAVE_WRITEV
|
||
struct io_internal_writev_struct {
|
||
int fd;
|
||
const struct iovec *iov;
|
||
int iovcnt;
|
||
};
|
||
#endif
|
||
static VALUE
|
||
internal_read_func(void *ptr)
|
||
{
|
||
... | ... | |
return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa);
|
||
}
|
||
#ifdef HAVE_WRITEV
|
||
static VALUE
|
||
internal_writev_func(void *ptr)
|
||
{
|
||
struct io_internal_writev_struct *iis = ptr;
|
||
return writev(iis->fd, iis->iov, iis->iovcnt);
|
||
}
|
||
#endif
|
||
static ssize_t
|
||
rb_read_internal(int fd, void *buf, size_t count)
|
||
{
|
||
... | ... | |
RUBY_UBF_IO, NULL);
|
||
}
|
||
#ifdef HAVE_WRITEV
|
||
static ssize_t
|
||
rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
|
||
{
|
||
struct io_internal_writev_struct iis;
|
||
iis.fd = fd;
|
||
iis.iov = iov;
|
||
iis.iovcnt = iovcnt;
|
||
return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
|
||
}
|
||
#endif
|
||
static long
|
||
io_writable_length(rb_io_t *fptr, long l)
|
||
{
|
||
... | ... | |
return io;
|
||
}
|
||
#ifdef HAVE_WRITEV
|
||
struct binwritev_arg {
|
||
rb_io_t *fptr;
|
||
const struct iovec *iov;
|
||
int iovcnt;
|
||
};
|
||
static VALUE
|
||
call_writev_internal(VALUE arg)
|
||
{
|
||
struct binwritev_arg *p = (struct binwritev_arg *)arg;
|
||
return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
|
||
}
|
||
static long
|
||
io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
|
||
{
|
||
int i;
|
||
long r, total = 0, written_len = 0;
|
||
/* don't write anything if current thread has a pending interrupt. */
|
||
rb_thread_check_ints();
|
||
if (iovcnt == 0) return 0;
|
||
for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
|
||
if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
|
||
fptr->wbuf.off = 0;
|
||
fptr->wbuf.len = 0;
|
||
fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
|
||
fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
|
||
fptr->write_lock = rb_mutex_new();
|
||
rb_mutex_allow_trap(fptr->write_lock, 1);
|
||
}
|
||
if (fptr->wbuf.ptr && fptr->wbuf.len) {
|
||
if (fptr->wbuf.off + fptr->wbuf.len + total <= fptr->wbuf.capa) {
|
||
long offset = fptr->wbuf.off;
|
||
for (i = 1; i < iovcnt; i++) {
|
||
memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
|
||
offset += iov[i].iov_len;
|
||
}
|
||
fptr->wbuf.len += total;
|
||
return total;
|
||
}
|
||
else {
|
||
iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
|
||
iov[0].iov_len = fptr->wbuf.len;
|
||
}
|
||
}
|
||
else {
|
||
iov++;
|
||
iovcnt--;
|
||
}
|
||
retry:
|
||
if (fptr->write_lock) {
|
||
struct binwritev_arg arg;
|
||
arg.fptr = fptr;
|
||
arg.iov = iov;
|
||
arg.iovcnt = iovcnt;
|
||
r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
|
||
}
|
||
else {
|
||
r = rb_writev_internal(fptr->fd, iov, iovcnt);
|
||
}
|
||
if (r >= 0) {
|
||
written_len += r;
|
||
if (fptr->wbuf.ptr && fptr->wbuf.len) {
|
||
if (written_len < fptr->wbuf.len) {
|
||
fptr->wbuf.off += r;
|
||
fptr->wbuf.len -= r;
|
||
}
|
||
else {
|
||
fptr->wbuf.off = 0;
|
||
fptr->wbuf.len = 0;
|
||
}
|
||
}
|
||
if (written_len == total) return written_len;
|
||
for (i = 0; i < iovcnt; i++) {
|
||
if (r > (ssize_t)iov[i].iov_len) {
|
||
r -= iov[i].iov_len;
|
||
iov[i].iov_len = 0;
|
||
}
|
||
else {
|
||
iov[i].iov_base = (char *)iov[i].iov_base + r;
|
||
iov[i].iov_len -= r;
|
||
break;
|
||
}
|
||
}
|
||
errno = EAGAIN;
|
||
}
|
||
if (rb_io_wait_writable(fptr->fd)) {
|
||
rb_io_check_closed(fptr);
|
||
goto retry;
|
||
}
|
||
return -1L;
|
||
}
|
||
static long
|
||
io_fwritev(VALUE ary, rb_io_t *fptr)
|
||
{
|
||
int i, iovcnt = RARRAY_LEN(ary) + 1;
|
||
long n;
|
||
VALUE v, str;
|
||
struct iovec *iov = ALLOCV_N(struct iovec, v, iovcnt);
|
||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||
str = rb_obj_as_string(RARRAY_AREF(ary, i));
|
||
str = do_writeconv(str, fptr);
|
||
str = rb_str_new_frozen(str);
|
||
iov[i+1].iov_base = RSTRING_PTR(str);
|
||
iov[i+1].iov_len = RSTRING_LEN(str);
|
||
}
|
||
n = io_binwritev(iov, iovcnt, fptr);
|
||
if (v) ALLOCV_END(v);
|
||
return n;
|
||
}
|
||
static VALUE
|
||
io_writev(VALUE io, VALUE ary)
|
||
{
|
||
rb_io_t *fptr;
|
||
long n;
|
||
VALUE tmp;
|
||
io = GetWriteIO(io);
|
||
ary = rb_check_array_type(ary);
|
||
tmp = rb_io_check_io(io);
|
||
if (NIL_P(tmp)) {
|
||
/* port is not IO, call writev method for it. */
|
||
return rb_funcallv(io, id_writev, 1, &ary);
|
||
}
|
||
io = tmp;
|
||
GetOpenFile(io, fptr);
|
||
rb_io_check_writable(fptr);
|
||
n = io_fwritev(ary, fptr);
|
||
if (n == -1L) rb_sys_fail_path(fptr->pathv);
|
||
return LONG2FIX(n);
|
||
}
|
||
#else
|
||
static VALUE
|
||
io_writev(VALUE io, VALUE ary)
|
||
{
|
||
rb_io_t *fptr;
|
||
long n;
|
||
VALUE str, tmp;
|
||
io = GetWriteIO(io);
|
||
ary = rb_check_array_type(ary);
|
||
tmp = rb_io_check_io(io);
|
||
if (NIL_P(tmp)) {
|
||
/* port is not IO, call writev method for it. */
|
||
return rb_funcallv(io, id_writev, 1, &ary);
|
||
}
|
||
io = tmp;
|
||
str = rb_ary_join(ary, rb_str_new(0, 0));
|
||
GetOpenFile(io, fptr);
|
||
rb_io_check_writable(fptr);
|
||
n = io_fwrite(str, fptr, 0);
|
||
if (n == -1L) rb_sys_fail_path(fptr->pathv);
|
||
return LONG2FIX(n);
|
||
}
|
||
#endif /* HAVE_WRITEV */
|
||
VALUE
|
||
rb_io_writev(VALUE io, VALUE ary)
|
||
{
|
||
return rb_funcallv(io, id_writev, 1, &ary);
|
||
}
|
||
#ifdef HAVE_FSYNC
|
||
static VALUE
|
||
nogvl_fsync(void *ptr)
|
||
... | ... | |
*/
|
||
# define USE_SENDFILE
|
||
# ifdef HAVE_SYS_UIO_H
|
||
# include <sys/uio.h>
|
||
# endif
|
||
static ssize_t
|
||
simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
|
||
{
|
||
... | ... | |
rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
|
||
id_write = rb_intern("write");
|
||
id_writev = rb_intern("writev");
|
||
id_read = rb_intern("read");
|
||
id_getc = rb_intern("getc");
|
||
id_flush = rb_intern("flush");
|
||
... | ... | |
rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
|
||
rb_define_method(rb_cIO, "read", io_read, -1);
|
||
rb_define_method(rb_cIO, "write", io_write_m, 1);
|
||
rb_define_method(rb_cIO, "writev", io_writev, 1);
|
||
rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
|
||
rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
|
||
rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
|