summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2026-02-07 17:50:54 -0800
committerJohn Hawthorn <john@hawthorn.email>2026-02-07 18:20:17 -0800
commitfd089e3e95ebbded14c9a2d51fce376fbbbf289d (patch)
tree4dada65e46ce1aa06d4ea62f22b44f701fbaf6ca
parentd5af159556b63c97ee35199dd7c70b5127e58cb3 (diff)
Revert "Wake timer to create new SNT when needed for dedicated task (#16009)"
This reverts commit 7b3370a5579956404d742a2e104d72e7c89480e4.
-rw-r--r--test/ruby/test_ractor.rb39
-rw-r--r--thread_pthread.c37
-rw-r--r--thread_pthread_mn.c17
3 files changed, 20 insertions, 73 deletions
diff --git a/test/ruby/test_ractor.rb b/test/ruby/test_ractor.rb
index d449f9f814..6ae511217a 100644
--- a/test/ruby/test_ractor.rb
+++ b/test/ruby/test_ractor.rb
@@ -201,45 +201,6 @@ class TestRactor < Test::Unit::TestCase
RUBY
end
- def test_timer_thread_create_snt_for_dedicated_task
- omit "timer thread works differently" if windows?
- omit "test relies on this as a best-effort safety mechanism" unless defined?(Process::WNOHANG)
- assert_separately([{ "RUBY_MAX_CPU" => "2" }], <<~'RUBY', timeout: 30)
- $VERBOSE = nil
- CHILD_PID = 0
-
- rs = []
- 2.times do |i|
- rs << Ractor.new(i) do |j|
- if j == 0
- pid = spawn("sleep 60", close_others: true)
- Object.const_set(:CHILD_PID, pid)
- Process.waitpid(pid) # block forever (dedicated task)
- else
- while CHILD_PID == 0
- sleep 1 # make sure first ractor blocks forever first (this is what we're testing)
- end
- 1_000.times do
- [nil] * 100
- end
- end
- end
- end
-
- rs.last.join
- begin
- result = Process.waitpid(CHILD_PID, Process::WNOHANG)
- rescue Errno::ECHILD, Errno::ESRCH
- # If it's somehow not a child (not running?), don't send it a signal
- else
- if result.nil?
- Process.kill('KILL', CHILD_PID) rescue nil
- end
- end
- rs.first.join # reap
- RUBY
- end
-
def test_symbol_proc_is_shareable
pr = :symbol.to_proc
assert_make_shareable(pr)
diff --git a/thread_pthread.c b/thread_pthread.c
index f455ac828e..5b461efec8 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -90,11 +90,6 @@ static const void *const condattr_monotonic = NULL;
#endif
#endif
-#ifndef MINIMUM_SNT
-// make at least MINIMUM_SNT snts for debug.
-#define MINIMUM_SNT 0
-#endif
-
#ifdef HAVE_SCHED_YIELD
#define native_thread_yield() (void)sched_yield()
#else
@@ -559,20 +554,6 @@ ractor_sched_timeslice_threads_contain_p(rb_vm_t *vm, rb_thread_t *th)
static void ractor_sched_barrier_join_signal_locked(rb_vm_t *vm);
-static bool
-need_more_shared_native_threads_p(rb_vm_t *vm)
-{
- ASSERT_ractor_sched_locked(vm, NULL);
-
- unsigned int schedulable_ractor_cnt = vm->ractor.cnt;
- unsigned int snt_cnt = vm->ractor.sched.snt_cnt;
- RUBY_ASSERT(schedulable_ractor_cnt >= 1);
- if (!vm->ractor.main_ractor->threads.sched.enable_mn_threads) {
- schedulable_ractor_cnt--; // do not need snt for main ractor
- }
- return snt_cnt < MINIMUM_SNT || (snt_cnt < schedulable_ractor_cnt && snt_cnt < vm->ractor.sched.max_cpu);
-}
-
// setup timeslice signals by the timer thread.
static void
thread_sched_setup_running_threads(struct rb_thread_sched *sched, rb_ractor_t *cr, rb_vm_t *vm,
@@ -583,7 +564,6 @@ thread_sched_setup_running_threads(struct rb_thread_sched *sched, rb_ractor_t *c
#endif
rb_thread_t *del_timeslice_th;
- bool wakeup_timer_thread = false;
if (del_th && sched->is_running_timeslice) {
del_timeslice_th = del_th;
@@ -612,12 +592,6 @@ thread_sched_setup_running_threads(struct rb_thread_sched *sched, rb_ractor_t *c
ractor_sched_barrier_join_signal_locked(vm);
}
sched->is_running = false;
-
- // If we need more SNTs, the timer thread should be awake and monitoring the situation so it can correct it.
- if (!del_th->has_dedicated_nt && del_th->nt->dedicated > 0 && (sched->running != NULL || vm->ractor.sched.grq_cnt > 0) &&
- need_more_shared_native_threads_p(vm)) {
- wakeup_timer_thread = true;
- }
}
if (add_th) {
@@ -642,7 +616,7 @@ thread_sched_setup_running_threads(struct rb_thread_sched *sched, rb_ractor_t *c
ccan_list_add(&vm->ractor.sched.timeslice_threads, &add_timeslice_th->sched.node.timeslice_threads);
sched->is_running_timeslice = true;
if (was_empty) {
- wakeup_timer_thread = true;
+ timer_thread_wakeup_locked(vm);
}
}
@@ -651,10 +625,6 @@ thread_sched_setup_running_threads(struct rb_thread_sched *sched, rb_ractor_t *c
ccan_list_del_init(&del_timeslice_th->sched.node.timeslice_threads);
}
- if (wakeup_timer_thread) {
- timer_thread_wakeup_locked(vm);
- }
-
VM_ASSERT(ractor_sched_running_threads_size(vm) == vm->ractor.sched.running_cnt);
VM_ASSERT(ractor_sched_timeslice_threads_size(vm) <= vm->ractor.sched.running_cnt);
}
@@ -1294,6 +1264,11 @@ ractor_sched_enq(rb_vm_t *vm, rb_ractor_t *r)
#define SNT_KEEP_SECONDS 0
#endif
+#ifndef MINIMUM_SNT
+// make at least MINIMUM_SNT snts for debug.
+#define MINIMUM_SNT 0
+#endif
+
static rb_ractor_t *
ractor_sched_deq(rb_vm_t *vm, rb_ractor_t *cr)
{
diff --git a/thread_pthread_mn.c b/thread_pthread_mn.c
index d6602cea77..69e81e5fbc 100644
--- a/thread_pthread_mn.c
+++ b/thread_pthread_mn.c
@@ -394,14 +394,25 @@ nt_free_stack(void *mstack)
rb_native_mutex_unlock(&nt_machine_stack_lock);
}
+
static int
native_thread_check_and_create_shared(rb_vm_t *vm)
{
bool need_to_make = false;
- ractor_sched_lock(vm, NULL);
+ rb_native_mutex_lock(&vm->ractor.sched.lock);
{
- if (need_more_shared_native_threads_p(vm)) {
+ unsigned int schedulable_ractor_cnt = vm->ractor.cnt;
+ RUBY_ASSERT(schedulable_ractor_cnt >= 1);
+
+ if (!vm->ractor.main_ractor->threads.sched.enable_mn_threads)
+ schedulable_ractor_cnt--; // do not need snt for main ractor
+
+ unsigned int snt_cnt = vm->ractor.sched.snt_cnt;
+ if (((int)snt_cnt < MINIMUM_SNT) ||
+ (snt_cnt < schedulable_ractor_cnt &&
+ snt_cnt < vm->ractor.sched.max_cpu)) {
+
RUBY_DEBUG_LOG("added snt:%u dnt:%u ractor_cnt:%u grq_cnt:%u",
vm->ractor.sched.snt_cnt,
vm->ractor.sched.dnt_cnt,
@@ -415,7 +426,7 @@ native_thread_check_and_create_shared(rb_vm_t *vm)
RUBY_DEBUG_LOG("snt:%d ractor_cnt:%d", (int)vm->ractor.sched.snt_cnt, (int)vm->ractor.cnt);
}
}
- ractor_sched_unlock(vm, NULL);
+ rb_native_mutex_unlock(&vm->ractor.sched.lock);
if (need_to_make) {
struct rb_native_thread *nt = native_thread_alloc();