Preparation to recursive mutexes, now unlock primitives have the mutex as parameter.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6706 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
1033792b73
commit
6c90d27a46
|
@ -183,6 +183,15 @@
|
||||||
*/
|
*/
|
||||||
#define CH_CFG_USE_MUTEXES TRUE
|
#define CH_CFG_USE_MUTEXES TRUE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables recursive behavior on mutexes.
|
||||||
|
* @note Recursive mutexes are heavier and have an increased
|
||||||
|
* memory footprint.
|
||||||
|
*
|
||||||
|
* @note The default is @p FALSE.
|
||||||
|
*/
|
||||||
|
#define CH_CFG_USE_MUTEXES_RECURSIVE TRUE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Conditional Variables APIs.
|
* @brief Conditional Variables APIs.
|
||||||
* @details If enabled then the conditional variables APIs are included
|
* @details If enabled then the conditional variables APIs are included
|
||||||
|
|
|
@ -839,8 +839,7 @@ static inline void osalMutexLock(mutex_t *mp) {
|
||||||
static inline void osalMutexUnlock(mutex_t *mp) {
|
static inline void osalMutexUnlock(mutex_t *mp) {
|
||||||
|
|
||||||
#if CH_CFG_USE_MUTEXES
|
#if CH_CFG_USE_MUTEXES
|
||||||
(void)mp;
|
chMtxUnlock(mp);
|
||||||
chMtxUnlock();
|
|
||||||
#elif CH_CFG_USE_SEMAPHORES
|
#elif CH_CFG_USE_SEMAPHORES
|
||||||
chSemSignal((semaphore_t *)mp);
|
chSemSignal((semaphore_t *)mp);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -62,6 +62,9 @@ struct mutex {
|
||||||
@p NULL. */
|
@p NULL. */
|
||||||
mutex_t *m_next; /**< @brief Next @p mutex_t into an
|
mutex_t *m_next; /**< @brief Next @p mutex_t into an
|
||||||
owner-list or @p NULL. */
|
owner-list or @p NULL. */
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE || defined(__DOXYGEN__)
|
||||||
|
cnt_t m_taken; /**< @brief Mutex recursion counter. */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -75,7 +78,11 @@ struct mutex {
|
||||||
*
|
*
|
||||||
* @param[in] name the name of the mutex variable
|
* @param[in] name the name of the mutex variable
|
||||||
*/
|
*/
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE || defined(__DOXYGEN__)
|
||||||
|
#define _MUTEX_DATA(name) {_threads_queue_t_DATA(name.m_queue), NULL, NULL, 0}
|
||||||
|
#else
|
||||||
#define _MUTEX_DATA(name) {_threads_queue_t_DATA(name.m_queue), NULL, NULL}
|
#define _MUTEX_DATA(name) {_threads_queue_t_DATA(name.m_queue), NULL, NULL}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Static mutex initializer.
|
* @brief Static mutex initializer.
|
||||||
|
@ -99,8 +106,8 @@ extern "C" {
|
||||||
void chMtxLockS(mutex_t *mp);
|
void chMtxLockS(mutex_t *mp);
|
||||||
bool chMtxTryLock(mutex_t *mp);
|
bool chMtxTryLock(mutex_t *mp);
|
||||||
bool chMtxTryLockS(mutex_t *mp);
|
bool chMtxTryLockS(mutex_t *mp);
|
||||||
mutex_t *chMtxUnlock(void);
|
void chMtxUnlock(mutex_t *mp);
|
||||||
mutex_t *chMtxUnlockS(void);
|
void chMtxUnlockS(mutex_t *mp);
|
||||||
void chMtxUnlockAll(void);
|
void chMtxUnlockAll(void);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -124,6 +131,17 @@ static inline bool chMtxQueueNotEmptyS(mutex_t *mp) {
|
||||||
return queue_notempty(&mp->m_queue);
|
return queue_notempty(&mp->m_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the next mutex in the mutexes stack of the current thread.
|
||||||
|
*
|
||||||
|
* @return A pointer to the next mutex in the stack.
|
||||||
|
* @retval NULL if the stack is empty.
|
||||||
|
*/
|
||||||
|
static inline mutex_t *chMtxGetNextMutex(void) {
|
||||||
|
|
||||||
|
return chThdGetSelfX()->p_mtxlist;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CH_CFG_USE_MUTEXES */
|
#endif /* CH_CFG_USE_MUTEXES */
|
||||||
|
|
||||||
#endif /* _CHMTX_H_ */
|
#endif /* _CHMTX_H_ */
|
||||||
|
|
|
@ -210,7 +210,8 @@ msg_t chCondWaitS(condition_variable_t *cp) {
|
||||||
chDbgCheck(cp != NULL);
|
chDbgCheck(cp != NULL);
|
||||||
chDbgAssert(ctp->p_mtxlist != NULL, "not owning a mutex");
|
chDbgAssert(ctp->p_mtxlist != NULL, "not owning a mutex");
|
||||||
|
|
||||||
mp = chMtxUnlockS();
|
mp = chMtxGetNextMutex();
|
||||||
|
chMtxUnlockS(mp);
|
||||||
ctp->p_u.wtobjp = cp;
|
ctp->p_u.wtobjp = cp;
|
||||||
queue_prio_insert(ctp, &cp->c_queue);
|
queue_prio_insert(ctp, &cp->c_queue);
|
||||||
chSchGoSleepS(CH_STATE_WTCOND);
|
chSchGoSleepS(CH_STATE_WTCOND);
|
||||||
|
@ -293,7 +294,8 @@ msg_t chCondWaitTimeoutS(condition_variable_t *cp, systime_t time) {
|
||||||
chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE));
|
chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE));
|
||||||
chDbgAssert(currp->p_mtxlist != NULL, "not owning a mutex");
|
chDbgAssert(currp->p_mtxlist != NULL, "not owning a mutex");
|
||||||
|
|
||||||
mp = chMtxUnlockS();
|
mp = chMtxGetNextMutex();
|
||||||
|
chMtxUnlockS(mp);
|
||||||
currp->p_u.wtobjp = cp;
|
currp->p_u.wtobjp = cp;
|
||||||
queue_prio_insert(currp, &cp->c_queue);
|
queue_prio_insert(currp, &cp->c_queue);
|
||||||
msg = chSchGoSleepTimeoutS(CH_STATE_WTCOND, time);
|
msg = chSchGoSleepTimeoutS(CH_STATE_WTCOND, time);
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
*/
|
*/
|
||||||
#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
|
#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
|
||||||
#define H_LOCK(h) chMtxLock(&(h)->h_mtx)
|
#define H_LOCK(h) chMtxLock(&(h)->h_mtx)
|
||||||
#define H_UNLOCK(h) chMtxUnlock()
|
#define H_UNLOCK(h) chMtxUnlock(&(h)->h_mtx)
|
||||||
#else
|
#else
|
||||||
#define H_LOCK(h) chSemWait(&(h)->h_sem)
|
#define H_LOCK(h) chSemWait(&(h)->h_sem)
|
||||||
#define H_UNLOCK(h) chSemSignal(&(h)->h_sem)
|
#define H_UNLOCK(h) chSemSignal(&(h)->h_sem)
|
||||||
|
|
|
@ -41,12 +41,18 @@
|
||||||
* owner of the mutex.
|
* owner of the mutex.
|
||||||
* .
|
* .
|
||||||
* <h2>Constraints</h2>
|
* <h2>Constraints</h2>
|
||||||
* In ChibiOS/RT the Unlock operations are always performed in
|
* In ChibiOS/RT the Unlock operations must always be performed
|
||||||
* lock-reverse order. The unlock API does not even have a parameter,
|
* in lock-reverse order. This restriction both improves the
|
||||||
* the mutex to unlock is selected from an internal, per-thread, stack
|
* performance and is required for an efficient implementation
|
||||||
* of owned mutexes. This both improves the performance and is
|
* of the priority inheritance mechanism.<br>
|
||||||
* required for an efficient implementation of the priority
|
* Operating under this restriction also ensures that deadlocks
|
||||||
* inheritance mechanism.
|
* are no possible.
|
||||||
|
*
|
||||||
|
* <h2>Recursive mode</h2>
|
||||||
|
* By default mutexes are not recursive, this mean that it is not
|
||||||
|
* possible to take a mutex already owned by the same thread.
|
||||||
|
* It is possible to enable the recursive behavior by enabling the
|
||||||
|
* option @p CH_CFG_USE_MUTEXES_RECURSIVE.
|
||||||
*
|
*
|
||||||
* <h2>The priority inversion problem</h2>
|
* <h2>The priority inversion problem</h2>
|
||||||
* The mutexes in ChibiOS/RT implements the <b>full</b> priority
|
* The mutexes in ChibiOS/RT implements the <b>full</b> priority
|
||||||
|
@ -270,39 +276,40 @@ bool chMtxTryLockS(mutex_t *mp) {
|
||||||
* @post The mutex is unlocked and removed from the per-thread stack of
|
* @post The mutex is unlocked and removed from the per-thread stack of
|
||||||
* owned mutexes.
|
* owned mutexes.
|
||||||
*
|
*
|
||||||
* @return A pointer to the unlocked mutex.
|
* @param[in] mp pointer to the @p mutex_t structure
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
mutex_t *chMtxUnlock(void) {
|
void chMtxUnlock(mutex_t *mp) {
|
||||||
thread_t *ctp = currp;
|
thread_t *ctp = currp;
|
||||||
mutex_t *ump, *mp;
|
mutex_t *lmp;
|
||||||
|
|
||||||
chSysLock();
|
chSysLock();
|
||||||
|
|
||||||
chDbgAssert(ctp->p_mtxlist != NULL, "owned mutexes list empty");
|
chDbgAssert(ctp->p_mtxlist != NULL, "owned mutexes list empty");
|
||||||
|
chDbgAssert(ctp->p_mtxlist != mp, "not next in list");
|
||||||
chDbgAssert(ctp->p_mtxlist->m_owner == ctp, "ownership failure");
|
chDbgAssert(ctp->p_mtxlist->m_owner == ctp, "ownership failure");
|
||||||
|
|
||||||
/* Removes the top mutex from the thread's owned mutexes list and marks it
|
/* Removes the top mutex from the thread's owned mutexes list and marks
|
||||||
as not owned.*/
|
it as not owned. Note, it is assumed to be the same mutex passed as
|
||||||
ump = ctp->p_mtxlist;
|
parameter of this function.*/
|
||||||
ctp->p_mtxlist = ump->m_next;
|
ctp->p_mtxlist = mp->m_next;
|
||||||
|
|
||||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||||
if (chMtxQueueNotEmptyS(ump)) {
|
if (chMtxQueueNotEmptyS(mp)) {
|
||||||
thread_t *tp;
|
thread_t *tp;
|
||||||
|
|
||||||
/* Recalculates the optimal thread priority by scanning the owned
|
/* Recalculates the optimal thread priority by scanning the owned
|
||||||
mutexes list.*/
|
mutexes list.*/
|
||||||
tprio_t newprio = ctp->p_realprio;
|
tprio_t newprio = ctp->p_realprio;
|
||||||
mp = ctp->p_mtxlist;
|
lmp = ctp->p_mtxlist;
|
||||||
while (mp != NULL) {
|
while (lmp != NULL) {
|
||||||
/* If the highest priority thread waiting in the mutexes list has a
|
/* If the highest priority thread waiting in the mutexes list has a
|
||||||
greater priority than the current thread base priority then the final
|
greater priority than the current thread base priority then the final
|
||||||
priority will have at least that priority.*/
|
priority will have at least that priority.*/
|
||||||
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
|
if (chMtxQueueNotEmptyS(lmp) && (lmp->m_queue.p_next->p_prio > newprio))
|
||||||
newprio = mp->m_queue.p_next->p_prio;
|
newprio = lmp->m_queue.p_next->p_prio;
|
||||||
mp = mp->m_next;
|
lmp = lmp->m_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assigns to the current thread the highest priority among all the
|
/* Assigns to the current thread the highest priority among all the
|
||||||
|
@ -311,16 +318,16 @@ mutex_t *chMtxUnlock(void) {
|
||||||
|
|
||||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||||
assigns the mutex to it.*/
|
assigns the mutex to it.*/
|
||||||
tp = queue_fifo_remove(&ump->m_queue);
|
tp = queue_fifo_remove(&mp->m_queue);
|
||||||
ump->m_owner = tp;
|
mp->m_owner = tp;
|
||||||
ump->m_next = tp->p_mtxlist;
|
mp->m_next = tp->p_mtxlist;
|
||||||
tp->p_mtxlist = ump;
|
tp->p_mtxlist = mp;
|
||||||
chSchWakeupS(tp, MSG_OK);
|
chSchWakeupS(tp, MSG_OK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ump->m_owner = NULL;
|
mp->m_owner = NULL;
|
||||||
|
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
return ump;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -331,53 +338,54 @@ mutex_t *chMtxUnlock(void) {
|
||||||
* @post This function does not reschedule so a call to a rescheduling
|
* @post This function does not reschedule so a call to a rescheduling
|
||||||
* function must be performed before unlocking the kernel.
|
* function must be performed before unlocking the kernel.
|
||||||
*
|
*
|
||||||
* @return A pointer to the unlocked mutex.
|
* @param[in] mp pointer to the @p mutex_t structure
|
||||||
*
|
*
|
||||||
* @sclass
|
* @sclass
|
||||||
*/
|
*/
|
||||||
mutex_t *chMtxUnlockS(void) {
|
void chMtxUnlockS(mutex_t *mp) {
|
||||||
thread_t *ctp = currp;
|
thread_t *ctp = currp;
|
||||||
mutex_t *ump, *mp;
|
mutex_t *lmp;
|
||||||
|
|
||||||
chDbgCheckClassS();
|
|
||||||
chDbgAssert(ctp->p_mtxlist != NULL, "owned mutexes list empty");
|
chDbgAssert(ctp->p_mtxlist != NULL, "owned mutexes list empty");
|
||||||
|
chDbgAssert(ctp->p_mtxlist != mp, "not next in list");
|
||||||
chDbgAssert(ctp->p_mtxlist->m_owner == ctp, "ownership failure");
|
chDbgAssert(ctp->p_mtxlist->m_owner == ctp, "ownership failure");
|
||||||
|
|
||||||
/* Removes the top mutex from the owned mutexes list and marks it as not
|
/* Removes the top mutex from the thread's owned mutexes list and marks
|
||||||
owned.*/
|
it as not owned. Note, it is assumed to be the same mutex passed as
|
||||||
ump = ctp->p_mtxlist;
|
parameter of this function.*/
|
||||||
ctp->p_mtxlist = ump->m_next;
|
ctp->p_mtxlist = mp->m_next;
|
||||||
|
|
||||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||||
if (chMtxQueueNotEmptyS(ump)) {
|
if (chMtxQueueNotEmptyS(mp)) {
|
||||||
thread_t *tp;
|
thread_t *tp;
|
||||||
|
|
||||||
/* Recalculates the optimal thread priority by scanning the owned
|
/* Recalculates the optimal thread priority by scanning the owned
|
||||||
mutexes list.*/
|
mutexes list.*/
|
||||||
tprio_t newprio = ctp->p_realprio;
|
tprio_t newprio = ctp->p_realprio;
|
||||||
mp = ctp->p_mtxlist;
|
lmp = ctp->p_mtxlist;
|
||||||
while (mp != NULL) {
|
while (lmp != NULL) {
|
||||||
/* If the highest priority thread waiting in the mutexes list has a
|
/* If the highest priority thread waiting in the mutexes list has a
|
||||||
greater priority than the current thread base priority then the final
|
greater priority than the current thread base priority then the final
|
||||||
priority will have at least that priority.*/
|
priority will have at least that priority.*/
|
||||||
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
|
if (chMtxQueueNotEmptyS(lmp) && (lmp->m_queue.p_next->p_prio > newprio))
|
||||||
newprio = mp->m_queue.p_next->p_prio;
|
newprio = lmp->m_queue.p_next->p_prio;
|
||||||
|
lmp = lmp->m_next;
|
||||||
mp = mp->m_next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Assigns to the current thread the highest priority among all the
|
||||||
|
waiting threads.*/
|
||||||
ctp->p_prio = newprio;
|
ctp->p_prio = newprio;
|
||||||
|
|
||||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||||
assigns the mutex to it.*/
|
assigns the mutex to it.*/
|
||||||
tp = queue_fifo_remove(&ump->m_queue);
|
tp = queue_fifo_remove(&mp->m_queue);
|
||||||
ump->m_owner = tp;
|
mp->m_owner = tp;
|
||||||
ump->m_next = tp->p_mtxlist;
|
mp->m_next = tp->p_mtxlist;
|
||||||
tp->p_mtxlist = ump;
|
tp->p_mtxlist = mp;
|
||||||
chSchReadyI(tp);
|
chSchReadyI(tp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ump->m_owner = NULL;
|
mp->m_owner = NULL;
|
||||||
return ump;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -601,13 +601,13 @@ static void bmk12_execute(void) {
|
||||||
test_start_timer(1000);
|
test_start_timer(1000);
|
||||||
do {
|
do {
|
||||||
chMtxLock(&mtx1);
|
chMtxLock(&mtx1);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&mtx1);
|
||||||
chMtxLock(&mtx1);
|
chMtxLock(&mtx1);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&mtx1);
|
||||||
chMtxLock(&mtx1);
|
chMtxLock(&mtx1);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&mtx1);
|
||||||
chMtxLock(&mtx1);
|
chMtxLock(&mtx1);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&mtx1);
|
||||||
n++;
|
n++;
|
||||||
#if defined(SIMULATOR)
|
#if defined(SIMULATOR)
|
||||||
ChkIntSources();
|
ChkIntSources();
|
||||||
|
|
|
@ -90,7 +90,7 @@ static msg_t thread1(void *p) {
|
||||||
|
|
||||||
chMtxLock(&m1);
|
chMtxLock(&m1);
|
||||||
test_emit_token(*(char *)p);
|
test_emit_token(*(char *)p);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ static void mtx1_execute(void) {
|
||||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread1, "C");
|
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread1, "C");
|
||||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread1, "B");
|
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread1, "B");
|
||||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A");
|
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A");
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m1);
|
||||||
test_wait_threads();
|
test_wait_threads();
|
||||||
test_assert(1, prio == chThdGetPriorityX(), "wrong priority level");
|
test_assert(1, prio == chThdGetPriorityX(), "wrong priority level");
|
||||||
test_assert_sequence(2, "ABCDE");
|
test_assert_sequence(2, "ABCDE");
|
||||||
|
@ -349,7 +349,7 @@ static msg_t thread4a(void *p) {
|
||||||
(void)p;
|
(void)p;
|
||||||
chThdSleepMilliseconds(50);
|
chThdSleepMilliseconds(50);
|
||||||
chMtxLock(&m2);
|
chMtxLock(&m2);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ static msg_t thread4b(void *p) {
|
||||||
(void)p;
|
(void)p;
|
||||||
chThdSleepMilliseconds(150);
|
chThdSleepMilliseconds(150);
|
||||||
chMtxLock(&m1);
|
chMtxLock(&m1);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ static void mtx4_execute(void) {
|
||||||
test_assert(3, chThdGetPriorityX() == p1, "wrong priority level");
|
test_assert(3, chThdGetPriorityX() == p1, "wrong priority level");
|
||||||
chThdSleepMilliseconds(100);
|
chThdSleepMilliseconds(100);
|
||||||
test_assert(4, chThdGetPriorityX() == p2, "wrong priority level");
|
test_assert(4, chThdGetPriorityX() == p2, "wrong priority level");
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m1);
|
||||||
test_assert(5, chThdGetPriorityX() == p1, "wrong priority level");
|
test_assert(5, chThdGetPriorityX() == p1, "wrong priority level");
|
||||||
chThdSleepMilliseconds(100);
|
chThdSleepMilliseconds(100);
|
||||||
test_assert(6, chThdGetPriorityX() == p1, "wrong priority level");
|
test_assert(6, chThdGetPriorityX() == p1, "wrong priority level");
|
||||||
|
@ -398,7 +398,7 @@ static void mtx4_execute(void) {
|
||||||
chThdSleepMilliseconds(100);
|
chThdSleepMilliseconds(100);
|
||||||
test_assert(11, chThdGetPriorityX() == p2, "wrong priority level");
|
test_assert(11, chThdGetPriorityX() == p2, "wrong priority level");
|
||||||
chSysLock();
|
chSysLock();
|
||||||
chMtxUnlockS();
|
chMtxUnlockS(&m1);
|
||||||
chSchRescheduleS();
|
chSchRescheduleS();
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
test_assert(12, chThdGetPriorityX() == p1, "wrong priority level");
|
test_assert(12, chThdGetPriorityX() == p1, "wrong priority level");
|
||||||
|
@ -444,7 +444,7 @@ static void mtx5_execute(void) {
|
||||||
test_assert(2, !b, "not locked");
|
test_assert(2, !b, "not locked");
|
||||||
|
|
||||||
chSysLock();
|
chSysLock();
|
||||||
chMtxUnlockS();
|
chMtxUnlockS(&m1);
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
|
|
||||||
test_assert(3, queue_isempty(&m1.m_queue), "queue not empty");
|
test_assert(3, queue_isempty(&m1.m_queue), "queue not empty");
|
||||||
|
@ -487,7 +487,7 @@ static msg_t thread10(void *p) {
|
||||||
chMtxLock(&m1);
|
chMtxLock(&m1);
|
||||||
chCondWait(&c1);
|
chCondWait(&c1);
|
||||||
test_emit_token(*(char *)p);
|
test_emit_token(*(char *)p);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,8 +580,8 @@ static msg_t thread11(void *p) {
|
||||||
chCondWait(&c1);
|
chCondWait(&c1);
|
||||||
#endif
|
#endif
|
||||||
test_emit_token(*(char *)p);
|
test_emit_token(*(char *)p);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m1);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,7 +589,7 @@ static msg_t thread12(void *p) {
|
||||||
|
|
||||||
chMtxLock(&m2);
|
chMtxLock(&m2);
|
||||||
test_emit_token(*(char *)p);
|
test_emit_token(*(char *)p);
|
||||||
chMtxUnlock();
|
chMtxUnlock(&m2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue