Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ext/json/lib/json/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@ class Coder
# JSON.new(options = nil, &block)
#
# Argument +options+, if given, contains a \Hash of options for both parsing and generating.
# See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options].
# See {Parsing Options}[rdoc-ref:JSON@Parsing+Options],
# and {Generating Options}[rdoc-ref:JSON@Generating+Options].
#
# For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
# encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
Expand Down
2 changes: 1 addition & 1 deletion ext/json/lib/json/ext/generator/state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class State
# Instantiates a new State object, configured by _opts_.
#
# Argument +opts+, if given, contains a \Hash of options for the generation.
# See {Generating Options}[#module-JSON-label-Generating+Options].
# See {Generating Options}[rdoc-ref:JSON@Generating+Options].
def initialize(opts = nil)
if opts && !opts.empty?
configure(opts)
Expand Down
1 change: 0 additions & 1 deletion internal/imemo.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ struct rb_imemo_tmpbuf_struct {
* */
struct MEMO {
VALUE flags;
VALUE reserved;
const VALUE v1;
const VALUE v2;
union {
Expand Down
39 changes: 0 additions & 39 deletions test/ruby/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,45 +201,6 @@ def test_max_cpu_1
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)
Expand Down
37 changes: 6 additions & 31 deletions thread_pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}
}

Expand All @@ -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);
}
Expand Down Expand Up @@ -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)
{
Expand Down
17 changes: 14 additions & 3 deletions thread_pthread_mn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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();
Expand Down