From 915a9272e40942c332923f8fc1efaf701f16d901 Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 10 Jul 2025 11:43:24 -0500 Subject: [PATCH] align & pad snc structs to cache line --- src/snc.c | 3 +-- src/snc.h | 18 +++++++++++++++--- src/sys_win32.c | 43 ++++++++++++++----------------------------- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/snc.c b/src/snc.c index 76c1c7fb..7d4efd8d 100644 --- a/src/snc.c +++ b/src/snc.c @@ -4,8 +4,7 @@ #include "memory.h" #include "intrinsics.h" -//#define DEFAULT_MUTEX_SPIN 4000 -#define DEFAULT_MUTEX_SPIN 0 +#define DEFAULT_MUTEX_SPIN 4000 /* ========================== * * Mutex diff --git a/src/snc.h b/src/snc.h index deb6cbb3..3a673a99 100644 --- a/src/snc.h +++ b/src/snc.h @@ -10,7 +10,7 @@ struct snc_lock { b32 exclusive; }; -struct snc_mutex { +struct alignas(64) snc_mutex { /* Bit 31 = Exclusive lock is held * Bit 30 = Exclusive lock is pending * Bit 0-30 = Shared locks count @@ -19,8 +19,13 @@ struct snc_mutex { #if RTC struct atomic_i32 exclusive_fiber_id; + u8 _pad[56]; +#else + u8 _pad[60]; #endif }; +STATIC_ASSERT(sizeof(struct snc_mutex) == 64); /* Padding validation */ +STATIC_ASSERT(alignof(struct snc_mutex) == 64); /* Prevent false sharing */ struct snc_lock snc_lock_spin_e(struct snc_mutex *m, i32 spin); struct snc_lock snc_lock_spin_s(struct snc_mutex *m, i32 spin); @@ -40,9 +45,12 @@ void snc_unlock(struct snc_lock *lock); * Condition variable * ========================== */ -struct snc_cv { +struct alignas(64) snc_cv { struct atomic_u64 wake_gen; + u8 _pad[56]; }; +STATIC_ASSERT(sizeof(struct snc_cv) == 64); /* Padding validation */ +STATIC_ASSERT(alignof(struct snc_cv) == 64); /* Prevent false sharing */ void snc_cv_wait(struct snc_cv *cv, struct snc_lock *lock); void snc_cv_wait_time(struct snc_cv *cv, struct snc_lock *l, i64 timeout_ns); @@ -56,9 +64,13 @@ void snc_cv_broadcast(struct snc_cv *cv); * Counter * ========================== */ -struct snc_counter { +struct alignas(64) snc_counter { struct atomic_i64 v; + u8 _pad[56]; }; +STATIC_ASSERT(sizeof(struct snc_counter) == 64); /* Padding validation */ +STATIC_ASSERT(alignof(struct snc_counter) == 64); /* Prevent false sharing */ + void snc_counter_add(struct snc_counter *counter, i64 x); void snc_counter_wait(struct snc_counter *counter); diff --git a/src/sys_win32.c b/src/sys_win32.c index d34a67cf..eb37d7fe 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -217,7 +217,6 @@ STATIC_ASSERT(sizeof(struct fiber) == 128); /* Padding validation (increase if STATIC_ASSERT(alignof(struct fiber) == 64); /* Avoid false sharing */ STATIC_ASSERT(SYS_MAX_FIBERS < I16_MAX); /* Max fibers should fit in fiber id */ - struct alignas(64) worker_ctx { i32 id; }; @@ -322,7 +321,7 @@ GLOBAL struct { struct job_queue job_queues[NUM_JOB_QUEUE_KINDS]; /* Workers */ - struct atomic_i64 workers_wake_gen; /* TODO: Prevent false sharing */ + struct atomic_i32 workers_shutdown; struct atomic_i64 num_jobs_in_queue; /* TODO: Prevent false sharing */ struct snc_mutex workers_wake_mutex; struct snc_cv workers_wake_cv; @@ -593,10 +592,7 @@ void sys_wake_all(void *addr) struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex); { atomic_i64_fetch_add(&G.num_jobs_in_queue, num_waiters); - if (atomic_i64_fetch(&G.workers_wake_gen) >= 0) { - atomic_i64_fetch_add(&G.workers_wake_gen, 1); - snc_cv_broadcast(&G.workers_wake_cv); - } + snc_cv_broadcast(&G.workers_wake_cv); } snc_unlock(&lock); } @@ -762,10 +758,7 @@ void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_priority priorit struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex); { atomic_i64_fetch_add(&G.num_jobs_in_queue, count); - if (atomic_i64_fetch(&G.workers_wake_gen) >= 0) { - atomic_i64_fetch_add(&G.workers_wake_gen, 1); - snc_cv_broadcast(&G.workers_wake_cv); - } + snc_cv_broadcast(&G.workers_wake_cv); } snc_unlock(&lock); } @@ -874,8 +867,8 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg) } struct fiber *job_fiber = NULL; - i64 last_seen_wake_gen = 0; - while (last_seen_wake_gen >= 0) { + b32 shutdown = false; + while (!shutdown) { /* Pull job from queue */ enum sys_priority job_priority = 0; i16 job_fiber_id = 0; @@ -1116,16 +1109,11 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg) /* Wait */ struct snc_lock wake_lock = snc_lock_s(&G.workers_wake_mutex); { - if (atomic_i64_fetch(&G.num_jobs_in_queue) <= 0) { - i64 new_wake_gen = atomic_i64_fetch(&G.workers_wake_gen); - while (new_wake_gen == last_seen_wake_gen) { - __profnc("Wait for job", RGB32_F(0.75, 0.75, 0)); - snc_cv_wait(&G.workers_wake_cv, &wake_lock); - new_wake_gen = atomic_i64_fetch(&G.workers_wake_gen); - } - last_seen_wake_gen = new_wake_gen; - } else { - last_seen_wake_gen = atomic_i64_fetch(&G.workers_wake_gen); + shutdown = atomic_i32_fetch(&G.workers_shutdown); + while (atomic_i64_fetch(&G.num_jobs_in_queue) <= 0 && !shutdown) { + __profnc("Wait for job", RGB32_F(0.75, 0.75, 0)); + snc_cv_wait(&G.workers_wake_cv, &wake_lock); + shutdown = atomic_i32_fetch(&G.workers_shutdown); } } snc_unlock(&wake_lock); @@ -1643,7 +1631,7 @@ INTERNAL SYS_THREAD_DEF(job_scheduler_entry, _) sys_panic(LIT("Failed to create high resolution timer")); } - /* Create ring buffer of scheduler cycles initialized to default value */ + /* Create rolling buffer of scheduler cycles initialized to default value */ i32 periods_index = 0; i64 periods[NUM_ROLLING_SCHEDULER_PERIODS] = ZI; for (i32 i = 0; i < (i32)countof(periods); ++i) { @@ -1651,7 +1639,7 @@ INTERNAL SYS_THREAD_DEF(job_scheduler_entry, _) } i64 last_cycle_ns = 0; - while (atomic_i64_fetch(&G.workers_wake_gen) >= 0) { + while (!atomic_i32_fetch(&G.workers_shutdown)) { __profn("Job scheduler cycle"); { __profn("Job scheduler wait"); @@ -1857,10 +1845,7 @@ INTERNAL SYS_THREAD_DEF(job_scheduler_entry, _) struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex); { atomic_i64_fetch_add(&G.num_jobs_in_queue, num_waiters); - if (atomic_i64_fetch(&G.workers_wake_gen) >= 0) { - atomic_i64_fetch_add(&G.workers_wake_gen, 1); - snc_cv_broadcast(&G.workers_wake_cv); - } + snc_cv_broadcast(&G.workers_wake_cv); } snc_unlock(&lock); } @@ -3886,7 +3871,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, /* Shutdown test thread */ { struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex); - atomic_i64_fetch_set(&G.workers_wake_gen, -1); + atomic_i32_fetch_set(&G.workers_shutdown, 1); snc_cv_broadcast(&G.workers_wake_cv); snc_unlock(&lock); }