Mutexes optimizations.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1536 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
gdisirio 2010-01-21 17:25:57 +00:00
parent 8cdf2dba5b
commit 6ce3901526
2 changed files with 57 additions and 63 deletions

View File

@ -66,22 +66,21 @@ void chMtxLock(Mutex *mp) {
* block. * block.
*/ */
void chMtxLockS(Mutex *mp) { void chMtxLockS(Mutex *mp) {
Thread *ctp = currp;
chDbgCheck(mp != NULL, "chMtxLockS"); chDbgCheck(mp != NULL, "chMtxLockS");
/* Ia the mutex already locked? */ /* Ia the mutex already locked? */
if (mp->m_owner != NULL) { if (mp->m_owner != NULL) {
/* /* Priority inheritance protocol; explores the thread-mutex dependencies
* Priority inheritance protocol; explores the thread-mutex dependencies boosting the priority of all the affected threads to equal the priority
* boosting the priority of all the affected threads to equal the priority of the running thread requesting the mutex.*/
* of the running thread requesting the mutex.
*/
Thread *tp = mp->m_owner; Thread *tp = mp->m_owner;
/* Does the running thread have higher priority than the mutex /* Does the running thread have higher priority than the mutex
* ownning thread? */ ownning thread? */
while (tp->p_prio < currp->p_prio) { while (tp->p_prio < ctp->p_prio) {
/* Make priority of thread tp match the running thread's priority.*/ /* Make priority of thread tp match the running thread's priority.*/
tp->p_prio = currp->p_prio; tp->p_prio = ctp->p_prio;
/* The following states need priority queues reordering.*/ /* The following states need priority queues reordering.*/
switch (tp->p_state) { switch (tp->p_state) {
case THD_STATE_WTMTX: case THD_STATE_WTMTX:
@ -110,17 +109,15 @@ void chMtxLockS(Mutex *mp) {
break; break;
} }
/* Sleep on the mutex.*/ /* Sleep on the mutex.*/
prio_insert(currp, &mp->m_queue); prio_insert(ctp, &mp->m_queue);
currp->p_u.wtobjp = mp; ctp->p_u.wtobjp = mp;
chSchGoSleepS(THD_STATE_WTMTX); chSchGoSleepS(THD_STATE_WTMTX);
chDbgAssert(mp->m_owner == NULL, "chMtxLockS(), #1", "still owned"); chDbgAssert(mp->m_owner == NULL, "chMtxLockS(), #1", "still owned");
} }
/* /* The mutex is now inserted in the owned mutexes list.*/
* The mutex is now inserted in the owned mutexes list. mp->m_owner = ctp;
*/ mp->m_next = ctp->p_mtxlist;
mp->m_owner = currp; ctp->p_mtxlist = mp;
mp->m_next = currp->p_mtxlist;
currp->p_mtxlist = mp;
} }
/** /**
@ -173,43 +170,40 @@ bool_t chMtxTryLockS(Mutex *mp) {
* @return The pointer to the unlocked mutex. * @return The pointer to the unlocked mutex.
*/ */
Mutex *chMtxUnlock(void) { Mutex *chMtxUnlock(void) {
Thread *ctp = currp;
Mutex *ump, *mp; Mutex *ump, *mp;
chSysLock(); chSysLock();
chDbgAssert(currp->p_mtxlist != NULL, chDbgAssert(ctp->p_mtxlist != NULL,
"chMtxUnlock(), #1", "chMtxUnlock(), #1",
"owned mutexes list empty"); "owned mutexes list empty");
chDbgAssert(currp->p_mtxlist->m_owner == currp, chDbgAssert(ctp->p_mtxlist->m_owner == ctp,
"chMtxUnlock(), #2", "chMtxUnlock(), #2",
"ownership failure"); "ownership failure");
/* remove the top Mutex from the Threads's owned mutexes list */ /* Removes the top Mutex from the Threads's owned mutexes list and matk it
ump = currp->p_mtxlist; as not owned.*/
currp->p_mtxlist = ump->m_next; ump = ctp->p_mtxlist;
/* mark the Mutex as not owned */ ctp->p_mtxlist = ump->m_next;
ump->m_owner = NULL; ump->m_owner = NULL;
/* /* If a thread is waiting on the mutex then the fun part begins.*/
* If a thread is waiting on the mutex then the hard part begins.
*/
if (chMtxQueueNotEmptyS(ump)) { if (chMtxQueueNotEmptyS(ump)) {
/* Get the highest priority thread waiting for the unlocked mutex.*/ /* Recalculates the optimal thread priority by scanning the owned
Thread *tp = fifo_remove(&ump->m_queue); mutexes list.*/
/* tprio_t newprio = ctp->p_realprio;
* Recalculates the optimal thread priority by scanning the owned mutexes list. mp = ctp->p_mtxlist;
*/
tprio_t newprio = currp->p_realprio;
/* Iterate mp over all the (other) mutexes the current thread still owns.*/
mp = currp->p_mtxlist;
while (mp != NULL) { while (mp != NULL) {
/* Has the mutex mp a higher priority thread pending? */ /* If the highest priority thread waiting in the mutexes list has a
greater priority than the current thread base priority then the final
priority will have at least that priority.*/
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio)) if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
/* Boost the recalculated thread's priority to waiting thread.*/
newprio = mp->m_queue.p_next->p_prio; newprio = mp->m_queue.p_next->p_prio;
mp = mp->m_next; mp = mp->m_next;
} }
/* Possibly restores the priority of the current thread.*/ /* Assigns to the current thread the highest priority among all the
currp->p_prio = newprio; waiting threads.*/
/* Awaken the highest priority thread waiting for the unlocked mutex.*/ ctp->p_prio = newprio;
chSchWakeupS(tp, RDY_OK); /* Awakens the highest priority thread waiting for the unlocked mutex.*/
chSchWakeupS(fifo_remove(&ump->m_queue), RDY_OK);
} }
chSysUnlock(); chSysUnlock();
return ump; return ump;
@ -224,38 +218,37 @@ Mutex *chMtxUnlock(void) {
* @note This function does not reschedule internally. * @note This function does not reschedule internally.
*/ */
Mutex *chMtxUnlockS(void) { Mutex *chMtxUnlockS(void) {
Thread *ctp = currp;
Mutex *ump, *mp; Mutex *ump, *mp;
chDbgAssert(currp->p_mtxlist != NULL, chDbgAssert(ctp->p_mtxlist != NULL,
"chMtxUnlockS(), #1", "chMtxUnlockS(), #1",
"owned mutexes list empty"); "owned mutexes list empty");
chDbgAssert(currp->p_mtxlist->m_owner == currp, chDbgAssert(ctp->p_mtxlist->m_owner == ctp,
"chMtxUnlockS(), #2", "chMtxUnlockS(), #2",
"ownership failure"); "ownership failure");
/* /* Removes the top Mutex from the owned mutexes list and marks it as not
* Removes the top Mutex from the owned mutexes list and marks it as not owned. owned.*/
*/ ump = ctp->p_mtxlist;
ump = currp->p_mtxlist; ctp->p_mtxlist = ump->m_next;
currp->p_mtxlist = ump->m_next;
ump->m_owner = NULL; ump->m_owner = NULL;
/* /* If a thread is waiting on the mutex then the fun part begins.*/
* If a thread is waiting on the mutex then the hard part begins.
*/
if (chMtxQueueNotEmptyS(ump)) { if (chMtxQueueNotEmptyS(ump)) {
Thread *tp = fifo_remove(&ump->m_queue); /* Recalculates the optimal thread priority by scanning the owned
/* mutexes list.*/
* Recalculates the optimal thread priority by scanning the owned mutexes list. tprio_t newprio = ctp->p_realprio;
*/ mp = ctp->p_mtxlist;
tprio_t newprio = currp->p_realprio;
mp = currp->p_mtxlist;
while (mp != NULL) { while (mp != NULL) {
/* If the highest priority thread waiting in the mutexes list has a
greater priority than the current thread base priority then the final
priority will have at least that priority.*/
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio)) if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
newprio = mp->m_queue.p_next->p_prio; newprio = mp->m_queue.p_next->p_prio;
mp = mp->m_next; mp = mp->m_next;
} }
currp->p_prio = newprio; ctp->p_prio = newprio;
chSchReadyI(tp); chSchReadyI(fifo_remove(&ump->m_queue));
} }
return ump; return ump;
} }
@ -268,17 +261,18 @@ Mutex *chMtxUnlockS(void) {
* inheritance mechanism. * inheritance mechanism.
*/ */
void chMtxUnlockAll(void) { void chMtxUnlockAll(void) {
Thread *ctp = currp;
chSysLock(); chSysLock();
if (currp->p_mtxlist != NULL) { if (ctp->p_mtxlist != NULL) {
do { do {
Mutex *mp = currp->p_mtxlist; Mutex *mp = ctp->p_mtxlist;
currp->p_mtxlist = mp->m_next; ctp->p_mtxlist = mp->m_next;
mp->m_owner = NULL; mp->m_owner = NULL;
if (chMtxQueueNotEmptyS(mp)) if (chMtxQueueNotEmptyS(mp))
chSchReadyI(fifo_remove(&mp->m_queue)); chSchReadyI(fifo_remove(&mp->m_queue));
} while (currp->p_mtxlist != NULL); } while (ctp->p_mtxlist != NULL);
currp->p_prio = currp->p_realprio; ctp->p_prio = ctp->p_realprio;
chSchRescheduleS(); chSchRescheduleS();
} }
chSysUnlock(); chSysUnlock();

View File

@ -59,7 +59,7 @@
- CHANGE: Removed the unnamed union from the Thread structure some compilers - CHANGE: Removed the unnamed union from the Thread structure some compilers
do not support this non standard construct. do not support this non standard construct.
- CHANGE: Modified the thread-related constant macros to have a THD_ prefix. - CHANGE: Modified the thread-related constant macros to have a THD_ prefix.
- OPT: Optimizations to the priority inheritance code. - OPT: Speed/size optimization to the mutexes subsystem.
- OPT: Speed/size optimization to the synchronous messages subsystem. - OPT: Speed/size optimization to the synchronous messages subsystem.
*** 1.3.8 *** *** 1.3.8 ***