Recursive mutexes, test code not done yet.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6707 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
6c90d27a46
commit
7a3da58ae2
|
@ -63,7 +63,7 @@ struct mutex {
|
||||||
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__)
|
#if CH_CFG_USE_MUTEXES_RECURSIVE || defined(__DOXYGEN__)
|
||||||
cnt_t m_taken; /**< @brief Mutex recursion counter. */
|
cnt_t m_cnt; /**< @brief Mutex recursion counter. */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,9 @@ void chMtxObjectInit(mutex_t *mp) {
|
||||||
|
|
||||||
queue_init(&mp->m_queue);
|
queue_init(&mp->m_queue);
|
||||||
mp->m_owner = NULL;
|
mp->m_owner = NULL;
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
mp->m_cnt = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,65 +148,84 @@ void chMtxLockS(mutex_t *mp) {
|
||||||
|
|
||||||
/* Is the mutex already locked? */
|
/* Is the mutex already locked? */
|
||||||
if (mp->m_owner != NULL) {
|
if (mp->m_owner != NULL) {
|
||||||
/* Priority inheritance protocol; explores the thread-mutex dependencies
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
boosting the priority of all the affected threads to equal the priority
|
|
||||||
of the running thread requesting the mutex.*/
|
|
||||||
thread_t *tp = mp->m_owner;
|
|
||||||
|
|
||||||
/* Does the running thread have higher priority than the mutex
|
chDbgAssert(mp->m_cnt >= 1, "counter is not positive");
|
||||||
owning thread? */
|
|
||||||
while (tp->p_prio < ctp->p_prio) {
|
|
||||||
/* Make priority of thread tp match the running thread's priority.*/
|
|
||||||
tp->p_prio = ctp->p_prio;
|
|
||||||
|
|
||||||
/* The following states need priority queues reordering.*/
|
/* If the mutex is already owned by this thread, the counter is increased
|
||||||
switch (tp->p_state) {
|
and there is no need of more actions.*/
|
||||||
case CH_STATE_WTMTX:
|
if (mp->m_owner == ctp)
|
||||||
/* Re-enqueues the mutex owner with its new priority.*/
|
mp->m_cnt++;
|
||||||
queue_prio_insert(queue_dequeue(tp),
|
else {
|
||||||
(threads_queue_t *)tp->p_u.wtobjp);
|
|
||||||
tp = ((mutex_t *)tp->p_u.wtobjp)->m_owner;
|
|
||||||
continue;
|
|
||||||
#if CH_CFG_USE_CONDVARS | \
|
|
||||||
(CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY) | \
|
|
||||||
(CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY)
|
|
||||||
#if CH_CFG_USE_CONDVARS
|
|
||||||
case CH_STATE_WTCOND:
|
|
||||||
#endif
|
#endif
|
||||||
#if CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY
|
/* Priority inheritance protocol; explores the thread-mutex dependencies
|
||||||
case CH_STATE_WTSEM:
|
boosting the priority of all the affected threads to equal the
|
||||||
#endif
|
priority of the running thread requesting the mutex.*/
|
||||||
#if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY
|
thread_t *tp = mp->m_owner;
|
||||||
case CH_STATE_SNDMSGQ:
|
|
||||||
#endif
|
/* Does the running thread have higher priority than the mutex
|
||||||
/* Re-enqueues tp with its new priority on the queue.*/
|
owning thread? */
|
||||||
queue_prio_insert(queue_dequeue(tp),
|
while (tp->p_prio < ctp->p_prio) {
|
||||||
(threads_queue_t *)tp->p_u.wtobjp);
|
/* Make priority of thread tp match the running thread's priority.*/
|
||||||
break;
|
tp->p_prio = ctp->p_prio;
|
||||||
#endif
|
|
||||||
case CH_STATE_READY:
|
/* The following states need priority queues reordering.*/
|
||||||
#if CH_DBG_ENABLE_ASSERTS
|
switch (tp->p_state) {
|
||||||
/* Prevents an assertion in chSchReadyI().*/
|
case CH_STATE_WTMTX:
|
||||||
tp->p_state = CH_STATE_CURRENT;
|
/* Re-enqueues the mutex owner with its new priority.*/
|
||||||
#endif
|
queue_prio_insert(queue_dequeue(tp),
|
||||||
/* Re-enqueues tp with its new priority on the ready list.*/
|
(threads_queue_t *)tp->p_u.wtobjp);
|
||||||
chSchReadyI(queue_dequeue(tp));
|
tp = ((mutex_t *)tp->p_u.wtobjp)->m_owner;
|
||||||
|
continue;
|
||||||
|
#if CH_CFG_USE_CONDVARS | \
|
||||||
|
(CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY) | \
|
||||||
|
(CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY)
|
||||||
|
#if CH_CFG_USE_CONDVARS
|
||||||
|
case CH_STATE_WTCOND:
|
||||||
|
#endif
|
||||||
|
#if CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY
|
||||||
|
case CH_STATE_WTSEM:
|
||||||
|
#endif
|
||||||
|
#if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY
|
||||||
|
case CH_STATE_SNDMSGQ:
|
||||||
|
#endif
|
||||||
|
/* Re-enqueues tp with its new priority on the queue.*/
|
||||||
|
queue_prio_insert(queue_dequeue(tp),
|
||||||
|
(threads_queue_t *)tp->p_u.wtobjp);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case CH_STATE_READY:
|
||||||
|
#if CH_DBG_ENABLE_ASSERTS
|
||||||
|
/* Prevents an assertion in chSchReadyI().*/
|
||||||
|
tp->p_state = CH_STATE_CURRENT;
|
||||||
|
#endif
|
||||||
|
/* Re-enqueues tp with its new priority on the ready list.*/
|
||||||
|
chSchReadyI(queue_dequeue(tp));
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
/* Sleep on the mutex.*/
|
||||||
|
queue_prio_insert(ctp, &mp->m_queue);
|
||||||
|
ctp->p_u.wtobjp = mp;
|
||||||
|
chSchGoSleepS(CH_STATE_WTMTX);
|
||||||
|
|
||||||
|
/* It is assumed that the thread performing the unlock operation assigns
|
||||||
|
the mutex to this thread.*/
|
||||||
|
chDbgAssert(mp->m_owner == ctp, "not owner");
|
||||||
|
chDbgAssert(ctp->p_mtxlist == mp, "not owned");
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
chDbgAssert(mp->m_cnt == 1, "counter is not one");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* Sleep on the mutex.*/
|
|
||||||
queue_prio_insert(ctp, &mp->m_queue);
|
|
||||||
ctp->p_u.wtobjp = mp;
|
|
||||||
chSchGoSleepS(CH_STATE_WTMTX);
|
|
||||||
|
|
||||||
/* It is assumed that the thread performing the unlock operation assigns
|
|
||||||
the mutex to this thread.*/
|
|
||||||
chDbgAssert(mp->m_owner == ctp, "not owner");
|
|
||||||
chDbgAssert(ctp->p_mtxlist == mp, "not owned");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
chDbgAssert(mp->m_cnt == 0, "counter is not zero");
|
||||||
|
|
||||||
|
mp->m_cnt++;
|
||||||
|
#endif
|
||||||
/* It was not owned, inserted in the owned mutexes list.*/
|
/* It was not owned, inserted in the owned mutexes list.*/
|
||||||
mp->m_owner = ctp;
|
mp->m_owner = ctp;
|
||||||
mp->m_next = ctp->p_mtxlist;
|
mp->m_next = ctp->p_mtxlist;
|
||||||
|
@ -261,9 +283,24 @@ bool chMtxTryLockS(mutex_t *mp) {
|
||||||
chDbgCheckClassS();
|
chDbgCheckClassS();
|
||||||
chDbgCheck(mp != NULL);
|
chDbgCheck(mp != NULL);
|
||||||
|
|
||||||
if (mp->m_owner != NULL)
|
if (mp->m_owner != NULL) {
|
||||||
return false;
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
|
||||||
|
chDbgAssert(mp->m_cnt >= 1, "counter is not positive");
|
||||||
|
|
||||||
|
if (mp->m_owner == currp) {
|
||||||
|
mp->m_cnt++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
|
||||||
|
chDbgAssert(mp->m_cnt == 0, "counter is not zero");
|
||||||
|
|
||||||
|
mp->m_cnt++;
|
||||||
|
#endif
|
||||||
mp->m_owner = currp;
|
mp->m_owner = currp;
|
||||||
mp->m_next = currp->p_mtxlist;
|
mp->m_next = currp->p_mtxlist;
|
||||||
currp->p_mtxlist = mp;
|
currp->p_mtxlist = mp;
|
||||||
|
@ -284,48 +321,62 @@ void chMtxUnlock(mutex_t *mp) {
|
||||||
thread_t *ctp = currp;
|
thread_t *ctp = currp;
|
||||||
mutex_t *lmp;
|
mutex_t *lmp;
|
||||||
|
|
||||||
|
chDbgCheck(mp != NULL);
|
||||||
|
|
||||||
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");
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
chDbgAssert(mp->m_cnt >= 1, "counter is not positive");
|
||||||
|
|
||||||
/* Removes the top mutex from the thread's owned mutexes list and marks
|
if (--mp->m_cnt == 0) {
|
||||||
it as not owned. Note, it is assumed to be the same mutex passed as
|
#endif
|
||||||
parameter of this function.*/
|
|
||||||
ctp->p_mtxlist = mp->m_next;
|
|
||||||
|
|
||||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
chDbgAssert(ctp->p_mtxlist == mp, "not next in list");
|
||||||
if (chMtxQueueNotEmptyS(mp)) {
|
|
||||||
thread_t *tp;
|
|
||||||
|
|
||||||
/* Recalculates the optimal thread priority by scanning the owned
|
/* Removes the top mutex from the thread's owned mutexes list and marks
|
||||||
mutexes list.*/
|
it as not owned. Note, it is assumed to be the same mutex passed as
|
||||||
tprio_t newprio = ctp->p_realprio;
|
parameter of this function.*/
|
||||||
lmp = ctp->p_mtxlist;
|
ctp->p_mtxlist = mp->m_next;
|
||||||
while (lmp != NULL) {
|
|
||||||
/* If the highest priority thread waiting in the mutexes list has a
|
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||||
greater priority than the current thread base priority then the final
|
if (chMtxQueueNotEmptyS(mp)) {
|
||||||
priority will have at least that priority.*/
|
thread_t *tp;
|
||||||
if (chMtxQueueNotEmptyS(lmp) && (lmp->m_queue.p_next->p_prio > newprio))
|
|
||||||
newprio = lmp->m_queue.p_next->p_prio;
|
/* Recalculates the optimal thread priority by scanning the owned
|
||||||
lmp = lmp->m_next;
|
mutexes list.*/
|
||||||
|
tprio_t newprio = ctp->p_realprio;
|
||||||
|
lmp = ctp->p_mtxlist;
|
||||||
|
while (lmp != 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(lmp) && (lmp->m_queue.p_next->p_prio > newprio))
|
||||||
|
newprio = lmp->m_queue.p_next->p_prio;
|
||||||
|
lmp = lmp->m_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assigns to the current thread the highest priority among all the
|
||||||
|
waiting threads.*/
|
||||||
|
ctp->p_prio = newprio;
|
||||||
|
|
||||||
|
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||||
|
assigns the mutex to it.*/
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
mp->m_cnt = 1;
|
||||||
|
#endif
|
||||||
|
tp = queue_fifo_remove(&mp->m_queue);
|
||||||
|
mp->m_owner = tp;
|
||||||
|
mp->m_next = tp->p_mtxlist;
|
||||||
|
tp->p_mtxlist = mp;
|
||||||
|
chSchWakeupS(tp, MSG_OK);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Assigns to the current thread the highest priority among all the
|
mp->m_owner = NULL;
|
||||||
waiting threads.*/
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
ctp->p_prio = newprio;
|
|
||||||
|
|
||||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
|
||||||
assigns the mutex to it.*/
|
|
||||||
tp = queue_fifo_remove(&mp->m_queue);
|
|
||||||
mp->m_owner = tp;
|
|
||||||
mp->m_next = tp->p_mtxlist;
|
|
||||||
tp->p_mtxlist = mp;
|
|
||||||
chSchWakeupS(tp, MSG_OK);
|
|
||||||
}
|
}
|
||||||
else
|
#endif
|
||||||
mp->m_owner = NULL;
|
|
||||||
|
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
}
|
}
|
||||||
|
@ -346,46 +397,61 @@ void chMtxUnlockS(mutex_t *mp) {
|
||||||
thread_t *ctp = currp;
|
thread_t *ctp = currp;
|
||||||
mutex_t *lmp;
|
mutex_t *lmp;
|
||||||
|
|
||||||
|
chDbgCheckClassS();
|
||||||
|
chDbgCheck(mp != NULL);
|
||||||
|
|
||||||
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");
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
chDbgAssert(mp->m_cnt >= 1, "counter is not positive");
|
||||||
|
|
||||||
/* Removes the top mutex from the thread's owned mutexes list and marks
|
if (--mp->m_cnt == 0) {
|
||||||
it as not owned. Note, it is assumed to be the same mutex passed as
|
#endif
|
||||||
parameter of this function.*/
|
|
||||||
ctp->p_mtxlist = mp->m_next;
|
|
||||||
|
|
||||||
/* If a thread is waiting on the mutex then the fun part begins.*/
|
chDbgAssert(ctp->p_mtxlist == mp, "not next in list");
|
||||||
if (chMtxQueueNotEmptyS(mp)) {
|
|
||||||
thread_t *tp;
|
|
||||||
|
|
||||||
/* Recalculates the optimal thread priority by scanning the owned
|
/* Removes the top mutex from the thread's owned mutexes list and marks
|
||||||
mutexes list.*/
|
it as not owned. Note, it is assumed to be the same mutex passed as
|
||||||
tprio_t newprio = ctp->p_realprio;
|
parameter of this function.*/
|
||||||
lmp = ctp->p_mtxlist;
|
ctp->p_mtxlist = mp->m_next;
|
||||||
while (lmp != NULL) {
|
|
||||||
/* If the highest priority thread waiting in the mutexes list has a
|
/* If a thread is waiting on the mutex then the fun part begins.*/
|
||||||
greater priority than the current thread base priority then the final
|
if (chMtxQueueNotEmptyS(mp)) {
|
||||||
priority will have at least that priority.*/
|
thread_t *tp;
|
||||||
if (chMtxQueueNotEmptyS(lmp) && (lmp->m_queue.p_next->p_prio > newprio))
|
|
||||||
newprio = lmp->m_queue.p_next->p_prio;
|
/* Recalculates the optimal thread priority by scanning the owned
|
||||||
lmp = lmp->m_next;
|
mutexes list.*/
|
||||||
|
tprio_t newprio = ctp->p_realprio;
|
||||||
|
lmp = ctp->p_mtxlist;
|
||||||
|
while (lmp != 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(lmp) && (lmp->m_queue.p_next->p_prio > newprio))
|
||||||
|
newprio = lmp->m_queue.p_next->p_prio;
|
||||||
|
lmp = lmp->m_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assigns to the current thread the highest priority among all the
|
||||||
|
waiting threads.*/
|
||||||
|
ctp->p_prio = newprio;
|
||||||
|
|
||||||
|
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
||||||
|
assigns the mutex to it.*/
|
||||||
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
mp->m_cnt = 1;
|
||||||
|
#endif
|
||||||
|
tp = queue_fifo_remove(&mp->m_queue);
|
||||||
|
mp->m_owner = tp;
|
||||||
|
mp->m_next = tp->p_mtxlist;
|
||||||
|
tp->p_mtxlist = mp;
|
||||||
|
chSchReadyI(tp);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Assigns to the current thread the highest priority among all the
|
mp->m_owner = NULL;
|
||||||
waiting threads.*/
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
ctp->p_prio = newprio;
|
|
||||||
|
|
||||||
/* Awakens the highest priority thread waiting for the unlocked mutex and
|
|
||||||
assigns the mutex to it.*/
|
|
||||||
tp = queue_fifo_remove(&mp->m_queue);
|
|
||||||
mp->m_owner = tp;
|
|
||||||
mp->m_next = tp->p_mtxlist;
|
|
||||||
tp->p_mtxlist = mp;
|
|
||||||
chSchReadyI(tp);
|
|
||||||
}
|
}
|
||||||
else
|
#endif
|
||||||
mp->m_owner = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -405,17 +471,24 @@ void chMtxUnlockAll(void) {
|
||||||
chSysLock();
|
chSysLock();
|
||||||
if (ctp->p_mtxlist != NULL) {
|
if (ctp->p_mtxlist != NULL) {
|
||||||
do {
|
do {
|
||||||
mutex_t *ump = ctp->p_mtxlist;
|
mutex_t *mp = ctp->p_mtxlist;
|
||||||
ctp->p_mtxlist = ump->m_next;
|
ctp->p_mtxlist = mp->m_next;
|
||||||
if (chMtxQueueNotEmptyS(ump)) {
|
if (chMtxQueueNotEmptyS(mp)) {
|
||||||
thread_t *tp = queue_fifo_remove(&ump->m_queue);
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
ump->m_owner = tp;
|
mp->m_cnt = 1;
|
||||||
ump->m_next = tp->p_mtxlist;
|
#endif
|
||||||
tp->p_mtxlist = ump;
|
thread_t *tp = queue_fifo_remove(&mp->m_queue);
|
||||||
|
mp->m_owner = tp;
|
||||||
|
mp->m_next = tp->p_mtxlist;
|
||||||
|
tp->p_mtxlist = mp;
|
||||||
chSchReadyI(tp);
|
chSchReadyI(tp);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
ump->m_owner = NULL;
|
#if CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
mp->m_cnt = 0;
|
||||||
|
#endif
|
||||||
|
mp->m_owner = NULL;
|
||||||
|
}
|
||||||
} while (ctp->p_mtxlist != NULL);
|
} while (ctp->p_mtxlist != NULL);
|
||||||
ctp->p_prio = ctp->p_realprio;
|
ctp->p_prio = ctp->p_realprio;
|
||||||
chSchRescheduleS();
|
chSchRescheduleS();
|
||||||
|
|
|
@ -432,10 +432,10 @@ static void mtx5_setup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtx5_execute(void) {
|
static void mtx5_execute(void) {
|
||||||
bool b;
|
|
||||||
tprio_t prio;
|
|
||||||
|
|
||||||
prio = chThdGetPriorityX();
|
#if !CH_CFG_USE_MUTEXES_RECURSIVE
|
||||||
|
bool b;
|
||||||
|
tprio_t prio = chThdGetPriorityX();
|
||||||
|
|
||||||
b = chMtxTryLock(&m1);
|
b = chMtxTryLock(&m1);
|
||||||
test_assert(1, b, "already locked");
|
test_assert(1, b, "already locked");
|
||||||
|
@ -450,6 +450,7 @@ static void mtx5_execute(void) {
|
||||||
test_assert(3, queue_isempty(&m1.m_queue), "queue not empty");
|
test_assert(3, queue_isempty(&m1.m_queue), "queue not empty");
|
||||||
test_assert(4, m1.m_owner == NULL, "still owned");
|
test_assert(4, m1.m_owner == NULL, "still owned");
|
||||||
test_assert(5, chThdGetPriorityX() == prio, "wrong priority level");
|
test_assert(5, chThdGetPriorityX() == prio, "wrong priority level");
|
||||||
|
#endif /* !CH_CFG_USE_MUTEXES_RECURSIVE */
|
||||||
|
|
||||||
chMtxLock(&m1);
|
chMtxLock(&m1);
|
||||||
chMtxUnlockAll();
|
chMtxUnlockAll();
|
||||||
|
|
Loading…
Reference in New Issue