mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
Introduce rb_io_blocking_region
which takes struct rb_io
argument. (#11795)
This does not change any actual behaviour, but provides a choke point for blocking IO operations. * Update `IO::Buffer` to use `rb_io_blocking_region`. * Update `File` to use `rb_io_blocking_region`. * Update `IO` to use `rb_io_blocking_region`.
This commit is contained in:
parent
e766cb3e57
commit
c50298d7d4
Notes:
git
2024-10-05 02:10:30 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
5 changed files with 69 additions and 46 deletions
|
@ -8601,6 +8601,7 @@ io_buffer.$(OBJEXT): $(top_srcdir)/internal/bits.h
|
|||
io_buffer.$(OBJEXT): $(top_srcdir)/internal/compilers.h
|
||||
io_buffer.$(OBJEXT): $(top_srcdir)/internal/error.h
|
||||
io_buffer.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
|
||||
io_buffer.$(OBJEXT): $(top_srcdir)/internal/io.h
|
||||
io_buffer.$(OBJEXT): $(top_srcdir)/internal/numeric.h
|
||||
io_buffer.$(OBJEXT): $(top_srcdir)/internal/serial.h
|
||||
io_buffer.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
|
||||
|
|
24
file.c
24
file.c
|
@ -1145,14 +1145,14 @@ no_gvl_fstat(void *data)
|
|||
}
|
||||
|
||||
static int
|
||||
fstat_without_gvl(int fd, struct stat *st)
|
||||
fstat_without_gvl(rb_io_t *fptr, struct stat *st)
|
||||
{
|
||||
no_gvl_stat_data data;
|
||||
|
||||
data.file.fd = fd;
|
||||
data.file.fd = fptr->fd;
|
||||
data.st = st;
|
||||
|
||||
return (int)(VALUE)rb_thread_io_blocking_region(no_gvl_fstat, &data, fd);
|
||||
return (int)rb_io_blocking_region(fptr, no_gvl_fstat, &data);
|
||||
}
|
||||
|
||||
static void *
|
||||
|
@ -1224,12 +1224,12 @@ statx_without_gvl(const char *path, struct statx *stx, unsigned int mask)
|
|||
}
|
||||
|
||||
static int
|
||||
fstatx_without_gvl(int fd, struct statx *stx, unsigned int mask)
|
||||
fstatx_without_gvl(rb_io_t *fptr, struct statx *stx, unsigned int mask)
|
||||
{
|
||||
no_gvl_statx_data data = {stx, fd, "", AT_EMPTY_PATH, mask};
|
||||
no_gvl_statx_data data = {stx, fptr->fd, "", AT_EMPTY_PATH, mask};
|
||||
|
||||
/* call statx(2) with fd */
|
||||
return (int)rb_thread_io_blocking_region(io_blocking_statx, &data, fd);
|
||||
return (int)rb_io_blocking_region(fptr, io_blocking_statx, &data);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1242,7 +1242,7 @@ rb_statx(VALUE file, struct statx *stx, unsigned int mask)
|
|||
if (!NIL_P(tmp)) {
|
||||
rb_io_t *fptr;
|
||||
GetOpenFile(tmp, fptr);
|
||||
result = fstatx_without_gvl(fptr->fd, stx, mask);
|
||||
result = fstatx_without_gvl(fptr, stx, mask);
|
||||
file = tmp;
|
||||
}
|
||||
else {
|
||||
|
@ -1283,7 +1283,7 @@ typedef struct statx statx_data;
|
|||
|
||||
#elif defined(HAVE_STAT_BIRTHTIME)
|
||||
# define statx_without_gvl(path, st, mask) stat_without_gvl(path, st)
|
||||
# define fstatx_without_gvl(fd, st, mask) fstat_without_gvl(fd, st)
|
||||
# define fstatx_without_gvl(fptr, st, mask) fstat_without_gvl(fptr, st)
|
||||
# define statx_birthtime(st, fname) stat_birthtime(st)
|
||||
# define statx_has_birthtime(st) 1
|
||||
# define rb_statx(file, st, mask) rb_stat(file, st)
|
||||
|
@ -1303,7 +1303,7 @@ rb_stat(VALUE file, struct stat *st)
|
|||
rb_io_t *fptr;
|
||||
|
||||
GetOpenFile(tmp, fptr);
|
||||
result = fstat_without_gvl(fptr->fd, st);
|
||||
result = fstat_without_gvl(fptr, st);
|
||||
file = tmp;
|
||||
}
|
||||
else {
|
||||
|
@ -2501,7 +2501,7 @@ rb_file_birthtime(VALUE obj)
|
|||
statx_data st;
|
||||
|
||||
GetOpenFile(obj, fptr);
|
||||
if (fstatx_without_gvl(fptr->fd, &st, STATX_BTIME) == -1) {
|
||||
if (fstatx_without_gvl(fptr, &st, STATX_BTIME) == -1) {
|
||||
rb_sys_fail_path(fptr->pathv);
|
||||
}
|
||||
return statx_birthtime(&st, fptr->pathv);
|
||||
|
@ -5280,7 +5280,7 @@ rb_file_truncate(VALUE obj, VALUE len)
|
|||
}
|
||||
rb_io_flush_raw(obj, 0);
|
||||
fa.fd = fptr->fd;
|
||||
if ((int)rb_thread_io_blocking_region(nogvl_ftruncate, &fa, fa.fd) < 0) {
|
||||
if ((int)rb_io_blocking_region(fptr, nogvl_ftruncate, &fa) < 0) {
|
||||
rb_sys_fail_path(fptr->pathv);
|
||||
}
|
||||
return INT2FIX(0);
|
||||
|
@ -5380,7 +5380,7 @@ rb_file_flock(VALUE obj, VALUE operation)
|
|||
if (fptr->mode & FMODE_WRITABLE) {
|
||||
rb_io_flush_raw(obj, 0);
|
||||
}
|
||||
while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
|
||||
while ((int)rb_io_blocking_region(fptr, rb_thread_flock, op) < 0) {
|
||||
int e = errno;
|
||||
switch (e) {
|
||||
case EAGAIN:
|
||||
|
|
|
@ -135,6 +135,9 @@ RUBY_SYMBOL_EXPORT_BEGIN
|
|||
void rb_maygvl_fd_fix_cloexec(int fd);
|
||||
int rb_gc_for_fd(int err);
|
||||
void rb_write_error_str(VALUE mesg);
|
||||
|
||||
VALUE rb_io_blocking_region_wait(struct rb_io *io, rb_blocking_function_t *function, void *argument, enum rb_io_event events);
|
||||
VALUE rb_io_blocking_region(struct rb_io *io, rb_blocking_function_t *function, void *argument);
|
||||
RUBY_SYMBOL_EXPORT_END
|
||||
|
||||
#endif /* INTERNAL_IO_H */
|
||||
|
|
64
io.c
64
io.c
|
@ -222,6 +222,17 @@ static VALUE sym_HOLE;
|
|||
|
||||
static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path);
|
||||
|
||||
VALUE
|
||||
rb_io_blocking_region_wait(struct rb_io *io, rb_blocking_function_t *function, void *argument, enum rb_io_event events)
|
||||
{
|
||||
return rb_thread_io_blocking_call(function, argument, io->fd, events);
|
||||
}
|
||||
|
||||
VALUE rb_io_blocking_region(struct rb_io *io, rb_blocking_function_t *function, void *argument)
|
||||
{
|
||||
return rb_io_blocking_region_wait(io, function, argument, 0);
|
||||
}
|
||||
|
||||
struct argf {
|
||||
VALUE filename, current_file;
|
||||
long last_lineno; /* $. */
|
||||
|
@ -1298,7 +1309,7 @@ rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
|
|||
iis.timeout = &timeout_storage;
|
||||
}
|
||||
|
||||
return (ssize_t)rb_thread_io_blocking_call(internal_read_func, &iis, fptr->fd, RB_WAITFD_IN);
|
||||
return (ssize_t)rb_io_blocking_region_wait(fptr, internal_read_func, &iis, RUBY_IO_READABLE);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
@ -1331,7 +1342,7 @@ rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
|
|||
iis.timeout = &timeout_storage;
|
||||
}
|
||||
|
||||
return (ssize_t)rb_thread_io_blocking_call(internal_write_func, &iis, fptr->fd, RB_WAITFD_OUT);
|
||||
return (ssize_t)rb_io_blocking_region_wait(fptr, internal_write_func, &iis, RUBY_IO_WRITABLE);
|
||||
}
|
||||
|
||||
#ifdef HAVE_WRITEV
|
||||
|
@ -1368,7 +1379,7 @@ rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
|
|||
iis.timeout = &timeout_storage;
|
||||
}
|
||||
|
||||
return (ssize_t)rb_thread_io_blocking_call(internal_writev_func, &iis, fptr->fd, RB_WAITFD_OUT);
|
||||
return (ssize_t)rb_io_blocking_region_wait(fptr, internal_writev_func, &iis, RUBY_IO_WRITABLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1398,7 +1409,7 @@ static VALUE
|
|||
io_flush_buffer_async(VALUE arg)
|
||||
{
|
||||
rb_io_t *fptr = (rb_io_t *)arg;
|
||||
return rb_thread_io_blocking_call(io_flush_buffer_sync, fptr, fptr->fd, RB_WAITFD_OUT);
|
||||
return rb_io_blocking_region_wait(fptr, io_flush_buffer_sync, fptr, RUBY_IO_WRITABLE);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -2788,8 +2799,10 @@ rb_io_fsync(VALUE io)
|
|||
|
||||
if (io_fflush(fptr) < 0)
|
||||
rb_sys_fail_on_write(fptr);
|
||||
if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
|
||||
|
||||
if ((int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
|
||||
rb_sys_fail_path(fptr->pathv);
|
||||
|
||||
return INT2FIX(0);
|
||||
}
|
||||
#else
|
||||
|
@ -2838,7 +2851,7 @@ rb_io_fdatasync(VALUE io)
|
|||
if (io_fflush(fptr) < 0)
|
||||
rb_sys_fail_on_write(fptr);
|
||||
|
||||
if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
|
||||
if ((int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
|
||||
return INT2FIX(0);
|
||||
|
||||
/* fall back */
|
||||
|
@ -3423,10 +3436,10 @@ io_read_memory_call(VALUE arg)
|
|||
}
|
||||
|
||||
if (iis->nonblock) {
|
||||
return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, 0);
|
||||
return rb_io_blocking_region(iis->fptr, internal_read_func, iis);
|
||||
}
|
||||
else {
|
||||
return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, RB_WAITFD_IN);
|
||||
return rb_io_blocking_region_wait(iis->fptr, internal_read_func, iis, RUBY_IO_READABLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6099,7 +6112,7 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
|
|||
}
|
||||
|
||||
struct prdwr_internal_arg {
|
||||
VALUE io;
|
||||
struct rb_io *io;
|
||||
int fd;
|
||||
void *buf;
|
||||
size_t count;
|
||||
|
@ -6121,14 +6134,14 @@ pread_internal_call(VALUE _arg)
|
|||
|
||||
VALUE scheduler = rb_fiber_scheduler_current();
|
||||
if (scheduler != Qnil) {
|
||||
VALUE result = rb_fiber_scheduler_io_pread_memory(scheduler, arg->io, arg->offset, arg->buf, arg->count, 0);
|
||||
VALUE result = rb_fiber_scheduler_io_pread_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
|
||||
|
||||
if (!UNDEF_P(result)) {
|
||||
return rb_fiber_scheduler_io_result_apply(result);
|
||||
}
|
||||
}
|
||||
|
||||
return rb_thread_io_blocking_call(internal_pread_func, arg, arg->fd, RB_WAITFD_IN);
|
||||
return rb_io_blocking_region_wait(arg->io, internal_pread_func, arg, RUBY_IO_READABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6165,7 +6178,7 @@ rb_io_pread(int argc, VALUE *argv, VALUE io)
|
|||
VALUE len, offset, str;
|
||||
rb_io_t *fptr;
|
||||
ssize_t n;
|
||||
struct prdwr_internal_arg arg = {.io = io};
|
||||
struct prdwr_internal_arg arg;
|
||||
int shrinkable;
|
||||
|
||||
rb_scan_args(argc, argv, "21", &len, &offset, &str);
|
||||
|
@ -6179,6 +6192,7 @@ rb_io_pread(int argc, VALUE *argv, VALUE io)
|
|||
GetOpenFile(io, fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
|
||||
arg.io = fptr;
|
||||
arg.fd = fptr->fd;
|
||||
rb_io_check_closed(fptr);
|
||||
|
||||
|
@ -6203,7 +6217,7 @@ internal_pwrite_func(void *_arg)
|
|||
|
||||
VALUE scheduler = rb_fiber_scheduler_current();
|
||||
if (scheduler != Qnil) {
|
||||
VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io, arg->offset, arg->buf, arg->count, 0);
|
||||
VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
|
||||
|
||||
if (!UNDEF_P(result)) {
|
||||
return rb_fiber_scheduler_io_result_apply(result);
|
||||
|
@ -6244,7 +6258,7 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
|
|||
{
|
||||
rb_io_t *fptr;
|
||||
ssize_t n;
|
||||
struct prdwr_internal_arg arg = {.io = io};
|
||||
struct prdwr_internal_arg arg;
|
||||
VALUE tmp;
|
||||
|
||||
if (!RB_TYPE_P(str, T_STRING))
|
||||
|
@ -6255,13 +6269,15 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
|
|||
io = GetWriteIO(io);
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_writable(fptr);
|
||||
|
||||
arg.io = fptr;
|
||||
arg.fd = fptr->fd;
|
||||
|
||||
tmp = rb_str_tmp_frozen_acquire(str);
|
||||
arg.buf = RSTRING_PTR(tmp);
|
||||
arg.count = (size_t)RSTRING_LEN(tmp);
|
||||
|
||||
n = (ssize_t)rb_thread_io_blocking_call(internal_pwrite_func, &arg, fptr->fd, RB_WAITFD_OUT);
|
||||
n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg, RUBY_IO_WRITABLE);
|
||||
if (n < 0) rb_sys_fail_path(fptr->pathv);
|
||||
rb_str_tmp_frozen_release(str, tmp);
|
||||
|
||||
|
@ -10806,7 +10822,7 @@ do_io_advise(rb_io_t *fptr, VALUE advice, rb_off_t offset, rb_off_t len)
|
|||
ias.offset = offset;
|
||||
ias.len = len;
|
||||
|
||||
rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
|
||||
rv = (int)rb_io_blocking_region(fptr, io_advise_internal, &ias);
|
||||
if (rv && rv != ENOSYS) {
|
||||
/* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
|
||||
it returns the error code. */
|
||||
|
@ -11099,16 +11115,16 @@ nogvl_ioctl(void *ptr)
|
|||
}
|
||||
|
||||
static int
|
||||
do_ioctl(int fd, ioctl_req_t cmd, long narg)
|
||||
do_ioctl(struct rb_io *io, ioctl_req_t cmd, long narg)
|
||||
{
|
||||
int retval;
|
||||
struct ioctl_arg arg;
|
||||
|
||||
arg.fd = fd;
|
||||
arg.fd = io->fd;
|
||||
arg.cmd = cmd;
|
||||
arg.narg = narg;
|
||||
|
||||
retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
|
||||
retval = (int)rb_io_blocking_region(io, nogvl_ioctl, &arg);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -11371,7 +11387,7 @@ rb_ioctl(VALUE io, VALUE req, VALUE arg)
|
|||
|
||||
narg = setup_narg(cmd, &arg, ioctl_narg_len);
|
||||
GetOpenFile(io, fptr);
|
||||
retval = do_ioctl(fptr->fd, cmd, narg);
|
||||
retval = do_ioctl(fptr, cmd, narg);
|
||||
return finish_narg(retval, arg, fptr);
|
||||
}
|
||||
|
||||
|
@ -11425,16 +11441,16 @@ nogvl_fcntl(void *ptr)
|
|||
}
|
||||
|
||||
static int
|
||||
do_fcntl(int fd, int cmd, long narg)
|
||||
do_fcntl(struct rb_io *io, int cmd, long narg)
|
||||
{
|
||||
int retval;
|
||||
struct fcntl_arg arg;
|
||||
|
||||
arg.fd = fd;
|
||||
arg.fd = io->fd;
|
||||
arg.cmd = cmd;
|
||||
arg.narg = narg;
|
||||
|
||||
retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
|
||||
retval = (int)rb_io_blocking_region(io, nogvl_fcntl, &arg);
|
||||
if (retval != -1) {
|
||||
switch (cmd) {
|
||||
#if defined(F_DUPFD)
|
||||
|
@ -11460,7 +11476,7 @@ rb_fcntl(VALUE io, VALUE req, VALUE arg)
|
|||
|
||||
narg = setup_narg(cmd, &arg, fcntl_narg_len);
|
||||
GetOpenFile(io, fptr);
|
||||
retval = do_fcntl(fptr->fd, cmd, narg);
|
||||
retval = do_fcntl(fptr, cmd, narg);
|
||||
return finish_narg(retval, arg, fptr);
|
||||
}
|
||||
|
||||
|
|
23
io_buffer.c
23
io_buffer.c
|
@ -6,7 +6,6 @@
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
#include "ruby/io.h"
|
||||
#include "ruby/io/buffer.h"
|
||||
#include "ruby/fiber/scheduler.h"
|
||||
|
||||
|
@ -16,7 +15,7 @@
|
|||
#include "internal/error.h"
|
||||
#include "internal/numeric.h"
|
||||
#include "internal/string.h"
|
||||
#include "internal/thread.h"
|
||||
#include "internal/io.h"
|
||||
|
||||
VALUE rb_cIOBuffer;
|
||||
VALUE rb_eIOBufferLockedError;
|
||||
|
@ -2656,10 +2655,10 @@ io_buffer_default_size(size_t page_size)
|
|||
}
|
||||
|
||||
struct io_buffer_blocking_region_argument {
|
||||
struct rb_io *io;
|
||||
struct rb_io_buffer *buffer;
|
||||
rb_blocking_function_t *function;
|
||||
void *data;
|
||||
int descriptor;
|
||||
};
|
||||
|
||||
static VALUE
|
||||
|
@ -2667,7 +2666,7 @@ io_buffer_blocking_region_begin(VALUE _argument)
|
|||
{
|
||||
struct io_buffer_blocking_region_argument *argument = (void*)_argument;
|
||||
|
||||
return rb_thread_io_blocking_region(argument->function, argument->data, argument->descriptor);
|
||||
return rb_io_blocking_region(argument->io, argument->function, argument->data);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -2681,13 +2680,17 @@ io_buffer_blocking_region_ensure(VALUE _argument)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
io_buffer_blocking_region(struct rb_io_buffer *buffer, rb_blocking_function_t *function, void *data, int descriptor)
|
||||
io_buffer_blocking_region(VALUE io, struct rb_io_buffer *buffer, rb_blocking_function_t *function, void *data)
|
||||
{
|
||||
io = rb_io_get_io(io);
|
||||
struct rb_io *ioptr;
|
||||
RB_IO_POINTER(io, ioptr);
|
||||
|
||||
struct io_buffer_blocking_region_argument argument = {
|
||||
.io = ioptr,
|
||||
.buffer = buffer,
|
||||
.function = function,
|
||||
.data = data,
|
||||
.descriptor = descriptor,
|
||||
};
|
||||
|
||||
// If the buffer is already locked, we can skip the ensure (unlock):
|
||||
|
@ -2774,7 +2777,7 @@ rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset)
|
|||
.length = length,
|
||||
};
|
||||
|
||||
return io_buffer_blocking_region(buffer, io_buffer_read_internal, &argument, descriptor);
|
||||
return io_buffer_blocking_region(io, buffer, io_buffer_read_internal, &argument);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2892,7 +2895,7 @@ rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t of
|
|||
.offset = from,
|
||||
};
|
||||
|
||||
return io_buffer_blocking_region(buffer, io_buffer_pread_internal, &argument, descriptor);
|
||||
return io_buffer_blocking_region(io, buffer, io_buffer_pread_internal, &argument);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3011,7 +3014,7 @@ rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset)
|
|||
.length = length,
|
||||
};
|
||||
|
||||
return io_buffer_blocking_region(buffer, io_buffer_write_internal, &argument, descriptor);
|
||||
return io_buffer_blocking_region(io, buffer, io_buffer_write_internal, &argument);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3129,7 +3132,7 @@ rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t o
|
|||
.offset = from,
|
||||
};
|
||||
|
||||
return io_buffer_blocking_region(buffer, io_buffer_pwrite_internal, &argument, descriptor);
|
||||
return io_buffer_blocking_region(io, buffer, io_buffer_pwrite_internal, &argument);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue