Skip to content

Commit c50298d

Browse files
authored
Introduce rb_io_blocking_region which takes struct rb_io argument. (ruby#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`.
1 parent e766cb3 commit c50298d

File tree

5 files changed

+69
-46
lines changed

5 files changed

+69
-46
lines changed

common.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8601,6 +8601,7 @@ io_buffer.$(OBJEXT): $(top_srcdir)/internal/bits.h
86018601
io_buffer.$(OBJEXT): $(top_srcdir)/internal/compilers.h
86028602
io_buffer.$(OBJEXT): $(top_srcdir)/internal/error.h
86038603
io_buffer.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
8604+
io_buffer.$(OBJEXT): $(top_srcdir)/internal/io.h
86048605
io_buffer.$(OBJEXT): $(top_srcdir)/internal/numeric.h
86058606
io_buffer.$(OBJEXT): $(top_srcdir)/internal/serial.h
86068607
io_buffer.$(OBJEXT): $(top_srcdir)/internal/static_assert.h

file.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,14 +1145,14 @@ no_gvl_fstat(void *data)
11451145
}
11461146

11471147
static int
1148-
fstat_without_gvl(int fd, struct stat *st)
1148+
fstat_without_gvl(rb_io_t *fptr, struct stat *st)
11491149
{
11501150
no_gvl_stat_data data;
11511151

1152-
data.file.fd = fd;
1152+
data.file.fd = fptr->fd;
11531153
data.st = st;
11541154

1155-
return (int)(VALUE)rb_thread_io_blocking_region(no_gvl_fstat, &data, fd);
1155+
return (int)rb_io_blocking_region(fptr, no_gvl_fstat, &data);
11561156
}
11571157

11581158
static void *
@@ -1224,12 +1224,12 @@ statx_without_gvl(const char *path, struct statx *stx, unsigned int mask)
12241224
}
12251225

12261226
static int
1227-
fstatx_without_gvl(int fd, struct statx *stx, unsigned int mask)
1227+
fstatx_without_gvl(rb_io_t *fptr, struct statx *stx, unsigned int mask)
12281228
{
1229-
no_gvl_statx_data data = {stx, fd, "", AT_EMPTY_PATH, mask};
1229+
no_gvl_statx_data data = {stx, fptr->fd, "", AT_EMPTY_PATH, mask};
12301230

12311231
/* call statx(2) with fd */
1232-
return (int)rb_thread_io_blocking_region(io_blocking_statx, &data, fd);
1232+
return (int)rb_io_blocking_region(fptr, io_blocking_statx, &data);
12331233
}
12341234

12351235
static int
@@ -1242,7 +1242,7 @@ rb_statx(VALUE file, struct statx *stx, unsigned int mask)
12421242
if (!NIL_P(tmp)) {
12431243
rb_io_t *fptr;
12441244
GetOpenFile(tmp, fptr);
1245-
result = fstatx_without_gvl(fptr->fd, stx, mask);
1245+
result = fstatx_without_gvl(fptr, stx, mask);
12461246
file = tmp;
12471247
}
12481248
else {
@@ -1283,7 +1283,7 @@ typedef struct statx statx_data;
12831283

12841284
#elif defined(HAVE_STAT_BIRTHTIME)
12851285
# define statx_without_gvl(path, st, mask) stat_without_gvl(path, st)
1286-
# define fstatx_without_gvl(fd, st, mask) fstat_without_gvl(fd, st)
1286+
# define fstatx_without_gvl(fptr, st, mask) fstat_without_gvl(fptr, st)
12871287
# define statx_birthtime(st, fname) stat_birthtime(st)
12881288
# define statx_has_birthtime(st) 1
12891289
# define rb_statx(file, st, mask) rb_stat(file, st)
@@ -1303,7 +1303,7 @@ rb_stat(VALUE file, struct stat *st)
13031303
rb_io_t *fptr;
13041304

13051305
GetOpenFile(tmp, fptr);
1306-
result = fstat_without_gvl(fptr->fd, st);
1306+
result = fstat_without_gvl(fptr, st);
13071307
file = tmp;
13081308
}
13091309
else {
@@ -2501,7 +2501,7 @@ rb_file_birthtime(VALUE obj)
25012501
statx_data st;
25022502

25032503
GetOpenFile(obj, fptr);
2504-
if (fstatx_without_gvl(fptr->fd, &st, STATX_BTIME) == -1) {
2504+
if (fstatx_without_gvl(fptr, &st, STATX_BTIME) == -1) {
25052505
rb_sys_fail_path(fptr->pathv);
25062506
}
25072507
return statx_birthtime(&st, fptr->pathv);
@@ -5280,7 +5280,7 @@ rb_file_truncate(VALUE obj, VALUE len)
52805280
}
52815281
rb_io_flush_raw(obj, 0);
52825282
fa.fd = fptr->fd;
5283-
if ((int)rb_thread_io_blocking_region(nogvl_ftruncate, &fa, fa.fd) < 0) {
5283+
if ((int)rb_io_blocking_region(fptr, nogvl_ftruncate, &fa) < 0) {
52845284
rb_sys_fail_path(fptr->pathv);
52855285
}
52865286
return INT2FIX(0);
@@ -5380,7 +5380,7 @@ rb_file_flock(VALUE obj, VALUE operation)
53805380
if (fptr->mode & FMODE_WRITABLE) {
53815381
rb_io_flush_raw(obj, 0);
53825382
}
5383-
while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
5383+
while ((int)rb_io_blocking_region(fptr, rb_thread_flock, op) < 0) {
53845384
int e = errno;
53855385
switch (e) {
53865386
case EAGAIN:

internal/io.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ RUBY_SYMBOL_EXPORT_BEGIN
135135
void rb_maygvl_fd_fix_cloexec(int fd);
136136
int rb_gc_for_fd(int err);
137137
void rb_write_error_str(VALUE mesg);
138+
139+
VALUE rb_io_blocking_region_wait(struct rb_io *io, rb_blocking_function_t *function, void *argument, enum rb_io_event events);
140+
VALUE rb_io_blocking_region(struct rb_io *io, rb_blocking_function_t *function, void *argument);
138141
RUBY_SYMBOL_EXPORT_END
139142

140143
#endif /* INTERNAL_IO_H */

io.c

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,17 @@ static VALUE sym_HOLE;
222222

223223
static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path);
224224

225+
VALUE
226+
rb_io_blocking_region_wait(struct rb_io *io, rb_blocking_function_t *function, void *argument, enum rb_io_event events)
227+
{
228+
return rb_thread_io_blocking_call(function, argument, io->fd, events);
229+
}
230+
231+
VALUE rb_io_blocking_region(struct rb_io *io, rb_blocking_function_t *function, void *argument)
232+
{
233+
return rb_io_blocking_region_wait(io, function, argument, 0);
234+
}
235+
225236
struct argf {
226237
VALUE filename, current_file;
227238
long last_lineno; /* $. */
@@ -1298,7 +1309,7 @@ rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
12981309
iis.timeout = &timeout_storage;
12991310
}
13001311

1301-
return (ssize_t)rb_thread_io_blocking_call(internal_read_func, &iis, fptr->fd, RB_WAITFD_IN);
1312+
return (ssize_t)rb_io_blocking_region_wait(fptr, internal_read_func, &iis, RUBY_IO_READABLE);
13021313
}
13031314

13041315
static ssize_t
@@ -1331,7 +1342,7 @@ rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
13311342
iis.timeout = &timeout_storage;
13321343
}
13331344

1334-
return (ssize_t)rb_thread_io_blocking_call(internal_write_func, &iis, fptr->fd, RB_WAITFD_OUT);
1345+
return (ssize_t)rb_io_blocking_region_wait(fptr, internal_write_func, &iis, RUBY_IO_WRITABLE);
13351346
}
13361347

13371348
#ifdef HAVE_WRITEV
@@ -1368,7 +1379,7 @@ rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
13681379
iis.timeout = &timeout_storage;
13691380
}
13701381

1371-
return (ssize_t)rb_thread_io_blocking_call(internal_writev_func, &iis, fptr->fd, RB_WAITFD_OUT);
1382+
return (ssize_t)rb_io_blocking_region_wait(fptr, internal_writev_func, &iis, RUBY_IO_WRITABLE);
13721383
}
13731384
#endif
13741385

@@ -1398,7 +1409,7 @@ static VALUE
13981409
io_flush_buffer_async(VALUE arg)
13991410
{
14001411
rb_io_t *fptr = (rb_io_t *)arg;
1401-
return rb_thread_io_blocking_call(io_flush_buffer_sync, fptr, fptr->fd, RB_WAITFD_OUT);
1412+
return rb_io_blocking_region_wait(fptr, io_flush_buffer_sync, fptr, RUBY_IO_WRITABLE);
14021413
}
14031414

14041415
static inline int
@@ -2788,8 +2799,10 @@ rb_io_fsync(VALUE io)
27882799

27892800
if (io_fflush(fptr) < 0)
27902801
rb_sys_fail_on_write(fptr);
2791-
if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
2802+
2803+
if ((int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
27922804
rb_sys_fail_path(fptr->pathv);
2805+
27932806
return INT2FIX(0);
27942807
}
27952808
#else
@@ -2838,7 +2851,7 @@ rb_io_fdatasync(VALUE io)
28382851
if (io_fflush(fptr) < 0)
28392852
rb_sys_fail_on_write(fptr);
28402853

2841-
if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
2854+
if ((int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
28422855
return INT2FIX(0);
28432856

28442857
/* fall back */
@@ -3423,10 +3436,10 @@ io_read_memory_call(VALUE arg)
34233436
}
34243437

34253438
if (iis->nonblock) {
3426-
return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, 0);
3439+
return rb_io_blocking_region(iis->fptr, internal_read_func, iis);
34273440
}
34283441
else {
3429-
return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, RB_WAITFD_IN);
3442+
return rb_io_blocking_region_wait(iis->fptr, internal_read_func, iis, RUBY_IO_READABLE);
34303443
}
34313444
}
34323445

@@ -6099,7 +6112,7 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
60996112
}
61006113

61016114
struct prdwr_internal_arg {
6102-
VALUE io;
6115+
struct rb_io *io;
61036116
int fd;
61046117
void *buf;
61056118
size_t count;
@@ -6121,14 +6134,14 @@ pread_internal_call(VALUE _arg)
61216134

61226135
VALUE scheduler = rb_fiber_scheduler_current();
61236136
if (scheduler != Qnil) {
6124-
VALUE result = rb_fiber_scheduler_io_pread_memory(scheduler, arg->io, arg->offset, arg->buf, arg->count, 0);
6137+
VALUE result = rb_fiber_scheduler_io_pread_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
61256138

61266139
if (!UNDEF_P(result)) {
61276140
return rb_fiber_scheduler_io_result_apply(result);
61286141
}
61296142
}
61306143

6131-
return rb_thread_io_blocking_call(internal_pread_func, arg, arg->fd, RB_WAITFD_IN);
6144+
return rb_io_blocking_region_wait(arg->io, internal_pread_func, arg, RUBY_IO_READABLE);
61326145
}
61336146

61346147
/*
@@ -6165,7 +6178,7 @@ rb_io_pread(int argc, VALUE *argv, VALUE io)
61656178
VALUE len, offset, str;
61666179
rb_io_t *fptr;
61676180
ssize_t n;
6168-
struct prdwr_internal_arg arg = {.io = io};
6181+
struct prdwr_internal_arg arg;
61696182
int shrinkable;
61706183

61716184
rb_scan_args(argc, argv, "21", &len, &offset, &str);
@@ -6179,6 +6192,7 @@ rb_io_pread(int argc, VALUE *argv, VALUE io)
61796192
GetOpenFile(io, fptr);
61806193
rb_io_check_byte_readable(fptr);
61816194

6195+
arg.io = fptr;
61826196
arg.fd = fptr->fd;
61836197
rb_io_check_closed(fptr);
61846198

@@ -6203,7 +6217,7 @@ internal_pwrite_func(void *_arg)
62036217

62046218
VALUE scheduler = rb_fiber_scheduler_current();
62056219
if (scheduler != Qnil) {
6206-
VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io, arg->offset, arg->buf, arg->count, 0);
6220+
VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
62076221

62086222
if (!UNDEF_P(result)) {
62096223
return rb_fiber_scheduler_io_result_apply(result);
@@ -6244,7 +6258,7 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
62446258
{
62456259
rb_io_t *fptr;
62466260
ssize_t n;
6247-
struct prdwr_internal_arg arg = {.io = io};
6261+
struct prdwr_internal_arg arg;
62486262
VALUE tmp;
62496263

62506264
if (!RB_TYPE_P(str, T_STRING))
@@ -6255,13 +6269,15 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
62556269
io = GetWriteIO(io);
62566270
GetOpenFile(io, fptr);
62576271
rb_io_check_writable(fptr);
6272+
6273+
arg.io = fptr;
62586274
arg.fd = fptr->fd;
62596275

62606276
tmp = rb_str_tmp_frozen_acquire(str);
62616277
arg.buf = RSTRING_PTR(tmp);
62626278
arg.count = (size_t)RSTRING_LEN(tmp);
62636279

6264-
n = (ssize_t)rb_thread_io_blocking_call(internal_pwrite_func, &arg, fptr->fd, RB_WAITFD_OUT);
6280+
n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg, RUBY_IO_WRITABLE);
62656281
if (n < 0) rb_sys_fail_path(fptr->pathv);
62666282
rb_str_tmp_frozen_release(str, tmp);
62676283

@@ -10806,7 +10822,7 @@ do_io_advise(rb_io_t *fptr, VALUE advice, rb_off_t offset, rb_off_t len)
1080610822
ias.offset = offset;
1080710823
ias.len = len;
1080810824

10809-
rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
10825+
rv = (int)rb_io_blocking_region(fptr, io_advise_internal, &ias);
1081010826
if (rv && rv != ENOSYS) {
1081110827
/* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
1081210828
it returns the error code. */
@@ -11099,16 +11115,16 @@ nogvl_ioctl(void *ptr)
1109911115
}
1110011116

1110111117
static int
11102-
do_ioctl(int fd, ioctl_req_t cmd, long narg)
11118+
do_ioctl(struct rb_io *io, ioctl_req_t cmd, long narg)
1110311119
{
1110411120
int retval;
1110511121
struct ioctl_arg arg;
1110611122

11107-
arg.fd = fd;
11123+
arg.fd = io->fd;
1110811124
arg.cmd = cmd;
1110911125
arg.narg = narg;
1111011126

11111-
retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
11127+
retval = (int)rb_io_blocking_region(io, nogvl_ioctl, &arg);
1111211128

1111311129
return retval;
1111411130
}
@@ -11371,7 +11387,7 @@ rb_ioctl(VALUE io, VALUE req, VALUE arg)
1137111387

1137211388
narg = setup_narg(cmd, &arg, ioctl_narg_len);
1137311389
GetOpenFile(io, fptr);
11374-
retval = do_ioctl(fptr->fd, cmd, narg);
11390+
retval = do_ioctl(fptr, cmd, narg);
1137511391
return finish_narg(retval, arg, fptr);
1137611392
}
1137711393

@@ -11425,16 +11441,16 @@ nogvl_fcntl(void *ptr)
1142511441
}
1142611442

1142711443
static int
11428-
do_fcntl(int fd, int cmd, long narg)
11444+
do_fcntl(struct rb_io *io, int cmd, long narg)
1142911445
{
1143011446
int retval;
1143111447
struct fcntl_arg arg;
1143211448

11433-
arg.fd = fd;
11449+
arg.fd = io->fd;
1143411450
arg.cmd = cmd;
1143511451
arg.narg = narg;
1143611452

11437-
retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
11453+
retval = (int)rb_io_blocking_region(io, nogvl_fcntl, &arg);
1143811454
if (retval != -1) {
1143911455
switch (cmd) {
1144011456
#if defined(F_DUPFD)
@@ -11460,7 +11476,7 @@ rb_fcntl(VALUE io, VALUE req, VALUE arg)
1146011476

1146111477
narg = setup_narg(cmd, &arg, fcntl_narg_len);
1146211478
GetOpenFile(io, fptr);
11463-
retval = do_fcntl(fptr->fd, cmd, narg);
11479+
retval = do_fcntl(fptr, cmd, narg);
1146411480
return finish_narg(retval, arg, fptr);
1146511481
}
1146611482

0 commit comments

Comments
 (0)