1#include "internal/gc.h"
2#include "internal/thread.h"
5#include "ractor_core.h"
16 return vm_locked_by_ractor_p(vm, GET_RACTOR());
21vm_lock_assertable_p(
void)
23 return rb_current_execution_context(
false) != NULL;
27RUBY_ASSERT_vm_locking(
void)
29 if (vm_lock_assertable_p() && rb_multi_ractor_p()) {
31 VM_ASSERT(vm_locked(vm));
36RUBY_ASSERT_vm_locking_with_barrier(
void)
38 if (vm_lock_assertable_p() && rb_multi_ractor_p()) {
40 VM_ASSERT(vm_locked(vm));
42 if (vm->ractor.cnt > 1) {
44 VM_ASSERT(vm->ractor.sched.barrier_is_waiting);
50RUBY_ASSERT_vm_unlocking(
void)
52 if (vm_lock_assertable_p() && rb_multi_ractor_p()) {
54 VM_ASSERT(!vm_locked(vm));
62 return vm_locked(GET_VM());
66vm_need_barrier_waiting(
const rb_vm_t *vm)
68 return vm->ractor.sched.barrier_is_waiting;
74 return !no_barrier && cr->threads.sched.running != NULL && vm_need_barrier_waiting(vm);
78vm_lock_enter(
rb_ractor_t *cr,
rb_vm_t *vm,
bool locked,
bool no_barrier,
unsigned int *lev APPEND_LOCATION_ARGS)
80 RUBY_DEBUG_LOG2(file, line,
"start locked:%d", locked);
88 VM_ASSERT(cr->sync.locked_by != rb_ractor_self(cr));
92 VM_ASSERT(vm->ractor.sync.lock_owner == NULL);
93 VM_ASSERT(vm->ractor.sync.lock_rec == 0);
96 if (vm_need_barrier(no_barrier, cr, vm)) {
98 RB_VM_SAVE_MACHINE_CONTEXT(rb_ec_thread_ptr(ec));
101 VM_ASSERT(vm_need_barrier_waiting(vm));
102 RUBY_DEBUG_LOG(
"barrier serial:%u", vm->ractor.sched.barrier_serial);
103 rb_ractor_sched_barrier_join(vm, cr);
104 }
while (vm_need_barrier_waiting(vm));
107 VM_ASSERT(vm->ractor.sync.lock_rec == 0);
108 VM_ASSERT(vm->ractor.sync.lock_owner == NULL);
109 vm->ractor.sync.lock_owner = cr;
112 vm->ractor.sync.lock_rec++;
113 *lev = vm->ractor.sync.lock_rec;
114 RUBY_ASSERT_CRITICAL_SECTION_ENTER();
116 RUBY_DEBUG_LOG2(file, line,
"rec:%u owner:%u", vm->ractor.sync.lock_rec,
117 (
unsigned int)rb_ractor_id(vm->ractor.sync.lock_owner));
119 if (RUBY_DTRACE_GVL_ACQUIRE_ENABLED()) {
120 RUBY_DTRACE_GVL_ACQUIRE();
125vm_lock_leave(
rb_vm_t *vm,
bool no_barrier,
unsigned int *lev APPEND_LOCATION_ARGS)
127 MAYBE_UNUSED(
rb_ractor_t *cr = vm->ractor.sync.lock_owner);
129 RUBY_DEBUG_LOG2(file, line,
"rec:%u owner:%u%s", vm->ractor.sync.lock_rec,
130 (
unsigned int)rb_ractor_id(cr),
131 vm->ractor.sync.lock_rec == 1 ?
" (leave)" :
"");
134 VM_ASSERT(vm->ractor.sync.lock_rec > 0);
135 VM_ASSERT(vm->ractor.sync.lock_rec == *lev);
136 VM_ASSERT(cr == GET_RACTOR());
138 if (vm->ractor.sched.barrier_ractor == cr &&
139 vm->ractor.sched.barrier_lock_rec == vm->ractor.sync.lock_rec) {
140 VM_ASSERT(!no_barrier);
141 rb_ractor_sched_barrier_end(vm, cr);
144 if (RUBY_DTRACE_GVL_RELEASE_ENABLED()) {
145 RUBY_DTRACE_GVL_RELEASE();
148 RUBY_ASSERT_CRITICAL_SECTION_LEAVE();
149 vm->ractor.sync.lock_rec--;
150 *lev = vm->ractor.sync.lock_rec;
152 if (vm->ractor.sync.lock_rec == 0) {
153 vm->ractor.sync.lock_owner = NULL;
159rb_vm_lock_enter_body(
unsigned int *lev APPEND_LOCATION_ARGS)
163 vm_lock_enter(NULL, vm,
true,
false, lev APPEND_LOCATION_PARAMS);
166 vm_lock_enter(GET_RACTOR(), vm,
false,
false, lev APPEND_LOCATION_PARAMS);
171rb_vm_lock_enter_body_nb(
unsigned int *lev APPEND_LOCATION_ARGS)
175 vm_lock_enter(NULL, vm,
true,
true, lev APPEND_LOCATION_PARAMS);
178 vm_lock_enter(GET_RACTOR(), vm,
false,
true, lev APPEND_LOCATION_PARAMS);
183rb_vm_lock_enter_body_cr(
rb_ractor_t *cr,
unsigned int *lev APPEND_LOCATION_ARGS)
186 vm_lock_enter(cr, vm, vm_locked(vm),
false, lev APPEND_LOCATION_PARAMS);
190rb_vm_lock_leave_body_nb(
unsigned int *lev APPEND_LOCATION_ARGS)
192 vm_lock_leave(GET_VM(),
true, lev APPEND_LOCATION_PARAMS);
196rb_vm_lock_leave_body(
unsigned int *lev APPEND_LOCATION_ARGS)
198 vm_lock_leave(GET_VM(),
false, lev APPEND_LOCATION_PARAMS);
202rb_vm_lock_body(LOCATION_ARGS)
205 ASSERT_vm_unlocking();
207 vm_lock_enter(GET_RACTOR(), vm,
false,
false, &vm->ractor.sync.lock_rec APPEND_LOCATION_PARAMS);
211rb_vm_unlock_body(LOCATION_ARGS)
215 VM_ASSERT(vm->ractor.sync.lock_rec == 1);
216 vm_lock_leave(vm,
false, &vm->ractor.sync.lock_rec APPEND_LOCATION_PARAMS);
222 return vm->ractor.sched.barrier_ractor == cr;
228 RB_DEBUG_COUNTER_INC(vm_sync_barrier);
230 if (!rb_multi_ractor_p()) {
239 VM_ASSERT(cr == GET_RACTOR());
240 VM_ASSERT(rb_ractor_status_p(cr, ractor_running));
242 if (vm_barrier_acquired_p(vm, cr)) {
247 VM_ASSERT(!vm->ractor.sched.barrier_is_waiting);
248 rb_ractor_sched_barrier_start(vm, cr);
255 unsigned int recorded_lock_rec,
256 unsigned int current_lock_rec)
258 VM_ASSERT(recorded_lock_rec != current_lock_rec);
260 if (UNLIKELY(recorded_lock_rec > current_lock_rec)) {
261 rb_bug(
"unexpected situation - recordd:%u current:%u",
262 recorded_lock_rec, current_lock_rec);
265 while (recorded_lock_rec < current_lock_rec) {
266 RB_VM_LOCK_LEAVE_LEV(¤t_lock_rec);
270 VM_ASSERT(recorded_lock_rec == rb_ec_vm_lock_rec(ec));
274rb_vm_lock_with_barrier(
VALUE (*func)(
void *args),
void *args)
void rb_native_mutex_lock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_lock.
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_unlock.
uintptr_t VALUE
Type that represents a Ruby object.