Minimize more thread contention

This commit is contained in:
gingerBill
2025-09-10 19:30:32 +01:00
parent 21b1173076
commit a36a8722dc
10 changed files with 74 additions and 58 deletions
+1 -1
View File
@@ -1163,7 +1163,7 @@ gb_internal String internal_odin_root_dir(void) {
return global_module_path; return global_module_path;
} }
auto path_buf = array_make<char>(heap_allocator(), 300); auto path_buf = array_make<char>(temporary_allocator(), 300);
defer (array_free(&path_buf)); defer (array_free(&path_buf));
len = 0; len = 0;
+2 -2
View File
@@ -1981,9 +1981,9 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de
ast_node(bs, BlockStmt, body); ast_node(bs, BlockStmt, body);
TEMPORARY_ALLOCATOR_GUARD();
Array<ProcUsingVar> using_entities = {}; Array<ProcUsingVar> using_entities = {};
using_entities.allocator = heap_allocator(); using_entities.allocator = temporary_allocator();
defer (array_free(&using_entities));
{ {
if (type->Proc.param_count > 0) { if (type->Proc.param_count > 0) {
+7 -9
View File
@@ -7516,11 +7516,10 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
return check_call_arguments_proc_group(c, operand, call); return check_call_arguments_proc_group(c, operand, call);
} }
auto positional_operands = array_make<Operand>(heap_allocator(), 0, positional_args.count); TEMPORARY_ALLOCATOR_GUARD();
auto named_operands = array_make<Operand>(heap_allocator(), 0, 0);
defer (array_free(&positional_operands)); auto positional_operands = array_make<Operand>(temporary_allocator(), 0, positional_args.count);
defer (array_free(&named_operands)); auto named_operands = array_make<Operand>(temporary_allocator(), 0, 0);
if (positional_args.count > 0) { if (positional_args.count > 0) {
Entity **lhs = nullptr; Entity **lhs = nullptr;
@@ -7623,11 +7622,10 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O
{ {
// NOTE(bill, 2019-10-26): Allow a cycle in the parameters but not in the fields themselves // NOTE(bill, 2019-10-26): Allow a cycle in the parameters but not in the fields themselves
auto prev_type_path = c->type_path; auto prev_type_path = c->type_path;
c->type_path = new_checker_type_path(); TEMPORARY_ALLOCATOR_GUARD();
defer ({
destroy_checker_type_path(c->type_path); c->type_path = new_checker_type_path(temporary_allocator());
c->type_path = prev_type_path; defer (c->type_path = prev_type_path);
});
if (is_call_expr_field_value(ce)) { if (is_call_expr_field_value(ce)) {
named_fields = true; named_fields = true;
+3 -2
View File
@@ -2567,8 +2567,9 @@ gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) {
result_count = proc_type->Proc.results->Tuple.variables.count; result_count = proc_type->Proc.results->Tuple.variables.count;
} }
auto operands = array_make<Operand>(heap_allocator(), 0, 2*rs->results.count); TEMPORARY_ALLOCATOR_GUARD();
defer (array_free(&operands));
auto operands = array_make<Operand>(temporary_allocator(), 0, 2*rs->results.count);
check_unpack_arguments(ctx, result_entities, result_count, &operands, rs->results, UnpackFlag_AllowOk); check_unpack_arguments(ctx, result_entities, result_count, &operands, rs->results, UnpackFlag_AllowOk);
+5 -4
View File
@@ -3512,8 +3512,9 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
case_ast_node(pt, PointerType, e); case_ast_node(pt, PointerType, e);
CheckerContext c = *ctx; CheckerContext c = *ctx;
c.type_path = new_checker_type_path();
defer (destroy_checker_type_path(c.type_path)); TEMPORARY_ALLOCATOR_GUARD();
c.type_path = new_checker_type_path(temporary_allocator());
Type *elem = t_invalid; Type *elem = t_invalid;
Operand o = {}; Operand o = {};
@@ -3747,8 +3748,8 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
gb_internal Type *check_type(CheckerContext *ctx, Ast *e) { gb_internal Type *check_type(CheckerContext *ctx, Ast *e) {
CheckerContext c = *ctx; CheckerContext c = *ctx;
c.type_path = new_checker_type_path(); TEMPORARY_ALLOCATOR_GUARD();
defer (destroy_checker_type_path(c.type_path)); c.type_path = new_checker_type_path(temporary_allocator());
return check_type_expr(&c, e, nullptr); return check_type_expr(&c, e, nullptr);
} }
+31 -27
View File
@@ -1441,7 +1441,8 @@ gb_internal void init_checker_info(CheckerInfo *i) {
map_init(&i->objc_method_implementations); map_init(&i->objc_method_implementations);
string_map_init(&i->load_file_cache); string_map_init(&i->load_file_cache);
array_init(&i->all_procedures, heap_allocator()); array_init(&i->all_procedures, a);
mpsc_init(&i->all_procedures_queue, a);
mpsc_init(&i->entity_queue, a); // 1<<20); mpsc_init(&i->entity_queue, a); // 1<<20);
mpsc_init(&i->definition_queue, a); //); // 1<<20); mpsc_init(&i->definition_queue, a); //); // 1<<20);
@@ -1475,6 +1476,10 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
array_free(&i->required_foreign_imports_through_force); array_free(&i->required_foreign_imports_through_force);
array_free(&i->defineables); array_free(&i->defineables);
array_free(&i->all_procedures);
mpsc_destroy(&i->all_procedures_queue);
mpsc_destroy(&i->entity_queue); mpsc_destroy(&i->entity_queue);
mpsc_destroy(&i->definition_queue); mpsc_destroy(&i->definition_queue);
mpsc_destroy(&i->required_global_variable_queue); mpsc_destroy(&i->required_global_variable_queue);
@@ -1502,12 +1507,12 @@ gb_internal CheckerContext make_checker_context(Checker *c) {
ctx.scope = builtin_pkg->scope; ctx.scope = builtin_pkg->scope;
ctx.pkg = builtin_pkg; ctx.pkg = builtin_pkg;
ctx.type_path = new_checker_type_path(); ctx.type_path = new_checker_type_path(heap_allocator());
ctx.type_level = 0; ctx.type_level = 0;
return ctx; return ctx;
} }
gb_internal void destroy_checker_context(CheckerContext *ctx) { gb_internal void destroy_checker_context(CheckerContext *ctx) {
destroy_checker_type_path(ctx->type_path); destroy_checker_type_path(ctx->type_path, heap_allocator());
} }
gb_internal bool add_curr_ast_file(CheckerContext *ctx, AstFile *file) { gb_internal bool add_curr_ast_file(CheckerContext *ctx, AstFile *file) {
@@ -1758,7 +1763,7 @@ gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode,
check_set_expr_info(c, expr, mode, type, value); check_set_expr_info(c, expr, mode, type, value);
} }
gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value) { gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value, bool use_mutex) {
if (expr == nullptr) { if (expr == nullptr) {
return; return;
} }
@@ -1776,7 +1781,7 @@ gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMo
mutex = &ctx->pkg->type_and_value_mutex; mutex = &ctx->pkg->type_and_value_mutex;
} }
mutex_lock(mutex); if (use_mutex) mutex_lock(mutex);
Ast *prev_expr = nullptr; Ast *prev_expr = nullptr;
while (prev_expr != expr) { while (prev_expr != expr) {
prev_expr = expr; prev_expr = expr;
@@ -1801,7 +1806,7 @@ gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMo
break; break;
}; };
} }
mutex_unlock(mutex); if (use_mutex) mutex_unlock(mutex);
} }
gb_internal void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) { gb_internal void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) {
@@ -2345,11 +2350,9 @@ gb_internal void check_procedure_later(Checker *c, ProcInfo *info) {
} }
if (DEBUG_CHECK_ALL_PROCEDURES) { if (DEBUG_CHECK_ALL_PROCEDURES) {
MUTEX_GUARD_BLOCK(&c->info.all_procedures_mutex) { GB_ASSERT(info != nullptr);
GB_ASSERT(info != nullptr); GB_ASSERT(info->decl != nullptr);
GB_ASSERT(info->decl != nullptr); mpsc_enqueue(&c->info.all_procedures_queue, info);
array_add(&c->info.all_procedures, info);
}
} }
} }
@@ -3195,19 +3198,17 @@ gb_internal Type *find_type_in_pkg(CheckerInfo *info, String const &pkg, String
return e->type; return e->type;
} }
gb_internal CheckerTypePath *new_checker_type_path() { gb_internal CheckerTypePath *new_checker_type_path(gbAllocator allocator) {
gbAllocator a = heap_allocator(); auto *tp = gb_alloc_item(allocator, CheckerTypePath);
auto *tp = gb_alloc_item(a, CheckerTypePath); array_init(tp, allocator, 0, 16);
array_init(tp, a, 0, 16);
return tp; return tp;
} }
gb_internal void destroy_checker_type_path(CheckerTypePath *tp) { gb_internal void destroy_checker_type_path(CheckerTypePath *tp, gbAllocator allocator) {
array_free(tp); array_free(tp);
gb_free(heap_allocator(), tp); gb_free(allocator, tp);
} }
gb_internal void check_type_path_push(CheckerContext *c, Entity *e) { gb_internal void check_type_path_push(CheckerContext *c, Entity *e) {
GB_ASSERT(c->type_path != nullptr); GB_ASSERT(c->type_path != nullptr);
GB_ASSERT(e != nullptr); GB_ASSERT(e != nullptr);
@@ -5283,9 +5284,10 @@ gb_internal void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
GB_ASSERT(scope->flags&ScopeFlag_Pkg); GB_ASSERT(scope->flags&ScopeFlag_Pkg);
if (ptr_set_update(&parent_scope->imported, scope)) { ptr_set_add(&parent_scope->imported, scope);
// error(token, "Multiple import of the same file within this scope"); // if (ptr_set_update(&parent_scope->imported, scope)) {
} // // error(token, "Multiple import of the same file within this scope");
// }
String import_name = path_to_entity_name(id->import_name.string, id->fullpath, false); String import_name = path_to_entity_name(id->import_name.string, id->fullpath, false);
if (is_blank_ident(import_name)) { if (is_blank_ident(import_name)) {
@@ -6041,10 +6043,10 @@ gb_internal void calculate_global_init_order(Checker *c) {
CheckerInfo *info = &c->info; CheckerInfo *info = &c->info;
TIME_SECTION("calculate_global_init_order: generate entity dependency graph"); TIME_SECTION("calculate_global_init_order: generate entity dependency graph");
Arena *arena = get_arena(ThreadArena_Temporary); Arena *temporary_arena = get_arena(ThreadArena_Temporary);
ArenaTempGuard arena_guard(arena); ArenaTempGuard temporary_arena_guard(temporary_arena);
Array<EntityGraphNode *> dep_graph = generate_entity_dependency_graph(info, arena); Array<EntityGraphNode *> dep_graph = generate_entity_dependency_graph(info, temporary_arena);
TIME_SECTION("calculate_global_init_order: priority queue create"); TIME_SECTION("calculate_global_init_order: priority queue create");
// NOTE(bill): Priority queue // NOTE(bill): Priority queue
@@ -6321,8 +6323,9 @@ gb_internal void check_safety_all_procedures_for_unchecked(Checker *c) {
defer (map_destroy(&untyped)); defer (map_destroy(&untyped));
for_array(i, c->info.all_procedures) { array_reserve(&c->info.all_procedures, c->info.all_procedures_queue.count.load());
ProcInfo *pi = c->info.all_procedures[i];
for (ProcInfo *pi = nullptr; mpsc_dequeue(&c->info.all_procedures_queue, &pi); /**/) {
GB_ASSERT(pi != nullptr); GB_ASSERT(pi != nullptr);
GB_ASSERT(pi->decl != nullptr); GB_ASSERT(pi->decl != nullptr);
Entity *e = pi->decl->entity; Entity *e = pi->decl->entity;
@@ -6337,6 +6340,8 @@ gb_internal void check_safety_all_procedures_for_unchecked(Checker *c) {
consume_proc_info(c, pi, &untyped); consume_proc_info(c, pi, &untyped);
} }
} }
array_add(&c->info.all_procedures, pi);
} }
} }
@@ -7412,7 +7417,6 @@ gb_internal void check_parsed_files(Checker *c) {
TIME_SECTION("add untyped expression values"); TIME_SECTION("add untyped expression values");
// Add untyped expression values
for (UntypedExprInfo u = {}; mpsc_dequeue(&c->global_untyped_queue, &u); /**/) { for (UntypedExprInfo u = {}; mpsc_dequeue(&c->global_untyped_queue, &u); /**/) {
GB_ASSERT(u.expr != nullptr && u.info != nullptr); GB_ASSERT(u.expr != nullptr && u.info != nullptr);
if (is_type_typed(u.info->type)) { if (is_type_typed(u.info->type)) {
+8 -7
View File
@@ -309,11 +309,12 @@ struct EntityGraphNode;
typedef PtrSet<EntityGraphNode *> EntityGraphNodeSet; typedef PtrSet<EntityGraphNode *> EntityGraphNodeSet;
struct EntityGraphNode { struct EntityGraphNode {
Entity * entity; // Procedure, Variable, Constant Entity *entity; // Procedure, Variable, Constant
EntityGraphNodeSet pred; EntityGraphNodeSet pred;
EntityGraphNodeSet succ; EntityGraphNodeSet succ;
isize index; // Index in array/queue isize index; // Index in array/queue
isize dep_count; isize dep_count;
}; };
@@ -516,7 +517,7 @@ struct CheckerInfo {
BlockingMutex load_file_mutex; BlockingMutex load_file_mutex;
StringMap<LoadFileCache *> load_file_cache; StringMap<LoadFileCache *> load_file_cache;
BlockingMutex all_procedures_mutex; MPSCQueue<ProcInfo *> all_procedures_queue;
Array<ProcInfo *> all_procedures; Array<ProcInfo *> all_procedures;
BlockingMutex instrumentation_mutex; BlockingMutex instrumentation_mutex;
@@ -629,7 +630,7 @@ gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **s
gb_internal Entity *scope_insert (Scope *s, Entity *entity); gb_internal Entity *scope_insert (Scope *s, Entity *entity);
gb_internal void add_type_and_value (CheckerContext *c, Ast *expression, AddressingMode mode, Type *type, ExactValue const &value); gb_internal void add_type_and_value (CheckerContext *c, Ast *expression, AddressingMode mode, Type *type, ExactValue const &value, bool use_mutex=true);
gb_internal ExprInfo *check_get_expr_info (CheckerContext *c, Ast *expr); gb_internal ExprInfo *check_get_expr_info (CheckerContext *c, Ast *expr);
gb_internal void add_untyped (CheckerContext *c, Ast *expression, AddressingMode mode, Type *basic_type, ExactValue const &value); gb_internal void add_untyped (CheckerContext *c, Ast *expression, AddressingMode mode, Type *basic_type, ExactValue const &value);
gb_internal void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity); gb_internal void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity);
@@ -650,8 +651,8 @@ gb_internal void check_collect_entities(CheckerContext *c, Slice<Ast *> const &n
gb_internal void check_collect_entities_from_when_stmt(CheckerContext *c, AstWhenStmt *ws); gb_internal void check_collect_entities_from_when_stmt(CheckerContext *c, AstWhenStmt *ws);
gb_internal void check_delayed_file_import_entity(CheckerContext *c, Ast *decl); gb_internal void check_delayed_file_import_entity(CheckerContext *c, Ast *decl);
gb_internal CheckerTypePath *new_checker_type_path(); gb_internal CheckerTypePath *new_checker_type_path(gbAllocator allocator);
gb_internal void destroy_checker_type_path(CheckerTypePath *tp); gb_internal void destroy_checker_type_path(CheckerTypePath *tp, gbAllocator allocator);
gb_internal void check_type_path_push(CheckerContext *c, Entity *e); gb_internal void check_type_path_push(CheckerContext *c, Entity *e);
gb_internal Entity *check_type_path_pop (CheckerContext *c); gb_internal Entity *check_type_path_pop (CheckerContext *c);
+1 -1
View File
@@ -348,7 +348,7 @@ gb_internal Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Typ
entity->type = type; entity->type = type;
entity->id = 1 + global_entity_id.fetch_add(1); entity->id = 1 + global_entity_id.fetch_add(1);
if (token.pos.file_id) { if (token.pos.file_id) {
entity->file = thread_safe_get_ast_file_from_id(token.pos.file_id); entity->file = thread_unsafe_get_ast_file_from_id(token.pos.file_id);
} }
return entity; return entity;
} }
+11
View File
@@ -153,6 +153,17 @@ gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) {
} }
// use AFTER PARSER
gb_internal AstFile *thread_unsafe_get_ast_file_from_id(i32 index) {
GB_ASSERT(index >= 0);
AstFile *file = nullptr;
if (index < global_files.count) {
file = global_files[index];
}
return file;
}
// NOTE: defined in build_settings.cpp // NOTE: defined in build_settings.cpp
gb_internal bool global_warnings_as_errors(void); gb_internal bool global_warnings_as_errors(void);
+5 -5
View File
@@ -448,9 +448,9 @@ gb_internal void semaphore_wait(Semaphore *s) {
} }
#endif #endif
static const int RWLOCK_WRITER = 1; static const int RWLOCK_WRITER = 1<<0;
static const int RWLOCK_UPGRADED = 2; static const int RWLOCK_UPGRADED = 1<<1;
static const int RWLOCK_READER = 4; static const int RWLOCK_READER = 1<<2;
struct RWSpinLock { struct RWSpinLock {
Futex bits; Futex bits;
}; };
@@ -467,7 +467,7 @@ bool rwlock_try_acquire_upgrade(RWSpinLock *l) {
void rwlock_acquire_upgrade(RWSpinLock *l) { void rwlock_acquire_upgrade(RWSpinLock *l) {
while (!rwlock_try_acquire_upgrade(l)) { while (!rwlock_try_acquire_upgrade(l)) {
futex_wait(&l->bits, RWLOCK_UPGRADED); futex_wait(&l->bits, RWLOCK_UPGRADED | RWLOCK_WRITER);
} }
} }
void rwlock_release_upgrade(RWSpinLock *l) { void rwlock_release_upgrade(RWSpinLock *l) {
@@ -481,7 +481,7 @@ bool rwlock_try_release_upgrade_and_acquire_write(RWSpinLock *l) {
void rwlock_release_upgrade_and_acquire_write(RWSpinLock *l) { void rwlock_release_upgrade_and_acquire_write(RWSpinLock *l) {
while (!rwlock_try_release_upgrade_and_acquire_write(l)) { while (!rwlock_try_release_upgrade_and_acquire_write(l)) {
futex_wait(&l->bits, RWLOCK_WRITER); futex_wait(&l->bits, RWLOCK_UPGRADED);
} }
} }