Feature #6082 » shift_fflush.diff
configure.in | ||
---|---|---|
syscall.h pwd.h grp.h a.out.h utime.h direct.h sys/resource.h \
|
||
sys/mkdev.h sys/utime.h xti.h netinet/in_systm.h float.h ieeefp.h \
|
||
ucontext.h intrinsics.h langinfo.h locale.h sys/sendfile.h time.h \
|
||
net/socket.h sys/socket.h process.h sys/prctl.h)
|
||
net/socket.h sys/socket.h process.h sys/prctl.h sys/uio.h)
|
||
AC_TYPE_SIZE_T
|
||
RUBY_CHECK_SIZEOF(size_t, [int long void*], [], [@%:@include <sys/types.h>])
|
||
... | ... | |
setuid setgid daemon select_large_fdset setenv unsetenv\
|
||
mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\
|
||
pread sendfile shutdown sigaltstack dl_iterate_phdr\
|
||
dup3 pipe2 posix_memalign memalign)
|
||
dup3 pipe2 posix_memalign memalign writev)
|
||
AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value,
|
||
[AC_TRY_COMPILE([
|
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)
|
||
... | ... | |
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 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)
|
||
{
|
||
... | ... | |
return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
|
||
}
|
||
#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)
|
||
{
|
||
... | ... | |
int nosync;
|
||
};
|
||
#ifdef HAVE_WRITEV
|
||
static VALUE
|
||
io_binwritev_string(VALUE arg)
|
||
{
|
||
struct binwrite_arg *p = (struct binwrite_arg *)arg;
|
||
rb_io_t *fptr = p->fptr;
|
||
long r;
|
||
if (fptr->wbuf.len) {
|
||
struct iovec iov[2];
|
||
iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
|
||
iov[0].iov_len = fptr->wbuf.len;
|
||
iov[1].iov_base = (char *)p->ptr;
|
||
iov[1].iov_len = p->length;
|
||
r = rb_writev_internal(fptr->fd, iov, 2);
|
||
if (fptr->wbuf.len <= r) {
|
||
r -= fptr->wbuf.len;
|
||
fptr->wbuf.off = 0;
|
||
fptr->wbuf.len = 0;
|
||
}
|
||
else {
|
||
fptr->wbuf.off += (int)r;
|
||
fptr->wbuf.len -= (int)r;
|
||
r = 0L;
|
||
}
|
||
}
|
||
else {
|
||
long l = io_writable_length(fptr, p->length);
|
||
r = rb_write_internal(fptr->fd, p->ptr, l);
|
||
}
|
||
return r;
|
||
}
|
||
#else
|
||
static VALUE
|
||
io_binwrite_string(VALUE arg)
|
||
{
|
||
... | ... | |
}
|
||
static long
|
||
io_shift_fflush(const char *ptr, long len, rb_io_t *fptr)
|
||
{
|
||
if (fptr->wbuf.len && fptr->wbuf.len+len <= fptr->wbuf.capa) {
|
||
if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
|
||
MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
|
||
fptr->wbuf.off = 0;
|
||
}
|
||
MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
|
||
fptr->wbuf.len += (int)len;
|
||
n = 0;
|
||
}
|
||
if (io_fflush(fptr) < 0)
|
||
return -1L;
|
||
if (n == 0)
|
||
return len;
|
||
return 0L;
|
||
}
|
||
#endif
|
||
static long
|
||
io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
|
||
{
|
||
long n, r, offset = 0;
|
||
... | ... | |
(fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
|
||
struct binwrite_arg arg;
|
||
/* xxx: use writev to avoid double write if available */
|
||
if (fptr->wbuf.len && fptr->wbuf.len+len <= fptr->wbuf.capa) {
|
||
if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
|
||
MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
|
||
fptr->wbuf.off = 0;
|
||
}
|
||
MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
|
||
fptr->wbuf.len += (int)len;
|
||
n = 0;
|
||
}
|
||
if (io_fflush(fptr) < 0)
|
||
return -1L;
|
||
if (n == 0)
|
||
return len;
|
||
/* avoid context switch between "a" and "\n" in STDERR.puts "a".
|
||
[ruby-dev:25080] */
|
||
if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
|
||
#ifndef HAVE_WRITEV
|
||
if ((r = io_shift_fflush(ptr, len, fptr)) != 0)
|
||
return r;
|
||
/* avoid context switch between "a" and "\n" in STDERR.puts "a".
|
||
[ruby-dev:25080] */
|
||
if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd))
|
||
rb_io_check_closed(fptr);
|
||
}
|
||
#endif
|
||
arg.fptr = fptr;
|
||
arg.str = str;
|
||
retry:
|
||
arg.ptr = ptr + offset;
|
||
arg.length = n;
|
||
if (fptr->write_lock) {
|
||
#ifdef HAVE_WRITEV
|
||
r = rb_mutex_synchronize(fptr->write_lock, io_binwritev_string, (VALUE)&arg);
|
||
#else
|
||
r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
|
||
#endif
|
||
}
|
||
else {
|
||
#ifdef HAVE_WRITEV
|
||
r = io_binwritev_string((VALUE)&arg);
|
||
#else
|
||
long l = io_writable_length(fptr, n);
|
||
r = rb_write_internal(fptr->fd, ptr+offset, l);
|
||
#endif
|
||
}
|
||
/* xxx: other threads may modify given string. */
|
||
if (r == n) return len;
|
||
... | ... | |
*/
|
||
# 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)
|
||
{
|