@@ -584,16 +584,18 @@ rb_find_global_entry(ID id)
584584 struct rb_global_entry * entry ;
585585 VALUE data ;
586586
587- if (!rb_id_table_lookup (rb_global_tbl , id , & data )) {
588- entry = NULL ;
589- }
590- else {
591- entry = (struct rb_global_entry * )data ;
592- RUBY_ASSERT (entry != NULL );
587+ RB_VM_LOCKING () {
588+ if (!rb_id_table_lookup (rb_global_tbl , id , & data )) {
589+ entry = NULL ;
590+ }
591+ else {
592+ entry = (struct rb_global_entry * )data ;
593+ RUBY_ASSERT (entry != NULL );
594+ }
593595 }
594596
595597 if (UNLIKELY (!rb_ractor_main_p ()) && (!entry || !entry -> ractor_local )) {
596- rb_raise (rb_eRactorIsolationError , "can not access global variables %s from non-main Ractors " , rb_id2name (id ));
598+ rb_raise (rb_eRactorIsolationError , "can not access global variable %s from non-main Ractor " , rb_id2name (id ));
597599 }
598600
599601 return entry ;
@@ -621,25 +623,28 @@ rb_gvar_undef_compactor(void *var)
621623static struct rb_global_entry *
622624rb_global_entry (ID id )
623625{
624- struct rb_global_entry * entry = rb_find_global_entry (id );
625- if (!entry ) {
626- struct rb_global_variable * var ;
627- entry = ALLOC (struct rb_global_entry );
628- var = ALLOC (struct rb_global_variable );
629- entry -> id = id ;
630- entry -> var = var ;
631- entry -> ractor_local = false;
632- var -> counter = 1 ;
633- var -> data = 0 ;
634- var -> getter = rb_gvar_undef_getter ;
635- var -> setter = rb_gvar_undef_setter ;
636- var -> marker = rb_gvar_undef_marker ;
637- var -> compactor = rb_gvar_undef_compactor ;
638-
639- var -> block_trace = 0 ;
640- var -> trace = 0 ;
641- var -> namespace_ready = false;
642- rb_id_table_insert (rb_global_tbl , id , (VALUE )entry );
626+ struct rb_global_entry * entry ;
627+ RB_VM_LOCKING () {
628+ entry = rb_find_global_entry (id );
629+ if (!entry ) {
630+ struct rb_global_variable * var ;
631+ entry = ALLOC (struct rb_global_entry );
632+ var = ALLOC (struct rb_global_variable );
633+ entry -> id = id ;
634+ entry -> var = var ;
635+ entry -> ractor_local = false;
636+ var -> counter = 1 ;
637+ var -> data = 0 ;
638+ var -> getter = rb_gvar_undef_getter ;
639+ var -> setter = rb_gvar_undef_setter ;
640+ var -> marker = rb_gvar_undef_marker ;
641+ var -> compactor = rb_gvar_undef_compactor ;
642+
643+ var -> block_trace = 0 ;
644+ var -> trace = 0 ;
645+ var -> namespace_ready = false;
646+ rb_id_table_insert (rb_global_tbl , id , (VALUE )entry );
647+ }
643648 }
644649 return entry ;
645650}
@@ -1003,15 +1008,17 @@ rb_gvar_set(ID id, VALUE val)
10031008 struct rb_global_entry * entry ;
10041009 const rb_namespace_t * ns = rb_current_namespace ();
10051010
1006- entry = rb_global_entry (id );
1011+ RB_VM_LOCKING () {
1012+ entry = rb_global_entry (id );
10071013
1008- if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1009- rb_hash_aset (ns -> gvar_tbl , rb_id2sym (entry -> id ), val );
1010- retval = val ;
1011- // TODO: think about trace
1012- }
1013- else {
1014- retval = rb_gvar_set_entry (entry , val );
1014+ if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1015+ rb_hash_aset (ns -> gvar_tbl , rb_id2sym (entry -> id ), val );
1016+ retval = val ;
1017+ // TODO: think about trace
1018+ }
1019+ else {
1020+ retval = rb_gvar_set_entry (entry , val );
1021+ }
10151022 }
10161023 return retval ;
10171024}
@@ -1026,27 +1033,30 @@ VALUE
10261033rb_gvar_get (ID id )
10271034{
10281035 VALUE retval , gvars , key ;
1029- struct rb_global_entry * entry = rb_global_entry (id );
1030- struct rb_global_variable * var = entry -> var ;
10311036 const rb_namespace_t * ns = rb_current_namespace ();
1032-
1033- if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1034- gvars = ns -> gvar_tbl ;
1035- key = rb_id2sym (entry -> id );
1036- if (RTEST (rb_hash_has_key (gvars , key ))) { // this gvar is already cached
1037- retval = rb_hash_aref (gvars , key );
1037+ // TODO: use lock-free rb_id_table when it's available for use (doesn't yet exist)
1038+ RB_VM_LOCKING () {
1039+ struct rb_global_entry * entry = rb_global_entry (id );
1040+ struct rb_global_variable * var = entry -> var ;
1041+
1042+ if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1043+ gvars = ns -> gvar_tbl ;
1044+ key = rb_id2sym (entry -> id );
1045+ if (RTEST (rb_hash_has_key (gvars , key ))) { // this gvar is already cached
1046+ retval = rb_hash_aref (gvars , key );
1047+ }
1048+ else {
1049+ retval = (* var -> getter )(entry -> id , var -> data );
1050+ if (rb_obj_respond_to (retval , rb_intern ("clone" ), 1 )) {
1051+ retval = rb_funcall (retval , rb_intern ("clone" ), 0 );
1052+ }
1053+ rb_hash_aset (gvars , key , retval );
1054+ }
10381055 }
10391056 else {
10401057 retval = (* var -> getter )(entry -> id , var -> data );
1041- if (rb_obj_respond_to (retval , rb_intern ("clone" ), 1 )) {
1042- retval = rb_funcall (retval , rb_intern ("clone" ), 0 );
1043- }
1044- rb_hash_aset (gvars , key , retval );
10451058 }
10461059 }
1047- else {
1048- retval = (* var -> getter )(entry -> id , var -> data );
1049- }
10501060 return retval ;
10511061}
10521062
@@ -1128,35 +1138,36 @@ rb_f_global_variables(void)
11281138void
11291139rb_alias_variable (ID name1 , ID name2 )
11301140{
1131- struct rb_global_entry * entry1 , * entry2 ;
1141+ struct rb_global_entry * entry1 = NULL , * entry2 ;
11321142 VALUE data1 ;
11331143 struct rb_id_table * gtbl = rb_global_tbl ;
11341144
11351145 if (!rb_ractor_main_p ()) {
11361146 rb_raise (rb_eRactorIsolationError , "can not access global variables from non-main Ractors" );
11371147 }
11381148
1139- entry2 = rb_global_entry (name2 );
1140- if (!rb_id_table_lookup (gtbl , name1 , & data1 )) {
1141- entry1 = ALLOC (struct rb_global_entry );
1142- entry1 -> id = name1 ;
1143- rb_id_table_insert (gtbl , name1 , (VALUE )entry1 );
1144- }
1145- else if ((entry1 = (struct rb_global_entry * )data1 )-> var != entry2 -> var ) {
1146- struct rb_global_variable * var = entry1 -> var ;
1147- if (var -> block_trace ) {
1148- rb_raise (rb_eRuntimeError , "can't alias in tracer" );
1149+ RB_VM_LOCKING () {
1150+ entry2 = rb_global_entry (name2 );
1151+ if (!rb_id_table_lookup (gtbl , name1 , & data1 )) {
1152+ entry1 = ALLOC (struct rb_global_entry );
1153+ entry1 -> id = name1 ;
1154+ rb_id_table_insert (gtbl , name1 , (VALUE )entry1 );
1155+ }
1156+ else if ((entry1 = (struct rb_global_entry * )data1 )-> var != entry2 -> var ) {
1157+ struct rb_global_variable * var = entry1 -> var ;
1158+ if (var -> block_trace ) {
1159+ rb_raise (rb_eRuntimeError , "can't alias in tracer" );
1160+ }
1161+ var -> counter -- ;
1162+ if (var -> counter == 0 ) {
1163+ free_global_variable (var );
1164+ }
11491165 }
1150- var -> counter -- ;
1151- if ( var -> counter == 0 ) {
1152- free_global_variable ( var ) ;
1166+ if ( entry1 ) {
1167+ entry2 -> var -> counter ++ ;
1168+ entry1 -> var = entry2 -> var ;
11531169 }
11541170 }
1155- else {
1156- return ;
1157- }
1158- entry2 -> var -> counter ++ ;
1159- entry1 -> var = entry2 -> var ;
11601171}
11611172
11621173static void
0 commit comments