Skip to content

Commit 9cba6ac

Browse files
committed
Make waiting_fd behaviour per-IO.
1 parent 3bfcb01 commit 9cba6ac

File tree

13 files changed

+172
-418
lines changed

13 files changed

+172
-418
lines changed

ext/-test-/thread_fd/depend

-161
This file was deleted.

ext/-test-/thread_fd/extconf.rb

-2
This file was deleted.

ext/-test-/thread_fd/thread_fd.c

-30
This file was deleted.

file.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -2625,11 +2625,11 @@ io_blocking_fchmod(void *ptr)
26252625
}
26262626

26272627
static int
2628-
rb_fchmod(int fd, mode_t mode)
2628+
rb_fchmod(struct rb_io* io, mode_t mode)
26292629
{
26302630
(void)rb_chmod; /* suppress unused-function warning when HAVE_FCHMOD */
2631-
struct nogvl_fchmod_data data = {.fd = fd, .mode = mode};
2632-
return (int)rb_thread_io_blocking_region(io_blocking_fchmod, &data, fd);
2631+
struct nogvl_fchmod_data data = {.fd = io->fd, .mode = mode};
2632+
return (int)rb_thread_io_blocking_region(io, io_blocking_fchmod, &data);
26332633
}
26342634
#endif
26352635

@@ -2659,7 +2659,7 @@ rb_file_chmod(VALUE obj, VALUE vmode)
26592659

26602660
GetOpenFile(obj, fptr);
26612661
#ifdef HAVE_FCHMOD
2662-
if (rb_fchmod(fptr->fd, mode) == -1) {
2662+
if (rb_fchmod(fptr, mode) == -1) {
26632663
if (HAVE_FCHMOD || errno != ENOSYS)
26642664
rb_sys_fail_path(fptr->pathv);
26652665
}

gc.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -1153,11 +1153,17 @@ cvar_table_free_i(VALUE value, void *ctx)
11531153
return ID_TABLE_CONTINUE;
11541154
}
11551155

1156+
static void
1157+
io_fptr_finalize(void *fptr)
1158+
{
1159+
rb_io_fptr_finalize((struct rb_io *)fptr);
1160+
}
1161+
11561162
static inline void
11571163
make_io_zombie(void *objspace, VALUE obj)
11581164
{
11591165
rb_io_t *fptr = RFILE(obj)->fptr;
1160-
rb_gc_impl_make_zombie(objspace, obj, rb_io_fptr_finalize_internal, fptr);
1166+
rb_gc_impl_make_zombie(objspace, obj, io_fptr_finalize, fptr);
11611167
}
11621168

11631169
static bool
@@ -2832,6 +2838,7 @@ rb_gc_mark_children(void *objspace, VALUE obj)
28322838
gc_mark_internal(RFILE(obj)->fptr->encs.ecopts);
28332839
gc_mark_internal(RFILE(obj)->fptr->write_lock);
28342840
gc_mark_internal(RFILE(obj)->fptr->timeout);
2841+
gc_mark_internal(RFILE(obj)->fptr->wakeup_mutex);
28352842
}
28362843
break;
28372844

internal.h

-3
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@
5858
/* internal/array.h */
5959
#define rb_ary_new_from_args(...) rb_nonexistent_symbol(__VA_ARGS__)
6060

61-
/* internal/io.h */
62-
#define rb_io_fptr_finalize(...) rb_nonexistent_symbol(__VA_ARGS__)
63-
6461
/* internal/string.h */
6562
#define rb_fstring_cstr(...) rb_nonexistent_symbol(__VA_ARGS__)
6663

internal/io.h

+25-6
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,23 @@
1313
#define HAVE_RB_IO_T
1414
struct rb_io;
1515

16-
#include "ruby/io.h" /* for rb_io_t */
16+
#include "ruby/io.h"
17+
18+
#include "vm_core.h"
19+
#include "ccan/list/list.h"
1720

1821
#define IO_WITHOUT_GVL(func, arg) rb_nogvl(func, arg, RUBY_UBF_IO, 0, RB_NOGVL_OFFLOAD_SAFE)
1922
#define IO_WITHOUT_GVL_INT(func, arg) (int)(VALUE)IO_WITHOUT_GVL(func, arg)
2023

24+
// Represents an in-flight blocking operation:
25+
struct rb_io_blocking_operation_node {
26+
// The linked list data structure.
27+
struct ccan_list_node list;
28+
29+
// The execution context of the blocking operation:
30+
rb_execution_context_t *ec;
31+
};
32+
2133
/** Ruby's IO, metadata and buffers. */
2234
struct rb_io {
2335

@@ -111,6 +123,15 @@ struct rb_io {
111123
* The timeout associated with this IO when performing blocking operations.
112124
*/
113125
VALUE timeout;
126+
127+
/**
128+
* Threads that are performing a blocking operation without the GVL using
129+
* this IO. On calling IO#close, these threads will be interrupted so that
130+
* the operation can be cancelled.
131+
*/
132+
struct ccan_list_head blocking_operations;
133+
rb_execution_context_t *closing_ec;
134+
VALUE wakeup_mutex;
114135
};
115136

116137
/* io.c */
@@ -119,17 +140,15 @@ void rb_stdio_set_default_encoding(void);
119140
VALUE rb_io_flush_raw(VALUE, int);
120141
size_t rb_io_memsize(const rb_io_t *);
121142
int rb_stderr_tty_p(void);
122-
void rb_io_fptr_finalize_internal(void *ptr);
123-
#ifdef rb_io_fptr_finalize
124-
# undef rb_io_fptr_finalize
125-
#endif
126-
#define rb_io_fptr_finalize rb_io_fptr_finalize_internal
127143
VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt);
128144

129145
VALUE rb_io_prep_stdin(void);
130146
VALUE rb_io_prep_stdout(void);
131147
VALUE rb_io_prep_stderr(void);
132148

149+
int rb_io_notify_close(struct rb_io *fptr);
150+
int rb_io_fptr_finalize(struct rb_io *fptr);
151+
133152
RUBY_SYMBOL_EXPORT_BEGIN
134153
/* io.c (export) */
135154
void rb_maygvl_fd_fix_cloexec(int fd);

internal/thread.h

+8-10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "ccan/list/list.h" /* for list in rb_io_close_wait_list */
1414

1515
struct rb_thread_struct; /* in vm_core.h */
16+
struct rb_io;
1617

1718
#define RB_VM_SAVE_MACHINE_CONTEXT(th) \
1819
do { \
@@ -55,16 +56,13 @@ VALUE rb_mutex_owned_p(VALUE self);
5556
VALUE rb_exec_recursive_outer_mid(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h, ID mid);
5657
void ruby_mn_threads_params(void);
5758

59+
int rb_thread_io_wait(struct rb_io *io, int events, struct timeval * timeout);
5860
int rb_thread_wait_for_single_fd(int fd, int events, struct timeval * timeout);
5961

60-
struct rb_io_close_wait_list {
61-
struct ccan_list_head pending_fd_users;
62-
VALUE closing_thread;
63-
VALUE closing_fiber;
64-
VALUE wakeup_mutex;
65-
};
66-
int rb_notify_fd_close(int fd, struct rb_io_close_wait_list *busy);
67-
void rb_notify_fd_close_wait(struct rb_io_close_wait_list *busy);
62+
63+
64+
int rb_thread_io_close(struct rb_io *);
65+
void rb_thread_io_close_wait(struct rb_io *);
6866

6967
void rb_ec_check_ints(struct rb_execution_context_struct *ec);
7068

@@ -73,8 +71,8 @@ RUBY_SYMBOL_EXPORT_BEGIN
7371
void *rb_thread_prevent_fork(void *(*func)(void *), void *data); /* for ext/socket/raddrinfo.c */
7472

7573
/* Temporary. This API will be removed (renamed). */
76-
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd);
77-
VALUE rb_thread_io_blocking_call(rb_blocking_function_t *func, void *data1, int fd, int events);
74+
VALUE rb_thread_io_blocking_region(struct rb_io *io, rb_blocking_function_t *func, void *data1);
75+
VALUE rb_thread_io_blocking_call(struct rb_io *io, rb_blocking_function_t *func, void *data1, int events);
7876

7977
/* thread.c (export) */
8078
int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */

0 commit comments

Comments
 (0)