Project

General

Profile

Feature #9323 ยป patch.diff

Glass_saga (Masaki Matsushita), 12/30/2013 10:08 PM

View differences:

configure.in
1116 1116
  sys/socket.h \
1117 1117
  process.h \
1118 1118
  sys/prctl.h \
1119
  sys/uio.h \
1119 1120
  atomic.h \
1120 1121
  malloc.h \
1121 1122
  malloc_np.h \
......
1900 1901
AC_CHECK_FUNCS(malloc_size)
1901 1902
AC_CHECK_FUNCS(mblen)
1902 1903
AC_CHECK_FUNCS(memalign)
1904
AC_CHECK_FUNCS(writev)
1903 1905
AC_CHECK_FUNCS(memrchr)
1904 1906
AC_CHECK_FUNCS(mktime)
1905 1907
AC_CHECK_FUNCS(pipe2)
include/ruby/intern.h
519 519
RUBY_EXTERN VALUE rb_default_rs;
520 520
RUBY_EXTERN VALUE rb_output_rs;
521 521
VALUE rb_io_write(VALUE, VALUE);
522
VALUE rb_io_writev(VALUE, VALUE);
522 523
VALUE rb_io_gets(VALUE);
523 524
VALUE rb_io_getbyte(VALUE);
524 525
VALUE rb_io_ungetc(VALUE, VALUE);
io.c
86 86
#include <sys/syscall.h>
87 87
#endif
88 88

  
89
#ifdef HAVE_SYS_UIO_H
90
#include <sys/uio.h>
91
#endif
92

  
89 93
#if defined(__BEOS__) || defined(__HAIKU__)
90 94
# ifndef NOFILE
91 95
#  define NOFILE (OPEN_MAX)
......
157 161

  
158 162
static VALUE argf;
159 163

  
160
static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
164
static ID id_write, id_writev, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
161 165
static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
162 166
static VALUE sym_textmode, sym_binmode, sym_autoclose, sym_exception;
163 167
static VALUE sym_SET, sym_CUR, sym_END;
......
918 922
    size_t capa;
919 923
};
920 924

  
925
#ifdef HAVE_WRITEV
926
struct io_internal_writev_struct {
927
    int fd;
928
    const struct iovec *iov;
929
    int iovcnt;
930
};
931
#endif
932

  
921 933
static VALUE
922 934
internal_read_func(void *ptr)
923 935
{
......
939 951
    return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa);
940 952
}
941 953

  
954
#ifdef HAVE_WRITEV
955
static VALUE
956
internal_writev_func(void *ptr)
957
{
958
    struct io_internal_writev_struct *iis = ptr;
959
    return writev(iis->fd, iis->iov, iis->iovcnt);
960
}
961
#endif
962

  
942 963
static ssize_t
943 964
rb_read_internal(int fd, void *buf, size_t count)
944 965
{
......
973 994
						RUBY_UBF_IO, NULL);
974 995
}
975 996

  
997
#ifdef HAVE_WRITEV
998
static ssize_t
999
rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
1000
{
1001
    struct io_internal_writev_struct iis;
1002
    iis.fd = fd;
1003
    iis.iov = iov;
1004
    iis.iovcnt = iovcnt;
1005

  
1006
    return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
1007
}
1008
#endif
1009

  
976 1010
static long
977 1011
io_writable_length(rb_io_t *fptr, long l)
978 1012
{
......
1450 1484
    return io;
1451 1485
}
1452 1486

  
1487
#ifdef HAVE_WRITEV
1488
struct binwritev_arg {
1489
    rb_io_t *fptr;
1490
    const struct iovec *iov;
1491
    int iovcnt;
1492
};
1493

  
1494
static VALUE
1495
call_writev_internal(VALUE arg)
1496
{
1497
    struct binwritev_arg *p = (struct binwritev_arg *)arg;
1498
    return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
1499
}
1500

  
1501
static long
1502
io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
1503
{
1504
    int i;
1505
    long r, total = 0, written_len = 0;
1506

  
1507
    /* don't write anything if current thread has a pending interrupt. */
1508
    rb_thread_check_ints();
1509

  
1510
    if (iovcnt == 0) return 0;
1511
    for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1512

  
1513
    if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
1514
	fptr->wbuf.off = 0;
1515
	fptr->wbuf.len = 0;
1516
	fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1517
	fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1518
	fptr->write_lock = rb_mutex_new();
1519
	rb_mutex_allow_trap(fptr->write_lock, 1);
1520
    }
1521

  
1522
    if (fptr->wbuf.ptr && fptr->wbuf.len) {
1523
	if (fptr->wbuf.off + fptr->wbuf.len + total <= fptr->wbuf.capa) {
1524
	    long offset = fptr->wbuf.off;
1525
	    for (i = 1; i < iovcnt; i++) {
1526
		memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
1527
		offset += iov[i].iov_len;
1528
	    }
1529
	    fptr->wbuf.len += total;
1530
	    return total;
1531
	}
1532
	else {
1533
	    iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
1534
	    iov[0].iov_len  = fptr->wbuf.len;
1535
	}
1536
    }
1537
    else {
1538
	iov++;
1539
	iovcnt--;
1540
    }
1541

  
1542
  retry:
1543
    if (fptr->write_lock) {
1544
	struct binwritev_arg arg;
1545
	arg.fptr = fptr;
1546
	arg.iov  = iov;
1547
	arg.iovcnt = iovcnt;
1548
	r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
1549
    }
1550
    else {
1551
	r = rb_writev_internal(fptr->fd, iov, iovcnt);
1552
    }
1553

  
1554
    if (r >= 0) {
1555
	written_len += r;
1556
	if (fptr->wbuf.ptr && fptr->wbuf.len) {
1557
	    if (written_len < fptr->wbuf.len) {
1558
		fptr->wbuf.off += r;
1559
		fptr->wbuf.len -= r;
1560
	    }
1561
	    else {
1562
		fptr->wbuf.off = 0;
1563
		fptr->wbuf.len = 0;
1564
	    }
1565
	}
1566
	if (written_len == total) return written_len;
1567

  
1568
	for (i = 0; i < iovcnt; i++) {
1569
	    if (r > (ssize_t)iov[i].iov_len) {
1570
		r -= iov[i].iov_len;
1571
		iov[i].iov_len = 0;
1572
            }
1573
	    else {
1574
		iov[i].iov_base = (char *)iov[i].iov_base + r;
1575
		iov[i].iov_len  -= r;
1576
		break;
1577
	    }
1578
	}
1579

  
1580
        errno = EAGAIN;
1581
    }
1582
    if (rb_io_wait_writable(fptr->fd)) {
1583
        rb_io_check_closed(fptr);
1584
	goto retry;
1585
    }
1586

  
1587
    return -1L;
1588
}
1589

  
1590
static long
1591
io_fwritev(VALUE ary, rb_io_t *fptr)
1592
{
1593
    int i, iovcnt = RARRAY_LEN(ary) + 1;
1594
    long n;
1595
    VALUE v, str;
1596
    struct iovec *iov = ALLOCV_N(struct iovec, v, iovcnt);
1597

  
1598
    for (i = 0; i < RARRAY_LEN(ary); i++) {
1599
	str = rb_obj_as_string(RARRAY_AREF(ary, i));
1600
	str = do_writeconv(str, fptr);
1601
	str = rb_str_new_frozen(str);
1602
	iov[i+1].iov_base = RSTRING_PTR(str);
1603
	iov[i+1].iov_len  = RSTRING_LEN(str);
1604
    }
1605

  
1606
    n = io_binwritev(iov, iovcnt, fptr);
1607
    if (v) ALLOCV_END(v);
1608

  
1609
    return n;
1610
}
1611

  
1612
static VALUE
1613
io_writev(VALUE io, VALUE ary)
1614
{
1615
    rb_io_t *fptr;
1616
    long n;
1617
    VALUE tmp;
1618

  
1619
    io = GetWriteIO(io);
1620
    ary = rb_check_array_type(ary);
1621
    tmp = rb_io_check_io(io);
1622
    if (NIL_P(tmp)) {
1623
	/* port is not IO, call writev method for it. */
1624
	return rb_funcallv(io, id_writev, 1, &ary);
1625
    }
1626
    io = tmp;
1627

  
1628
    GetOpenFile(io, fptr);
1629
    rb_io_check_writable(fptr);
1630

  
1631
    n = io_fwritev(ary, fptr);
1632
    if (n == -1L) rb_sys_fail_path(fptr->pathv);
1633

  
1634
    return LONG2FIX(n);
1635
}
1636
#else
1637
static VALUE
1638
io_writev(VALUE io, VALUE ary)
1639
{
1640
    rb_io_t *fptr;
1641
    long n;
1642
    VALUE str, tmp;
1643

  
1644
    io = GetWriteIO(io);
1645
    ary = rb_check_array_type(ary);
1646
    tmp = rb_io_check_io(io);
1647
    if (NIL_P(tmp)) {
1648
	/* port is not IO, call writev method for it. */
1649
	return rb_funcallv(io, id_writev, 1, &ary);
1650
    }
1651
    io = tmp;
1652

  
1653
    str = rb_ary_join(ary, rb_str_new(0, 0));
1654

  
1655
    GetOpenFile(io, fptr);
1656
    rb_io_check_writable(fptr);
1657

  
1658
    n = io_fwrite(str, fptr, 0);
1659
    if (n == -1L) rb_sys_fail_path(fptr->pathv);
1660

  
1661
    return LONG2FIX(n);
1662
}
1663
#endif /* HAVE_WRITEV */
1664

  
1665
VALUE
1666
rb_io_writev(VALUE io, VALUE ary)
1667
{
1668
    return rb_funcallv(io, id_writev, 1, &ary);
1669
}
1670

  
1453 1671
#ifdef HAVE_FSYNC
1454 1672
static VALUE
1455 1673
nogvl_fsync(void *ptr)
......
9899 10117
 */
9900 10118
#  define USE_SENDFILE
9901 10119

  
9902
#  ifdef HAVE_SYS_UIO_H
9903
#   include <sys/uio.h>
9904
#  endif
9905

  
9906 10120
static ssize_t
9907 10121
simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9908 10122
{
......
11869 12083
    rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
11870 12084

  
11871 12085
    id_write = rb_intern("write");
12086
    id_writev = rb_intern("writev");
11872 12087
    id_read = rb_intern("read");
11873 12088
    id_getc = rb_intern("getc");
11874 12089
    id_flush = rb_intern("flush");
......
11997 12212
    rb_define_method(rb_cIO, "readpartial",  io_readpartial, -1);
11998 12213
    rb_define_method(rb_cIO, "read",  io_read, -1);
11999 12214
    rb_define_method(rb_cIO, "write", io_write_m, 1);
12215
    rb_define_method(rb_cIO, "writev", io_writev, 1);
12000 12216
    rb_define_method(rb_cIO, "gets",  rb_io_gets_m, -1);
12001 12217
    rb_define_method(rb_cIO, "readline",  rb_io_readline, -1);
12002 12218
    rb_define_method(rb_cIO, "getc",  rb_io_getc, 0);