Adjust snt < max_cpu calculation

[Bug #20146]

Previously we dealt with the main Ractor not being enabled for M:N by
incrementing snt_cnt++. This worked for comparing against ractor count,
but meant that we always had one less SNT than was specified by
RUBY_MAX_CPU.

This was notably a problem for RUBY_MAX_CPU=1, which would cause Ractors
to hang.

This commit instead of adjusting snt, adjusts a
"schedulable_ractor_cnt". This way snt_cnt will actually reach
RUBY_MAX_CPU.
This commit is contained in:
John Hawthorn 2025-08-19 22:22:51 -07:00
parent acb29f7fa1
commit 7ac16eff31
2 changed files with 14 additions and 3 deletions

View File

@ -202,6 +202,13 @@ class TestRactor < Test::Unit::TestCase
RUBY
end
# [Bug #20146]
def test_max_cpu_1
assert_ractor(<<~'RUBY', args: [{ "RUBY_MAX_CPU" => "1" }])
assert_equal :ok, Ractor.new { :ok }.value
RUBY
end
def assert_make_shareable(obj)
refute Ractor.shareable?(obj), "object was already shareable"
Ractor.make_shareable(obj)

View File

@ -397,11 +397,15 @@ native_thread_check_and_create_shared(rb_vm_t *vm)
rb_native_mutex_lock(&vm->ractor.sched.lock);
{
unsigned int snt_cnt = vm->ractor.sched.snt_cnt;
if (!vm->ractor.main_ractor->threads.sched.enable_mn_threads) snt_cnt++; // do not need snt for main ractor
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 < vm->ractor.cnt &&
(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",