@@ -584,16 +584,18 @@ rb_find_global_entry(ID id)
584
584
struct rb_global_entry * entry ;
585
585
VALUE data ;
586
586
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
+ }
593
595
}
594
596
595
597
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 ));
597
599
}
598
600
599
601
return entry ;
@@ -621,25 +623,28 @@ rb_gvar_undef_compactor(void *var)
621
623
static struct rb_global_entry *
622
624
rb_global_entry (ID id )
623
625
{
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
+ }
643
648
}
644
649
return entry ;
645
650
}
@@ -1003,15 +1008,17 @@ rb_gvar_set(ID id, VALUE val)
1003
1008
struct rb_global_entry * entry ;
1004
1009
const rb_namespace_t * ns = rb_current_namespace ();
1005
1010
1006
- entry = rb_global_entry (id );
1011
+ RB_VM_LOCKING () {
1012
+ entry = rb_global_entry (id );
1007
1013
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
+ }
1015
1022
}
1016
1023
return retval ;
1017
1024
}
@@ -1026,27 +1033,30 @@ VALUE
1026
1033
rb_gvar_get (ID id )
1027
1034
{
1028
1035
VALUE retval , gvars , key ;
1029
- struct rb_global_entry * entry = rb_global_entry (id );
1030
- struct rb_global_variable * var = entry -> var ;
1031
1036
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
+ }
1038
1055
}
1039
1056
else {
1040
1057
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 );
1045
1058
}
1046
1059
}
1047
- else {
1048
- retval = (* var -> getter )(entry -> id , var -> data );
1049
- }
1050
1060
return retval ;
1051
1061
}
1052
1062
@@ -1128,35 +1138,36 @@ rb_f_global_variables(void)
1128
1138
void
1129
1139
rb_alias_variable (ID name1 , ID name2 )
1130
1140
{
1131
- struct rb_global_entry * entry1 , * entry2 ;
1141
+ struct rb_global_entry * entry1 = NULL , * entry2 ;
1132
1142
VALUE data1 ;
1133
1143
struct rb_id_table * gtbl = rb_global_tbl ;
1134
1144
1135
1145
if (!rb_ractor_main_p ()) {
1136
1146
rb_raise (rb_eRactorIsolationError , "can not access global variables from non-main Ractors" );
1137
1147
}
1138
1148
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
+ }
1149
1165
}
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 ;
1153
1169
}
1154
1170
}
1155
- else {
1156
- return ;
1157
- }
1158
- entry2 -> var -> counter ++ ;
1159
- entry1 -> var = entry2 -> var ;
1160
1171
}
1161
1172
1162
1173
static void
0 commit comments