align & pad snc structs to cache line

This commit is contained in:
jacob 2025-07-10 11:43:24 -05:00
parent f1f54fe519
commit 915a9272e4
3 changed files with 30 additions and 34 deletions

View File

@ -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

View File

@ -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);

View File

@ -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,11 +592,8 @@ 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_unlock(&lock);
}
@ -762,11 +758,8 @@ 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_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) {
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);
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);
}
}
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,11 +1845,8 @@ 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_unlock(&lock);
}
arena_temp_end(temp);
@ -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);
}