From afd9deb6f7b1b9e08a47cb2ca9d30f48546f776b Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sun, 21 Oct 2018 06:23:41 +0000 Subject: Fixed bugs #982 and #983. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12374 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- os/nil/include/ch.h | 8 +-- os/nil/src/ch.c | 159 ++++++++++++++++++++++++++-------------------------- 2 files changed, 85 insertions(+), 82 deletions(-) (limited to 'os') diff --git a/os/nil/include/ch.h b/os/nil/include/ch.h index 6d595a88b..d46664bc3 100644 --- a/os/nil/include/ch.h +++ b/os/nil/include/ch.h @@ -55,7 +55,7 @@ /** * @brief Kernel version string. */ -#define CH_KERNEL_VERSION "3.1.0" +#define CH_KERNEL_VERSION "3.1.1" /** * @brief Kernel version major number. @@ -70,7 +70,7 @@ /** * @brief Kernel version patch number. */ -#define CH_KERNEL_PATCH 0 +#define CH_KERNEL_PATCH 1 /** @} */ /** @@ -81,7 +81,7 @@ * @note It is meant to be used in configuration files as switch. */ #if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 +#define FALSE 0 #endif /** @@ -89,7 +89,7 @@ * @note It is meant to be used in configuration files as switch. */ #if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE 1 +#define TRUE 1 #endif /** @} */ diff --git a/os/nil/src/ch.c b/os/nil/src/ch.c index 38fb936e2..fcabcfdb7 100644 --- a/os/nil/src/ch.c +++ b/os/nil/src/ch.c @@ -48,6 +48,59 @@ nil_system_t nil; /* Module local functions. */ /*===========================================================================*/ +/** + * @brief Retrieves the highest priority thread in the specified state and + * associated to the specified object. + * @note The search is unbounded, the thread is assumed to exist. + * + * @param[in] state thread state + * @param[in] p object pointer + */ +static thread_t *nil_find_thread(tstate_t state, void * p) { + thread_t *tp = nil.threads; + + while (true) { + /* Is this thread matching?*/ + if ((tp->state == state) && (tp->u1.p == p)) { + return tp; + } + tp++; + + chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS], + "pointer out of range"); + } +} + +/** + * @brief Puts in ready state all thread matching the specified status and + * associated object. + * + * @param[in] p object pointer + * @param[in] cnt number of threads to be readied as a negative number, + * non negative numbers are ignored + * @param[in] msg the wakeup message + * + * @iclass + */ +static cnt_t nil_ready_all(void * p, cnt_t cnt, msg_t msg) { + thread_t *tp = nil.threads;; + + while (cnt < (cnt_t)0) { + + chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS], + "pointer out of range"); + + /* Is this thread waiting on this queue?*/ + if ((tp->state == NIL_STATE_WTQUEUE) && (tp->u1.p == p)) { + cnt++; + (void) chSchReadyI(tp, msg); + } + tp++; + } + + return cnt; +} + /*===========================================================================*/ /* Module interrupt handlers. */ /*===========================================================================*/ @@ -621,7 +674,7 @@ void chSchRescheduleS(void) { * @param[in] timeout the number of ticks before the operation timeouts. * the following special values are allowed: * - @a TIME_INFINITE no timeout. - * + * . * @return The wakeup message. * @retval NIL_MSG_TMO if a timeout occurred. * @@ -703,7 +756,8 @@ msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout) { * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_INFINITE no timeout. - * + * - @a TIME_IMMEDIATE immediate timeout. + * . * @return The wake up message. * * @sclass @@ -712,6 +766,10 @@ msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) { chDbgAssert(*trp == NULL, "not NULL"); + if (TIME_IMMEDIATE == timeout) { + return MSG_TIMEOUT; + } + *trp = nil.current; nil.current->u1.trp = trp; return chSchGoSleepTimeoutS(NIL_STATE_SUSP, timeout); @@ -794,12 +852,9 @@ void chThdSleepUntil(systime_t abstime) { * @param[in] tqp pointer to the threads queue object * @param[in] timeout the timeout in system ticks, the special values are * handled as follow: - * - @a TIME_INFINITE the thread enters an infinite sleep - * state. - * - @a TIME_IMMEDIATE the thread is not enqueued and - * the function returns @p MSG_TIMEOUT as if a timeout - * occurred. - * + * - @a TIME_INFINITE no timeout. + * - @a TIME_IMMEDIATE immediate timeout. + * . * @return The message from @p osalQueueWakeupOneI() or * @p osalQueueWakeupAllI() functions. * @retval MSG_TIMEOUT if the thread has not been dequeued within the @@ -837,25 +892,13 @@ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) { * @iclass */ void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) { - thread_t *tp = nil.threads; + thread_t *tp; chDbgAssert(tqp->cnt < (cnt_t)0, "empty queue"); - while (true) { - /* Is this thread waiting on this queue?*/ - if (tp->u1.tqp == tqp) { - tqp->cnt++; - - chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting"); - - (void) chSchReadyI(tp, msg); - return; - } - tp++; - - chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS], - "pointer out of range"); - } + tqp->cnt++; + tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)tqp); + (void) chSchReadyI(tp, msg); } /** @@ -886,27 +929,11 @@ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) { * @iclass */ void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) { - thread_t *tp; chDbgCheckClassI(); chDbgCheck(tqp != NULL); - tp = nil.threads; - while (tqp->cnt < (cnt_t)0) { - - chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS], - "pointer out of range"); - - /* Is this thread waiting on this queue?*/ - if (tp->u1.tqp == tqp) { - - chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting"); - - tqp->cnt++; - (void) chSchReadyI(tp, msg); - } - tp++; - } + tqp->cnt = nil_ready_all((void *)tqp, tqp->cnt, msg); } #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) @@ -916,9 +943,9 @@ void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) { * @param[in] sp pointer to a @p semaphore_t structure * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. * - @a TIME_INFINITE no timeout. - * + * - @a TIME_IMMEDIATE immediate timeout. + * . * @return A message specifying how the invoking thread has been * released from the semaphore. * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the @@ -945,9 +972,9 @@ msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout) { * @param[in] sp pointer to a @p semaphore_t structure * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. * - @a TIME_INFINITE no timeout. - * + * - @a TIME_IMMEDIATE immediate timeout. + * . * @return A message specifying how the invoking thread has been * released from the semaphore. * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the @@ -968,13 +995,16 @@ msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout) { cnt_t cnt = sp->cnt; if (cnt <= (cnt_t)0) { if (TIME_IMMEDIATE == timeout) { + return MSG_TIMEOUT; } sp->cnt = cnt - (cnt_t)1; nil.current->u1.semp = sp; + return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout); } sp->cnt = cnt - (cnt_t)1; + return MSG_OK; } @@ -1010,21 +1040,8 @@ void chSemSignalI(semaphore_t *sp) { chDbgCheck(sp != NULL); if (++sp->cnt <= (cnt_t)0) { - thread_t *tp = nil.threads; - while (true) { - /* Is this thread waiting on this semaphore?*/ - if (tp->u1.semp == sp) { - - chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting"); - - (void) chSchReadyI(tp, MSG_OK); - return; - } - tp++; - - chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS], - "pointer out of range"); - } + thread_t *tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)sp); + (void) chSchReadyI(tp, MSG_OK); } } @@ -1065,7 +1082,6 @@ void chSemReset(semaphore_t *sp, cnt_t n) { * @iclass */ void chSemResetI(semaphore_t *sp, cnt_t n) { - thread_t *tp; cnt_t cnt; chDbgCheckClassI(); @@ -1073,22 +1089,9 @@ void chSemResetI(semaphore_t *sp, cnt_t n) { cnt = sp->cnt; sp->cnt = n; - tp = nil.threads; - while (cnt < (cnt_t)0) { - chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS], - "pointer out of range"); - - /* Is this thread waiting on this semaphore?*/ - if (tp->u1.semp == sp) { - - chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting"); - - cnt++; - (void) chSchReadyI(tp, MSG_RESET); - } - tp++; - } + /* Does nothing for cnt >= 0, calling anyway.*/ + (void) nil_ready_all((void *)sp, cnt, MSG_RESET); } #endif /* CH_CFG_USE_SEMAPHORES == TRUE */ @@ -1143,9 +1146,9 @@ void chEvtSignalI(thread_t *tp, eventmask_t mask) { * for, @p ALL_EVENTS enables all the events * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. * - @a TIME_INFINITE no timeout. - * + * - @a TIME_IMMEDIATE immediate timeout. + * . * @return The mask of the served and cleared events. * @retval 0 if the operation has timed out. * -- cgit v1.2.3