align & pad snc structs to cache line
This commit is contained in:
parent
f1f54fe519
commit
915a9272e4
@ -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
|
||||
|
||||
18
src/snc.h
18
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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user