From: quzar <qu...@us...> - 2024-10-11 08:50:57
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 22c8c2063dc13ddfcf717aa3f5a335f8f0d493ad (commit) from b96c8042f0e7f9c51dd75216d18164dfb298fe95 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 22c8c2063dc13ddfcf717aa3f5a335f8f0d493ad Author: Falco Girgis <gyr...@gm...> Date: Fri Oct 11 03:50:26 2024 -0500 Fixed Thread Starvation Issue with Priority Boosting (#803) * Fixed thread starvation issue with priority boost - Added comments - Added #define for pseudo-IRQ Thread for sake of my sanity. :) * Only reschedule threads in STATE_READY. Previously it would allow sleeping/waiting threads to be rescheduled when they weren't in the runnable queue to begin with. Now *only* STATE_READY threads, which also helps by excluding zombie/finished threads. * Only reset priority back if you are releasing the last lock a thread holds. Previously recursive mutexes may have reverted priority after locally unlocking but before waking the thread that boosted them. ----------------------------------------------------------------------- Summary of changes: kernel/thread/mutex.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/kernel/thread/mutex.c b/kernel/thread/mutex.c index 3d438965..4490ad63 100644 --- a/kernel/thread/mutex.c +++ b/kernel/thread/mutex.c @@ -2,6 +2,7 @@ mutex.c Copyright (C) 2012, 2015 Lawrence Sebald + Copyright (C) 2024 Paul Cercueil */ @@ -16,6 +17,9 @@ #include <arch/irq.h> #include <arch/timer.h> +/* Thread pseudo-ptr representing an active IRQ context. */ +#define IRQ_THREAD ((kthread_t *)0xFFFFFFFF) + mutex_t *mutex_create(void) { mutex_t *rv; @@ -133,13 +137,17 @@ int mutex_lock_timed(mutex_t *m, int timeout) { deadline = timer_ms_gettime64() + timeout; for(;;) { + /* Check whether we should boost priority. */ if (m->holder->prio >= thd_current->prio) { m->holder->prio = thd_current->prio; - /* Thread list is sorted by priority, update the position - * of the thread holding the lock */ - thd_remove_from_runnable(m->holder); - thd_add_to_runnable(m->holder, true); + /* Reschedule if currently scheduled. */ + if(m->holder->state == STATE_READY) { + /* Thread list is sorted by priority, update the position + * of the thread holding the lock */ + thd_remove_from_runnable(m->holder); + thd_add_to_runnable(m->holder, true); + } } rv = genwait_wait(m, timeout ? "mutex_lock_timed" : "mutex_lock", @@ -181,7 +189,7 @@ int mutex_trylock(mutex_t *m) { /* If we're inside of an interrupt, pick a special value for the thread that would otherwise be impossible... */ if(irq_inside_int()) - thd = (kthread_t *)0xFFFFFFFF; + thd = IRQ_THREAD; if(m->type < MUTEX_TYPE_NORMAL || m->type > MUTEX_TYPE_RECURSIVE) { errno = EINVAL; @@ -262,12 +270,14 @@ static int mutex_unlock_common(mutex_t *m, kthread_t *thd) { return -1; } - if (thd != (kthread_t *)0xffffffff) - thd->prio = thd->real_prio; - /* If we need to wake up a thread, do so. */ - if(wakeup) + if(wakeup) { + /* Restore real priority in case we were dynamically boosted. */ + if (thd != IRQ_THREAD) + thd->prio = thd->real_prio; + genwait_wake_one(m); + } return 0; } @@ -278,7 +288,7 @@ int mutex_unlock(mutex_t *m) { /* If we're inside of an interrupt, use the special value for the thread from mutex_trylock(). */ if(irq_inside_int()) - thd = (kthread_t *)0xFFFFFFFF; + thd = IRQ_THREAD; return mutex_unlock_common(m, thd); } hooks/post-receive -- A pseudo Operating System for the Dreamcast. |