11#include "internal/error.h"
24static VALUE rb_eRactorError;
25static VALUE rb_eRactorRemoteError;
26static VALUE rb_eRactorMovedError;
27static VALUE rb_eRactorClosedError;
28static VALUE rb_cRactorMovedObject;
35#if RACTOR_CHECK_MODE > 0
37 if (rb_current_execution_context(
false) !=
NULL && r->
sync.locked_by == rb_ractor_self(GET_RACTOR())) {
38 rb_bug(
"recursive ractor locking");
46#if RACTOR_CHECK_MODE > 0
48 if (rb_current_execution_context(
false) !=
NULL && r->
sync.locked_by != rb_ractor_self(GET_RACTOR())) {
50 rb_bug(
"ractor lock is not acquired.");
60 ASSERT_ractor_unlocking(r);
63#if RACTOR_CHECK_MODE > 0
64 if (rb_current_execution_context(
false) !=
NULL) {
65 r->
sync.locked_by = rb_ractor_self(GET_RACTOR());
77 ractor_lock(cr,
file, line);
83 ASSERT_ractor_locking(r);
84#if RACTOR_CHECK_MODE > 0
97 ractor_unlock(cr,
file, line);
100#define RACTOR_LOCK(r) ractor_lock(r, __FILE__, __LINE__)
101#define RACTOR_UNLOCK(r) ractor_unlock(r, __FILE__, __LINE__)
102#define RACTOR_LOCK_SELF(r) ractor_lock_self(r, __FILE__, __LINE__)
103#define RACTOR_UNLOCK_SELF(r) ractor_unlock_self(r, __FILE__, __LINE__)
108#if RACTOR_CHECK_MODE > 0
114#if RACTOR_CHECK_MODE > 0
115 r->
sync.locked_by = locked_by;
120ractor_status_str(
enum ractor_status status)
123 case ractor_created:
return "created";
124 case ractor_running:
return "running";
125 case ractor_blocking:
return "blocking";
126 case ractor_terminated:
return "terminated";
132ractor_status_set(
rb_ractor_t *r,
enum ractor_status status)
137 if (r->
status_ != ractor_created) {
149 status == ractor_terminated);
151 case ractor_blocking:
154 case ractor_terminated:
163ractor_status_p(
rb_ractor_t *r,
enum ractor_status status)
165 return rb_ractor_status_p(r, status);
173 for (
int i=0; i<rq->
cnt; i++) {
180static void ractor_local_storage_mark(
rb_ractor_t *r);
181static void ractor_local_storage_free(
rb_ractor_t *r);
184ractor_mark(
void *
ptr)
210 ractor_local_storage_mark(r);
226ractor_free(
void *
ptr)
233 ractor_local_storage_free(r);
251ractor_memsize(
const void *
ptr)
284RACTOR_PTR(
VALUE self)
295#if RACTOR_CHECK_MODE > 0
297rb_ractor_current_id(
void)
299 if (GET_THREAD()->ractor ==
NULL) {
303 return rb_ractor_id(GET_RACTOR());
326 ASSERT_ractor_locking(GET_RACTOR());
349 ASSERT_ractor_locking(r);
352 ractor_queue_advance(rq);
359 ASSERT_ractor_locking(r);
365 ractor_queue_compact(r, rq);
367 for (
int i=0; i<rq->
cnt; i++) {
368 if (!ractor_queue_skip_p(rq, i)) {
383 if (!ractor_queue_empty_p(r, rq)) {
384 for (
int i=0; i<rq->
cnt; i++) {
385 if (!ractor_queue_skip_p(rq, i)) {
391 ractor_queue_compact(r, rq);
406 ASSERT_ractor_locking(r);
427static VALUE ractor_reset_belonging(
VALUE obj);
439 b->
v = ractor_reset_belonging(b->
v);
451 VALUE v = ractor_basket_value(b);
457 ractor_basket_clear(b);
458 rb_ec_setup_exception(
NULL,
err, cause);
462 ractor_basket_clear(b);
470 rb_raise(rb_eRactorError,
"can not call receive/receive_if recursively");
480 ractor_recursive_receive_if(r);
482 if (ractor_queue_deq(r, rq, &basket) ==
false) {
484 rb_raise(rb_eRactorClosedError,
"The incoming port is already closed");
491 return ractor_basket_accept(&basket);
495ractor_sleep_wo_gvl(
void *
ptr)
502 ractor_cond_wait(cr);
511ractor_sleep_interrupt(
void *
ptr)
523#if USE_RUBY_DEBUG_LOG
525wait_status_str(
enum ractor_wait_status wait_status)
527 switch ((
int)wait_status) {
528 case wait_none:
return "none";
529 case wait_receiving:
return "receiving";
530 case wait_taking:
return "taking";
531 case wait_yielding:
return "yielding";
532 case wait_receiving|wait_taking:
return "receiving|taking";
533 case wait_receiving|wait_yielding:
return "receiving|yielding";
534 case wait_taking|wait_yielding:
return "taking|yielding";
535 case wait_receiving|wait_taking|wait_yielding:
return "receiving|taking|yielding";
541wakeup_status_str(
enum ractor_wakeup_status wakeup_status)
543 switch (wakeup_status) {
544 case wakeup_none:
return "none";
545 case wakeup_by_send:
return "by_send";
546 case wakeup_by_yield:
return "by_yield";
547 case wakeup_by_take:
return "by_take";
548 case wakeup_by_close:
return "by_close";
549 case wakeup_by_interrupt:
return "by_interrupt";
550 case wakeup_by_retry:
return "by_retry";
567 ractor_sleep_interrupt, cr,
584ractor_sleeping_by(
const rb_ractor_t *r,
enum ractor_wait_status wait_status)
590ractor_wakeup(
rb_ractor_t *r,
enum ractor_wait_status wait_status,
enum ractor_wakeup_status wakeup_status)
592 ASSERT_ractor_locking(r);
598 if (ractor_sleeping_by(r, wait_status)) {
612 bool retry_try =
false;
616 if (ractor_sleeping_by(r, wait_yielding)) {
624 for (
int i=0; i<wl->
cnt; i++) {
637 else if (wl->
size <= wl->
cnt + 1) {
667 for (
int i=0; i<wl->
cnt; i++) {
675 for (
int i=pos; i<wl->
cnt; i++) {
686 ASSERT_ractor_locking(r);
691 for (
int i=1; i<wl->
cnt; i++) {
706 ractor_recursive_receive_if(cr);
714 ractor_sleep(ec, cr);
727 while ((v = ractor_try_receive(ec, cr)) ==
Qundef) {
728 ractor_receive_wait(ec, cr);
740#define T(t) case basket_type_##t: return #t
748 default:
rb_bug(
"unreachable");
756 for (
int i=0; i<rq->
cnt; i++) {
788 ractor_receive_if_lock(data->
cr);
797 if (
RTEST(block_result)) {
799 ractor_queue_compact(data->
cr, data->
rq);
809 if (
RTEST(block_result)) {
843 unsigned int serial = (
unsigned int)-1;
850 ractor_receive_wait(ec, cr);
860 for (
int i=index; i<rq->
cnt; i++) {
861 if (!ractor_queue_skip_p(rq, i)) {
863 v = ractor_basket_value(b);
883 receive_if_ensure, (
VALUE)&data);
885 if (result !=
Qundef)
return result;
903 ractor_queue_enq(r, rq, b);
904 if (ractor_wakeup(r, wait_receiving, wakeup_by_send)) {
912 rb_raise(rb_eRactorClosedError,
"The incoming-port is already closed");
922 basket->
sender = rb_ec_ractor_ptr(ec)->pub.self;
929 else if (rb_ractor_shareable_p(obj)) {
933 else if (!
RTEST(move)) {
934 basket->
v = ractor_copy(obj);
944 basket->
v = ractor_move(obj);
953 ractor_basket_setup(ec, &basket, obj, move,
false,
false,
false);
954 ractor_send_basket(ec, r, &basket);
968 if (ractor_sleeping_by(r, wait_yielding)) {
973 wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_retry);
976 wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_take);
990 rb_raise(rb_eRactorClosedError,
"The outgoing-port is already closed");
997 return ractor_basket_accept(&basket);
1002ractor_yield_move_body(
VALUE v)
1004 return ractor_move(
v);
1010 ASSERT_ractor_unlocking(cr);
1014 rb_raise(rb_eRactorClosedError,
"The outgoing-port is already closed");
1027 bool retry_shift =
false;
1031 if (ractor_sleeping_by(r, wait_taking)) {
1047 basket->
v = moved_value;
1052 if (!ractor_wakeup(r, wait_moving, wakeup_by_yield)) {
1057 ractor_wakeup(r, wait_taking, wakeup_by_yield);
1089 bool interrupted =
false;
1090 enum ractor_wait_status wait_status = 0;
1091 bool yield_p = (yielded_value !=
Qundef) ?
true :
false;
1092 const int alen = rs_len + (yield_p ? 1 : 0);
1094 struct ractor_select_action {
1095 enum ractor_select_action_type {
1096 ractor_select_action_take,
1097 ractor_select_action_receive,
1098 ractor_select_action_yield,
1101 } *actions =
ALLOCA_N(
struct ractor_select_action, alen);
1109 for (i=0; i<rs_len; i++) {
1113 actions[i].type = ractor_select_action_receive;
1114 actions[i].v =
Qnil;
1115 wait_status |= wait_receiving;
1118 actions[i].type = ractor_select_action_take;
1120 wait_status |= wait_taking;
1131 actions[rs_len].type = ractor_select_action_yield;
1132 actions[rs_len].v =
Qundef;
1133 wait_status |= wait_yielding;
1140 RUBY_DEBUG_LOG(
"try actions (%s)", wait_status_str(wait_status));
1142 for (i=0; i<alen; i++) {
1144 switch (actions[i].
type) {
1145 case ractor_select_action_take:
1147 v = ractor_try_take(ec, RACTOR_PTR(rv));
1154 case ractor_select_action_receive:
1155 v = ractor_try_receive(ec, cr);
1162 case ractor_select_action_yield:
1174 RUBY_DEBUG_LOG(
"wait actions (%s)", wait_status_str(wait_status));
1185 for (i=0; i<alen; i++) {
1187 switch (actions[i].
type) {
1188 case ractor_select_action_take:
1189 r = RACTOR_PTR(actions[i].v);
1190 ractor_register_taking(r, cr);
1192 case ractor_select_action_yield:
1193 case ractor_select_action_receive:
1202 for (i=0; i<alen; i++) {
1205 switch (actions[i].
type) {
1206 case ractor_select_action_take:
1207 r = RACTOR_PTR(actions[i].v);
1208 if (ractor_sleeping_by(r, wait_yielding)) {
1214 case ractor_select_action_receive:
1221 case ractor_select_action_yield:
1236 ractor_sleep(ec, cr);
1250 for (i=0; i<alen; i++) {
1252 switch (actions[i].
type) {
1253 case ractor_select_action_take:
1254 r = RACTOR_PTR(actions[i].v);
1257 case ractor_select_action_receive:
1258 case ractor_select_action_yield:
1267 switch (wakeup_status) {
1272 case wakeup_by_retry:
1275 case wakeup_by_send:
1279 case wakeup_by_yield:
1287 case wakeup_by_take:
1291 case wakeup_by_close:
1295 case wakeup_by_interrupt:
1303 RUBY_DEBUG_LOG(
"cleanup actions (%s)", wait_status_str(wait_status));
1316 interrupted =
false;
1328 ractor_select(ec,
NULL, 0, obj,
RTEST(move) ?
true :
false, &ret_r);
1350 if (ractor_wakeup(r, wait_receiving, wakeup_by_close)) {
1382 ractor_wakeup(taking_ractor, wait_taking, wakeup_by_close);
1388 ractor_wakeup(r, wait_yielding, wakeup_by_close)) {
1405 id = ++ractor_last_id;
1423cancel_single_ractor_mode(
void)
1435 "Ractor is experimental, and the behavior may change in future versions of Ruby! "
1436 "Also there are many implementation issues.");
1443 VM_ASSERT(ractor_status_p(r, ractor_created));
1445 if (rb_multi_ractor_p()) {
1448 vm_insert_ractor0(vm, r,
false);
1449 vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__);
1456 vm_insert_ractor0(vm, r,
true);
1457 ractor_status_set(r, ractor_blocking);
1458 ractor_status_set(r, ractor_running);
1461 cancel_single_ractor_mode();
1462 vm_insert_ractor0(vm, r,
true);
1463 vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__);
1471 VM_ASSERT(ractor_status_p(cr, ractor_running));
1491 ractor_status_set(cr, ractor_terminated);
1497ractor_alloc(
VALUE klass)
1503 VM_ASSERT(ractor_status_p(r, ractor_created));
1512 fprintf(stderr,
"[FATAL] failed to allocate memory for main ractor\n");
1516 r->
pub.
id = ++ractor_last_id;
1525#if defined(HAVE_WORKING_FORK)
1593 VALUE rv = ractor_alloc(self);
1595 ractor_init(r,
name, loc);
1598 r->
pub.
id = ractor_next_id();
1618 ASSERT_ractor_unlocking(cr);
1621 ractor_basket_setup(ec, &basket,
v,
Qfalse, exc,
true,
true );
1624 if (ractor_try_yield(ec, cr, &basket)) {
1647 if (retry)
goto retry;
1655 ractor_close_incoming(ec, cr);
1656 ractor_close_outgoing(ec, cr);
1671 ractor_yield_atexit(ec, cr, result,
false);
1678 ractor_yield_atexit(ec, cr, ec->
errinfo,
true);
1684 for (
int i=0; i<
len; i++) {
1685 ptr[i] = ractor_receive(ec, r);
1692 int len = RARRAY_LENINT(args);
1693 for (
int i=0; i<
len; i++) {
1703 return rb_ec_ractor_ptr(ec) == rb_ec_vm_ptr(ec)->ractor.main_ractor;
1711 return r == GET_VM()->ractor.main_ractor;
1738 list_for_each(&r->
threads.
set, th, lt_node) {
1739 switch (th->status) {
1743 ts[ts_cnt++] = th->
self;
1752 for (
int i=0; i<ts_cnt; i++) {
1774 VM_ASSERT(ractor_status_p(r, ractor_created));
1775 vm_insert_ractor(th->
vm, r);
1782 ractor_status_set(r, ractor_blocking);
1794 vm_ractor_blocking_cnt_inc(vm, cr,
file, line);
1807 ractor_status_set(cr, ractor_running);
1811ractor_check_blocking(
rb_ractor_t *cr,
unsigned int remained_thread_cnt,
const char *
file,
int line)
1816 "cr->threads.cnt:%u cr->threads.blocking_cnt:%u vm->ractor.cnt:%u vm->ractor.blocking_cnt:%u",
1818 GET_VM()->ractor.cnt, GET_VM()->ractor.blocking_cnt);
1822 if (remained_thread_cnt > 0 &&
1842 ractor_check_blocking(cr, cr->
threads.
cnt - 1, __FILE__, __LINE__);
1845 vm_remove_ractor(th->
vm, cr);
1865 ractor_check_blocking(cr, cr->
threads.
cnt, __FILE__, __LINE__);
1873 "r->threads.blocking_cnt:%d--, r->threads.cnt:%u",
1895 ASSERT_ractor_unlocking(r);
1900 if (ractor_status_p(r, ractor_running)) {
1914 ASSERT_ractor_unlocking(r);
1932ractor_terminal_interrupt_all(
rb_vm_t *vm)
1937 list_for_each(&vm->
ractor.
set, r, vmlr_node) {
1955 ractor_terminal_interrupt_all(vm);
1971 ractor_terminal_interrupt_all(vm);
1986 rb_raise(rb_eRactorMovedError,
"can not send any methods to a moved object");
2097 rb_define_method(rb_cRactorMovedObject,
"method_missing", ractor_moved_missing, -1);
2100 rb_define_method(rb_cRactorMovedObject,
"__send__", ractor_moved_missing, -1);
2104 rb_define_method(rb_cRactorMovedObject,
"__id__", ractor_moved_missing, -1);
2105 rb_define_method(rb_cRactorMovedObject,
"equal?", ractor_moved_missing, -1);
2106 rb_define_method(rb_cRactorMovedObject,
"instance_eval", ractor_moved_missing, -1);
2107 rb_define_method(rb_cRactorMovedObject,
"instance_exec", ractor_moved_missing, -1);
2116 list_for_each(&vm->
ractor.
set, r, vmlr_node) {
2118 fprintf(stderr,
"r:%u (%s)\n", r->
pub.
id, ractor_status_str(r->
status_));
2126 if (rb_ractor_main_p()) {
2138 if (rb_ractor_main_p()) {
2150 if (rb_ractor_main_p()) {
2162 if (rb_ractor_main_p()) {
2174 if (rb_ractor_main_p()) {
2186 if (rb_ractor_main_p()) {
2240 if (obj_traverse_i(
key, d->
data)) {
2245 if (obj_traverse_i(val, d->
data)) {
2254obj_traverse_reachable_i(
VALUE obj,
void *
ptr)
2258 if (obj_traverse_i(obj, d->
data)) {
2276 if (RB_SPECIAL_CONST_P(obj))
return 0;
2294 if (val !=
Qundef && obj_traverse_i(val, data))
return 1;
2316 if (val !=
Qundef && obj_traverse_i(val, data))
return 1;
2323 for (
int i = 0; i < RARRAY_LENINT(obj); i++) {
2325 if (obj_traverse_i(e, data))
return 1;
2339 if (d.
stop)
return 1;
2346 const VALUE *
ptr = RSTRUCT_CONST_PTR(obj);
2348 for (
long i=0; i<
len; i++) {
2349 if (obj_traverse_i(
ptr[i],
data))
return 1;
2359 if (obj_traverse_i(
RCOMPLEX(obj)->real,
data))
return 1;
2360 if (obj_traverse_i(
RCOMPLEX(obj)->imag,
data))
return 1;
2375 if (d.
stop)
return 1;
2415rb_obj_traverse(
VALUE obj,
2426 if (obj_traverse_i(obj, &data))
return 1;
2427 if (final_func && data.
rec) {
2436frozen_shareable_p(
VALUE obj,
bool *made_shareable)
2438 if (!RB_TYPE_P(obj,
T_DATA)) {
2441 else if (RTYPEDDATA_P(obj)) {
2449 *made_shareable =
true;
2459make_shareable_check_shareable(
VALUE obj)
2462 bool made_shareable =
false;
2464 if (rb_ractor_shareable_p(obj)) {
2467 else if (!frozen_shareable_p(obj, &made_shareable)) {
2468 if (made_shareable) {
2476 if (!RB_OBJ_FROZEN_RAW(obj)) {
2479 if (
UNLIKELY(!RB_OBJ_FROZEN_RAW(obj))) {
2480 rb_raise(rb_eRactorError,
"#freeze does not freeze object correctly");
2492mark_shareable(
VALUE obj)
2501 rb_obj_traverse(obj,
2502 make_shareable_check_shareable,
2503 null_leave, mark_shareable);
2510 VALUE copy = ractor_copy(obj);
2511 rb_obj_traverse(copy,
2512 make_shareable_check_shareable,
2513 null_leave, mark_shareable);
2520 if (!rb_ractor_shareable_p(obj)) {
2529shareable_p_enter(
VALUE obj)
2534 else if (RB_TYPE_P(obj,
T_CLASS) ||
2538 mark_shareable(obj);
2541 else if (RB_OBJ_FROZEN_RAW(obj) &&
2542 frozen_shareable_p(obj,
NULL)) {
2552 if (rb_obj_traverse(obj,
2553 shareable_p_enter, null_leave,
2562#if RACTOR_CHECK_MODE > 0
2564reset_belonging_enter(
VALUE obj)
2566 if (rb_ractor_shareable_p(obj)) {
2570 rb_ractor_setup_belonging(obj);
2577null_leave(
VALUE obj)
2583ractor_reset_belonging(
VALUE obj)
2585#if RACTOR_CHECK_MODE > 0
2586 rb_obj_traverse(obj, reset_belonging_enter, null_leave,
NULL);
2632 if (obj_traverse_replace_i(*
key, data)) {
2641 if (obj_traverse_replace_i(*val, data)) {
2663#if USE_TRANSIENT_HEAP
2671obj_refer_only_shareables_p_i(
VALUE obj,
void *
ptr)
2673 int *pcnt = (
int *)
ptr;
2675 if (!rb_ractor_shareable_p(obj)) {
2681obj_refer_only_shareables_p(
VALUE obj)
2697 if (RB_SPECIAL_CONST_P(obj)) {
2722#define CHECK_AND_REPLACE(v) do { \
2724 if (obj_traverse_replace_i(_val, data)) { return 1; } \
2725 else if (data->replacement != _val) { RB_OBJ_WRITE(obj, &v, data->replacement); } \
2753#if USE_TRANSIENT_HEAP
2771#if USE_TRANSIENT_HEAP
2775 for (
int i = 0; i < RARRAY_LENINT(obj); i++) {
2778 if (obj_traverse_replace_i(e, data)) {
2791#if USE_TRANSIENT_HEAP
2800 obj_hash_traverse_replace_foreach_i,
2801 obj_hash_traverse_replace_i,
2803 if (d.
stop)
return 1;
2807 if (obj_traverse_replace_i(ifnone,
data)) {
2818#if USE_TRANSIENT_HEAP
2822 const VALUE *
ptr = RSTRUCT_CONST_PTR(obj);
2824 for (
long i=0; i<
len; i++) {
2840 if (!
data->
move && obj_refer_only_shareables_p(obj)) {
2845 data->
move ?
"move" :
"copy", rb_class_of(obj));
2874rb_obj_traverse_replace(
VALUE obj,
2887 if (obj_traverse_replace_i(obj, &data)) {
2910ractor_moved_bang(
VALUE obj)
2913 struct RVALUE *rv = (
void *)obj;
2915 rv->
klass = rb_cRactorMovedObject;
2927 if (rb_ractor_shareable_p(obj)) {
2928 data->replacement = obj;
2958 ractor_moved_bang(obj);
2963ractor_move(
VALUE obj)
2965 VALUE val = rb_obj_traverse_replace(obj, move_enter, move_leave,
true);
2970 rb_raise(rb_eRactorError,
"can not move the object");
2977 if (rb_ractor_shareable_p(obj)) {
2978 data->replacement = obj;
2994ractor_copy(
VALUE obj)
2996 VALUE val = rb_obj_traverse_replace(obj, copy_enter, copy_leave,
false);
3001 rb_raise(rb_eRactorError,
"can not copy the object");
3012static struct freed_ractor_local_keys_struct {
3016} freed_ractor_local_keys;
3027idkey_local_storage_mark_i(
ID id,
VALUE val,
void *dmy)
3039 for (
int i=0; i<freed_ractor_local_keys.cnt; i++) {
3044 (*
key->type->free)((
void *)val);
3076rb_ractor_local_storage_value_mark(
void *
ptr)
3092 rb_ractor_local_storage_value_mark,
3100 key->type =
type ?
type : &ractor_local_storage_type_null;
3116 if (freed_ractor_local_keys.cnt == freed_ractor_local_keys.capa) {
3117 freed_ractor_local_keys.capa = freed_ractor_local_keys.capa ? freed_ractor_local_keys.capa * 2 : 4;
3120 freed_ractor_local_keys.keys[freed_ractor_local_keys.cnt++] =
key;
3128 if (rb_ractor_main_p()) {
3130 *pret =
key->main_cache;
3160 if (rb_ractor_main_p()) {
3169 if (ractor_local_ref(
key, (
void **)&val)) {
3180 if (ractor_local_ref(
key, (
void **)val)) {
3191 ractor_local_set(
key, (
void *)val);
3198 if (ractor_local_ref(
key, &ret)) {
3209 ractor_local_set(
key,
ptr);
3212#define DEFAULT_KEYS_CAPA 0x10
3217 for (
int i=0; i<freed_ractor_local_keys.cnt; i++) {
3220 freed_ractor_local_keys.cnt = 0;
3257#include "ractor.rbinc"
VALUE rb_ary_push(VALUE ary, VALUE item)
void rb_ary_cancel_sharing(VALUE ary)
VALUE rb_ary_entry(VALUE ary, long offset)
#define rb_category_warn(category,...)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define MJIT_FUNC_EXPORTED
rb_encoding * rb_enc_get(VALUE obj)
#define RSTRING_PTR(string)
void ruby_xfree(void *x)
Deallocates a storage instance.
void * ruby_mimmalloc(size_t size)
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache)
void rb_gc_mark(VALUE ptr)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_raise(VALUE exc, const char *fmt,...)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
void rb_bug(const char *fmt,...)
VALUE rb_ident_hash_new(void)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
VALUE rb_exc_new_str(VALUE etype, VALUE str)
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
bool rb_warning_category_enabled_p(rb_warning_category_t category)
VALUE rb_cObject
Object class.
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
VALUE rb_cBasicObject
BasicObject class.
VALUE rb_obj_clone(VALUE)
Almost same as Object::clone.
unsigned in(void *in_desc, z_const unsigned char **buf)
int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
st_table * rb_hash_st_table(VALUE hash)
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val)
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
void rb_id_table_free(struct rb_id_table *tbl)
struct rb_id_table * rb_id_table_create(size_t capa)
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data)
rb_id_table_iterator_result
#define rb_enc_asciicompat(enc)
@ RB_WARN_CATEGORY_EXPERIMENTAL
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
VALUE rb_obj_is_proc(VALUE)
#define rb_exc_new_cstr(exc, str)
VALUE rb_str_new_frozen(VALUE)
void rb_thread_check_ints(void)
VALUE rb_mutex_unlock(VALUE mutex)
VALUE rb_mutex_lock(VALUE mutex)
VALUE rb_ivar_set(VALUE, ID, VALUE)
void rb_undef_alloc_func(VALUE)
ID rb_intern(const char *)
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
VALUE rb_to_symbol(VALUE name)
#define RB_NOGVL_UBF_ASYNC_SAFE
#define RB_NOGVL_INTR_FAIL
void * rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags)
Internal header for Complex.
Internal header for Hash.
Internal header for Rational.
void rb_str_make_independent(VALUE str)
Internal header for Struct.
Internal header for Thread.
VALUE rb_mutex_owned_p(VALUE self)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define ALLOCA_N(type, n)
#define MEMZERO(p, type, n)
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RARRAY_AREF(a, i)
bool rb_obj_is_main_ractor(VALUE gv)
const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free
rb_ractor_t * rb_ractor_main_alloc(void)
VALUE rb_ractor_make_shareable_copy(VALUE obj)
bool rb_ractor_p(VALUE gv)
void rb_ractor_local_storage_delkey(rb_ractor_local_key_t key)
VALUE rb_ractor_ensure_shareable(VALUE obj, VALUE name)
void * rb_ractor_local_storage_ptr(rb_ractor_local_key_t key)
rb_execution_context_t * rb_vm_main_ractor_ec(rb_vm_t *vm)
void rb_ractor_blocking_threads_dec(rb_ractor_t *cr, const char *file, int line)
void rb_ractor_teardown(rb_execution_context_t *ec)
void rb_ractor_stdin_set(VALUE in)
rb_global_vm_lock_t * rb_ractor_gvl(rb_ractor_t *r)
void rb_ractor_terminate_all(void)
enum obj_traverse_iterator_result(* rb_obj_traverse_final_func)(VALUE obj)
void rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr)
void rb_ractor_stdout_set(VALUE out)
enum obj_traverse_iterator_result(* rb_obj_traverse_replace_enter_func)(VALUE obj, struct obj_traverse_replace_data *data)
#define RACTOR_UNLOCK_SELF(r)
void rb_ractor_living_threads_insert(rb_ractor_t *r, rb_thread_t *th)
void rb_ractor_living_threads_remove(rb_ractor_t *cr, rb_thread_t *th)
rb_ractor_local_key_t rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type)
void rb_gvl_init(rb_global_vm_lock_t *gvl)
obj_traverse_iterator_result
traverse function
void rb_ractor_dump(void)
VALUE rb_ractor_stderr(void)
void rb_vm_ractor_blocking_cnt_dec(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line)
#define RACTOR_LOCK_SELF(r)
VALUE rb_ractor_stdin(void)
bool rb_ractor_main_p_(void)
void rb_ractor_finish_marking(void)
#define CHECK_AND_REPLACE(v)
enum obj_traverse_iterator_result(* rb_obj_traverse_replace_leave_func)(VALUE obj, struct obj_traverse_replace_data *data)
void rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val)
void rb_ractor_atexit_exception(rb_execution_context_t *ec)
void rb_ractor_vm_barrier_interrupt_running_thread(rb_ractor_t *r)
void rb_ractor_send_parameters(rb_execution_context_t *ec, rb_ractor_t *r, VALUE args)
VALUE rb_eRactorUnsafeError
void rb_ractor_blocking_threads_inc(rb_ractor_t *cr, const char *file, int line)
bool rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val)
VALUE rb_ractor_stdout(void)
void rb_ractor_atexit(rb_execution_context_t *ec, VALUE result)
void rb_thread_terminate_all(rb_thread_t *th)
void rb_ractor_stderr_set(VALUE err)
VALUE rb_ractor_thread_list(rb_ractor_t *r)
rb_hook_list_t * rb_ractor_hooks(rb_ractor_t *cr)
VALUE rb_ractor_make_shareable(VALUE obj)
enum obj_traverse_iterator_result(* rb_obj_traverse_enter_func)(VALUE obj)
void rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r)
void rb_replace_generic_ivar(VALUE clone, VALUE obj)
#define DEFAULT_KEYS_CAPA
VALUE rb_eRactorIsolationError
void rb_ractor_living_threads_init(rb_ractor_t *r)
rb_ractor_local_key_t rb_ractor_local_storage_value_newkey(void)
void rb_ractor_main_setup(rb_vm_t *vm, rb_ractor_t *r, rb_thread_t *th)
bool rb_ractor_shareable_p_continue(VALUE obj)
enum obj_traverse_iterator_result(* rb_obj_traverse_leave_func)(VALUE obj)
void rb_ractor_receive_parameters(rb_execution_context_t *ec, rb_ractor_t *r, int len, VALUE *ptr)
void rb_vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line)
VALUE rb_ractor_local_storage_value(rb_ractor_local_key_t key)
int rb_ractor_living_thread_num(const rb_ractor_t *r)
#define RB_OBJ_SHAREABLE_P(obj)
VALUE rb_thread_create_ractor(rb_ractor_t *g, VALUE args, VALUE proc)
void rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th)
#define RB_OBJ_WRITE(a, slot, b)
WB for new reference from ‘a’ to ‘b’.
#define RB_OBJ_WRITTEN(a, oldv, b)
WB for new reference from ‘a’ to ‘b’.
#define RHASH_SET_IFNONE(h, ifnone)
#define StringValueCStr(v)
#define TypedData_Wrap_Struct(klass, data_type, sval)
@ RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FROZEN_SHAREABLE
#define TypedData_Make_Struct(klass, type, data_type, sval)
rb_atomic_t cnt[RUBY_NSIG]
VALUE rb_sprintf(const char *,...)
VALUE ivptr[FLEX_ARY_LEN]
struct obj_traverse_data * data
rb_obj_traverse_enter_func enter_func
rb_obj_traverse_leave_func leave_func
struct obj_traverse_replace_data * data
rb_obj_traverse_replace_leave_func leave_func
rb_obj_traverse_replace_enter_func enter_func
rb_obj_traverse_final_func final_func
enum rb_ractor_basket_type type
const struct rb_ractor_local_storage_type * type
struct rb_ractor_basket * baskets
unsigned int reserved_cnt
rb_nativethread_cond_t barrier_wait_cond
struct list_node vmlr_node
unsigned int blocking_cnt
rb_execution_context_t * running_ec
struct rb_ractor_struct::@141 threads
enum rb_ractor_struct::ractor_status status_
struct rb_ractor_sync sync
struct rb_id_table * idkey_local_storage
rb_ractor_newobj_cache_t newobj_cache
struct rb_ractor_basket taken_basket
enum rb_ractor_sync::ractor_wait::ractor_wait_status status
enum rb_ractor_sync::ractor_wait::ractor_wakeup_status wakeup_status
struct rb_ractor_basket yielded_basket
struct rb_ractor_waiting_list taking_ractors
struct rb_ractor_sync::ractor_wait wait
bool incoming_port_closed
struct rb_ractor_queue incoming_queue
rb_nativethread_cond_t cond
bool outgoing_port_closed
rb_nativethread_lock_t lock
rb_execution_context_t * ec
struct rb_vm_struct::@194::@197 sync
struct rb_vm_struct::@194 ractor
struct rb_ractor_struct * main_ractor
unsigned int blocking_cnt
rb_nativethread_cond_t terminate_cond
struct rb_ractor_queue * rq
void rb_threadptr_interrupt(rb_thread_t *th)
int rb_vm_check_ints_blocking(rb_execution_context_t *ec)
void rb_native_mutex_lock(rb_nativethread_lock_t *lock)
void rb_native_cond_initialize(rb_nativethread_cond_t *cond)
void rb_native_mutex_initialize(rb_nativethread_lock_t *lock)
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
void rb_native_mutex_destroy(rb_nativethread_lock_t *lock)
void rb_native_cond_destroy(rb_nativethread_cond_t *cond)
void rb_native_cond_signal(rb_nativethread_cond_t *cond)
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
#define rb_obj_transient_heap_evacuate(x, y)
#define rb_ary_transient_heap_evacuate(x, y)
#define rb_hash_transient_heap_evacuate(x, y)
#define rb_struct_transient_heap_evacuate(x, y)
#define rb_transient_heap_evacuate()
void error(const char *msg)
int rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **ivtbl)
rb_ractor_t * ruby_single_main_ractor
VALUE rb_proc_ractor_make_shareable(VALUE self)
#define RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec)
struct rb_ractor_struct rb_ractor_t
void rb_hook_list_free(rb_hook_list_t *hooks)
#define RUBY_VM_SET_TERMINATE_INTERRUPT(ec)
void rb_hook_list_mark(rb_hook_list_t *hooks)
void rb_vm_cond_timedwait(rb_vm_t *vm, rb_nativethread_cond_t *cond, unsigned long msec)
#define RUBY_DEBUG_LOG2(file, line, fmt,...)
#define RUBY_DEBUG_LOG(fmt,...)
#define RB_VM_LOCK_ENTER_NO_BARRIER()
#define ASSERT_vm_locking()
#define RB_VM_LOCK_LEAVE_NO_BARRIER()
#define RB_VM_LOCK_ENTER()
#define RB_VM_LOCK_LEAVE()
#define ASSERT_vm_unlocking()