summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <[email protected]>2025-06-05 13:48:34 -0700
committerJohn Hawthorn <[email protected]>2025-06-12 13:13:55 -0700
commita34fcf401b5b20c38eb98b42815e17bc2af9bad5 (patch)
tree6345fd91f8caba0646adae640cf0389b124c41d7
parent97994c77fb5b82ca959e1188ecaee7d633d60a8e (diff)
Add a new_thread flag to rb_interrupt_exec
Previously rb_ractor_interrupt_exec would use an intermediate function to create a new thread with the actual target function, replacing the data being passed in with a piece of malloc memory holding the "next" function and the original data. Because of this, passing rb_interrupt_exec_flag_value_data to rb_ractor_interrupt_exec didn't have the intended effect of allowing data to be passed in and marked. This commit adds a rb_interrupt_exec_flag_new_thread flag, which both simplifies the implementation and allows the original data to be marked.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13531
-rw-r--r--internal/thread.h1
-rw-r--r--thread.c36
2 files changed, 7 insertions, 30 deletions
diff --git a/internal/thread.h b/internal/thread.h
index 8403ac2663..00fcbfc560 100644
--- a/internal/thread.h
+++ b/internal/thread.h
@@ -90,6 +90,7 @@ typedef VALUE (rb_interrupt_exec_func_t)(void *data);
enum rb_interrupt_exec_flag {
rb_interrupt_exec_flag_none = 0x00,
rb_interrupt_exec_flag_value_data = 0x01,
+ rb_interrupt_exec_flag_new_thread = 0x02,
};
// interrupt the target_th and run func.
diff --git a/thread.c b/thread.c
index d79603d64b..232c677382 100644
--- a/thread.c
+++ b/thread.c
@@ -6206,7 +6206,11 @@ threadptr_interrupt_exec_exec(rb_thread_t *th)
RUBY_DEBUG_LOG("task:%p", task);
if (task) {
- (*task->func)(task->data);
+ if (task->flags & rb_interrupt_exec_flag_new_thread) {
+ rb_thread_create(task->func, task->data);
+ } else {
+ (*task->func)(task->data);
+ }
ruby_xfree(task);
}
else {
@@ -6229,43 +6233,15 @@ threadptr_interrupt_exec_cleanup(rb_thread_t *th)
rb_native_mutex_unlock(&th->interrupt_lock);
}
-struct interrupt_ractor_new_thread_data {
- rb_interrupt_exec_func_t *func;
- void *data;
-};
-
-static VALUE
-interrupt_ractor_new_thread_func(void *data)
-{
- struct interrupt_ractor_new_thread_data d = *(struct interrupt_ractor_new_thread_data *)data;
- ruby_xfree(data);
-
- d.func(d.data);
- return Qnil;
-}
-
-static VALUE
-interrupt_ractor_func(void *data)
-{
- rb_thread_create(interrupt_ractor_new_thread_func, data);
- return Qnil;
-}
-
// native thread safe
// func/data should be native thread safe
void
rb_ractor_interrupt_exec(struct rb_ractor_struct *target_r,
rb_interrupt_exec_func_t *func, void *data, enum rb_interrupt_exec_flag flags)
{
- struct interrupt_ractor_new_thread_data *d = ALLOC(struct interrupt_ractor_new_thread_data);
-
RUBY_DEBUG_LOG("flags:%d", (int)flags);
- d->func = func;
- d->data = data;
rb_thread_t *main_th = target_r->threads.main;
- rb_threadptr_interrupt_exec(main_th, interrupt_ractor_func, d, flags);
-
- // TODO MEMO: we can create a new thread in a ractor, but not sure how to do that now.
+ rb_threadptr_interrupt_exec(main_th, func, data, flags | rb_interrupt_exec_flag_new_thread);
}