Forráskód Böngészése

Potentially fix race condition #2463 #2814

gingerBill 1 éve
szülő
commit
d358ebd7e6
2 módosított fájl, 26 hozzáadás és 7 törlés
  1. 3 0
      src/check_type.cpp
  2. 23 7
      src/types.cpp

+ 3 - 0
src/check_type.cpp

@@ -613,6 +613,9 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
 	
 	scope_reserve(ctx->scope, min_field_count);
 
+	rw_mutex_lock(&struct_type->Struct.fields_mutex);
+	defer (rw_mutex_unlock(&struct_type->Struct.fields_mutex));
+
 	if (st->is_raw_union && min_field_count > 1) {
 		struct_type->Struct.is_raw_union = true;
 		context = str_lit("struct #raw_union");

+ 23 - 7
src/types.cpp

@@ -143,7 +143,8 @@ struct TypeStruct {
 	Type *          soa_elem;
 	i32             soa_count;
 	StructSoaKind   soa_kind;
-	BlockingMutex   mutex; // for settings offsets
+	RwMutex         fields_mutex;
+	BlockingMutex   offset_mutex; // for settings offsets
 
 	bool            is_polymorphic;
 	bool            are_offsets_set             : 1;
@@ -2951,7 +2952,11 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
 	gbAllocator a = permanent_allocator();
 	isize max_count = 0;
 	switch (type->kind) {
-	case Type_Struct:   max_count = type->Struct.fields.count;   break;
+	case Type_Struct:
+		rw_mutex_shared_lock(&type->Struct.fields_mutex);
+		max_count = type->Struct.fields.count;
+		rw_mutex_shared_unlock(&type->Struct.fields_mutex);
+		break;
 	case Type_Tuple:    max_count = type->Tuple.variables.count; break;
 	}
 
@@ -2960,7 +2965,9 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
 	}
 
 	switch (type->kind) {
-	case Type_Struct:
+	case Type_Struct: {
+		rw_mutex_shared_lock(&type->Struct.fields_mutex);
+		defer (rw_mutex_shared_unlock(&type->Struct.fields_mutex));
 		for (isize i = 0; i < max_count; i++) {
 			Entity *f = type->Struct.fields[i];
 			if (f->kind == Entity_Variable) {
@@ -2971,7 +2978,8 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
 				}
 			}
 		}
-		break;
+	} break;
+
 	case Type_Tuple:
 		for (isize i = 0; i < max_count; i++) {
 			Entity *f = type->Tuple.variables[i];
@@ -3024,7 +3032,10 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
 				}
 			}
 			if (type->kind == Type_Struct) {
-				for_array(i, type->Struct.fields) {
+				rw_mutex_shared_lock(&type->Struct.fields_mutex);
+				isize field_count = type->Struct.fields.count;
+				rw_mutex_shared_unlock(&type->Struct.fields_mutex);
+				if (field_count != 0) for_array(i, type->Struct.fields) {
 					Entity *f = type->Struct.fields[i];
 					if (f->flags&EntityFlag_Using) {
 						sel = lookup_field_with_selection(f->type, field_name, is_type, sel, allow_blank_ident);
@@ -3052,7 +3063,9 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
 		}
 
 		if (type->kind == Type_Struct) {
+			rw_mutex_shared_lock(&type->Struct.fields_mutex);
 			Scope *s = type->Struct.scope;
+			rw_mutex_shared_unlock(&type->Struct.fields_mutex);
 			if (s != nullptr) {
 				Entity *found = scope_lookup_current(s, field_name);
 				if (found != nullptr && found->kind != Entity_Variable) {
@@ -3100,7 +3113,10 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
 			}
 		}
 
-		for_array(i, type->Struct.fields) {
+		rw_mutex_shared_lock(&type->Struct.fields_mutex);
+		isize field_count = type->Struct.fields.count;
+		rw_mutex_shared_unlock(&type->Struct.fields_mutex);
+		if (field_count != 0) for_array(i, type->Struct.fields) {
 			Entity *f = type->Struct.fields[i];
 			if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
 				continue;
@@ -3680,7 +3696,7 @@ gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_pack
 gb_internal bool type_set_offsets(Type *t) {
 	t = base_type(t);
 	if (t->kind == Type_Struct) {
-		MUTEX_GUARD(&t->Struct.mutex);
+		MUTEX_GUARD(&t->Struct.offset_mutex);
 		if (!t->Struct.are_offsets_set) {
 			t->Struct.are_offsets_being_processed = true;
 			t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union);