@@ -580,16 +580,18 @@ rb_find_global_entry(ID id)
580
580
struct rb_global_entry * entry ;
581
581
VALUE data ;
582
582
583
- if (!rb_id_table_lookup (rb_global_tbl , id , & data )) {
584
- entry = NULL ;
585
- }
586
- else {
587
- entry = (struct rb_global_entry * )data ;
588
- RUBY_ASSERT (entry != NULL );
583
+ RB_VM_LOCKING () {
584
+ if (!rb_id_table_lookup (rb_global_tbl , id , & data )) {
585
+ entry = NULL ;
586
+ }
587
+ else {
588
+ entry = (struct rb_global_entry * )data ;
589
+ RUBY_ASSERT (entry != NULL );
590
+ }
589
591
}
590
592
591
593
if (UNLIKELY (!rb_ractor_main_p ()) && (!entry || !entry -> ractor_local )) {
592
- rb_raise (rb_eRactorIsolationError , "can not access global variables %s from non-main Ractors " , rb_id2name (id ));
594
+ rb_raise (rb_eRactorIsolationError , "can not access global variable %s from non-main Ractor " , rb_id2name (id ));
593
595
}
594
596
595
597
return entry ;
@@ -617,25 +619,28 @@ rb_gvar_undef_compactor(void *var)
617
619
static struct rb_global_entry *
618
620
rb_global_entry (ID id )
619
621
{
620
- struct rb_global_entry * entry = rb_find_global_entry (id );
621
- if (!entry ) {
622
- struct rb_global_variable * var ;
623
- entry = ALLOC (struct rb_global_entry );
624
- var = ALLOC (struct rb_global_variable );
625
- entry -> id = id ;
626
- entry -> var = var ;
627
- entry -> ractor_local = false;
628
- var -> counter = 1 ;
629
- var -> data = 0 ;
630
- var -> getter = rb_gvar_undef_getter ;
631
- var -> setter = rb_gvar_undef_setter ;
632
- var -> marker = rb_gvar_undef_marker ;
633
- var -> compactor = rb_gvar_undef_compactor ;
634
-
635
- var -> block_trace = 0 ;
636
- var -> trace = 0 ;
637
- var -> namespace_ready = false;
638
- rb_id_table_insert (rb_global_tbl , id , (VALUE )entry );
622
+ struct rb_global_entry * entry ;
623
+ RB_VM_LOCKING () {
624
+ 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 );
643
+ }
639
644
}
640
645
return entry ;
641
646
}
@@ -999,15 +1004,17 @@ rb_gvar_set(ID id, VALUE val)
999
1004
struct rb_global_entry * entry ;
1000
1005
const rb_namespace_t * ns = rb_current_namespace ();
1001
1006
1002
- entry = rb_global_entry (id );
1007
+ RB_VM_LOCKING () {
1008
+ entry = rb_global_entry (id );
1003
1009
1004
- if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1005
- rb_hash_aset (ns -> gvar_tbl , rb_id2sym (entry -> id ), val );
1006
- retval = val ;
1007
- // TODO: think about trace
1008
- }
1009
- else {
1010
- retval = rb_gvar_set_entry (entry , val );
1010
+ if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1011
+ rb_hash_aset (ns -> gvar_tbl , rb_id2sym (entry -> id ), val );
1012
+ retval = val ;
1013
+ // TODO: think about trace
1014
+ }
1015
+ else {
1016
+ retval = rb_gvar_set_entry (entry , val );
1017
+ }
1011
1018
}
1012
1019
return retval ;
1013
1020
}
@@ -1022,27 +1029,30 @@ VALUE
1022
1029
rb_gvar_get (ID id )
1023
1030
{
1024
1031
VALUE retval , gvars , key ;
1025
- struct rb_global_entry * entry = rb_global_entry (id );
1026
- struct rb_global_variable * var = entry -> var ;
1027
1032
const rb_namespace_t * ns = rb_current_namespace ();
1028
-
1029
- if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1030
- gvars = ns -> gvar_tbl ;
1031
- key = rb_id2sym (entry -> id );
1032
- if (RTEST (rb_hash_has_key (gvars , key ))) { // this gvar is already cached
1033
- retval = rb_hash_aref (gvars , key );
1033
+ // TODO: use lock-free rb_id_table when it's available for use (doesn't yet exist)
1034
+ RB_VM_LOCKING () {
1035
+ struct rb_global_entry * entry = rb_global_entry (id );
1036
+ struct rb_global_variable * var = entry -> var ;
1037
+
1038
+ if (USE_NAMESPACE_GVAR_TBL (ns , entry )) {
1039
+ gvars = ns -> gvar_tbl ;
1040
+ key = rb_id2sym (entry -> id );
1041
+ if (RTEST (rb_hash_has_key (gvars , key ))) { // this gvar is already cached
1042
+ retval = rb_hash_aref (gvars , key );
1043
+ }
1044
+ else {
1045
+ retval = (* var -> getter )(entry -> id , var -> data );
1046
+ if (rb_obj_respond_to (retval , rb_intern ("clone" ), 1 )) {
1047
+ retval = rb_funcall (retval , rb_intern ("clone" ), 0 );
1048
+ }
1049
+ rb_hash_aset (gvars , key , retval );
1050
+ }
1034
1051
}
1035
1052
else {
1036
1053
retval = (* var -> getter )(entry -> id , var -> data );
1037
- if (rb_obj_respond_to (retval , rb_intern ("clone" ), 1 )) {
1038
- retval = rb_funcall (retval , rb_intern ("clone" ), 0 );
1039
- }
1040
- rb_hash_aset (gvars , key , retval );
1041
1054
}
1042
1055
}
1043
- else {
1044
- retval = (* var -> getter )(entry -> id , var -> data );
1045
- }
1046
1056
return retval ;
1047
1057
}
1048
1058
@@ -1124,35 +1134,36 @@ rb_f_global_variables(void)
1124
1134
void
1125
1135
rb_alias_variable (ID name1 , ID name2 )
1126
1136
{
1127
- struct rb_global_entry * entry1 , * entry2 ;
1137
+ struct rb_global_entry * entry1 = NULL , * entry2 ;
1128
1138
VALUE data1 ;
1129
1139
struct rb_id_table * gtbl = rb_global_tbl ;
1130
1140
1131
1141
if (!rb_ractor_main_p ()) {
1132
1142
rb_raise (rb_eRactorIsolationError , "can not access global variables from non-main Ractors" );
1133
1143
}
1134
1144
1135
- entry2 = rb_global_entry (name2 );
1136
- if (!rb_id_table_lookup (gtbl , name1 , & data1 )) {
1137
- entry1 = ALLOC (struct rb_global_entry );
1138
- entry1 -> id = name1 ;
1139
- rb_id_table_insert (gtbl , name1 , (VALUE )entry1 );
1140
- }
1141
- else if ((entry1 = (struct rb_global_entry * )data1 )-> var != entry2 -> var ) {
1142
- struct rb_global_variable * var = entry1 -> var ;
1143
- if (var -> block_trace ) {
1144
- rb_raise (rb_eRuntimeError , "can't alias in tracer" );
1145
+ RB_VM_LOCKING () {
1146
+ entry2 = rb_global_entry (name2 );
1147
+ if (!rb_id_table_lookup (gtbl , name1 , & data1 )) {
1148
+ entry1 = ALLOC (struct rb_global_entry );
1149
+ entry1 -> id = name1 ;
1150
+ rb_id_table_insert (gtbl , name1 , (VALUE )entry1 );
1151
+ }
1152
+ else if ((entry1 = (struct rb_global_entry * )data1 )-> var != entry2 -> var ) {
1153
+ struct rb_global_variable * var = entry1 -> var ;
1154
+ if (var -> block_trace ) {
1155
+ rb_raise (rb_eRuntimeError , "can't alias in tracer" );
1156
+ }
1157
+ var -> counter -- ;
1158
+ if (var -> counter == 0 ) {
1159
+ free_global_variable (var );
1160
+ }
1145
1161
}
1146
- var -> counter -- ;
1147
- if ( var -> counter == 0 ) {
1148
- free_global_variable ( var ) ;
1162
+ if ( entry1 ) {
1163
+ entry2 -> var -> counter ++ ;
1164
+ entry1 -> var = entry2 -> var ;
1149
1165
}
1150
1166
}
1151
- else {
1152
- return ;
1153
- }
1154
- entry2 -> var -> counter ++ ;
1155
- entry1 -> var = entry2 -> var ;
1156
1167
}
1157
1168
1158
1169
static void
0 commit comments