fix sheet evictor breaking before releasing bucket lock

This commit is contained in:
jacob 2024-04-30 17:29:33 -05:00
parent 38d9bde9e6
commit 42a2d97d3d
2 changed files with 18 additions and 20 deletions

View File

@ -136,7 +136,6 @@ GLOBAL READONLY struct sheet g_sheet_loading = {
.loading = true .loading = true
}; };
/* ========================== * /* ========================== *
* Thread local state * Thread local state
* ========================== */ * ========================== */
@ -611,13 +610,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sheet_loader_thread_entry_point, arg)
__prof; __prof;
(UNUSED)arg; (UNUSED)arg;
while (true) { b32 abort = false;
while (!abort) {
sys_mutex_lock(&G.loaders_mutex); sys_mutex_lock(&G.loaders_mutex);
if (G.loaders_shutdown) { if (G.loaders_shutdown) {
/* Thread shutdown */ /* Exit thread */
sys_mutex_unlock(&G.loaders_mutex); abort = true;
break;
} else if (!G.first_loader_cmd) { } else if (!G.first_loader_cmd) {
/* Wait for work */ /* Wait for work */
sys_condition_variable_wait(&G.loaders_cv, &G.loaders_mutex); sys_condition_variable_wait(&G.loaders_cv, &G.loaders_mutex);
@ -667,13 +666,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sheet_evictor_thread_entry_point, arg)
{ {
(UNUSED)arg; (UNUSED)arg;
while (true) { b32 abort = false;
while (!abort) {
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;
struct evict_node *head_consider_lru = NULL; struct evict_node *head_consider_lru = NULL;
struct evict_node *head_evicted = NULL; struct evict_node *head_evicted = NULL;
b32 abort = false;
sys_mutex_lock(&G.evictor_mutex); sys_mutex_lock(&G.evictor_mutex);
{ {
/* Thread shutdown */ /* Thread shutdown */
@ -729,7 +728,10 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sheet_evictor_thread_entry_point, arg)
#endif #endif
/* Check usage time */ /* Check usage time */
if (!RESOURCE_RELOADING || (!consider_for_eviction && cache_over_budget)) { #if RESOURCE_RELOADING
if (cache_over_budget) /* Only check conditional if RESOURCE_RELOADING, since over-budget is assumed to be true otherwise */
#endif
{
f64 last_used_time = (f64)refcount.last_modified_cycle * EVICTOR_CYCLE_INTERVAL; f64 last_used_time = (f64)refcount.last_modified_cycle * EVICTOR_CYCLE_INTERVAL;
if (cur_time - last_used_time > EVICTOR_GRACE_PERIOD) { if (cur_time - last_used_time > EVICTOR_GRACE_PERIOD) {
/* Cache is over budget and node hasn't been referenced in a while */ /* Cache is over budget and node hasn't been referenced in a while */
@ -782,18 +784,16 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sheet_evictor_thread_entry_point, arg)
/* Remove evictable nodes from cache table until under budget */ /* Remove evictable nodes from cache table until under budget */
if (head_consider_lru) { if (head_consider_lru) {
__profscope(eviction_cache_removal); __profscope(eviction_cache_removal);
for (struct evict_node *en = head_consider_lru; en; en = en->next_consider_lru) { b32 stop_evicting = false;
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); sys_rw_mutex_lock_exclusive(&bucket->rw_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)) {
/* Cache node has been referenced since scan, skip eviction. */ /* Cache node has been referenced since scan, skip eviction. */
continue; } else if (en->force_evict || atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET) {
}
if (en->force_evict || atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET) {
/* Remove from cache bucket */ /* Remove from cache bucket */
if (n->prev_hash) { if (n->prev_hash) {
n->prev_hash->next_hash = n->next_hash; n->prev_hash->next_hash = n->next_hash;
@ -809,7 +809,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sheet_evictor_thread_entry_point, arg)
head_evicted = en; head_evicted = en;
} else { } else {
/* Cache is no longer over budget or force evicting, stop iteration */ /* Cache is no longer over budget or force evicting, stop iteration */
break; stop_evicting = true;
} }
} }
sys_rw_mutex_unlock_exclusive(&bucket->rw_mutex); sys_rw_mutex_unlock_exclusive(&bucket->rw_mutex);
@ -843,8 +843,5 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sheet_evictor_thread_entry_point, arg)
} }
sys_mutex_unlock(&G.evictor_mutex); sys_mutex_unlock(&G.evictor_mutex);
scratch_end(scratch); scratch_end(scratch);
if (abort) {
break;
}
} }
} }

View File

@ -391,13 +391,14 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(worker_thread_entry_point, thread_data)
.is_worker = true .is_worker = true
}; };
while (true) { b32 abort = false;
while (!abort) {
sys_mutex_lock(&G.mutex); sys_mutex_lock(&G.mutex);
{ {
/* Check for exit */ /* Check for exit */
if (G.workers_shutdown) { if (G.workers_shutdown) {
sys_mutex_unlock(&G.mutex); /* Exit thread */
break; abort = true;
} else if (!G.scheduled_work_head) { } else if (!G.scheduled_work_head) {
/* Wait for work */ /* Wait for work */
sys_condition_variable_wait(&G.cv, &G.mutex); sys_condition_variable_wait(&G.cv, &G.mutex);