add SYS_PRIORITY_INHERIT
This commit is contained in:
parent
a397458c72
commit
2b08223472
@ -199,6 +199,7 @@ INTERNAL struct app_arg_list parse_args(struct arena *arena, struct string args_
|
||||
void sys_app_entry(struct string args_str)
|
||||
{
|
||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
||||
snc_counter_add(&G.exit_fence, 1);
|
||||
|
||||
struct app_arg_list args = parse_args(scratch.arena, args_str);
|
||||
struct string logfile_name = LIT("log.log");
|
||||
@ -315,7 +316,7 @@ void sys_app_entry(struct string args_str)
|
||||
sys_window_show(window);
|
||||
|
||||
/* Wait for app_exit() */
|
||||
snc_counter_wait_gtz(&G.exit_fence);
|
||||
snc_counter_wait(&G.exit_fence);
|
||||
|
||||
/* Run exit callbacks */
|
||||
/* FIXME: Only wait on shutdown for a certain period of time before
|
||||
@ -358,5 +359,5 @@ void sys_app_entry(struct string args_str)
|
||||
|
||||
void app_exit(void)
|
||||
{
|
||||
snc_counter_add(&G.exit_fence, 1);
|
||||
snc_counter_add(&G.exit_fence, -1);
|
||||
}
|
||||
|
||||
@ -107,9 +107,6 @@ u64 asset_cache_hash(struct string key)
|
||||
struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch)
|
||||
{
|
||||
struct asset *asset = NULL;
|
||||
if (is_first_touch) {
|
||||
*is_first_touch = false;
|
||||
}
|
||||
|
||||
/* Lookup */
|
||||
{
|
||||
@ -119,7 +116,11 @@ struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch
|
||||
}
|
||||
|
||||
/* Insert if not found */
|
||||
if (!asset->hash) {
|
||||
if (asset->hash) {
|
||||
if (is_first_touch) {
|
||||
*is_first_touch = false;
|
||||
}
|
||||
} else {
|
||||
struct snc_lock lock = snc_lock_e(&G.lookup_mutex);
|
||||
|
||||
/* Re-check asset presence in case it was inserted since lock */
|
||||
@ -143,6 +144,7 @@ struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch
|
||||
.hash = hash,
|
||||
.key = key_stored
|
||||
};
|
||||
snc_counter_add(&asset->counter, 1);
|
||||
if (is_first_touch) {
|
||||
*is_first_touch = true;
|
||||
}
|
||||
@ -172,7 +174,7 @@ void asset_cache_mark_ready(struct asset *asset, void *store_data)
|
||||
{
|
||||
asset->store_data = store_data;
|
||||
asset->status = ASSET_STATUS_READY;
|
||||
snc_counter_add(&asset->counter, 1);
|
||||
snc_counter_add(&asset->counter, -1);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -181,7 +183,7 @@ void asset_cache_mark_ready(struct asset *asset, void *store_data)
|
||||
|
||||
void asset_cache_wait(struct asset *asset)
|
||||
{
|
||||
snc_counter_wait_gtz(&asset->counter);
|
||||
snc_counter_wait(&asset->counter);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
|
||||
@ -920,8 +920,8 @@ INTERNAL SYS_JOB_DEF(pipeline_init_job, job)
|
||||
struct shader_compile_job_param *params[] = { &vs, &ps };
|
||||
struct shader_compile_job_sig comp_sig = { .params = params };
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(countof(params), shader_compile_job, &comp_sig, SYS_PRIORITY_HIGH, &counter);
|
||||
snc_counter_wait_ltez(&counter);
|
||||
sys_run(countof(params), shader_compile_job, &comp_sig, SYS_PRIORITY_INHERIT, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
success = vs.success && ps.success;
|
||||
}
|
||||
|
||||
@ -1114,8 +1114,8 @@ INTERNAL void pipeline_alloc(u64 num_pipelines, struct pipeline_desc *descs_in,
|
||||
__prof;
|
||||
struct pipeline_init_job_sig sig = { .descs_in = descs_in, .pipelines_out = pipelines_out };
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(num_pipelines, pipeline_init_job, &sig, SYS_PRIORITY_HIGH, &counter);
|
||||
snc_counter_wait_ltez(&counter);
|
||||
sys_run(num_pipelines, pipeline_init_job, &sig, SYS_PRIORITY_INHERIT, &counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
|
||||
INTERNAL void pipeline_release_now(struct pipeline *pipeline)
|
||||
|
||||
@ -287,7 +287,7 @@ INTERNAL SYS_THREAD_DEF(resource_watch_dispatcher_thread_entry_point, _)
|
||||
sig.callbacks = callbacks;
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(num_callbacks, resource_watch_callback_job, &sig, SYS_PRIORITY_BACKGROUND, &counter);
|
||||
snc_counter_wait_ltez(&counter);
|
||||
snc_counter_wait(&counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
src/snc.c
19
src/snc.c
@ -129,16 +129,16 @@ void snc_cv_broadcast(struct snc_cv *cv)
|
||||
* Counter
|
||||
* ========================== */
|
||||
|
||||
void snc_counter_add(struct snc_counter *counter, i64 amount)
|
||||
void snc_counter_add(struct snc_counter *counter, i64 x)
|
||||
{
|
||||
i64 old_v = atomic_i64_fetch_add(&counter->v, amount);
|
||||
i64 new_v = old_v + amount;
|
||||
if ((old_v > 0 && new_v <= 0) || (old_v <= 0 && new_v > 0)) {
|
||||
i64 old_v = atomic_i64_fetch_add(&counter->v, x);
|
||||
i64 new_v = old_v + x;
|
||||
if (old_v > 0 && new_v <= 0) {
|
||||
sys_wake_all(&counter->v);
|
||||
}
|
||||
}
|
||||
|
||||
void snc_counter_wait_ltez(struct snc_counter *counter)
|
||||
void snc_counter_wait(struct snc_counter *counter)
|
||||
{
|
||||
i64 v = atomic_i64_fetch(&counter->v);
|
||||
while (v > 0) {
|
||||
@ -146,12 +146,3 @@ void snc_counter_wait_ltez(struct snc_counter *counter)
|
||||
v = atomic_i64_fetch(&counter->v);
|
||||
}
|
||||
}
|
||||
|
||||
void snc_counter_wait_gtz(struct snc_counter *counter)
|
||||
{
|
||||
i64 v = atomic_i64_fetch(&counter->v);
|
||||
while (v <= 0) {
|
||||
sys_wait(&counter->v, &v, sizeof(v));
|
||||
v = atomic_i64_fetch(&counter->v);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,8 +51,7 @@ struct snc_counter {
|
||||
struct atomic_i64 v;
|
||||
};
|
||||
|
||||
void snc_counter_add(struct snc_counter *counter, i64 amount);
|
||||
void snc_counter_wait_ltez(struct snc_counter *counter);
|
||||
void snc_counter_wait_gtz(struct snc_counter *counter);
|
||||
void snc_counter_add(struct snc_counter *counter, i64 x);
|
||||
void snc_counter_wait(struct snc_counter *counter);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1374,7 +1374,7 @@ INTERNAL SYS_THREAD_DEF(sprite_evictor_scheduler_thread_entry_point, arg)
|
||||
while (!G.evictor_scheduler_shutdown) {
|
||||
struct snc_counter counter = ZI;
|
||||
sys_run(1, sprite_evictor_job, NULL, SYS_PRIORITY_BACKGROUND, &counter);
|
||||
snc_counter_wait_ltez(&counter);
|
||||
snc_counter_wait(&counter);
|
||||
/* FIXME: Enable this */
|
||||
#if 0
|
||||
snc_cv_wait_time(G.evictor_scheduler_shutdown_cv, &evictor_lock, SECONDS_FROM_NS(EVICTOR_CYCLE_INTERVAL_NS));
|
||||
|
||||
11
src/sys.h
11
src/sys.h
@ -459,16 +459,17 @@ void sys_wake_all(void *addr);
|
||||
|
||||
#define SYS_MAX_FIBERS 4096
|
||||
|
||||
i32 sys_current_fiber_id(void);
|
||||
i16 sys_current_fiber_id(void);
|
||||
|
||||
/* ========================== *
|
||||
* Job
|
||||
* ========================== */
|
||||
|
||||
enum sys_priority {
|
||||
SYS_PRIORITY_HIGH = 0,
|
||||
SYS_PRIORITY_NORMAL = 1,
|
||||
SYS_PRIORITY_BACKGROUND = 2,
|
||||
SYS_PRIORITY_INHERIT = -1,
|
||||
SYS_PRIORITY_HIGH = 0,
|
||||
SYS_PRIORITY_NORMAL = 1,
|
||||
SYS_PRIORITY_BACKGROUND = 2,
|
||||
|
||||
NUM_SYS_PRIORITIES
|
||||
};
|
||||
@ -494,7 +495,7 @@ struct sys_scratch_ctx {
|
||||
struct arena *arenas[SYS_SCRATCH_ARENAS_PER_CTX];
|
||||
};
|
||||
|
||||
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i32 fiber_id);
|
||||
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i16 fiber_id);
|
||||
|
||||
/* ========================== *
|
||||
* App entry point
|
||||
|
||||
@ -101,7 +101,7 @@ struct win32_window {
|
||||
};
|
||||
|
||||
|
||||
#define NUM_WAIT_BINS 4096
|
||||
#define NUM_WAIT_ADDR_BINS 4096
|
||||
|
||||
struct alignas(64) wait_list {
|
||||
/* =================================================== */
|
||||
@ -121,7 +121,7 @@ struct alignas(64) wait_list {
|
||||
/* =================================================== */
|
||||
u8 _pad1[8]; /* 8 bytes (padding) */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct wait_list) == 64); /* Assume wait_list fits in one cache line (increase if necessary) */
|
||||
STATIC_ASSERT(sizeof(struct wait_list) == 64); /* Padding validation (increase if necessary) */
|
||||
STATIC_ASSERT(alignof(struct wait_list) == 64); /* Avoid false sharing */
|
||||
|
||||
struct alignas(64) wait_bin {
|
||||
@ -139,12 +139,13 @@ struct alignas(64) wait_bin {
|
||||
/* =================================================== */
|
||||
u8 _pad1[24]; /* 24 bytes (padding) */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct wait_bin) == 64); /* Assume wait_bin fits in one cache line (increase if necessary) */
|
||||
STATIC_ASSERT(sizeof(struct wait_bin) == 64); /* Padding validation (increase if necessary) */
|
||||
STATIC_ASSERT(alignof(struct wait_bin) == 64); /* Avoid false sharing */
|
||||
|
||||
struct alignas(64) yielder {
|
||||
/* =================================================== */
|
||||
i32 fiber_id; /* 4 bytes */
|
||||
i16 fiber_id; /* 2 bytes */
|
||||
u8 _pad0[2]; /* 2 bytes (padding) */
|
||||
i32 job_queue_kind; /* 4 bytes */
|
||||
/* =================================================== */
|
||||
sys_job_func *job_func; /* 8 bytes */
|
||||
@ -158,11 +159,11 @@ struct alignas(64) yielder {
|
||||
struct yielder *prev; /* 8 bytes */
|
||||
/* =================================================== */
|
||||
i32 job_id; /* 4 bytes */
|
||||
u8 _pad0[4]; /* 4 bytes (padding) */
|
||||
u8 _pad1[4]; /* 4 bytes (padding) */
|
||||
/* =================================================== */
|
||||
u8 _pad1[8]; /* 8 bytes (padding) */
|
||||
u8 _pad2[8]; /* 8 bytes (padding) */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct yielder) == 64); /* Assume yielder fits in one cache line (increase if necessary) */
|
||||
STATIC_ASSERT(sizeof(struct yielder) == 64); /* Padding validation (increase if necessary) */
|
||||
STATIC_ASSERT(alignof(struct yielder) == 64); /* Avoid false sharing */
|
||||
|
||||
|
||||
@ -175,7 +176,7 @@ struct alignas(64) counter {
|
||||
/* =================================================== */
|
||||
u8 _pad[48]; /* 56 bytes (padding) */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct counter) == 64); /* Assume counter fits in one cache line (increase if necessary) */
|
||||
STATIC_ASSERT(sizeof(struct counter) == 64); /* Padding validation (increase if necessary) */
|
||||
STATIC_ASSERT(alignof(struct counter) == 64); /* Avoid false sharing */
|
||||
|
||||
|
||||
@ -211,8 +212,9 @@ struct alignas(64) fiber {
|
||||
/* =================================================== */
|
||||
char *name_cstr; /* 8 bytes */
|
||||
/* =================================================== */
|
||||
i32 id; /* 4 bytes */
|
||||
i32 parent_id; /* 4 bytes */
|
||||
i16 id; /* 2 bytes */
|
||||
i16 parent_id; /* 2 bytes */
|
||||
u8 _pad0[4]; /* 4 bytes (padding) */
|
||||
/* =================================================== */
|
||||
void *addr; /* 8 bytes */
|
||||
/* =================================================== */
|
||||
@ -225,10 +227,11 @@ struct alignas(64) fiber {
|
||||
/* =================================================== */
|
||||
struct yield_param *yield_param; /* 8 bytes */
|
||||
/* =================================================== */
|
||||
u8 _pad0[8]; /* 8 bytes (padding) */
|
||||
u8 _pad1[8]; /* 8 bytes (padding) */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct fiber) == 64); /* Assume fiber fits in one cache line (increase if necessary) */
|
||||
STATIC_ASSERT(sizeof(struct fiber) == 64); /* Padding validation (increase if necessary) */
|
||||
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) fiber_ctx {
|
||||
/* ==================================================== */
|
||||
@ -244,7 +247,7 @@ struct alignas(64) fiber_ctx {
|
||||
/* ==================================================== */
|
||||
u8 _pad4[8]; /* 8 bytes (padding) */
|
||||
};
|
||||
STATIC_ASSERT(sizeof(struct fiber_ctx) == 64); /* Assume ctx fits in one cache line (increase if necessary) */
|
||||
STATIC_ASSERT(sizeof(struct fiber_ctx) == 64); /* Padding validation (increase if necessary) */
|
||||
STATIC_ASSERT(alignof(struct fiber_ctx) == 64); /* Avoid false sharing */
|
||||
|
||||
|
||||
@ -264,7 +267,7 @@ struct job_info {
|
||||
void *sig;
|
||||
struct snc_counter *counter;
|
||||
|
||||
i32 fiber_id; /* If the job is being resumed from a yield */
|
||||
i16 fiber_id; /* If the job is being resumed from a yield */
|
||||
|
||||
struct job_info *next;
|
||||
};
|
||||
@ -340,11 +343,11 @@ GLOBAL struct {
|
||||
struct arena *wait_lists_arena;
|
||||
|
||||
/* Wait table */
|
||||
struct wait_bin wait_bins[NUM_WAIT_BINS];
|
||||
struct wait_bin wait_bins[NUM_WAIT_ADDR_BINS];
|
||||
|
||||
/* Fibers */
|
||||
i32 num_fibers;
|
||||
i32 first_free_fiber_id;
|
||||
i16 num_fibers;
|
||||
i16 first_free_fiber_id;
|
||||
struct arena *fiber_names_arena;
|
||||
struct atomic_i32 fibers_lock; /* TODO: Prevent false sharing */
|
||||
struct fiber fibers[SYS_MAX_FIBERS];
|
||||
@ -365,7 +368,7 @@ GLOBAL struct {
|
||||
|
||||
|
||||
|
||||
INTERNAL struct fiber *fiber_from_id(i32 id);
|
||||
INTERNAL struct fiber *fiber_from_id(i16 id);
|
||||
INTERNAL void job_fiber_yield(struct fiber *fiber, struct fiber *parent_fiber);
|
||||
|
||||
|
||||
@ -394,7 +397,7 @@ void sys_wait(void *addr, void *cmp, u32 size)
|
||||
WaitOnAddress(addr, cmp, size, INFINITE);
|
||||
#else
|
||||
struct fiber *fiber = fiber_from_id(sys_current_fiber_id());
|
||||
i32 parent_fiber_id = fiber->parent_id;
|
||||
i16 parent_fiber_id = fiber->parent_id;
|
||||
/* Yield if job fiber, otherwise fall back to windows blocking function */
|
||||
if (parent_fiber_id > 0) {
|
||||
/* Yield if job fiber */
|
||||
@ -422,7 +425,7 @@ void sys_wake_single(void *addr)
|
||||
|
||||
void sys_wake_all(void *addr)
|
||||
{
|
||||
u64 wait_bin_index = (u64)addr % NUM_WAIT_BINS;
|
||||
u64 wait_bin_index = (u64)addr % NUM_WAIT_ADDR_BINS;
|
||||
struct wait_bin *bin = &G.wait_bins[wait_bin_index];
|
||||
|
||||
while (atomic_i32_fetch_test_set(&bin->lock, 0, 1) != 0) ix_pause();
|
||||
@ -514,7 +517,7 @@ INTERNAL void job_fiber_entry(void *id_ptr);
|
||||
|
||||
INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
||||
{
|
||||
i32 fiber_id = 0;
|
||||
i16 fiber_id = 0;
|
||||
struct fiber *fiber = NULL;
|
||||
char *new_name_cstr = NULL;
|
||||
{
|
||||
@ -583,7 +586,7 @@ INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
||||
return fiber;
|
||||
}
|
||||
|
||||
INTERNAL void fiber_release(struct fiber *fiber, i32 fiber_id)
|
||||
INTERNAL void fiber_release(struct fiber *fiber, i16 fiber_id)
|
||||
{
|
||||
while (atomic_i32_fetch_test_set(&G.fibers_lock, 0, 1) != 0) ix_pause();
|
||||
{
|
||||
@ -593,13 +596,13 @@ INTERNAL void fiber_release(struct fiber *fiber, i32 fiber_id)
|
||||
atomic_i32_fetch_set(&G.fibers_lock, 0);
|
||||
}
|
||||
|
||||
INTERNAL struct fiber *fiber_from_id(i32 id)
|
||||
INTERNAL struct fiber *fiber_from_id(i16 id)
|
||||
{
|
||||
ASSERT(id >= 0 && id < SYS_MAX_FIBERS);
|
||||
return &G.fibers[id];
|
||||
}
|
||||
|
||||
INTERNAL struct fiber_ctx *fiber_ctx_from_id(i32 id)
|
||||
INTERNAL struct fiber_ctx *fiber_ctx_from_id(i16 id)
|
||||
{
|
||||
ASSERT(id >= 0 && id < SYS_MAX_FIBERS);
|
||||
return &G.fiber_contexts[id];
|
||||
@ -609,9 +612,9 @@ INTERNAL struct fiber_ctx *fiber_ctx_from_id(i32 id)
|
||||
* Test job
|
||||
* ========================== */
|
||||
|
||||
i32 sys_current_fiber_id(void)
|
||||
i16 sys_current_fiber_id(void)
|
||||
{
|
||||
return (i32)(i64)GetFiberData();
|
||||
return (i16)(i64)GetFiberData();
|
||||
}
|
||||
|
||||
void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_priority priority, struct snc_counter *counter)
|
||||
@ -682,7 +685,7 @@ INTERNAL void job_fiber_resume(struct fiber *fiber)
|
||||
|
||||
INTERNAL void job_fiber_entry(void *id_ptr)
|
||||
{
|
||||
i32 id = (i32)(i64)id_ptr;
|
||||
i16 id = (i32)(i64)id_ptr;
|
||||
struct fiber *fiber = fiber_from_id(id);
|
||||
__prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS + fiber->id);
|
||||
while (true) {
|
||||
@ -846,7 +849,7 @@ INTERNAL SYS_THREAD_DEF(worker_entry, worker_ctx_arg)
|
||||
void *wait_cmp = yield.wait.cmp;
|
||||
u32 wait_size = yield.wait.size;
|
||||
|
||||
u64 wait_bin_index = (u64)wait_addr % NUM_WAIT_BINS;
|
||||
u64 wait_bin_index = (u64)wait_addr % NUM_WAIT_ADDR_BINS;
|
||||
struct wait_bin *bin = &G.wait_bins[wait_bin_index];
|
||||
|
||||
while (atomic_i32_fetch_test_set(&bin->lock, 0, 1) != 0) ix_pause();
|
||||
@ -986,7 +989,7 @@ INTERNAL SYS_THREAD_DEF(test_entry, _)
|
||||
* Scratch context
|
||||
* ========================== */
|
||||
|
||||
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i32 id)
|
||||
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i16 id)
|
||||
{
|
||||
struct fiber_ctx *fiber_ctx = fiber_ctx_from_id(id);
|
||||
struct sys_scratch_ctx *scratch_ctx = &fiber_ctx->scratch_ctx;
|
||||
@ -1810,7 +1813,7 @@ INTERNAL SYS_THREAD_DEF(window_thread_entry_point, arg)
|
||||
win32_update_window_from_system(window);
|
||||
BringWindowToTop(window->hwnd);
|
||||
|
||||
snc_counter_add(&window->ready_fence, 1);
|
||||
snc_counter_add(&window->ready_fence, -1);
|
||||
|
||||
while (!atomic_i32_fetch(&window->event_thread_shutdown)) {
|
||||
MSG msg = ZI;
|
||||
@ -1902,10 +1905,9 @@ INTERNAL struct win32_window *win32_window_alloc(void)
|
||||
MEMZERO_STRUCT(window);
|
||||
|
||||
/* Start window thread for processing events */
|
||||
snc_counter_add(&window->ready_fence, 1);
|
||||
window->event_thread = sys_thread_alloc(&window_thread_entry_point, window, LIT("Window thread"), PROF_THREAD_GROUP_WINDOW);
|
||||
|
||||
/* Wait for event thread to create actual window */
|
||||
snc_counter_wait_gtz(&window->ready_fence);
|
||||
snc_counter_wait(&window->ready_fence);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user