allocate counters in sys layer
This commit is contained in:
parent
ca5c1d6ee3
commit
5e99224b28
@ -191,7 +191,9 @@ void asset_cache_wait(struct asset *asset)
|
||||
{
|
||||
if (asset->status != ASSET_STATUS_READY) {
|
||||
/* Wait on job */
|
||||
sys_wait(&asset->counter);
|
||||
if (asset->counter) {
|
||||
sys_wait(asset->counter);
|
||||
}
|
||||
/* Wait for asset to be ready */
|
||||
sync_flag_wait(&asset->asset_ready_sf);
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ struct asset {
|
||||
u64 hash;
|
||||
struct string key;
|
||||
|
||||
struct sys_counter counter;
|
||||
struct sys_counter *counter;
|
||||
|
||||
/* Managed via asset_cache_mark_x functions */
|
||||
enum asset_status status;
|
||||
|
||||
@ -188,7 +188,10 @@ struct asset *font_load_asset(struct string path, f32 point_size, b32 wait)
|
||||
|
||||
/* Push task */
|
||||
asset_cache_mark_loading(asset);
|
||||
sys_run(1, font_load_asset_job, params, SYS_PRIORITY_BACKGROUND, &asset->counter);
|
||||
if (wait) {
|
||||
asset->counter = sys_counter_alloc();
|
||||
}
|
||||
sys_run(1, font_load_asset_job, params, SYS_PRIORITY_BACKGROUND, asset->counter);
|
||||
if (wait) {
|
||||
asset_cache_wait(asset);
|
||||
}
|
||||
|
||||
@ -927,9 +927,12 @@ INTERNAL SYS_JOB_DEF(pipeline_init_job, job)
|
||||
if (success) {
|
||||
struct shader_compile_job_param *params[] = { &vs, &ps };
|
||||
struct shader_compile_job_sig comp_sig = { .params = params };
|
||||
struct sys_counter counter = ZI;
|
||||
sys_run(countof(params), shader_compile_job, &comp_sig, SYS_PRIORITY_HIGH, &counter);
|
||||
sys_wait(&counter);
|
||||
struct sys_counter *counter = sys_counter_alloc();
|
||||
{
|
||||
sys_run(countof(params), shader_compile_job, &comp_sig, SYS_PRIORITY_HIGH, counter);
|
||||
sys_wait(counter);
|
||||
}
|
||||
sys_counter_release(counter);
|
||||
success = vs.success && ps.success;
|
||||
}
|
||||
|
||||
@ -1120,10 +1123,13 @@ INTERNAL SYS_JOB_DEF(pipeline_init_job, job)
|
||||
INTERNAL void pipeline_alloc(u64 num_pipelines, struct pipeline_desc *descs_in, struct pipeline **pipelines_out)
|
||||
{
|
||||
__prof;
|
||||
struct sys_counter counter = ZI;
|
||||
struct pipeline_init_job_sig sig = { .descs_in = descs_in, .pipelines_out = pipelines_out };
|
||||
sys_run(num_pipelines, pipeline_init_job, &sig, SYS_PRIORITY_HIGH, &counter);
|
||||
sys_wait(&counter);
|
||||
struct sys_counter *counter = sys_counter_alloc();
|
||||
{
|
||||
sys_run(num_pipelines, pipeline_init_job, &sig, SYS_PRIORITY_HIGH, counter);
|
||||
sys_wait(counter);
|
||||
}
|
||||
sys_counter_release(counter);
|
||||
}
|
||||
|
||||
INTERNAL void pipeline_release_now(struct pipeline *pipeline)
|
||||
|
||||
@ -288,9 +288,12 @@ INTERNAL SYS_THREAD_DEF(resource_watch_dispatcher_thread_entry_point, _)
|
||||
struct resource_watch_callback_job_sig sig = ZI;
|
||||
sig.name = info->name;
|
||||
sig.callbacks = callbacks;
|
||||
struct sys_counter counter = ZI;
|
||||
sys_run(num_callbacks, resource_watch_callback_job, &sig, SYS_PRIORITY_BACKGROUND, &counter);
|
||||
sys_wait(&counter);
|
||||
struct sys_counter *counter = sys_counter_alloc();
|
||||
{
|
||||
sys_run(num_callbacks, resource_watch_callback_job, &sig, SYS_PRIORITY_BACKGROUND, counter);
|
||||
sys_wait(counter);
|
||||
}
|
||||
sys_counter_release(counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +181,10 @@ struct asset *sound_load_asset(struct string path, u32 flags, b32 wait)
|
||||
|
||||
/* Push task */
|
||||
asset_cache_mark_loading(asset);
|
||||
sys_run(1, sound_load_asset_job, params, SYS_PRIORITY_BACKGROUND, &asset->counter);
|
||||
if (wait) {
|
||||
asset->counter = sys_counter_alloc();
|
||||
}
|
||||
sys_run(1, sound_load_asset_job, params, SYS_PRIORITY_BACKGROUND, asset->counter);
|
||||
if (wait) {
|
||||
asset_cache_wait(asset);
|
||||
}
|
||||
|
||||
@ -1377,12 +1377,11 @@ INTERNAL SYS_JOB_DEF(sprite_evictor_job, _)
|
||||
INTERNAL SYS_THREAD_DEF(sprite_evictor_scheduler_thread_entry_point, arg)
|
||||
{
|
||||
(UNUSED)arg;
|
||||
|
||||
struct sys_counter *job_counter = sys_counter_alloc();
|
||||
struct sys_lock evictor_lock = sys_mutex_lock_e(G.evictor_scheduler_mutex);
|
||||
while (!G.evictor_scheduler_shutdown) {
|
||||
struct sys_counter counter = ZI;
|
||||
sys_run(1, sprite_evictor_job, NULL, SYS_PRIORITY_BACKGROUND, &counter);
|
||||
sys_wait(&counter);
|
||||
sys_run(1, sprite_evictor_job, NULL, SYS_PRIORITY_BACKGROUND, job_counter);
|
||||
sys_wait(job_counter);
|
||||
sys_condition_variable_wait_time(G.evictor_scheduler_shutdown_cv, &evictor_lock, SECONDS_FROM_NS(EVICTOR_CYCLE_INTERVAL_NS));
|
||||
}
|
||||
sys_mutex_unlock(&evictor_lock);
|
||||
|
||||
@ -482,13 +482,12 @@ b32 sys_run_command(struct string cmd);
|
||||
* Counter
|
||||
* ========================== */
|
||||
|
||||
struct sys_counter {
|
||||
struct atomic_i64 v;
|
||||
};
|
||||
struct sys_counter *sys_counter_alloc(void);
|
||||
void sys_counter_release(struct sys_counter *counter);
|
||||
|
||||
void sys_counter_add(struct sys_counter *sys_counter, i64 amount);
|
||||
void sys_counter_add(struct sys_counter *counter, i64 amount);
|
||||
|
||||
void sys_wait(struct sys_counter *sys_counter);
|
||||
void sys_wait(struct sys_counter *counter);
|
||||
|
||||
/* ========================== *
|
||||
* Fiber
|
||||
|
||||
@ -118,12 +118,14 @@ struct win32_window {
|
||||
|
||||
|
||||
|
||||
#define MAX_COUNTERS 4096
|
||||
|
||||
struct alignas(64) counter {
|
||||
/* =================================================== */
|
||||
i32 id; /* 4 bytes */
|
||||
struct atomic_i32 value; /* 4 bytes */
|
||||
struct atomic_i64 v; /* 8 bytes */
|
||||
/* =================================================== */
|
||||
struct counter *next_free; /* 8 bytes */
|
||||
/* =================================================== */
|
||||
u8 _pad0[8]; /* 8 bytes (padding) */
|
||||
/* =================================================== */
|
||||
u8 _pad1[8]; /* 8 bytes (padding) */
|
||||
/* =================================================== */
|
||||
@ -134,10 +136,6 @@ struct alignas(64) counter {
|
||||
u8 _pad4[8]; /* 8 bytes (padding) */
|
||||
/* =================================================== */
|
||||
u8 _pad5[8]; /* 8 bytes (padding) */
|
||||
/* =================================================== */
|
||||
u8 _pad6[8]; /* 8 bytes (padding) */
|
||||
/* =================================================== */
|
||||
u8 _pad7[8]; /* 8 bytes (padding) */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct counter) == 64); /* Assume counter fits in one cache line (increase if necessary) */
|
||||
STATIC_ASSERT(alignof(struct counter) == 64); /* Avoid false sharing */
|
||||
@ -217,7 +215,7 @@ struct job_info {
|
||||
i32 count;
|
||||
sys_job_func *func;
|
||||
void *sig;
|
||||
struct sys_counter *counter;
|
||||
struct counter *counter;
|
||||
|
||||
struct job_info *next;
|
||||
};
|
||||
@ -301,10 +299,9 @@ GLOBAL struct {
|
||||
|
||||
|
||||
/* Counters */
|
||||
i32 num_counters;
|
||||
struct arena *counters_arena;
|
||||
struct atomic_i32 counters_lock; /* TODO: Prevent false sharing */
|
||||
i32 first_free_counter_id;
|
||||
struct counter counters[MAX_COUNTERS];
|
||||
struct counter *first_free_counter;
|
||||
|
||||
/* Fibers */
|
||||
i32 num_fibers;
|
||||
@ -333,7 +330,36 @@ GLOBAL struct {
|
||||
* Counters
|
||||
* ========================== */
|
||||
|
||||
void sys_counter_add(struct sys_counter *counter, i64 amount)
|
||||
INTERNAL struct counter *counter_alloc(void)
|
||||
{
|
||||
struct counter *counter = NULL;
|
||||
{
|
||||
while (atomic_i32_fetch_test_set(&G.counters_lock, 0, 1) != 0) ix_pause();
|
||||
{
|
||||
if (G.first_free_counter) {
|
||||
counter = G.first_free_counter;
|
||||
G.first_free_counter = counter->next_free;
|
||||
} else {
|
||||
counter = arena_push_no_zero(G.counters_arena, struct counter);
|
||||
}
|
||||
}
|
||||
atomic_i32_fetch_set(&G.counters_lock, 0);
|
||||
}
|
||||
MEMZERO_STRUCT(counter);
|
||||
return counter;
|
||||
}
|
||||
|
||||
INTERNAL void counter_release(struct counter *counter)
|
||||
{
|
||||
while (atomic_i32_fetch_test_set(&G.counters_lock, 0, 1) != 0) ix_pause();
|
||||
{
|
||||
counter->next_free = G.first_free_counter;
|
||||
G.first_free_counter = counter;
|
||||
}
|
||||
atomic_i32_fetch_set(&G.counters_lock, 0);
|
||||
}
|
||||
|
||||
INTERNAL void counter_add(struct counter *counter, i64 amount)
|
||||
{
|
||||
i64 old_v = atomic_i64_fetch_add(&counter->v, amount);
|
||||
i64 new_v = old_v + amount;
|
||||
@ -344,21 +370,27 @@ void sys_counter_add(struct sys_counter *counter, i64 amount)
|
||||
}
|
||||
}
|
||||
|
||||
void sys_wait(struct sys_counter *sys_counter)
|
||||
INTERNAL void counter_wait(struct counter *counter)
|
||||
{
|
||||
__prof;
|
||||
while (atomic_i64_fetch(&sys_counter->v) > 0) {
|
||||
/* TODO: Yield with configurable spin count */
|
||||
while (atomic_i64_fetch(&counter->v) > 0) {
|
||||
ix_pause();
|
||||
}
|
||||
}
|
||||
|
||||
struct sys_counter *sys_counter_alloc(void) { return (struct sys_counter *)counter_alloc(); }
|
||||
void sys_counter_release(struct sys_counter *counter) { counter_release((struct counter *)counter); }
|
||||
void sys_counter_add(struct sys_counter *counter, i64 amount) { counter_add((struct counter *)counter, amount); }
|
||||
void sys_wait(struct sys_counter *counter) { counter_wait((struct counter *)counter); }
|
||||
|
||||
/* ========================== *
|
||||
* Fibers
|
||||
* ========================== */
|
||||
|
||||
enum fiber_kind {
|
||||
FIBER_KIND_CONVERTED_THREAD,
|
||||
FIBER_KIND_JOB_RUNNER
|
||||
FIBER_KIND_JOB_WORKER
|
||||
};
|
||||
|
||||
INTERNAL void job_fiber_entry(void *id_ptr);
|
||||
@ -372,7 +404,7 @@ INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
||||
while (atomic_i32_fetch_test_set(&G.fibers_lock, 0, 1) != 0) ix_pause();
|
||||
{
|
||||
fiber_id = G.first_free_fiber_id;
|
||||
if (fiber_id && kind == FIBER_KIND_JOB_RUNNER) {
|
||||
if (fiber_id && kind == FIBER_KIND_JOB_WORKER) {
|
||||
fiber = &G.fibers[fiber_id];
|
||||
G.first_free_fiber_id = fiber->parent_id;
|
||||
} else {
|
||||
@ -419,7 +451,7 @@ INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
||||
fiber->name_cstr = new_name_cstr;
|
||||
|
||||
/* Init win32 fiber */
|
||||
if (kind == FIBER_KIND_JOB_RUNNER) {
|
||||
if (kind == FIBER_KIND_JOB_WORKER) {
|
||||
fiber->addr = CreateFiber(FIBER_STACK_SIZE, job_fiber_entry, (void *)(i64)fiber_id);
|
||||
} else {
|
||||
fiber->addr = ConvertThreadToFiber((void *)(i64)fiber_id);
|
||||
@ -488,9 +520,10 @@ void sys_yield(void)
|
||||
|
||||
void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_priority priority, struct sys_counter *counter)
|
||||
{
|
||||
struct counter *job_counter = (struct counter *)counter;
|
||||
if (count > 0) {
|
||||
if (counter) {
|
||||
sys_counter_add(counter, count);
|
||||
if (job_counter) {
|
||||
counter_add(job_counter, count);
|
||||
}
|
||||
struct fiber *fiber = fiber_from_id(sys_current_fiber_id());
|
||||
priority = clamp_i32(priority, fiber->job_priority, SYS_PRIORITY_BACKGROUND); /* A job cannot create a job with a higher priority than itself */
|
||||
@ -510,7 +543,7 @@ void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_priority priorit
|
||||
info->count = count;
|
||||
info->func = func;
|
||||
info->sig = sig;
|
||||
info->counter = counter;
|
||||
info->counter = job_counter;
|
||||
if (queue->last) {
|
||||
queue->last->next = info;
|
||||
} else {
|
||||
@ -574,7 +607,7 @@ INTERNAL SYS_THREAD_DEF(worker_entry, worker_ctx_arg)
|
||||
i32 job_id = 0;
|
||||
sys_job_func *job_func = 0;
|
||||
void *job_sig = 0;
|
||||
struct sys_counter *job_counter = 0;
|
||||
struct counter *job_counter = 0;
|
||||
{
|
||||
//__profscope(Pull job);
|
||||
for (u32 queue_index = 0; queue_index < countof(queues) && !job_func; ++queue_index) {
|
||||
@ -613,7 +646,7 @@ INTERNAL SYS_THREAD_DEF(worker_entry, worker_ctx_arg)
|
||||
if (job_func) {
|
||||
__profscope(Run fiber);
|
||||
if (!job_fiber) {
|
||||
job_fiber = fiber_alloc(FIBER_KIND_JOB_RUNNER);
|
||||
job_fiber = fiber_alloc(FIBER_KIND_JOB_WORKER);
|
||||
}
|
||||
job_fiber->job_func = job_func;
|
||||
job_fiber->job_sig = job_sig;
|
||||
@ -640,7 +673,7 @@ INTERNAL SYS_THREAD_DEF(worker_entry, worker_ctx_arg)
|
||||
case YIELD_KIND_DONE:
|
||||
{
|
||||
if (job_counter) {
|
||||
sys_counter_add(job_counter, -1);
|
||||
counter_add(job_counter, -1);
|
||||
}
|
||||
|
||||
/* TODO: remove this */
|
||||
@ -2918,7 +2951,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
||||
__profthread("Main thread", PROF_THREAD_GROUP_MAIN);
|
||||
|
||||
/* Init counters */
|
||||
G.num_counters = 1; /* Counter at index 0 always nil */
|
||||
G.counters_arena = arena_alloc(GIGABYTE(64));
|
||||
|
||||
/* Init fibers */
|
||||
G.num_fibers = 1; /* Fiber at index 0 always nil */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user