mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Fix race condition with #soa
This commit is contained in:
+2
-4
@@ -632,9 +632,6 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
|
|||||||
|
|
||||||
scope_reserve(ctx->scope, min_field_count);
|
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) {
|
if (st->is_raw_union && min_field_count > 1) {
|
||||||
struct_type->Struct.is_raw_union = true;
|
struct_type->Struct.is_raw_union = true;
|
||||||
context = str_lit("struct #raw_union");
|
context = str_lit("struct #raw_union");
|
||||||
@@ -662,6 +659,7 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
|
|||||||
gb_unused(where_clause_ok);
|
gb_unused(where_clause_ok);
|
||||||
}
|
}
|
||||||
check_struct_fields(ctx, node, &struct_type->Struct.fields, &struct_type->Struct.tags, st->fields, min_field_count, struct_type, context);
|
check_struct_fields(ctx, node, &struct_type->Struct.fields, &struct_type->Struct.tags, st->fields, min_field_count, struct_type, context);
|
||||||
|
wait_signal_set(&struct_type->Struct.fields_wait_signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ST_ALIGN(_name) if (st->_name != nullptr) { \
|
#define ST_ALIGN(_name) if (st->_name != nullptr) { \
|
||||||
@@ -2553,8 +2551,8 @@ gb_internal Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_e
|
|||||||
GB_ASSERT(is_type_struct(elem));
|
GB_ASSERT(is_type_struct(elem));
|
||||||
|
|
||||||
Type *old_struct = base_type(elem);
|
Type *old_struct = base_type(elem);
|
||||||
RW_MUTEX_GUARD(&old_struct->Struct.fields_mutex);
|
|
||||||
|
|
||||||
|
wait_signal_until_available(&old_struct->Struct.fields_wait_signal);
|
||||||
field_count = old_struct->Struct.fields.count;
|
field_count = old_struct->Struct.fields.count;
|
||||||
|
|
||||||
soa_struct = alloc_type_struct();
|
soa_struct = alloc_type_struct();
|
||||||
|
|||||||
@@ -107,6 +107,22 @@ gb_internal void thread_set_name (Thread *t, char const *name);
|
|||||||
gb_internal void yield_thread(void);
|
gb_internal void yield_thread(void);
|
||||||
gb_internal void yield_process(void);
|
gb_internal void yield_process(void);
|
||||||
|
|
||||||
|
struct Wait_Signal {
|
||||||
|
Futex futex;
|
||||||
|
};
|
||||||
|
|
||||||
|
gb_internal void wait_signal_until_available(Wait_Signal *ws) {
|
||||||
|
if (ws->futex.load() == 0) {
|
||||||
|
futex_wait(&ws->futex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal void wait_signal_set(Wait_Signal *ws) {
|
||||||
|
ws->futex.store(1);
|
||||||
|
futex_broadcast(&ws->futex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct MutexGuard {
|
struct MutexGuard {
|
||||||
MutexGuard() = delete;
|
MutexGuard() = delete;
|
||||||
|
|||||||
+6
-11
@@ -144,7 +144,7 @@ struct TypeStruct {
|
|||||||
Type * soa_elem;
|
Type * soa_elem;
|
||||||
i32 soa_count;
|
i32 soa_count;
|
||||||
StructSoaKind soa_kind;
|
StructSoaKind soa_kind;
|
||||||
RwMutex fields_mutex;
|
Wait_Signal fields_wait_signal;
|
||||||
BlockingMutex offset_mutex; // for settings offsets
|
BlockingMutex offset_mutex; // for settings offsets
|
||||||
|
|
||||||
bool is_polymorphic;
|
bool is_polymorphic;
|
||||||
@@ -2969,9 +2969,8 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
|
|||||||
isize max_count = 0;
|
isize max_count = 0;
|
||||||
switch (type->kind) {
|
switch (type->kind) {
|
||||||
case Type_Struct:
|
case Type_Struct:
|
||||||
rw_mutex_shared_lock(&type->Struct.fields_mutex);
|
wait_signal_until_available(&type->Struct.fields_wait_signal);
|
||||||
max_count = type->Struct.fields.count;
|
max_count = type->Struct.fields.count;
|
||||||
rw_mutex_shared_unlock(&type->Struct.fields_mutex);
|
|
||||||
break;
|
break;
|
||||||
case Type_Tuple: max_count = type->Tuple.variables.count; break;
|
case Type_Tuple: max_count = type->Tuple.variables.count; break;
|
||||||
}
|
}
|
||||||
@@ -2982,8 +2981,7 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
|
|||||||
|
|
||||||
switch (type->kind) {
|
switch (type->kind) {
|
||||||
case Type_Struct: {
|
case Type_Struct: {
|
||||||
rw_mutex_shared_lock(&type->Struct.fields_mutex);
|
wait_signal_until_available(&type->Struct.fields_wait_signal);
|
||||||
defer (rw_mutex_shared_unlock(&type->Struct.fields_mutex));
|
|
||||||
for (isize i = 0; i < max_count; i++) {
|
for (isize i = 0; i < max_count; i++) {
|
||||||
Entity *f = type->Struct.fields[i];
|
Entity *f = type->Struct.fields[i];
|
||||||
if (f->kind == Entity_Variable) {
|
if (f->kind == Entity_Variable) {
|
||||||
@@ -3048,9 +3046,8 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type->kind == Type_Struct) {
|
if (type->kind == Type_Struct) {
|
||||||
rw_mutex_shared_lock(&type->Struct.fields_mutex);
|
wait_signal_until_available(&type->Struct.fields_wait_signal);
|
||||||
isize field_count = type->Struct.fields.count;
|
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) {
|
if (field_count != 0) for_array(i, type->Struct.fields) {
|
||||||
Entity *f = type->Struct.fields[i];
|
Entity *f = type->Struct.fields[i];
|
||||||
if (f->flags&EntityFlag_Using) {
|
if (f->flags&EntityFlag_Using) {
|
||||||
@@ -3079,9 +3076,8 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type->kind == Type_Struct) {
|
if (type->kind == Type_Struct) {
|
||||||
rw_mutex_shared_lock(&type->Struct.fields_mutex);
|
wait_signal_until_available(&type->Struct.fields_wait_signal);
|
||||||
Scope *s = type->Struct.scope;
|
Scope *s = type->Struct.scope;
|
||||||
rw_mutex_shared_unlock(&type->Struct.fields_mutex);
|
|
||||||
if (s != nullptr) {
|
if (s != nullptr) {
|
||||||
Entity *found = scope_lookup_current(s, field_name);
|
Entity *found = scope_lookup_current(s, field_name);
|
||||||
if (found != nullptr && found->kind != Entity_Variable) {
|
if (found != nullptr && found->kind != Entity_Variable) {
|
||||||
@@ -3129,9 +3125,8 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rw_mutex_shared_lock(&type->Struct.fields_mutex);
|
wait_signal_until_available(&type->Struct.fields_wait_signal);
|
||||||
isize field_count = type->Struct.fields.count;
|
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) {
|
if (field_count != 0) for_array(i, type->Struct.fields) {
|
||||||
Entity *f = type->Struct.fields[i];
|
Entity *f = type->Struct.fields[i];
|
||||||
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
|
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user