1#include "internal/gc.h"
8#ifndef RACTOR_CHECK_MODE
9#define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE)
12enum rb_ractor_basket_type {
29 basket_type_take_basket,
43 enum rb_ractor_basket_type e;
64 return b->type.e ==
type;
70 return basket_type_p(b, basket_type_none);
79 unsigned int reserved_cnt;
82enum rb_ractor_wait_status {
84 wait_receiving = 0x01,
90enum rb_ractor_wakeup_status {
102 rb_nativethread_lock_t lock;
103#if RACTOR_CHECK_MODE > 0
107 bool incoming_port_closed;
108 bool outgoing_port_closed;
120 enum rb_ractor_wait_status status;
121 enum rb_ractor_wakeup_status wakeup_status;
122 rb_thread_t *waiting_thread;
125#ifndef RUBY_THREAD_PTHREAD_H
126 rb_nativethread_cond_t cond;
155 VALUE receiving_mutex;
158 rb_nativethread_cond_t barrier_wait_cond;
162 struct ccan_list_head set;
164 unsigned int blocking_cnt;
165 unsigned int sleeper;
167 rb_execution_context_t *running_ec;
170 VALUE thgroup_default;
175 enum ractor_status status_;
177 struct ccan_list_node vmlr_node;
190 rb_ractor_newobj_cache_t newobj_cache;
195 void (*mark_func)(
VALUE v,
void *data);
201rb_ractor_self(
const rb_ractor_t *r)
206rb_ractor_t *rb_ractor_main_alloc(
void);
207void rb_ractor_main_setup(rb_vm_t *vm, rb_ractor_t *main_ractor, rb_thread_t *main_thread);
208void rb_ractor_atexit(rb_execution_context_t *ec,
VALUE result);
209void rb_ractor_atexit_exception(rb_execution_context_t *ec);
210void rb_ractor_teardown(rb_execution_context_t *ec);
211void rb_ractor_receive_parameters(rb_execution_context_t *ec, rb_ractor_t *g,
int len,
VALUE *ptr);
212void rb_ractor_send_parameters(rb_execution_context_t *ec, rb_ractor_t *g,
VALUE args);
216int rb_ractor_living_thread_num(
const rb_ractor_t *);
217VALUE rb_ractor_thread_list(
void);
218bool rb_ractor_p(
VALUE rv);
220void rb_ractor_living_threads_init(rb_ractor_t *r);
221void rb_ractor_living_threads_insert(rb_ractor_t *r, rb_thread_t *th);
222void rb_ractor_living_threads_remove(rb_ractor_t *r, rb_thread_t *th);
223void rb_ractor_blocking_threads_inc(rb_ractor_t *r,
const char *file,
int line);
224void rb_ractor_blocking_threads_dec(rb_ractor_t *r,
const char *file,
int line);
226void rb_ractor_vm_barrier_interrupt_running_thread(rb_ractor_t *r);
227void rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r);
228void rb_ractor_terminate_all(
void);
229bool rb_ractor_main_p_(
void);
230void rb_ractor_finish_marking(
void);
231void rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th);
235RUBY_SYMBOL_EXPORT_BEGIN
236bool rb_ractor_shareable_p_continue(
VALUE obj);
242RUBY_SYMBOL_EXPORT_END
245rb_ractor_main_p(
void)
247 if (ruby_single_main_ractor) {
251 return rb_ractor_main_p_();
256rb_ractor_status_p(rb_ractor_t *r,
enum ractor_status status)
258 return r->status_ == status;
262rb_ractor_sleeper_threads_inc(rb_ractor_t *r)
264 r->threads.sleeper++;
268rb_ractor_sleeper_threads_dec(rb_ractor_t *r)
270 r->threads.sleeper--;
274rb_ractor_sleeper_threads_clear(rb_ractor_t *r)
276 r->threads.sleeper = 0;
280rb_ractor_sleeper_thread_num(rb_ractor_t *r)
282 return r->threads.sleeper;
286rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th)
288 RUBY_DEBUG_LOG(
"th:%d->%u%s",
289 cr->threads.running_ec ? (
int)rb_th_serial(cr->threads.running_ec->thread_ptr) : -1,
290 rb_th_serial(th), cr->threads.running_ec == th->ec ?
" (same)" :
"");
292 if (cr->threads.running_ec != th->ec) {
294 ruby_debug_printf(
"rb_ractor_thread_switch ec:%p->%p\n",
295 (
void *)cr->threads.running_ec, (
void *)th->ec);
302 if (cr->threads.running_ec != th->ec) {
303 th->running_time_us = 0;
306 cr->threads.running_ec = th->ec;
308 VM_ASSERT(cr == GET_RACTOR());
311#define rb_ractor_set_current_ec(cr, ec) rb_ractor_set_current_ec_(cr, ec, __FILE__, __LINE__)
314rb_ractor_set_current_ec_(rb_ractor_t *cr, rb_execution_context_t *ec,
const char *file,
int line)
316#ifdef RB_THREAD_LOCAL_SPECIFIER
319 rb_current_ec_set(ec);
321 ruby_current_ec = ec;
325 native_tls_set(ruby_current_ec_key, ec);
327 RUBY_DEBUG_LOG2(file, line,
"ec:%p->%p", (
void *)cr->threads.running_ec, (
void *)ec);
328 VM_ASSERT(ec == NULL || cr->threads.running_ec != ec);
329 cr->threads.running_ec = ec;
332void rb_vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *cr,
const char *file,
int line);
333void rb_vm_ractor_blocking_cnt_dec(rb_vm_t *vm, rb_ractor_t *cr,
const char *file,
int line);
335static inline uint32_t
336rb_ractor_id(
const rb_ractor_t *r)
341#if RACTOR_CHECK_MODE > 0
342# define RACTOR_BELONGING_ID(obj) (*(uint32_t *)(((uintptr_t)(obj)) + rb_gc_obj_slot_size(obj)))
344uint32_t rb_ractor_current_id(
void);
347rb_ractor_setup_belonging_to(
VALUE obj, uint32_t rid)
349 RACTOR_BELONGING_ID(obj) = rid;
353rb_ractor_setup_belonging(
VALUE obj)
355 rb_ractor_setup_belonging_to(obj, rb_ractor_current_id());
358static inline uint32_t
359rb_ractor_belonging(
VALUE obj)
365 return RACTOR_BELONGING_ID(obj);
370rb_ractor_confirm_belonging(
VALUE obj)
372 uint32_t
id = rb_ractor_belonging(obj);
377 rb_bug(
"id == 0 but not shareable");
380 else if (UNLIKELY(
id != rb_ractor_current_id())) {
386 rb_bug(
"rb_ractor_confirm_belonging object-ractor id:%u, current-ractor id:%u",
id, rb_ractor_current_id());
392#define rb_ractor_confirm_belonging(obj) obj
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
int len
Length of the buffer.
struct rb_ractor_local_key_struct * rb_ractor_local_key_t
(Opaque) struct that holds a ractor-local storage key.
static bool rb_ractor_shareable_p(VALUE obj)
Queries if multiple Ractors can share the passed object or not.
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
VALUE type(ANYARGS)
ANYARGS-ed function type.
uintptr_t VALUE
Type that represents a Ruby object.