Mutexes optimizations.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1536 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
8cdf2dba5b
commit
6ce3901526
|
@ -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();
|
||||||
|
|
|
@ -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 ***
|
||||||
|
|
Loading…
Reference in New Issue