1#include "internal/gc.h"
2#include "internal/thread.h"
5#include "ractor_core.h"
15 return vm_locked_by_ractor_p(vm, GET_RACTOR());
20RUBY_ASSERT_vm_locking(
void)
22 if (rb_multi_ractor_p()) {
24 VM_ASSERT(vm_locked(vm));
29RUBY_ASSERT_vm_locking_with_barrier(
void)
31 if (rb_multi_ractor_p()) {
33 VM_ASSERT(vm_locked(vm));
35 if (vm->ractor.cnt > 1) {
37 VM_ASSERT(vm->ractor.sched.barrier_waiting);
43RUBY_ASSERT_vm_unlocking(
void)
45 if (rb_multi_ractor_p()) {
47 VM_ASSERT(!vm_locked(vm));
55 return vm_locked(GET_VM());
59vm_need_barrier_waiting(
const rb_vm_t *vm)
61#ifdef RUBY_THREAD_PTHREAD_H
62 return vm->ractor.sched.barrier_waiting;
64 return vm->ractor.sync.barrier_waiting;
71#ifdef RUBY_THREAD_PTHREAD_H
72 return !no_barrier && cr->threads.sched.running != NULL && vm_need_barrier_waiting(vm);
74 return !no_barrier && vm_need_barrier_waiting(vm);
79vm_lock_enter(
rb_ractor_t *cr,
rb_vm_t *vm,
bool locked,
bool no_barrier,
unsigned int *lev APPEND_LOCATION_ARGS)
81 RUBY_DEBUG_LOG2(file, line,
"start locked:%d", locked);
89 VM_ASSERT(cr->sync.locked_by != rb_ractor_self(cr));
93 VM_ASSERT(vm->ractor.sync.lock_owner == NULL);
94 VM_ASSERT(vm->ractor.sync.lock_rec == 0);
97 if (vm_need_barrier(no_barrier, cr, vm)) {
99 RB_VM_SAVE_MACHINE_CONTEXT(rb_ec_thread_ptr(ec));
102 VM_ASSERT(vm_need_barrier_waiting(vm));
103 RUBY_DEBUG_LOG(
"barrier serial:%u", vm->ractor.sched.barrier_serial);
104 rb_ractor_sched_barrier_join(vm, cr);
105 }
while (vm_need_barrier_waiting(vm));
108 VM_ASSERT(vm->ractor.sync.lock_rec == 0);
109 VM_ASSERT(vm->ractor.sync.lock_owner == NULL);
110 vm->ractor.sync.lock_owner = cr;
113 vm->ractor.sync.lock_rec++;
114 *lev = vm->ractor.sync.lock_rec;
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));
121vm_lock_leave(
rb_vm_t *vm,
bool no_barrier,
unsigned int *lev APPEND_LOCATION_ARGS)
123 MAYBE_UNUSED(
rb_ractor_t *cr = vm->ractor.sync.lock_owner);
125 RUBY_DEBUG_LOG2(file, line,
"rec:%u owner:%u%s", vm->ractor.sync.lock_rec,
126 (
unsigned int)rb_ractor_id(cr),
127 vm->ractor.sync.lock_rec == 1 ?
" (leave)" :
"");
130 VM_ASSERT(vm->ractor.sync.lock_rec > 0);
131 VM_ASSERT(vm->ractor.sync.lock_rec == *lev);
132 VM_ASSERT(cr == GET_RACTOR());
134#ifdef RUBY_THREAD_PTHREAD_H
135 if (vm->ractor.sched.barrier_ractor == cr &&
136 vm->ractor.sched.barrier_lock_rec == vm->ractor.sync.lock_rec) {
137 VM_ASSERT(!no_barrier);
138 rb_ractor_sched_barrier_end(vm, cr);
142 vm->ractor.sync.lock_rec--;
143 *lev = vm->ractor.sync.lock_rec;
145 if (vm->ractor.sync.lock_rec == 0) {
146 vm->ractor.sync.lock_owner = NULL;
152rb_vm_lock_enter_body(
unsigned int *lev APPEND_LOCATION_ARGS)
156 vm_lock_enter(NULL, vm,
true,
false, lev APPEND_LOCATION_PARAMS);
159 vm_lock_enter(GET_RACTOR(), vm,
false,
false, lev APPEND_LOCATION_PARAMS);
164rb_vm_lock_enter_body_nb(
unsigned int *lev APPEND_LOCATION_ARGS)
168 vm_lock_enter(NULL, vm,
true,
true, lev APPEND_LOCATION_PARAMS);
171 vm_lock_enter(GET_RACTOR(), vm,
false,
true, lev APPEND_LOCATION_PARAMS);
176rb_vm_lock_enter_body_cr(
rb_ractor_t *cr,
unsigned int *lev APPEND_LOCATION_ARGS)
179 vm_lock_enter(cr, vm, vm_locked(vm),
false, lev APPEND_LOCATION_PARAMS);
183rb_vm_lock_leave_body_nb(
unsigned int *lev APPEND_LOCATION_ARGS)
185 vm_lock_leave(GET_VM(),
true, lev APPEND_LOCATION_PARAMS);
189rb_vm_lock_leave_body(
unsigned int *lev APPEND_LOCATION_ARGS)
191 vm_lock_leave(GET_VM(),
false, lev APPEND_LOCATION_PARAMS);
195rb_vm_lock_body(LOCATION_ARGS)
198 ASSERT_vm_unlocking();
200 vm_lock_enter(GET_RACTOR(), vm,
false,
false, &vm->ractor.sync.lock_rec APPEND_LOCATION_PARAMS);
204rb_vm_unlock_body(LOCATION_ARGS)
208 VM_ASSERT(vm->ractor.sync.lock_rec == 1);
209 vm_lock_leave(vm,
false, &vm->ractor.sync.lock_rec APPEND_LOCATION_PARAMS);
213vm_cond_wait(
rb_vm_t *vm, rb_nativethread_cond_t *cond,
unsigned long msec)
216 unsigned int lock_rec = vm->ractor.sync.lock_rec;
219 vm->ractor.sync.lock_rec = 0;
220 vm->ractor.sync.lock_owner = NULL;
227 vm->ractor.sync.lock_rec = lock_rec;
228 vm->ractor.sync.lock_owner = cr;
232rb_vm_cond_wait(
rb_vm_t *vm, rb_nativethread_cond_t *cond)
234 vm_cond_wait(vm, cond, 0);
238rb_vm_cond_timedwait(
rb_vm_t *vm, rb_nativethread_cond_t *cond,
unsigned long msec)
240 vm_cond_wait(vm, cond, msec);
246#ifdef RUBY_THREAD_PTHREAD_H
247 return vm->ractor.sched.barrier_ractor == cr;
256 RB_DEBUG_COUNTER_INC(vm_sync_barrier);
258 if (!rb_multi_ractor_p()) {
267 VM_ASSERT(cr == GET_RACTOR());
268 VM_ASSERT(rb_ractor_status_p(cr, ractor_running));
270 if (vm_barrier_acquired_p(vm, cr)) {
275 VM_ASSERT(!vm->ractor.sched.barrier_waiting);
276 rb_ractor_sched_barrier_start(vm, cr);
283 unsigned int recorded_lock_rec,
284 unsigned int current_lock_rec)
286 VM_ASSERT(recorded_lock_rec != current_lock_rec);
288 if (UNLIKELY(recorded_lock_rec > current_lock_rec)) {
289 rb_bug(
"unexpected situation - recordd:%u current:%u",
290 recorded_lock_rec, current_lock_rec);
293 while (recorded_lock_rec < current_lock_rec) {
294 RB_VM_LOCK_LEAVE_LEV(¤t_lock_rec);
298 VM_ASSERT(recorded_lock_rec == rb_ec_vm_lock_rec(ec));
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.
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
Waits for the passed condition variable to be signalled.
void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec)
Identical to rb_native_cond_wait(), except it additionally takes timeout in msec resolution.