refactor mutexes to use 'sys_lock' objects. make all mutexes rw mutexes.
This commit is contained in:
parent
3061d465d1
commit
04db1226e2
13
src/app.c
13
src/app.c
@ -108,14 +108,12 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(exit_callback_thread_entry_point, vcall
|
|||||||
|
|
||||||
void app_register_exit_callback(app_exit_callback_func *func)
|
void app_register_exit_callback(app_exit_callback_func *func)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.exit_callbacks_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.exit_callbacks_mutex);
|
||||||
{
|
|
||||||
struct exit_callback *callback = arena_push_zero(&G.exit_callbacks_arena, struct exit_callback);
|
struct exit_callback *callback = arena_push_zero(&G.exit_callbacks_arena, struct exit_callback);
|
||||||
callback->func = func;
|
callback->func = func;
|
||||||
callback->next = G.exit_callbacks_head;
|
callback->next = G.exit_callbacks_head;
|
||||||
G.exit_callbacks_head = callback;
|
G.exit_callbacks_head = callback;
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.exit_callbacks_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -232,18 +230,21 @@ void app_entry_point(void)
|
|||||||
/* FIXME: Only wait on threads for a certain period of time before
|
/* FIXME: Only wait on threads for a certain period of time before
|
||||||
* forcing process exit (to prevent process hanging in the background
|
* forcing process exit (to prevent process hanging in the background
|
||||||
* when a thread gets stuck) */
|
* when a thread gets stuck) */
|
||||||
sys_mutex_lock(&G.exit_callbacks_mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.exit_callbacks_mutex);
|
||||||
|
|
||||||
/* Start callback threads */
|
/* Start callback threads */
|
||||||
for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) {
|
for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) {
|
||||||
callback->thread = sys_thread_alloc(&exit_callback_thread_entry_point, callback, STR("[P4] Exit callback thread"));
|
callback->thread = sys_thread_alloc(&exit_callback_thread_entry_point, callback, STR("[P4] Exit callback thread"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait on callback threads */
|
/* Wait on callback threads */
|
||||||
for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) {
|
for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) {
|
||||||
sys_thread_wait_release(&callback->thread);
|
sys_thread_wait_release(&callback->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.exit_callbacks_mutex);
|
|
||||||
|
|
||||||
/* Write window settings to file */
|
/* Write window settings to file */
|
||||||
{
|
{
|
||||||
|
|||||||
@ -16,11 +16,11 @@
|
|||||||
#define ASSET_LOOKUP_TABLE_CAPACITY (MAX_ASSETS * 4)
|
#define ASSET_LOOKUP_TABLE_CAPACITY (MAX_ASSETS * 4)
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct sys_rw_mutex lookup_rw_mutex;
|
struct sys_mutex lookup_mutex;
|
||||||
struct asset lookup[ASSET_LOOKUP_TABLE_CAPACITY];
|
struct asset lookup[ASSET_LOOKUP_TABLE_CAPACITY];
|
||||||
u64 num_assets;
|
u64 num_assets;
|
||||||
|
|
||||||
struct sys_rw_mutex store_rw_mutex;
|
struct sys_mutex store_mutex;
|
||||||
struct arena store_arena;
|
struct arena store_arena;
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
@ -40,9 +40,9 @@ struct asset_cache_startup_receipt asset_cache_startup(struct work_startup_recei
|
|||||||
(UNUSED)work_sr;
|
(UNUSED)work_sr;
|
||||||
|
|
||||||
/* Init lookup */
|
/* Init lookup */
|
||||||
G.lookup_rw_mutex = sys_rw_mutex_alloc();
|
G.lookup_mutex = sys_mutex_alloc();
|
||||||
/* Init store */
|
/* Init store */
|
||||||
G.store_rw_mutex = sys_rw_mutex_alloc();
|
G.store_mutex = sys_mutex_alloc();
|
||||||
G.store_arena = arena_alloc(GIGABYTE(64));
|
G.store_arena = arena_alloc(GIGABYTE(64));
|
||||||
#if RTC
|
#if RTC
|
||||||
/* Init debug */
|
/* Init debug */
|
||||||
@ -59,8 +59,7 @@ struct asset_cache_startup_receipt asset_cache_startup(struct work_startup_recei
|
|||||||
INTERNAL void refresh_dbg_table(void)
|
INTERNAL void refresh_dbg_table(void)
|
||||||
{
|
{
|
||||||
#if RTC
|
#if RTC
|
||||||
sys_mutex_lock(&G.dbg_table_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.dbg_table_mutex);
|
||||||
{
|
|
||||||
MEMZERO_ARRAY(G.dbg_table);
|
MEMZERO_ARRAY(G.dbg_table);
|
||||||
G.dbg_table_count = 0;
|
G.dbg_table_count = 0;
|
||||||
for (u64 i = 0; i < ARRAY_COUNT(G.lookup); ++i) {
|
for (u64 i = 0; i < ARRAY_COUNT(G.lookup); ++i) {
|
||||||
@ -69,15 +68,16 @@ INTERNAL void refresh_dbg_table(void)
|
|||||||
G.dbg_table[G.dbg_table_count++] = asset;
|
G.dbg_table[G.dbg_table_count++] = asset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.dbg_table_mutex);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns first matching slot or first empty slot if not found.
|
/* Returns first matching slot or first empty slot if not found.
|
||||||
* Check returned slot->hash != 0 for presence. */
|
* Check returned slot->hash != 0 for presence. */
|
||||||
INTERNAL struct asset *asset_cache_get_slot_assume_locked(struct string key, u64 hash)
|
INTERNAL struct asset *asset_cache_get_slot_assume_locked(struct sys_lock *lock, struct string key, u64 hash)
|
||||||
{
|
{
|
||||||
|
sys_assert_locked_s(lock, &G.lookup_mutex);
|
||||||
|
|
||||||
u64 index = hash % ARRAY_COUNT(G.lookup);
|
u64 index = hash % ARRAY_COUNT(G.lookup);
|
||||||
while (true) {
|
while (true) {
|
||||||
struct asset *slot = &G.lookup[index];
|
struct asset *slot = &G.lookup[index];
|
||||||
@ -122,17 +122,17 @@ struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch
|
|||||||
|
|
||||||
/* Lookup */
|
/* Lookup */
|
||||||
{
|
{
|
||||||
sys_rw_mutex_lock_shared(&G.lookup_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_s(&G.lookup_mutex);
|
||||||
asset = asset_cache_get_slot_assume_locked(key, hash);
|
asset = asset_cache_get_slot_assume_locked(&lock, key, hash);
|
||||||
sys_rw_mutex_unlock_shared(&G.lookup_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert if not found */
|
/* Insert if not found */
|
||||||
if (!asset->hash) {
|
if (!asset->hash) {
|
||||||
sys_rw_mutex_lock_exclusive(&G.lookup_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.lookup_mutex);
|
||||||
|
|
||||||
/* Re-check asset presence in case it was inserted since lock */
|
/* Re-check asset presence in case it was inserted since lock */
|
||||||
asset = asset_cache_get_slot_assume_locked(key, hash);
|
asset = asset_cache_get_slot_assume_locked(&lock, key, hash);
|
||||||
|
|
||||||
if (!asset->hash) {
|
if (!asset->hash) {
|
||||||
if (G.num_assets >= MAX_ASSETS) {
|
if (G.num_assets >= MAX_ASSETS) {
|
||||||
@ -162,7 +162,7 @@ struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch
|
|||||||
refresh_dbg_table();
|
refresh_dbg_table();
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_rw_mutex_unlock_exclusive(&G.lookup_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return asset;
|
return asset;
|
||||||
@ -231,15 +231,15 @@ void *asset_cache_get_store_data(struct asset *asset)
|
|||||||
/* Asset store should be opened to allocate memory to the store arena */
|
/* Asset store should be opened to allocate memory to the store arena */
|
||||||
struct asset_cache_store asset_cache_store_open(void)
|
struct asset_cache_store asset_cache_store_open(void)
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.store_mutex);
|
||||||
struct asset_cache_store store = {
|
struct asset_cache_store store = {
|
||||||
.rw_mutex = &G.store_rw_mutex,
|
.lock = lock,
|
||||||
.arena = &G.store_arena
|
.arena = &G.store_arena
|
||||||
};
|
};
|
||||||
sys_rw_mutex_lock_exclusive(store.rw_mutex);
|
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
void asset_cache_store_close(struct asset_cache_store *store)
|
void asset_cache_store_close(struct asset_cache_store *store)
|
||||||
{
|
{
|
||||||
sys_rw_mutex_unlock_exclusive(store->rw_mutex);
|
sys_mutex_unlock(&store->lock);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ struct asset_cache_store {
|
|||||||
struct arena *arena;
|
struct arena *arena;
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
struct sys_rw_mutex *rw_mutex;
|
struct sys_lock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct asset_cache_startup_receipt { i32 _; };
|
struct asset_cache_startup_receipt { i32 _; };
|
||||||
|
|||||||
10
src/font.c
10
src/font.c
@ -66,27 +66,25 @@ struct font_startup_receipt font_startup(struct work_startup_receipt *work_sr,
|
|||||||
INTERNAL struct font_task_params *font_task_params_alloc(void)
|
INTERNAL struct font_task_params *font_task_params_alloc(void)
|
||||||
{
|
{
|
||||||
struct font_task_params *p = NULL;
|
struct font_task_params *p = NULL;
|
||||||
sys_mutex_lock(&G.params.mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.params.mutex);
|
||||||
if (G.params.head_free) {
|
if (G.params.head_free) {
|
||||||
p = G.params.head_free;
|
p = G.params.head_free;
|
||||||
G.params.head_free = p->next_free;
|
G.params.head_free = p->next_free;
|
||||||
} else {
|
} else {
|
||||||
p = arena_push_zero(&G.params.arena, struct font_task_params);
|
p = arena_push_zero(&G.params.arena, struct font_task_params);
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.params.mutex);
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void font_task_params_release(struct font_task_params *p)
|
INTERNAL void font_task_params_release(struct font_task_params *p)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.params.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.params.mutex);
|
||||||
{
|
|
||||||
p->next_free = G.params.head_free;
|
p->next_free = G.params.head_free;
|
||||||
G.params.head_free = p;
|
G.params.head_free = p;
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.params.mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
24
src/game.c
24
src/game.c
@ -73,28 +73,24 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(game_shutdown)
|
|||||||
|
|
||||||
INTERNAL void push_cmds(struct game_cmd_array cmd_array)
|
INTERNAL void push_cmds(struct game_cmd_array cmd_array)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.game_cmds_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.game_cmds_mutex);
|
||||||
{
|
|
||||||
struct game_cmd *cmds = arena_push_array(&G.game_cmds_arena, struct game_cmd, cmd_array.count);
|
struct game_cmd *cmds = arena_push_array(&G.game_cmds_arena, struct game_cmd, cmd_array.count);
|
||||||
MEMCPY(cmds, cmd_array.cmds, cmd_array.count * sizeof(*cmds));
|
MEMCPY(cmds, cmd_array.cmds, cmd_array.count * sizeof(*cmds));
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.game_cmds_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
||||||
{
|
{
|
||||||
struct game_cmd_array array = { 0 };
|
struct game_cmd_array array = { 0 };
|
||||||
if (G.game_cmds_arena.pos > 0) {
|
if (G.game_cmds_arena.pos > 0) {
|
||||||
sys_mutex_lock(&G.game_cmds_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.game_cmds_mutex);
|
||||||
{
|
|
||||||
struct buffer game_cmds_buff = arena_to_buffer(&G.game_cmds_arena);
|
struct buffer game_cmds_buff = arena_to_buffer(&G.game_cmds_arena);
|
||||||
arena_align(arena, alignof(struct game_cmd));
|
arena_align(arena, alignof(struct game_cmd));
|
||||||
array.cmds = (struct game_cmd *)arena_push_array(arena, u8, game_cmds_buff.size);
|
array.cmds = (struct game_cmd *)arena_push_array(arena, u8, game_cmds_buff.size);
|
||||||
array.count = game_cmds_buff.size / sizeof(struct game_cmd);
|
array.count = game_cmds_buff.size / sizeof(struct game_cmd);
|
||||||
MEMCPY(array.cmds, game_cmds_buff.data, game_cmds_buff.size);
|
MEMCPY(array.cmds, game_cmds_buff.data, game_cmds_buff.size);
|
||||||
arena_reset(&G.game_cmds_arena);
|
arena_reset(&G.game_cmds_arena);
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.game_cmds_mutex);
|
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
@ -106,12 +102,10 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
|||||||
INTERNAL void publish_game_tick(void)
|
INTERNAL void publish_game_tick(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&G.published_tick_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.published_tick_mutex);
|
||||||
{
|
|
||||||
world_copy_replace(&G.published_tick, &G.world);
|
world_copy_replace(&G.published_tick, &G.world);
|
||||||
atomic_u64_eval_exchange(&G.published_tick_id, G.published_tick.tick_id);
|
atomic_u64_eval_exchange(&G.published_tick_id, G.published_tick.tick_id);
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.published_tick_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void recalculate_world_xform_recurse(struct entity *parent)
|
INTERNAL void recalculate_world_xform_recurse(struct entity *parent)
|
||||||
@ -532,11 +526,9 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
|
|||||||
|
|
||||||
void game_get_latest_tick(struct world *dest)
|
void game_get_latest_tick(struct world *dest)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.published_tick_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.published_tick_mutex);
|
||||||
{
|
|
||||||
world_copy_replace(dest, &G.published_tick);
|
world_copy_replace(dest, &G.published_tick);
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.published_tick_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 game_get_latest_tick_id(void)
|
u64 game_get_latest_tick_id(void)
|
||||||
|
|||||||
10
src/log.c
10
src/log.c
@ -75,14 +75,14 @@ struct log_startup_receipt log_startup(struct string logfile_path)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void log_register_callback(log_event_callback_func *func)
|
void log_register_callback(log_event_callback_func *func)
|
||||||
{
|
|
||||||
if (!atomic_i32_eval(&G.initialized)) { return; }
|
|
||||||
sys_mutex_lock(&G.mutex);
|
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
(UNUSED)func;
|
(UNUSED)func;
|
||||||
}
|
#if 0
|
||||||
sys_mutex_unlock(&G.mutex);
|
if (!atomic_i32_eval(&G.initialized)) { return; }
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
38
src/mixer.c
38
src/mixer.c
@ -102,9 +102,9 @@ INTERNAL struct track *track_from_handle(struct mixer_track_handle handle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct track *track_alloc_assume_locked(struct sound *sound)
|
INTERNAL struct track *track_alloc_assume_locked(struct sys_lock *lock, struct sound *sound)
|
||||||
{
|
{
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct track *track = NULL;
|
struct track *track = NULL;
|
||||||
if (G.track_first_free) {
|
if (G.track_first_free) {
|
||||||
@ -140,9 +140,9 @@ INTERNAL struct track *track_alloc_assume_locked(struct sound *sound)
|
|||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void track_release_assume_locked(struct track *track)
|
INTERNAL void track_release_assume_locked(struct sys_lock *lock, struct track *track)
|
||||||
{
|
{
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
/* Remove from playing list */
|
/* Remove from playing list */
|
||||||
struct track *prev = track->prev;
|
struct track *prev = track->prev;
|
||||||
@ -187,12 +187,12 @@ struct mixer_track_handle mixer_play_ex(struct sound *sound, struct mixer_desc d
|
|||||||
{
|
{
|
||||||
struct track *track;
|
struct track *track;
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
track = track_alloc_assume_locked(sound);
|
track = track_alloc_assume_locked(&lock, sound);
|
||||||
track->desc = desc;
|
track->desc = desc;
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
return track_to_handle(track);
|
return track_to_handle(track);
|
||||||
}
|
}
|
||||||
@ -205,7 +205,7 @@ struct mixer_desc mixer_track_get(struct mixer_track_handle handle)
|
|||||||
struct track *track = track_from_handle(handle);
|
struct track *track = track_from_handle(handle);
|
||||||
if (track) {
|
if (track) {
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
/* Confirm handle is still valid now that we're locked */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
track = track_from_handle(handle);
|
track = track_from_handle(handle);
|
||||||
@ -213,7 +213,7 @@ struct mixer_desc mixer_track_get(struct mixer_track_handle handle)
|
|||||||
res = track->desc;
|
res = track->desc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -225,7 +225,7 @@ void mixer_track_set(struct mixer_track_handle handle, struct mixer_desc desc)
|
|||||||
struct track *track = track_from_handle(handle);
|
struct track *track = track_from_handle(handle);
|
||||||
if (track) {
|
if (track) {
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
/* Confirm handle is still valid now that we're locked */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
track = track_from_handle(handle);
|
track = track_from_handle(handle);
|
||||||
@ -233,18 +233,18 @@ void mixer_track_set(struct mixer_track_handle handle, struct mixer_desc desc)
|
|||||||
track->desc = desc;
|
track->desc = desc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mixer_set_listener(struct v2 pos, struct v2 dir)
|
void mixer_set_listener(struct v2 pos, struct v2 dir)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
G.listener_pos = pos;
|
G.listener_pos = pos;
|
||||||
G.listener_dir = v2_norm(dir);
|
G.listener_dir = v2_norm(dir);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -279,8 +279,9 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
/* Create temp array of mixes */
|
/* Create temp array of mixes */
|
||||||
struct mix **mixes = NULL;
|
struct mix **mixes = NULL;
|
||||||
u64 mixes_count = 0;
|
u64 mixes_count = 0;
|
||||||
sys_mutex_lock(&G.mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
|
|
||||||
/* Read listener info */
|
/* Read listener info */
|
||||||
listener_pos = G.listener_pos;
|
listener_pos = G.listener_pos;
|
||||||
listener_dir = G.listener_dir;
|
listener_dir = G.listener_dir;
|
||||||
@ -293,8 +294,9 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
mix->desc = track->desc;
|
mix->desc = track->desc;
|
||||||
mixes[mixes_count++] = mix;
|
mixes[mixes_count++] = mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
|
||||||
|
|
||||||
for (u64 mix_index = 0; mix_index < mixes_count; ++mix_index) {
|
for (u64 mix_index = 0; mix_index < mixes_count; ++mix_index) {
|
||||||
__profscope(mix_track);
|
__profscope(mix_track);
|
||||||
@ -463,21 +465,21 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_mutex_lock(&G.mutex);
|
|
||||||
{
|
{
|
||||||
__profscope(update_track_effect_data);
|
__profscope(update_track_effect_data);
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
for (u64 i = 0; i < mixes_count; ++i) {
|
for (u64 i = 0; i < mixes_count; ++i) {
|
||||||
struct mix *mix = mixes[i];
|
struct mix *mix = mixes[i];
|
||||||
struct track *track = track_from_handle(mix->track_handle);
|
struct track *track = track_from_handle(mix->track_handle);
|
||||||
if (track) {
|
if (track) {
|
||||||
if (mix->track_finished) {
|
if (mix->track_finished) {
|
||||||
/* Release finished tracks */
|
/* Release finished tracks */
|
||||||
track_release_assume_locked(track);
|
track_release_assume_locked(&lock, track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@ -198,7 +198,7 @@ INTERNAL struct renderer_handle handle_alloc(void *data)
|
|||||||
struct handle_store *store = &G.handle_store;
|
struct handle_store *store = &G.handle_store;
|
||||||
struct handle_slot *slot = NULL;
|
struct handle_slot *slot = NULL;
|
||||||
|
|
||||||
sys_mutex_lock(&store->mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&store->mutex);
|
||||||
{
|
{
|
||||||
if (store->head_free) {
|
if (store->head_free) {
|
||||||
/* Take first from free list */
|
/* Take first from free list */
|
||||||
@ -217,7 +217,7 @@ INTERNAL struct renderer_handle handle_alloc(void *data)
|
|||||||
}
|
}
|
||||||
slot->data = data;
|
slot->data = data;
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&store->mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
struct renderer_handle handle = HANDLE_CREATE(slot->idx, slot->gen);
|
struct renderer_handle handle = HANDLE_CREATE(slot->idx, slot->gen);
|
||||||
return handle;
|
return handle;
|
||||||
@ -231,7 +231,7 @@ INTERNAL void handle_release(struct renderer_handle handle)
|
|||||||
u32 idx = HANDLE_IDX(handle);
|
u32 idx = HANDLE_IDX(handle);
|
||||||
u32 gen = HANDLE_GEN(handle);
|
u32 gen = HANDLE_GEN(handle);
|
||||||
|
|
||||||
sys_mutex_lock(&store->mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&store->mutex);
|
||||||
{
|
{
|
||||||
if (idx < store->count) {
|
if (idx < store->count) {
|
||||||
struct handle_slot *slot = &store->array[idx];
|
struct handle_slot *slot = &store->array[idx];
|
||||||
@ -256,7 +256,7 @@ INTERNAL void handle_release(struct renderer_handle handle)
|
|||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&store->mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void *handle_data(struct renderer_handle handle)
|
INTERNAL void *handle_data(struct renderer_handle handle)
|
||||||
|
|||||||
12
src/sound.c
12
src/sound.c
@ -57,28 +57,24 @@ INTERNAL struct sound_task_params *sound_task_params_alloc(void)
|
|||||||
{
|
{
|
||||||
struct sound_task_params *p = NULL;
|
struct sound_task_params *p = NULL;
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.params.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.params.mutex);
|
||||||
{
|
|
||||||
if (G.params.head_free) {
|
if (G.params.head_free) {
|
||||||
p = G.params.head_free;
|
p = G.params.head_free;
|
||||||
G.params.head_free = p->next_free;
|
G.params.head_free = p->next_free;
|
||||||
} else {
|
} else {
|
||||||
p = arena_push_zero(&G.params.arena, struct sound_task_params);
|
p = arena_push_zero(&G.params.arena, struct sound_task_params);
|
||||||
}
|
}
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.params.mutex);
|
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void sound_task_params_release(struct sound_task_params *p)
|
INTERNAL void sound_task_params_release(struct sound_task_params *p)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.params.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.params.mutex);
|
||||||
{
|
|
||||||
p->next_free = G.params.head_free;
|
p->next_free = G.params.head_free;
|
||||||
G.params.head_free = p;
|
G.params.head_free = p;
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.params.mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
53
src/sprite.c
53
src/sprite.c
@ -95,7 +95,7 @@ struct cache_node {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cache_bucket {
|
struct cache_bucket {
|
||||||
struct sys_rw_mutex rw_mutex;
|
struct sys_mutex mutex;
|
||||||
struct cache_node *first;
|
struct cache_node *first;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ struct sprite_startup_receipt sprite_startup(struct renderer_startup_receipt *re
|
|||||||
G.cache.arena = arena_alloc(GIGABYTE(64));
|
G.cache.arena = arena_alloc(GIGABYTE(64));
|
||||||
G.cache.buckets = arena_push_array_zero(&G.cache.arena, struct cache_bucket, CACHE_BUCKETS_COUNT);
|
G.cache.buckets = arena_push_array_zero(&G.cache.arena, struct cache_bucket, CACHE_BUCKETS_COUNT);
|
||||||
for (u64 i = 0; i < CACHE_BUCKETS_COUNT; ++i) {
|
for (u64 i = 0; i < CACHE_BUCKETS_COUNT; ++i) {
|
||||||
G.cache.buckets[i].rw_mutex = sys_rw_mutex_alloc();
|
G.cache.buckets[i].mutex = sys_mutex_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
G.load_cmds_arena = arena_alloc(GIGABYTE(64));
|
G.load_cmds_arena = arena_alloc(GIGABYTE(64));
|
||||||
@ -261,14 +261,13 @@ struct sprite_startup_receipt sprite_startup(struct renderer_startup_receipt *re
|
|||||||
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown)
|
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
/* Signal evictor shutdown */
|
/* Signal evictor shutdown */
|
||||||
sys_mutex_lock(&G.evictor_mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.evictor_mutex);
|
||||||
G.evictor_shutdown = true;
|
G.evictor_shutdown = true;
|
||||||
sys_condition_variable_broadcast(&G.evictor_cv);
|
sys_condition_variable_broadcast(&G.evictor_cv);
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.evictor_mutex);
|
|
||||||
sys_thread_wait_release(&G.evictor_thread);
|
sys_thread_wait_release(&G.evictor_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,8 +572,8 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
|
|||||||
|
|
||||||
/* Lookup */
|
/* Lookup */
|
||||||
/* TODO: Spinlock */
|
/* TODO: Spinlock */
|
||||||
sys_rw_mutex_lock_shared(&bucket->rw_mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_s(&bucket->mutex);
|
||||||
nonmatching_next = &bucket->first;
|
nonmatching_next = &bucket->first;
|
||||||
n = *nonmatching_next;
|
n = *nonmatching_next;
|
||||||
while (n) {
|
while (n) {
|
||||||
@ -587,17 +586,17 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
|
|||||||
n = *nonmatching_next;
|
n = *nonmatching_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_shared(&bucket->rw_mutex);
|
|
||||||
|
|
||||||
/* Allocate new node if necessary */
|
/* Allocate new node if necessary */
|
||||||
if (!n) {
|
if (!n) {
|
||||||
__profscope(node_lookup_allocate);
|
__profscope(node_lookup_allocate);
|
||||||
sys_rw_mutex_lock_exclusive(&bucket->rw_mutex);
|
struct sys_lock bucket_lock = sys_mutex_lock_e(&bucket->mutex);
|
||||||
{
|
{
|
||||||
/* Alloc node */
|
/* Alloc node */
|
||||||
sys_mutex_lock(&G.cache.node_pool_mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock pool_lock = sys_mutex_lock_e(&G.cache.node_pool_mutex);
|
||||||
if (G.cache.node_pool_first_free) {
|
if (G.cache.node_pool_first_free) {
|
||||||
n = G.cache.node_pool_first_free;
|
n = G.cache.node_pool_first_free;
|
||||||
G.cache.node_pool_first_free = n->next_free;
|
G.cache.node_pool_first_free = n->next_free;
|
||||||
@ -605,8 +604,8 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
|
|||||||
} else {
|
} else {
|
||||||
n = arena_push_zero(&G.cache.arena, struct cache_node);
|
n = arena_push_zero(&G.cache.arena, struct cache_node);
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&pool_lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.cache.node_pool_mutex);
|
|
||||||
/* Init node and add to bucket */
|
/* Init node and add to bucket */
|
||||||
scope_ensure_reference(scope, n, cache_bucket_index);
|
scope_ensure_reference(scope, n, cache_bucket_index);
|
||||||
*nonmatching_next = n;
|
*nonmatching_next = n;
|
||||||
@ -619,7 +618,7 @@ INTERNAL struct cache_node *node_lookup_touch(struct sprite_scope *scope, struct
|
|||||||
n->texture = G.nil_texture;
|
n->texture = G.nil_texture;
|
||||||
n->sheet = G.nil_sheet;
|
n->sheet = G.nil_sheet;
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_exclusive(&bucket->rw_mutex);
|
sys_mutex_unlock(&bucket_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@ -657,8 +656,8 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
|
|||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sys_mutex_lock(&G.load_cmds_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.load_cmds_mutex);
|
||||||
{
|
|
||||||
/* Allocate cmd */
|
/* Allocate cmd */
|
||||||
struct load_cmd *cmd = NULL;
|
struct load_cmd *cmd = NULL;
|
||||||
if (G.first_free_load_cmd) {
|
if (G.first_free_load_cmd) {
|
||||||
@ -683,8 +682,8 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
|
|||||||
|
|
||||||
/* Push work */
|
/* Push work */
|
||||||
work_push_task(&sprite_load_task, cmd, WORK_PRIORITY_NORMAL);
|
work_push_task(&sprite_load_task, cmd, WORK_PRIORITY_NORMAL);
|
||||||
}
|
|
||||||
sys_mutex_unlock(&G.load_cmds_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -774,12 +773,12 @@ INTERNAL WORK_TASK_FUNC_DEF(sprite_load_task, arg)
|
|||||||
|
|
||||||
/* Free cmd */
|
/* Free cmd */
|
||||||
node_refcount_add(n, -1);
|
node_refcount_add(n, -1);
|
||||||
sys_mutex_lock(&G.load_cmds_mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.load_cmds_mutex);
|
||||||
cmd->next_free = G.first_free_load_cmd;
|
cmd->next_free = G.first_free_load_cmd;
|
||||||
G.first_free_load_cmd = cmd;
|
G.first_free_load_cmd = cmd;
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.load_cmds_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -801,8 +800,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
{
|
{
|
||||||
(UNUSED)arg;
|
(UNUSED)arg;
|
||||||
|
|
||||||
sys_mutex_lock(&G.evictor_mutex);
|
struct sys_lock evictor_lock = sys_mutex_lock_e(&G.evictor_mutex);
|
||||||
{
|
|
||||||
while (!G.evictor_shutdown) {
|
while (!G.evictor_shutdown) {
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
struct evict_node *head_consider = NULL;
|
struct evict_node *head_consider = NULL;
|
||||||
@ -817,7 +815,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
__profscope(eviction_scan);
|
__profscope(eviction_scan);
|
||||||
for (u64 i = 0; i < CACHE_BUCKETS_COUNT; ++i) {
|
for (u64 i = 0; i < CACHE_BUCKETS_COUNT; ++i) {
|
||||||
struct cache_bucket *bucket = &G.cache.buckets[i];
|
struct cache_bucket *bucket = &G.cache.buckets[i];
|
||||||
sys_rw_mutex_lock_shared(&bucket->rw_mutex);
|
struct sys_lock bucket_lock = sys_mutex_lock_s(&bucket->mutex);
|
||||||
{
|
{
|
||||||
struct cache_node *n = bucket->first;
|
struct cache_node *n = bucket->first;
|
||||||
while (n) {
|
while (n) {
|
||||||
@ -883,8 +881,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
|
|
||||||
n = n->next_hash;
|
n = n->next_hash;
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_shared(&bucket->rw_mutex);
|
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&bucket_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -916,7 +914,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
for (struct evict_node *en = head_consider_lru; en && !stop_evicting; en = en->next_consider_lru) {
|
for (struct evict_node *en = head_consider_lru; en && !stop_evicting; en = en->next_consider_lru) {
|
||||||
struct cache_bucket *bucket = en->cache_bucket;
|
struct cache_bucket *bucket = en->cache_bucket;
|
||||||
struct cache_node *n = en->cache_node;
|
struct cache_node *n = en->cache_node;
|
||||||
sys_rw_mutex_lock_exclusive(&bucket->rw_mutex);
|
struct sys_lock bucket_lock = sys_mutex_lock_e(&bucket->mutex);
|
||||||
{
|
{
|
||||||
struct cache_node_refcount refcount = *(struct cache_node_refcount *)atomic_u64_raw(&n->refcount_struct);
|
struct cache_node_refcount refcount = *(struct cache_node_refcount *)atomic_u64_raw(&n->refcount_struct);
|
||||||
if (refcount.count > 0 || ((refcount.last_modified_cycle != en->refcount.last_modified_cycle) && !en->force_evict)) {
|
if (refcount.count > 0 || ((refcount.last_modified_cycle != en->refcount.last_modified_cycle) && !en->force_evict)) {
|
||||||
@ -940,7 +938,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
stop_evicting = true;
|
stop_evicting = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_exclusive(&bucket->rw_mutex);
|
sys_mutex_unlock(&bucket_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -958,24 +956,23 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add evicted nodes to free list */
|
/* Add evicted nodes to free list */
|
||||||
sys_mutex_lock(&G.cache.node_pool_mutex);
|
|
||||||
{
|
{
|
||||||
__profscope(eviction_free_list_append);
|
__profscope(eviction_free_list_append);
|
||||||
|
struct sys_lock pool_lock = sys_mutex_lock_e(&G.cache.node_pool_mutex);
|
||||||
for (struct evict_node *en = head_evicted; en; en = en->next_evicted) {
|
for (struct evict_node *en = head_evicted; en; en = en->next_evicted) {
|
||||||
struct cache_node *n = en->cache_node;
|
struct cache_node *n = en->cache_node;
|
||||||
n->next_free = G.cache.node_pool_first_free;
|
n->next_free = G.cache.node_pool_first_free;
|
||||||
G.cache.node_pool_first_free = n;
|
G.cache.node_pool_first_free = n;
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&pool_lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.cache.node_pool_mutex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
atomic_u32_inc_eval(&G.evictor_cycle);
|
atomic_u32_inc_eval(&G.evictor_cycle);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
/* Wait */
|
/* Wait */
|
||||||
sys_condition_variable_wait_time(&G.evictor_cv, &G.evictor_mutex, EVICTOR_CYCLE_INTERVAL);
|
sys_condition_variable_wait_time(&G.evictor_cv, &evictor_lock, EVICTOR_CYCLE_INTERVAL);
|
||||||
}
|
}
|
||||||
}
|
sys_mutex_unlock(&evictor_lock);
|
||||||
sys_mutex_unlock(&G.evictor_mutex);
|
|
||||||
}
|
}
|
||||||
|
|||||||
51
src/sys.h
51
src/sys.h
@ -334,48 +334,27 @@ struct sys_mutex {
|
|||||||
u64 handle;
|
u64 handle;
|
||||||
#if RTC
|
#if RTC
|
||||||
u64 owner_tid;
|
u64 owner_tid;
|
||||||
|
struct atomic_i64 count;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sys_lock {
|
||||||
|
b32 exclusive;
|
||||||
|
struct sys_mutex *mutex;
|
||||||
|
};
|
||||||
|
|
||||||
struct sys_mutex sys_mutex_alloc(void);
|
struct sys_mutex sys_mutex_alloc(void);
|
||||||
void sys_mutex_release(struct sys_mutex *mutex);
|
void sys_mutex_release(struct sys_mutex *mutex);
|
||||||
void sys_mutex_lock(struct sys_mutex *mutex);
|
struct sys_lock sys_mutex_lock_e(struct sys_mutex *mutex);
|
||||||
void sys_mutex_unlock(struct sys_mutex *mutex);
|
struct sys_lock sys_mutex_lock_s(struct sys_mutex *mutex);
|
||||||
|
void sys_mutex_unlock(struct sys_lock *lock);
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
void sys_mutex_assert_locked(struct sys_mutex *mutex);
|
void sys_assert_locked_e(struct sys_lock *lock, struct sys_mutex *mutex);
|
||||||
|
void sys_assert_locked_s(struct sys_lock *lock, struct sys_mutex *mutex);
|
||||||
#else
|
#else
|
||||||
# define sys_mutex_assert_locked(m)
|
# define sys_assert_locked_e(l, m)
|
||||||
#endif
|
# define sys_assert_locked_s(l, m)
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* RW Mutex
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
struct sys_rw_mutex {
|
|
||||||
u64 handle;
|
|
||||||
#if RTC
|
|
||||||
struct atomic_i64 num_shared;
|
|
||||||
u64 owner_tid;
|
|
||||||
# if _WIN32
|
|
||||||
wchar_t *owner_name;
|
|
||||||
# else
|
|
||||||
char *owner_name;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sys_rw_mutex sys_rw_mutex_alloc(void);
|
|
||||||
void sys_rw_mutex_release(struct sys_rw_mutex *mutex);
|
|
||||||
void sys_rw_mutex_lock_exclusive(struct sys_rw_mutex *mutex);
|
|
||||||
void sys_rw_mutex_unlock_exclusive(struct sys_rw_mutex *mutex);
|
|
||||||
void sys_rw_mutex_lock_shared(struct sys_rw_mutex *mutex);
|
|
||||||
void sys_rw_mutex_unlock_shared(struct sys_rw_mutex *mutex);
|
|
||||||
|
|
||||||
#if RTC
|
|
||||||
void sys_rw_mutex_assert_locked_exclusive(struct sys_rw_mutex *mutex);
|
|
||||||
#else
|
|
||||||
# define sys_rw_mutex_assert_locked_exclusive(m)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -391,8 +370,8 @@ struct sys_condition_variable {
|
|||||||
|
|
||||||
struct sys_condition_variable sys_condition_variable_alloc(void);
|
struct sys_condition_variable sys_condition_variable_alloc(void);
|
||||||
void sys_condition_variable_release(struct sys_condition_variable *cv);
|
void sys_condition_variable_release(struct sys_condition_variable *cv);
|
||||||
void sys_condition_variable_wait(struct sys_condition_variable *cv, struct sys_mutex *mutex);
|
void sys_condition_variable_wait(struct sys_condition_variable *cv, struct sys_lock *lock);
|
||||||
void sys_condition_variable_wait_time(struct sys_condition_variable *cv, struct sys_mutex *mutex, f64 seconds);
|
void sys_condition_variable_wait_time(struct sys_condition_variable *cv, struct sys_lock *lock, f64 seconds);
|
||||||
void sys_condition_variable_signal(struct sys_condition_variable *cv, u32 count);
|
void sys_condition_variable_signal(struct sys_condition_variable *cv, u32 count);
|
||||||
void sys_condition_variable_broadcast(struct sys_condition_variable *cv);
|
void sys_condition_variable_broadcast(struct sys_condition_variable *cv);
|
||||||
|
|
||||||
|
|||||||
226
src/sys_win32.c
226
src/sys_win32.c
@ -68,7 +68,7 @@ struct win32_window {
|
|||||||
|
|
||||||
u16 utf16_high_surrogate_last_input;
|
u16 utf16_high_surrogate_last_input;
|
||||||
|
|
||||||
struct sys_rw_mutex settings_rw_mutex;
|
struct sys_mutex settings_mutex;
|
||||||
struct sys_window_settings settings;
|
struct sys_window_settings settings;
|
||||||
|
|
||||||
i32 monitor_width;
|
i32 monitor_width;
|
||||||
@ -119,7 +119,7 @@ GLOBAL struct {
|
|||||||
struct win32_condition_variable *first_free_condition_variable;
|
struct win32_condition_variable *first_free_condition_variable;
|
||||||
|
|
||||||
/* Thread params */
|
/* Thread params */
|
||||||
struct sys_rw_mutex threads_rw_mutex;
|
struct sys_mutex threads_mutex;
|
||||||
struct arena threads_arena;
|
struct arena threads_arena;
|
||||||
struct win32_thread *threads_first;
|
struct win32_thread *threads_first;
|
||||||
struct win32_thread *threads_last;
|
struct win32_thread *threads_last;
|
||||||
@ -674,13 +674,11 @@ INTERNAL void win32_update_window_from_system(struct win32_window *window);
|
|||||||
|
|
||||||
INTERNAL void win32_window_process_event(struct win32_window *window, struct sys_event event)
|
INTERNAL void win32_window_process_event(struct win32_window *window, struct sys_event event)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&window->event_callbacks_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&window->event_callbacks_mutex);
|
||||||
{
|
|
||||||
for (u64 i = 0; i < window->event_callbacks_count; ++i) {
|
for (u64 i = 0; i < window->event_callbacks_count; ++i) {
|
||||||
window->event_callbacks[i](event);
|
window->event_callbacks[i](event);
|
||||||
}
|
}
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&window->event_callbacks_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL HWND win32_create_window(struct win32_window *window)
|
INTERNAL HWND win32_create_window(struct win32_window *window)
|
||||||
@ -802,24 +800,23 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(window_thread_entry_point, arg)
|
|||||||
INTERNAL struct win32_window *win32_window_alloc(void)
|
INTERNAL struct win32_window *win32_window_alloc(void)
|
||||||
{
|
{
|
||||||
struct win32_window *window = NULL;
|
struct win32_window *window = NULL;
|
||||||
|
|
||||||
sys_mutex_lock(&G.windows_mutex);
|
|
||||||
{
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.windows_mutex);
|
||||||
if (G.first_free_window) {
|
if (G.first_free_window) {
|
||||||
window = G.first_free_window;
|
window = G.first_free_window;
|
||||||
G.first_free_window = window->next_free;
|
G.first_free_window = window->next_free;
|
||||||
} else {
|
} else {
|
||||||
window = arena_push(&G.windows_arena, struct win32_window);
|
window = arena_push(&G.windows_arena, struct win32_window);
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.windows_mutex);
|
|
||||||
MEMZERO_STRUCT(window);
|
MEMZERO_STRUCT(window);
|
||||||
|
|
||||||
/* Allocate sync flag */
|
/* Allocate sync flag */
|
||||||
window->ready_sf = sync_flag_alloc();
|
window->ready_sf = sync_flag_alloc();
|
||||||
|
|
||||||
/* Allocate mutexes */
|
/* Allocate mutexes */
|
||||||
window->settings_rw_mutex = sys_rw_mutex_alloc();
|
window->settings_mutex = sys_mutex_alloc();
|
||||||
window->event_callbacks_mutex = sys_mutex_alloc();
|
window->event_callbacks_mutex = sys_mutex_alloc();
|
||||||
|
|
||||||
/* Start window thread for processing events */
|
/* Start window thread for processing events */
|
||||||
@ -833,8 +830,8 @@ INTERNAL struct win32_window *win32_window_alloc(void)
|
|||||||
|
|
||||||
INTERNAL void win32_window_release(struct win32_window *window)
|
INTERNAL void win32_window_release(struct win32_window *window)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.windows_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.windows_mutex);
|
||||||
{
|
|
||||||
window->next_free = G.first_free_window;
|
window->next_free = G.first_free_window;
|
||||||
G.first_free_window = window;
|
G.first_free_window = window;
|
||||||
|
|
||||||
@ -844,12 +841,12 @@ INTERNAL void win32_window_release(struct win32_window *window)
|
|||||||
|
|
||||||
/* Release mutexes */
|
/* Release mutexes */
|
||||||
sys_mutex_release(&window->event_callbacks_mutex);
|
sys_mutex_release(&window->event_callbacks_mutex);
|
||||||
sys_rw_mutex_release(&window->settings_rw_mutex);
|
sys_mutex_release(&window->settings_mutex);
|
||||||
|
|
||||||
/* Release sync flag */
|
/* Release sync flag */
|
||||||
sync_flag_release(&window->ready_sf);
|
sync_flag_release(&window->ready_sf);
|
||||||
}
|
|
||||||
sys_mutex_unlock(&G.windows_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void win32_update_window_from_system(struct win32_window *window)
|
INTERNAL void win32_update_window_from_system(struct win32_window *window)
|
||||||
@ -1211,8 +1208,7 @@ void sys_window_release(struct sys_window *sys_window)
|
|||||||
void sys_window_register_event_callback(struct sys_window *sys_window, sys_window_event_callback_func *func)
|
void sys_window_register_event_callback(struct sys_window *sys_window, sys_window_event_callback_func *func)
|
||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&window->event_callbacks_mutex);
|
||||||
sys_mutex_lock(&window->event_callbacks_mutex);
|
|
||||||
{
|
{
|
||||||
if (window->event_callbacks_count + 1 > ARRAY_COUNT(window->event_callbacks)) {
|
if (window->event_callbacks_count + 1 > ARRAY_COUNT(window->event_callbacks)) {
|
||||||
sys_panic(STR("Too many window event callbacks registered"));
|
sys_panic(STR("Too many window event callbacks registered"));
|
||||||
@ -1220,14 +1216,14 @@ void sys_window_register_event_callback(struct sys_window *sys_window, sys_windo
|
|||||||
window->event_callbacks[window->event_callbacks_count++] = func;
|
window->event_callbacks[window->event_callbacks_count++] = func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&window->event_callbacks_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_window_unregister_event_callback(struct sys_window *sys_window, sys_window_event_callback_func *func)
|
void sys_window_unregister_event_callback(struct sys_window *sys_window, sys_window_event_callback_func *func)
|
||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
||||||
|
|
||||||
sys_mutex_lock(&window->event_callbacks_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&window->event_callbacks_mutex);
|
||||||
{
|
{
|
||||||
u64 count = window->event_callbacks_count;
|
u64 count = window->event_callbacks_count;
|
||||||
sys_window_event_callback_func *last = count > 0 ? window->event_callbacks[count - 1] : NULL;
|
sys_window_event_callback_func *last = count > 0 ? window->event_callbacks[count - 1] : NULL;
|
||||||
@ -1242,18 +1238,18 @@ void sys_window_unregister_event_callback(struct sys_window *sys_window, sys_win
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&window->event_callbacks_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_window_update_settings(struct sys_window *sys_window, struct sys_window_settings *settings)
|
void sys_window_update_settings(struct sys_window *sys_window, struct sys_window_settings *settings)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
||||||
sys_rw_mutex_lock_exclusive(&window->settings_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&window->settings_mutex);
|
||||||
{
|
{
|
||||||
win32_update_window_from_settings(window, settings);
|
win32_update_window_from_settings(window, settings);
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_exclusive(&window->settings_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Lock settings mutex for these functions */
|
/* FIXME: Lock settings mutex for these functions */
|
||||||
@ -1268,7 +1264,7 @@ void sys_window_show(struct sys_window *sys_window)
|
|||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
struct win32_window *window = (struct win32_window *)sys_window->handle;
|
||||||
HWND hwnd = window->hwnd;
|
HWND hwnd = window->hwnd;
|
||||||
sys_rw_mutex_lock_exclusive(&window->settings_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&window->settings_mutex);
|
||||||
{
|
{
|
||||||
i32 show_cmd = SW_NORMAL;
|
i32 show_cmd = SW_NORMAL;
|
||||||
struct sys_window_settings *settings = &window->settings;
|
struct sys_window_settings *settings = &window->settings;
|
||||||
@ -1281,7 +1277,7 @@ void sys_window_show(struct sys_window *sys_window)
|
|||||||
ShowWindow(hwnd, show_cmd);
|
ShowWindow(hwnd, show_cmd);
|
||||||
BringWindowToTop(hwnd);
|
BringWindowToTop(hwnd);
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_exclusive(&window->settings_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 sys_window_get_size(struct sys_window *sys_window)
|
struct v2 sys_window_get_size(struct sys_window *sys_window)
|
||||||
@ -1357,101 +1353,61 @@ void sys_mutex_release(struct sys_mutex *mutex)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
(UNUSED)mutex;
|
(UNUSED)mutex;
|
||||||
/* Mutex must be unlocked */
|
/* Mutex should be unlocked */
|
||||||
ASSERT(mutex->owner_tid == 0);
|
ASSERT(atomic_i64_eval(&mutex->count) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_mutex_lock(struct sys_mutex *mutex)
|
struct sys_lock sys_mutex_lock_e(struct sys_mutex *mutex)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
AcquireSRWLockExclusive((SRWLOCK *)&mutex->handle);
|
AcquireSRWLockExclusive((SRWLOCK *)&mutex->handle);
|
||||||
#if RTC
|
#if RTC
|
||||||
mutex->owner_tid = (u64)GetCurrentThreadId();
|
mutex->owner_tid = (u64)GetCurrentThreadId();
|
||||||
|
atomic_i64_inc_eval(&mutex->count);
|
||||||
#endif
|
#endif
|
||||||
|
struct sys_lock lock = { 0 };
|
||||||
|
lock.exclusive = true;
|
||||||
|
lock.mutex = mutex;
|
||||||
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_mutex_unlock(struct sys_mutex *mutex)
|
struct sys_lock sys_mutex_lock_s(struct sys_mutex *mutex)
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
#if RTC
|
|
||||||
mutex->owner_tid = 0;
|
|
||||||
#endif
|
|
||||||
ReleaseSRWLockExclusive((SRWLOCK *)&mutex->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if RTC
|
|
||||||
void sys_mutex_assert_locked(struct sys_mutex *mutex)
|
|
||||||
{
|
|
||||||
ASSERT(mutex->owner_tid == (u64)GetCurrentThreadId());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* RW Mutex
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
struct sys_rw_mutex sys_rw_mutex_alloc(void)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
SRWLOCK srwlock;
|
|
||||||
InitializeSRWLock(&srwlock);
|
|
||||||
struct sys_rw_mutex mutex = {
|
|
||||||
.handle = *(u64 *)&srwlock
|
|
||||||
};
|
|
||||||
return mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sys_rw_mutex_release(struct sys_rw_mutex *mutex)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
(UNUSED)mutex;
|
|
||||||
/* Mutex must be unlocked */
|
|
||||||
ASSERT(mutex->owner_tid == 0);
|
|
||||||
ASSERT(atomic_i64_eval(&mutex->num_shared) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sys_rw_mutex_lock_exclusive(struct sys_rw_mutex *mutex)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
AcquireSRWLockExclusive((SRWLOCK *)&mutex->handle);
|
|
||||||
#if RTC
|
|
||||||
mutex->owner_tid = (u64)GetCurrentThreadId();
|
|
||||||
GetThreadDescription(GetCurrentThread(), &mutex->owner_name);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void sys_rw_mutex_unlock_exclusive(struct sys_rw_mutex *mutex)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
#if RTC
|
|
||||||
mutex->owner_name = L"None";
|
|
||||||
mutex->owner_tid = 0;
|
|
||||||
#endif
|
|
||||||
ReleaseSRWLockExclusive((SRWLOCK *)&mutex->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sys_rw_mutex_lock_shared(struct sys_rw_mutex *mutex)
|
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
AcquireSRWLockShared((SRWLOCK *)&mutex->handle);
|
AcquireSRWLockShared((SRWLOCK *)&mutex->handle);
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_i64_inc_eval(&mutex->num_shared);
|
atomic_i64_inc_eval(&mutex->count);
|
||||||
#endif
|
#endif
|
||||||
|
struct sys_lock lock = { 0 };
|
||||||
|
lock.mutex = mutex;
|
||||||
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_rw_mutex_unlock_shared(struct sys_rw_mutex *mutex)
|
void sys_mutex_unlock(struct sys_lock *lock)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_i64_dec_eval(&mutex->num_shared);
|
atomic_i64_dec_eval(&lock->mutex->count);
|
||||||
|
lock->mutex->owner_tid = 0;
|
||||||
#endif
|
#endif
|
||||||
ReleaseSRWLockShared((SRWLOCK *)&mutex->handle);
|
if (lock->exclusive) {
|
||||||
|
ReleaseSRWLockExclusive((SRWLOCK *)&lock->mutex->handle);
|
||||||
|
} else {
|
||||||
|
ReleaseSRWLockShared((SRWLOCK *)&lock->mutex->handle);
|
||||||
|
}
|
||||||
|
MEMZERO_STRUCT(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
void sys_rw_mutex_assert_locked_exclusive(struct sys_rw_mutex *mutex)
|
void sys_assert_locked_e(struct sys_lock *lock, struct sys_mutex *mutex)
|
||||||
{
|
{
|
||||||
ASSERT(mutex->owner_tid == (u64)GetCurrentThreadId());
|
ASSERT(lock->mutex == mutex);
|
||||||
|
ASSERT(lock->exclusive == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_assert_locked_s(struct sys_lock *lock, struct sys_mutex *mutex)
|
||||||
|
{
|
||||||
|
ASSERT(lock->mutex == mutex);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1464,16 +1420,14 @@ INTERNAL struct win32_condition_variable *win32_condition_variable_alloc(void)
|
|||||||
__prof;
|
__prof;
|
||||||
struct win32_condition_variable *cv = NULL;
|
struct win32_condition_variable *cv = NULL;
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.condition_variables_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.condition_variables_mutex);
|
||||||
{
|
|
||||||
if (G.first_free_condition_variable) {
|
if (G.first_free_condition_variable) {
|
||||||
cv = G.first_free_condition_variable;
|
cv = G.first_free_condition_variable;
|
||||||
G.first_free_condition_variable = cv->next_free;
|
G.first_free_condition_variable = cv->next_free;
|
||||||
} else {
|
} else {
|
||||||
cv = arena_push_zero(&G.condition_variables_arena, struct win32_condition_variable);
|
cv = arena_push_zero(&G.condition_variables_arena, struct win32_condition_variable);
|
||||||
}
|
}
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.condition_variables_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MEMZERO_STRUCT(cv);
|
MEMZERO_STRUCT(cv);
|
||||||
@ -1485,13 +1439,10 @@ INTERNAL struct win32_condition_variable *win32_condition_variable_alloc(void)
|
|||||||
INTERNAL void win32_condition_variable_release(struct win32_condition_variable *w32cv)
|
INTERNAL void win32_condition_variable_release(struct win32_condition_variable *w32cv)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&G.condition_variables_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.condition_variables_mutex);
|
||||||
{
|
|
||||||
w32cv->next_free = G.first_free_condition_variable;
|
w32cv->next_free = G.first_free_condition_variable;
|
||||||
G.first_free_condition_variable = w32cv;
|
G.first_free_condition_variable = w32cv;
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&G.condition_variables_mutex);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_condition_variable sys_condition_variable_alloc(void)
|
struct sys_condition_variable sys_condition_variable_alloc(void)
|
||||||
@ -1511,33 +1462,49 @@ void sys_condition_variable_release(struct sys_condition_variable *cv)
|
|||||||
win32_condition_variable_release((struct win32_condition_variable *)cv->handle);
|
win32_condition_variable_release((struct win32_condition_variable *)cv->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_condition_variable_wait(struct sys_condition_variable *cv, struct sys_mutex *mutex)
|
void sys_condition_variable_wait(struct sys_condition_variable *cv, struct sys_lock *lock)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
struct sys_mutex *mutex = lock->mutex;
|
||||||
|
b32 exclusive = lock->exclusive;
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_i64_inc_eval(&cv->num_waiters);
|
atomic_i64_inc_eval(&cv->num_waiters);
|
||||||
|
if (exclusive) {
|
||||||
mutex->owner_tid = 0;
|
mutex->owner_tid = 0;
|
||||||
|
}
|
||||||
|
atomic_i64_dec_eval(&mutex->count);
|
||||||
#endif
|
#endif
|
||||||
struct win32_condition_variable *w32cv = (struct win32_condition_variable *)cv->handle;
|
struct win32_condition_variable *w32cv = (struct win32_condition_variable *)cv->handle;
|
||||||
SleepConditionVariableSRW(&w32cv->condition_variable, (SRWLOCK *)&mutex->handle, INFINITE, 0);
|
SleepConditionVariableSRW(&w32cv->condition_variable, (SRWLOCK *)&mutex->handle, INFINITE, exclusive ? 0 : CONDITION_VARIABLE_LOCKMODE_SHARED);
|
||||||
#if RTC
|
#if RTC
|
||||||
|
atomic_i64_inc_eval(&mutex->count);
|
||||||
|
if (exclusive) {
|
||||||
mutex->owner_tid = (u64)GetCurrentThreadId();
|
mutex->owner_tid = (u64)GetCurrentThreadId();
|
||||||
|
}
|
||||||
atomic_i64_dec_eval(&cv->num_waiters);
|
atomic_i64_dec_eval(&cv->num_waiters);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_condition_variable_wait_time(struct sys_condition_variable *cv, struct sys_mutex *mutex, f64 seconds)
|
void sys_condition_variable_wait_time(struct sys_condition_variable *cv, struct sys_lock *lock, f64 seconds)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
struct sys_mutex *mutex = lock->mutex;
|
||||||
|
b32 exclusive = lock->exclusive;
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_i64_inc_eval(&cv->num_waiters);
|
atomic_i64_inc_eval(&cv->num_waiters);
|
||||||
|
if (exclusive) {
|
||||||
mutex->owner_tid = 0;
|
mutex->owner_tid = 0;
|
||||||
|
}
|
||||||
|
atomic_i64_dec_eval(&mutex->count);
|
||||||
#endif
|
#endif
|
||||||
struct win32_condition_variable *w32cv = (struct win32_condition_variable *)cv->handle;
|
struct win32_condition_variable *w32cv = (struct win32_condition_variable *)cv->handle;
|
||||||
u32 ms = (u32)math_round_to_int((f32)seconds * 1000.f);
|
u32 ms = (u32)math_round_to_int((f32)seconds * 1000.f);
|
||||||
SleepConditionVariableSRW(&w32cv->condition_variable, (SRWLOCK *)&mutex->handle, ms, 0);
|
SleepConditionVariableSRW(&w32cv->condition_variable, (SRWLOCK *)&mutex->handle, ms, exclusive ? 0 : CONDITION_VARIABLE_LOCKMODE_SHARED);
|
||||||
#if RTC
|
#if RTC
|
||||||
|
atomic_i64_inc_eval(&mutex->count);
|
||||||
|
if (exclusive) {
|
||||||
mutex->owner_tid = (u64)GetCurrentThreadId();
|
mutex->owner_tid = (u64)GetCurrentThreadId();
|
||||||
|
}
|
||||||
atomic_i64_dec_eval(&cv->num_waiters);
|
atomic_i64_dec_eval(&cv->num_waiters);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1610,8 +1577,10 @@ struct thread_local_store *sys_thread_get_thread_local_store(void)
|
|||||||
* Threads
|
* Threads
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct win32_thread *win32_thread_alloc_assume_locked(void)
|
INTERNAL struct win32_thread *win32_thread_alloc_assume_locked(struct sys_lock *lock)
|
||||||
{
|
{
|
||||||
|
sys_assert_locked_e(lock, &G.threads_mutex);
|
||||||
|
|
||||||
struct win32_thread *t = NULL;
|
struct win32_thread *t = NULL;
|
||||||
if (G.threads_first_free) {
|
if (G.threads_first_free) {
|
||||||
t = G.threads_first_free;
|
t = G.threads_first_free;
|
||||||
@ -1631,8 +1600,10 @@ INTERNAL struct win32_thread *win32_thread_alloc_assume_locked(void)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void win32_thread_release_assume_locked(struct win32_thread *t)
|
INTERNAL void win32_thread_release_assume_locked(struct sys_lock *lock, struct win32_thread *t)
|
||||||
{
|
{
|
||||||
|
sys_assert_locked_e(lock, &G.threads_mutex);
|
||||||
|
|
||||||
if (t->prev) {
|
if (t->prev) {
|
||||||
t->prev->next = t->next;
|
t->prev->next = t->next;
|
||||||
}
|
}
|
||||||
@ -1652,8 +1623,10 @@ INTERNAL void win32_thread_release_assume_locked(struct win32_thread *t)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct win32_thread *win32_thread_from_sys_thread_assume_locked(struct sys_thread st)
|
INTERNAL struct win32_thread *win32_thread_from_sys_thread_assume_locked(struct sys_lock *lock, struct sys_thread st)
|
||||||
{
|
{
|
||||||
|
sys_assert_locked_s(lock, &G.threads_mutex);
|
||||||
|
|
||||||
u64 gen = st.handle[0];
|
u64 gen = st.handle[0];
|
||||||
struct win32_thread *t = (struct win32_thread *)st.handle[1];
|
struct win32_thread *t = (struct win32_thread *)st.handle[1];
|
||||||
if (t->gen == gen) {
|
if (t->gen == gen) {
|
||||||
@ -1663,8 +1636,10 @@ INTERNAL struct win32_thread *win32_thread_from_sys_thread_assume_locked(struct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct sys_thread sys_thread_from_win32_thread_assume_locked(struct win32_thread *t)
|
INTERNAL struct sys_thread sys_thread_from_win32_thread_assume_locked(struct sys_lock *lock, struct win32_thread *t)
|
||||||
{
|
{
|
||||||
|
sys_assert_locked_s(lock, &G.threads_mutex);
|
||||||
|
|
||||||
return (struct sys_thread) {
|
return (struct sys_thread) {
|
||||||
.handle[0] = t->gen,
|
.handle[0] = t->gen,
|
||||||
.handle[1] = (u64)t
|
.handle[1] = (u64)t
|
||||||
@ -1697,11 +1672,11 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
|
|||||||
t->entry_point(t->thread_data);
|
t->entry_point(t->thread_data);
|
||||||
|
|
||||||
/* Release thread object */
|
/* Release thread object */
|
||||||
sys_rw_mutex_lock_exclusive(&G.threads_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
|
||||||
{
|
{
|
||||||
win32_thread_release_assume_locked(t);
|
win32_thread_release_assume_locked(&lock, t);
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_exclusive(&G.threads_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
/* Release TLS */
|
/* Release TLS */
|
||||||
win32_tls_release(&tls);
|
win32_tls_release(&tls);
|
||||||
@ -1718,10 +1693,10 @@ struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, voi
|
|||||||
logf_info("Creating thread \"%F\"", FMT_STR(thread_name));
|
logf_info("Creating thread \"%F\"", FMT_STR(thread_name));
|
||||||
|
|
||||||
struct sys_thread res = { 0 };
|
struct sys_thread res = { 0 };
|
||||||
sys_rw_mutex_lock_exclusive(&G.threads_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.threads_mutex);
|
||||||
{
|
{
|
||||||
/* Allocate thread object */
|
/* Allocate thread object */
|
||||||
struct win32_thread *t = win32_thread_alloc_assume_locked();
|
struct win32_thread *t = win32_thread_alloc_assume_locked(&lock);
|
||||||
t->entry_point = entry_point;
|
t->entry_point = entry_point;
|
||||||
t->thread_data = thread_data;
|
t->thread_data = thread_data;
|
||||||
|
|
||||||
@ -1741,9 +1716,10 @@ struct sys_thread sys_thread_alloc(sys_thread_entry_point_func *entry_point, voi
|
|||||||
sys_panic(STR("Failed to create thread"));
|
sys_panic(STR("Failed to create thread"));
|
||||||
}
|
}
|
||||||
|
|
||||||
res = sys_thread_from_win32_thread_assume_locked(t);
|
res = sys_thread_from_win32_thread_assume_locked(&lock, t);
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_exclusive(&G.threads_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1752,14 +1728,14 @@ void sys_thread_wait_release(struct sys_thread *thread)
|
|||||||
HANDLE handle = 0;
|
HANDLE handle = 0;
|
||||||
|
|
||||||
/* Lookup */
|
/* Lookup */
|
||||||
sys_rw_mutex_lock_shared(&G.threads_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_s(&G.threads_mutex);
|
||||||
{
|
{
|
||||||
struct win32_thread *t = win32_thread_from_sys_thread_assume_locked(*thread);
|
struct win32_thread *t = win32_thread_from_sys_thread_assume_locked(&lock, *thread);
|
||||||
if (t) {
|
if (t) {
|
||||||
handle = t->handle;
|
handle = t->handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_shared(&G.threads_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
/* Wait */
|
/* Wait */
|
||||||
if (handle) {
|
if (handle) {
|
||||||
@ -2082,7 +2058,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
G.condition_variables_arena = arena_alloc(GIGABYTE(64));
|
G.condition_variables_arena = arena_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
/* Set up threads */
|
/* Set up threads */
|
||||||
G.threads_rw_mutex = sys_rw_mutex_alloc();
|
G.threads_mutex = sys_mutex_alloc();
|
||||||
G.threads_arena = arena_alloc(GIGABYTE(64));
|
G.threads_arena = arena_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
/* Set up windows */
|
/* Set up windows */
|
||||||
@ -2154,12 +2130,12 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
|
|
||||||
/* Get app thread handle */
|
/* Get app thread handle */
|
||||||
HANDLE app_thread_handle = 0;
|
HANDLE app_thread_handle = 0;
|
||||||
sys_rw_mutex_lock_shared(&G.threads_rw_mutex);
|
struct sys_lock lock = sys_mutex_lock_s(&G.threads_mutex);
|
||||||
{
|
{
|
||||||
struct win32_thread *wt = win32_thread_from_sys_thread_assume_locked(app_thread);
|
struct win32_thread *wt = win32_thread_from_sys_thread_assume_locked(&lock, app_thread);
|
||||||
app_thread_handle = wt->handle;
|
app_thread_handle = wt->handle;
|
||||||
}
|
}
|
||||||
sys_rw_mutex_unlock_shared(&G.threads_rw_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
/* Wait for either app thread exit or panic */
|
/* Wait for either app thread exit or panic */
|
||||||
if (app_thread_handle) {
|
if (app_thread_handle) {
|
||||||
|
|||||||
@ -151,7 +151,7 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(user_shutdown)
|
|||||||
INTERNAL struct sys_event_array pop_sys_events(struct arena *arena)
|
INTERNAL struct sys_event_array pop_sys_events(struct arena *arena)
|
||||||
{
|
{
|
||||||
struct sys_event_array array = { 0 };
|
struct sys_event_array array = { 0 };
|
||||||
sys_mutex_lock(&G.sys_events_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.sys_events_mutex);
|
||||||
{
|
{
|
||||||
struct buffer events_buff = arena_to_buffer(&G.sys_events_arena);
|
struct buffer events_buff = arena_to_buffer(&G.sys_events_arena);
|
||||||
arena_align(arena, alignof(struct sys_event));
|
arena_align(arena, alignof(struct sys_event));
|
||||||
@ -160,17 +160,17 @@ INTERNAL struct sys_event_array pop_sys_events(struct arena *arena)
|
|||||||
MEMCPY(array.events, events_buff.data, events_buff.size);
|
MEMCPY(array.events, events_buff.data, events_buff.size);
|
||||||
arena_reset(&G.sys_events_arena);
|
arena_reset(&G.sys_events_arena);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.sys_events_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL SYS_WINDOW_EVENT_CALLBACK_FUNC_DEF(window_event_callback, event)
|
INTERNAL SYS_WINDOW_EVENT_CALLBACK_FUNC_DEF(window_event_callback, event)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&G.sys_events_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.sys_events_mutex);
|
||||||
{
|
{
|
||||||
*arena_push(&G.sys_events_arena, struct sys_event) = event;
|
*arena_push(&G.sys_events_arena, struct sys_event) = event;
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.sys_events_mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
45
src/util.h
45
src/util.h
@ -126,7 +126,6 @@ INLINE void *fixed_dict_get(const struct fixed_dict *dict, struct string key)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sync_flag {
|
struct sync_flag {
|
||||||
/* TODO: Make this a rw mutex? */
|
|
||||||
struct sys_mutex mutex;
|
struct sys_mutex mutex;
|
||||||
struct sys_condition_variable cv;
|
struct sys_condition_variable cv;
|
||||||
b32 flag;
|
b32 flag;
|
||||||
@ -149,24 +148,20 @@ INLINE void sync_flag_release(struct sync_flag *sf)
|
|||||||
INLINE void sync_flag_set(struct sync_flag *sf)
|
INLINE void sync_flag_set(struct sync_flag *sf)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&sf->mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&sf->mutex);
|
||||||
{
|
|
||||||
sf->flag = 1;
|
sf->flag = 1;
|
||||||
sys_condition_variable_broadcast(&sf->cv);
|
sys_condition_variable_broadcast(&sf->cv);
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&sf->mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void sync_flag_wait(struct sync_flag *sf)
|
INLINE void sync_flag_wait(struct sync_flag *sf)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&sf->mutex);
|
struct sys_lock lock = sys_mutex_lock_s(&sf->mutex);
|
||||||
{
|
while (sf->flag != 1) {
|
||||||
while (sf->flag == 0) {
|
sys_condition_variable_wait(&sf->cv, &lock);
|
||||||
sys_condition_variable_wait(&sf->cv, &sf->mutex);
|
|
||||||
}
|
}
|
||||||
}
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&sf->mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -185,32 +180,4 @@ INLINE void sleep_frame(sys_timestamp_t last_frame_time, f64 target_dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* ========================== *
|
|
||||||
* Sync buffer
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
struct sync_buff {
|
|
||||||
struct arena arena;
|
|
||||||
struct sys_mutex mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sync_buff sync_buff_alloc(u64 arena_reserve)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void sync_buff_release(struct sync_buff *sb)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE void sync_buff_read(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE void sync_buff_write(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
155
src/work.c
155
src/work.c
@ -24,11 +24,6 @@
|
|||||||
* also do work themselves (IE: callers of "work_wait")
|
* also do work themselves (IE: callers of "work_wait")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* NOTE:
|
|
||||||
* Functions suffixed with "assume_locked" require `G.mutex` to be
|
|
||||||
* locked & unlocked by the caller.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct worker {
|
struct worker {
|
||||||
struct sys_thread thread;
|
struct sys_thread thread;
|
||||||
struct worker *next;
|
struct worker *next;
|
||||||
@ -122,7 +117,7 @@ struct work_startup_receipt work_startup(u32 num_worker_threads)
|
|||||||
app_register_exit_callback(&work_shutdown);
|
app_register_exit_callback(&work_shutdown);
|
||||||
|
|
||||||
/* Initialize threads */
|
/* Initialize threads */
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
struct worker *prev = NULL;
|
struct worker *prev = NULL;
|
||||||
for (u32 i = 0; i < num_worker_threads; ++i) {
|
for (u32 i = 0; i < num_worker_threads; ++i) {
|
||||||
@ -140,7 +135,7 @@ struct work_startup_receipt work_startup(u32 num_worker_threads)
|
|||||||
prev = worker;
|
prev = worker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
@ -150,12 +145,14 @@ struct work_startup_receipt work_startup(u32 num_worker_threads)
|
|||||||
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(work_shutdown)
|
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(work_shutdown)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&G.mutex);
|
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
G.workers_shutdown = true;
|
G.workers_shutdown = true;
|
||||||
sys_condition_variable_broadcast(&G.cv);
|
sys_condition_variable_broadcast(&G.cv);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
for (struct worker *worker = G.worker_head; worker; worker = worker->next) {
|
for (struct worker *worker = G.worker_head; worker; worker = worker->next) {
|
||||||
sys_thread_wait_release(&worker->thread);
|
sys_thread_wait_release(&worker->thread);
|
||||||
}
|
}
|
||||||
@ -165,10 +162,11 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(work_shutdown)
|
|||||||
* Internal work / task allocation
|
* Internal work / task allocation
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct work *work_alloc_assume_locked(void)
|
INTERNAL struct work *work_alloc_assume_locked(struct sys_lock *lock)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct work *work = NULL;
|
struct work *work = NULL;
|
||||||
|
|
||||||
/* Allocate work */
|
/* Allocate work */
|
||||||
@ -191,26 +189,29 @@ INTERNAL struct work *work_alloc_assume_locked(void)
|
|||||||
return work;
|
return work;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void work_release_assume_locked(struct work *work)
|
INTERNAL void work_release_assume_locked(struct sys_lock *lock, struct work *work)
|
||||||
{
|
{
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
work->next_free = G.free_work_head;
|
work->next_free = G.free_work_head;
|
||||||
G.free_work_head = work;
|
G.free_work_head = work;
|
||||||
++work->gen;
|
++work->gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct work_handle work_to_handle_assume_locked(struct work *work)
|
INTERNAL struct work_handle work_to_handle_assume_locked(struct sys_lock *lock, struct work *work)
|
||||||
{
|
{
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
return (struct work_handle) {
|
return (struct work_handle) {
|
||||||
.work = work,
|
.work = work,
|
||||||
.gen = work->gen
|
.gen = work->gen
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct work_task *task_alloc_assume_locked(void)
|
INTERNAL struct work_task *task_alloc_assume_locked(struct sys_lock *lock)
|
||||||
{
|
{
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct work_task *task = NULL;
|
struct work_task *task = NULL;
|
||||||
|
|
||||||
/* Allocate task */
|
/* Allocate task */
|
||||||
@ -227,9 +228,10 @@ INTERNAL struct work_task *task_alloc_assume_locked(void)
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void task_release_assume_locked(struct work_task *task)
|
INTERNAL void task_release_assume_locked(struct sys_lock *lock, struct work_task *task)
|
||||||
{
|
{
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
task->next_free = G.free_task_head;
|
task->next_free = G.free_task_head;
|
||||||
G.free_task_head = task;
|
G.free_task_head = task;
|
||||||
}
|
}
|
||||||
@ -238,10 +240,11 @@ INTERNAL void task_release_assume_locked(struct work_task *task)
|
|||||||
* Work scheduling / insertion
|
* Work scheduling / insertion
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void work_schedule_assume_locked(struct work *work)
|
INTERNAL void work_schedule_assume_locked(struct sys_lock *lock, struct work *work)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
enum work_priority priority = work->priority;
|
enum work_priority priority = work->priority;
|
||||||
|
|
||||||
if (G.scheduled_work_head) {
|
if (G.scheduled_work_head) {
|
||||||
@ -275,10 +278,10 @@ INTERNAL void work_schedule_assume_locked(struct work *work)
|
|||||||
sys_condition_variable_signal(&G.cv, work->tasks_incomplete);
|
sys_condition_variable_signal(&G.cv, work->tasks_incomplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void work_unschedule_assume_locked(struct work *work)
|
INTERNAL void work_unschedule_assume_locked(struct sys_lock *lock, struct work *work)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct work *prev = (struct work *)work->prev_scheduled;
|
struct work *prev = (struct work *)work->prev_scheduled;
|
||||||
struct work *next = (struct work *)work->next_scheduled;
|
struct work *next = (struct work *)work->next_scheduled;
|
||||||
@ -306,16 +309,17 @@ INTERNAL void work_unschedule_assume_locked(struct work *work)
|
|||||||
* Task dequeuing
|
* Task dequeuing
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct work_task *work_dequeue_task_assume_locked(struct work *work)
|
INTERNAL struct work_task *work_dequeue_task_assume_locked(struct sys_lock *lock, struct work *work)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct work_task *task = work->task_head;
|
struct work_task *task = work->task_head;
|
||||||
if (task) {
|
if (task) {
|
||||||
work->task_head = task->next_in_work;
|
work->task_head = task->next_in_work;
|
||||||
if (!work->task_head) {
|
if (!work->task_head) {
|
||||||
/* Unschedule work if last task */
|
/* Unschedule work if last task */
|
||||||
work_unschedule_assume_locked(work);
|
work_unschedule_assume_locked(lock, work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return task;
|
return task;
|
||||||
@ -327,12 +331,12 @@ INTERNAL struct work_task *work_dequeue_task_assume_locked(struct work *work)
|
|||||||
|
|
||||||
/* NOTE: This function will release `work` if there are no more tasks once completed.
|
/* NOTE: This function will release `work` if there are no more tasks once completed.
|
||||||
* Returns `true` if more tasks are still present in the work after completion. */
|
* Returns `true` if more tasks are still present in the work after completion. */
|
||||||
INTERNAL b32 work_exec_single_task_maybe_release_assume_locked(struct work *work)
|
INTERNAL b32 work_exec_single_task_maybe_release_assume_locked(struct sys_lock *lock, struct work *work)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct work_task *task = work_dequeue_task_assume_locked(work);
|
struct work_task *task = work_dequeue_task_assume_locked(lock, work);
|
||||||
b32 more_tasks = work->task_head != NULL;
|
b32 more_tasks = work->task_head != NULL;
|
||||||
|
|
||||||
if (task) {
|
if (task) {
|
||||||
@ -340,15 +344,14 @@ INTERNAL b32 work_exec_single_task_maybe_release_assume_locked(struct work *work
|
|||||||
|
|
||||||
++work->workers;
|
++work->workers;
|
||||||
/* Do task (temporarily unlock) */
|
/* Do task (temporarily unlock) */
|
||||||
sys_mutex_unlock(&G.mutex);
|
|
||||||
{
|
{
|
||||||
|
sys_mutex_unlock(lock);
|
||||||
task->func(task->data);
|
task->func(task->data);
|
||||||
|
*lock = sys_mutex_lock_e(&G.mutex);
|
||||||
}
|
}
|
||||||
sys_mutex_lock(&G.mutex);
|
|
||||||
--work->workers;
|
--work->workers;
|
||||||
--work->tasks_incomplete;
|
--work->tasks_incomplete;
|
||||||
task_release_assume_locked(task);
|
task_release_assume_locked(lock, task);
|
||||||
|
|
||||||
|
|
||||||
if (work->tasks_incomplete == 0) {
|
if (work->tasks_incomplete == 0) {
|
||||||
/* Signal finished */
|
/* Signal finished */
|
||||||
@ -356,23 +359,22 @@ INTERNAL b32 work_exec_single_task_maybe_release_assume_locked(struct work *work
|
|||||||
sys_condition_variable_broadcast(&work->condition_variable_finished);
|
sys_condition_variable_broadcast(&work->condition_variable_finished);
|
||||||
|
|
||||||
/* Release */
|
/* Release */
|
||||||
work_release_assume_locked(work);
|
work_release_assume_locked(lock, work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return more_tasks;
|
return more_tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void work_exec_remaining_tasks_maybe_release_assume_locked(struct work *work)
|
INTERNAL void work_exec_remaining_tasks_maybe_release_assume_locked(struct sys_lock *lock, struct work *work)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
b32 more_tasks = true;
|
b32 more_tasks = true;
|
||||||
while (more_tasks) {
|
while (more_tasks) {
|
||||||
more_tasks = work_exec_single_task_maybe_release_assume_locked(work);
|
more_tasks = work_exec_single_task_maybe_release_assume_locked(lock, work);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -388,21 +390,21 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(worker_thread_entry_point, thread_data)
|
|||||||
.is_worker = true
|
.is_worker = true
|
||||||
};
|
};
|
||||||
|
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
while (!G.workers_shutdown) {
|
while (!G.workers_shutdown) {
|
||||||
struct work *work = G.scheduled_work_head;
|
struct work *work = G.scheduled_work_head;
|
||||||
if (work) {
|
if (work) {
|
||||||
__profscope(work_pool_task);
|
__profscope(work_pool_task);
|
||||||
--G.idle_worker_count;
|
--G.idle_worker_count;
|
||||||
work_exec_single_task_maybe_release_assume_locked(work);
|
work_exec_single_task_maybe_release_assume_locked(&lock, work);
|
||||||
++G.idle_worker_count;
|
++G.idle_worker_count;
|
||||||
} else {
|
} else {
|
||||||
sys_condition_variable_wait(&G.cv, &G.mutex);
|
sys_condition_variable_wait(&G.cv, &lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -410,13 +412,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(worker_thread_entry_point, thread_data)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* If `help` is true, then the calling thread will start picking up tasks immediately (before other workers can see it) */
|
/* If `help` is true, then the calling thread will start picking up tasks immediately (before other workers can see it) */
|
||||||
INTERNAL struct work_handle work_push_from_slate_assume_locked(struct work_slate *ws, b32 help, enum work_priority priority)
|
INTERNAL struct work_handle work_push_from_slate_assume_locked(struct sys_lock *lock, struct work_slate *ws, b32 help, enum work_priority priority)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct work *work = work_alloc_assume_locked();
|
struct work *work = work_alloc_assume_locked(lock);
|
||||||
struct work_handle wh = work_to_handle_assume_locked(work);
|
struct work_handle wh = work_to_handle_assume_locked(lock, work);
|
||||||
|
|
||||||
work->priority = priority;
|
work->priority = priority;
|
||||||
work->status = WORK_STATUS_IN_PROGRESS;
|
work->status = WORK_STATUS_IN_PROGRESS;
|
||||||
@ -424,10 +426,10 @@ INTERNAL struct work_handle work_push_from_slate_assume_locked(struct work_slate
|
|||||||
work->task_head = ws->task_head;
|
work->task_head = ws->task_head;
|
||||||
work->tasks_incomplete = ws->num_tasks;
|
work->tasks_incomplete = ws->num_tasks;
|
||||||
|
|
||||||
work_schedule_assume_locked(work);
|
work_schedule_assume_locked(lock, work);
|
||||||
|
|
||||||
if (help) {
|
if (help) {
|
||||||
work_exec_remaining_tasks_maybe_release_assume_locked(work);
|
work_exec_remaining_tasks_maybe_release_assume_locked(lock, work);
|
||||||
} else {
|
} else {
|
||||||
/* When work is submitted from a worker thread, we want the worker to pick
|
/* When work is submitted from a worker thread, we want the worker to pick
|
||||||
* up the tasks itself when idle workers = 0 and work.workers = 0
|
* up the tasks itself when idle workers = 0 and work.workers = 0
|
||||||
@ -447,7 +449,7 @@ INTERNAL struct work_handle work_push_from_slate_assume_locked(struct work_slate
|
|||||||
if (ctx->is_worker) {
|
if (ctx->is_worker) {
|
||||||
b32 work_done = false;
|
b32 work_done = false;
|
||||||
while (!work_done && G.idle_worker_count == 0 && work->workers == 0) {
|
while (!work_done && G.idle_worker_count == 0 && work->workers == 0) {
|
||||||
work_done = !work_exec_single_task_maybe_release_assume_locked(work);
|
work_done = !work_exec_single_task_maybe_release_assume_locked(lock, work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,9 +460,9 @@ INTERNAL struct work_handle work_push_from_slate_assume_locked(struct work_slate
|
|||||||
INTERNAL struct work_handle work_push_task_internal(work_task_func *func, void *data, b32 help, enum work_priority priority)
|
INTERNAL struct work_handle work_push_task_internal(work_task_func *func, void *data, b32 help, enum work_priority priority)
|
||||||
{
|
{
|
||||||
struct work_handle handle;
|
struct work_handle handle;
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
struct work_task *task = task_alloc_assume_locked();
|
struct work_task *task = task_alloc_assume_locked(&lock);
|
||||||
task->data = data;
|
task->data = data;
|
||||||
task->func = func;
|
task->func = func;
|
||||||
|
|
||||||
@ -469,10 +471,9 @@ INTERNAL struct work_handle work_push_task_internal(work_task_func *func, void *
|
|||||||
.task_tail = task,
|
.task_tail = task,
|
||||||
.num_tasks = 1
|
.num_tasks = 1
|
||||||
};
|
};
|
||||||
handle = work_push_from_slate_assume_locked(&ws, help, priority);
|
handle = work_push_from_slate_assume_locked(&lock, &ws, help, priority);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,11 +504,11 @@ void work_slate_push_task(struct work_slate *ws, work_task_func *func, void *dat
|
|||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct work_task *task = NULL;
|
struct work_task *task = NULL;
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
task = task_alloc_assume_locked();
|
task = task_alloc_assume_locked(&lock);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
task->data = data;
|
task->data = data;
|
||||||
task->func = func;
|
task->func = func;
|
||||||
@ -528,11 +529,11 @@ struct work_handle work_slate_end(struct work_slate *ws, enum work_priority prio
|
|||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct work_handle handle;
|
struct work_handle handle;
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
handle = work_push_from_slate_assume_locked(ws, false, priority);
|
handle = work_push_from_slate_assume_locked(&lock, ws, false, priority);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
@ -541,9 +542,9 @@ struct work_handle work_slate_end_and_help(struct work_slate *ws, enum work_prio
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
struct work_handle handle = work_push_from_slate_assume_locked(ws, true, priority);
|
struct work_handle handle = work_push_from_slate_assume_locked(&lock, ws, true, priority);
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
@ -552,9 +553,9 @@ struct work_handle work_slate_end_and_help(struct work_slate *ws, enum work_prio
|
|||||||
* Work intervention interface
|
* Work intervention interface
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct work *work_from_handle_assume_locked(struct work_handle handle)
|
INTERNAL struct work *work_from_handle_assume_locked(struct sys_lock *lock, struct work_handle handle)
|
||||||
{
|
{
|
||||||
sys_mutex_assert_locked(&G.mutex);
|
sys_assert_locked_e(lock, &G.mutex);
|
||||||
|
|
||||||
struct work *work = handle.work;
|
struct work *work = handle.work;
|
||||||
if (work->gen != handle.gen) {
|
if (work->gen != handle.gen) {
|
||||||
@ -568,35 +569,35 @@ INTERNAL struct work *work_from_handle_assume_locked(struct work_handle handle)
|
|||||||
void work_wait(struct work_handle handle)
|
void work_wait(struct work_handle handle)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
struct work *work = work_from_handle_assume_locked(handle);
|
struct work *work = work_from_handle_assume_locked(&lock, handle);
|
||||||
if (work) {
|
if (work) {
|
||||||
/* Help with tasks */
|
/* Help with tasks */
|
||||||
work_exec_remaining_tasks_maybe_release_assume_locked(work);
|
work_exec_remaining_tasks_maybe_release_assume_locked(&lock, work);
|
||||||
|
|
||||||
/* Wait for work completion */
|
/* Wait for work completion */
|
||||||
work = work_from_handle_assume_locked(handle); /* Re-checking work is sitll valid here in case work_do caused work to release */
|
work = work_from_handle_assume_locked(&lock, handle); /* Re-checking work is sitll valid here in case work_exec caused work to release */
|
||||||
if (work) {
|
if (work) {
|
||||||
while (work->status != WORK_STATUS_DONE) {
|
while (work->status != WORK_STATUS_DONE) {
|
||||||
sys_condition_variable_wait(&work->condition_variable_finished, &G.mutex);
|
sys_condition_variable_wait(&work->condition_variable_finished, &lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to pick up any scheduled tasks */
|
/* Try to pick up any scheduled tasks */
|
||||||
void work_help(struct work_handle handle)
|
void work_help(struct work_handle handle)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||||
|
{
|
||||||
struct work *work = work_from_handle_assume_locked(handle);
|
struct work *work = work_from_handle_assume_locked(&lock, handle);
|
||||||
if (work) {
|
if (work) {
|
||||||
work_exec_remaining_tasks_maybe_release_assume_locked(work);
|
work_exec_remaining_tasks_maybe_release_assume_locked(&lock, work);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sys_mutex_unlock(&G.mutex);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user