align & pad snc structs to cache line
This commit is contained in:
parent
f1f54fe519
commit
915a9272e4
@ -4,8 +4,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "intrinsics.h"
|
#include "intrinsics.h"
|
||||||
|
|
||||||
//#define DEFAULT_MUTEX_SPIN 4000
|
#define DEFAULT_MUTEX_SPIN 4000
|
||||||
#define DEFAULT_MUTEX_SPIN 0
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Mutex
|
* Mutex
|
||||||
|
|||||||
18
src/snc.h
18
src/snc.h
@ -10,7 +10,7 @@ struct snc_lock {
|
|||||||
b32 exclusive;
|
b32 exclusive;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct snc_mutex {
|
struct alignas(64) snc_mutex {
|
||||||
/* Bit 31 = Exclusive lock is held
|
/* Bit 31 = Exclusive lock is held
|
||||||
* Bit 30 = Exclusive lock is pending
|
* Bit 30 = Exclusive lock is pending
|
||||||
* Bit 0-30 = Shared locks count
|
* Bit 0-30 = Shared locks count
|
||||||
@ -19,8 +19,13 @@ struct snc_mutex {
|
|||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
struct atomic_i32 exclusive_fiber_id;
|
struct atomic_i32 exclusive_fiber_id;
|
||||||
|
u8 _pad[56];
|
||||||
|
#else
|
||||||
|
u8 _pad[60];
|
||||||
#endif
|
#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_e(struct snc_mutex *m, i32 spin);
|
||||||
struct snc_lock snc_lock_spin_s(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
|
* Condition variable
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct snc_cv {
|
struct alignas(64) snc_cv {
|
||||||
struct atomic_u64 wake_gen;
|
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(struct snc_cv *cv, struct snc_lock *lock);
|
||||||
void snc_cv_wait_time(struct snc_cv *cv, struct snc_lock *l, i64 timeout_ns);
|
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
|
* Counter
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct snc_counter {
|
struct alignas(64) snc_counter {
|
||||||
struct atomic_i64 v;
|
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_add(struct snc_counter *counter, i64 x);
|
||||||
void snc_counter_wait(struct snc_counter *counter);
|
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(alignof(struct fiber) == 64); /* Avoid false sharing */
|
||||||
STATIC_ASSERT(SYS_MAX_FIBERS < I16_MAX); /* Max fibers should fit in fiber id */
|
STATIC_ASSERT(SYS_MAX_FIBERS < I16_MAX); /* Max fibers should fit in fiber id */
|
||||||
|
|
||||||
|
|
||||||
struct alignas(64) worker_ctx {
|
struct alignas(64) worker_ctx {
|
||||||
i32 id;
|
i32 id;
|
||||||
};
|
};
|
||||||
@ -322,7 +321,7 @@ GLOBAL struct {
|
|||||||
struct job_queue job_queues[NUM_JOB_QUEUE_KINDS];
|
struct job_queue job_queues[NUM_JOB_QUEUE_KINDS];
|
||||||
|
|
||||||
/* Workers */
|
/* 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 atomic_i64 num_jobs_in_queue; /* TODO: Prevent false sharing */
|
||||||
struct snc_mutex workers_wake_mutex;
|
struct snc_mutex workers_wake_mutex;
|
||||||
struct snc_cv workers_wake_cv;
|
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);
|
struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex);
|
||||||
{
|
{
|
||||||
atomic_i64_fetch_add(&G.num_jobs_in_queue, num_waiters);
|
atomic_i64_fetch_add(&G.num_jobs_in_queue, num_waiters);
|
||||||
if (atomic_i64_fetch(&G.workers_wake_gen) >= 0) {
|
snc_cv_broadcast(&G.workers_wake_cv);
|
||||||
atomic_i64_fetch_add(&G.workers_wake_gen, 1);
|
|
||||||
snc_cv_broadcast(&G.workers_wake_cv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
snc_unlock(&lock);
|
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);
|
struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex);
|
||||||
{
|
{
|
||||||
atomic_i64_fetch_add(&G.num_jobs_in_queue, count);
|
atomic_i64_fetch_add(&G.num_jobs_in_queue, count);
|
||||||
if (atomic_i64_fetch(&G.workers_wake_gen) >= 0) {
|
snc_cv_broadcast(&G.workers_wake_cv);
|
||||||
atomic_i64_fetch_add(&G.workers_wake_gen, 1);
|
|
||||||
snc_cv_broadcast(&G.workers_wake_cv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
@ -874,8 +867,8 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct fiber *job_fiber = NULL;
|
struct fiber *job_fiber = NULL;
|
||||||
i64 last_seen_wake_gen = 0;
|
b32 shutdown = false;
|
||||||
while (last_seen_wake_gen >= 0) {
|
while (!shutdown) {
|
||||||
/* Pull job from queue */
|
/* Pull job from queue */
|
||||||
enum sys_priority job_priority = 0;
|
enum sys_priority job_priority = 0;
|
||||||
i16 job_fiber_id = 0;
|
i16 job_fiber_id = 0;
|
||||||
@ -1116,16 +1109,11 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg)
|
|||||||
/* Wait */
|
/* Wait */
|
||||||
struct snc_lock wake_lock = snc_lock_s(&G.workers_wake_mutex);
|
struct snc_lock wake_lock = snc_lock_s(&G.workers_wake_mutex);
|
||||||
{
|
{
|
||||||
if (atomic_i64_fetch(&G.num_jobs_in_queue) <= 0) {
|
shutdown = atomic_i32_fetch(&G.workers_shutdown);
|
||||||
i64 new_wake_gen = atomic_i64_fetch(&G.workers_wake_gen);
|
while (atomic_i64_fetch(&G.num_jobs_in_queue) <= 0 && !shutdown) {
|
||||||
while (new_wake_gen == last_seen_wake_gen) {
|
__profnc("Wait for job", RGB32_F(0.75, 0.75, 0));
|
||||||
__profnc("Wait for job", RGB32_F(0.75, 0.75, 0));
|
snc_cv_wait(&G.workers_wake_cv, &wake_lock);
|
||||||
snc_cv_wait(&G.workers_wake_cv, &wake_lock);
|
shutdown = atomic_i32_fetch(&G.workers_shutdown);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snc_unlock(&wake_lock);
|
snc_unlock(&wake_lock);
|
||||||
@ -1643,7 +1631,7 @@ INTERNAL SYS_THREAD_DEF(job_scheduler_entry, _)
|
|||||||
sys_panic(LIT("Failed to create high resolution timer"));
|
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;
|
i32 periods_index = 0;
|
||||||
i64 periods[NUM_ROLLING_SCHEDULER_PERIODS] = ZI;
|
i64 periods[NUM_ROLLING_SCHEDULER_PERIODS] = ZI;
|
||||||
for (i32 i = 0; i < (i32)countof(periods); ++i) {
|
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;
|
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 cycle");
|
||||||
{
|
{
|
||||||
__profn("Job scheduler wait");
|
__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);
|
struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex);
|
||||||
{
|
{
|
||||||
atomic_i64_fetch_add(&G.num_jobs_in_queue, num_waiters);
|
atomic_i64_fetch_add(&G.num_jobs_in_queue, num_waiters);
|
||||||
if (atomic_i64_fetch(&G.workers_wake_gen) >= 0) {
|
snc_cv_broadcast(&G.workers_wake_cv);
|
||||||
atomic_i64_fetch_add(&G.workers_wake_gen, 1);
|
|
||||||
snc_cv_broadcast(&G.workers_wake_cv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
@ -3886,7 +3871,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
/* Shutdown test thread */
|
/* Shutdown test thread */
|
||||||
{
|
{
|
||||||
struct snc_lock lock = snc_lock_e(&G.workers_wake_mutex);
|
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_cv_broadcast(&G.workers_wake_cv);
|
||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user