From 4f49b546b101841d523df17806bea67b269a2a85 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 17 Aug 2013 11:04:57 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6167 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/osal/chibios/osal.c | 149 ------------------------------------- os/hal/osal/chibios/osal.h | 131 +++++++++++++++++++++++++++----- os/rt/include/chlists.h | 26 ++++++- os/rt/include/chthreads.h | 40 ++++++---- os/rt/src/chlists.c | 81 ++++++++++++++++++-- os/rt/src/chqueues.c | 48 +++--------- os/rt/src/chschd.c | 7 +- os/rt/src/chthreads.c | 99 ++++++++++++++++++++---- test/testthd.c | 4 +- 9 files changed, 336 insertions(+), 249 deletions(-) diff --git a/os/hal/osal/chibios/osal.c b/os/hal/osal/chibios/osal.c index da3746eaf..d46840e91 100644 --- a/os/hal/osal/chibios/osal.c +++ b/os/hal/osal/chibios/osal.c @@ -84,153 +84,4 @@ void osalSysHalt(const char *reason) { chSysHalt(); } -/** - * @brief Sends the current thread sleeping and sets a reference variable. - * @note This function must reschedule, it can only be called from thread - * context. - * - * @param[in] trp a pointer to a thread reference object - * @return The wake up message. - * - * @sclass - */ -msg_t osalThreadSuspendS(thread_reference_t *trp) { - - chDbgAssert(*trp == NULL, "not NULL"); - - *trp = (thread_reference_t)chThdGetSelfX(); - chSchGoSleepS(CH_STATE_SUSPENDED); - return chThdGetSelfX()->p_msg; -} - -/** - * @brief Wakes up a thread waiting on a thread reference object. - * @note This function must not reschedule because it can be called from - * ISR context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] msg the message code - * - * @iclass - */ -void osalThreadResumeI(thread_reference_t *trp, msg_t msg) { - - if (*trp != NULL) { - - chDbgAssert((*trp)->p_state == CH_STATE_SUSPENDED, - "not THD_STATE_SUSPENDED"); - - (*trp)->p_u.rdymsg = msg; - chSchReadyI((thread_t *)*trp); - *trp = NULL; - } -} - -/** - * @brief Wakes up a thread waiting on a thread reference object. - * @note This function must reschedule, it can only be called from thread - * context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] msg the message code - * - * @iclass - */ -void osalThreadResumeS(thread_reference_t *trp, msg_t msg) { - - if (*trp != NULL) { - thread_t *tp = (thread_t *)*trp; - - chDbgAssert(tp->p_state == CH_STATE_SUSPENDED, "not THD_STATE_SUSPENDED"); - - *trp = NULL; - chSchWakeupS(tp, msg); - } -} - -/** - * @brief Enqueues the caller thread. - * @details The caller thread is enqueued and put to sleep until it is - * dequeued or the specified timeouts expires. - * - * @param[in] tqp pointer to the threads queue object - * @param[in] time 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. - * . - * @return The message from @p osalQueueWakeupOneI() or - * @p osalQueueWakeupAllI() functions. - * @retval RDY_TIMEOUT if the thread has not been dequeued within the - * specified timeout or if the function has been - * invoked with @p TIME_IMMEDIATE as timeout - * specification. - * - * @sclass - */ -msg_t osalQueueGoSleepTimeoutS(threads_queue_t *tqp, systime_t time) { - - void wakeup(void *p) { - thread_t *tp = (thread_t *)p; - - chSysUnlockFromISR(); - tp->p_u.rdymsg = RDY_TIMEOUT; - chSchReadyI(queue_dequeue(tp)); - chSysUnlockFromISR(); - } - - if (TIME_IMMEDIATE == time) - return MSG_TIMEOUT; - - queue_insert(currp, tqp); - if (TIME_INFINITE == time) - chSchGoSleepS(CH_STATE_SUSPENDED); - else { - virtual_timer_t vt; - - chVTDoSetI(&vt, time, wakeup, currp); - chSchGoSleepS(CH_STATE_SUSPENDED); - if (chVTIsArmedI(&vt)) - chVTDoResetI(&vt); - } - return currp->p_u.rdymsg; -} - -/** - * @brief Dequeues and wakes up one thread from the queue, if any. - * - * @param[in] tqp pointer to the threads queue object - * @param[in] msg the message code - * - * @iclass - */ -void osalQueueWakeupOneI(threads_queue_t *tqp, msg_t msg) { - - if (queue_notempty(tqp)) { - thread_t *tp = queue_fifo_remove(tqp); - tp->p_u.rdymsg = msg; - chSchReadyI(tp); - } -} - -/** - * @brief Dequeues and wakes up all threads from the queue. - * - * @param[in] tqp pointer to the threads queue object - * @param[in] msg the message code - * - * @iclass - */ -void osalQueueWakeupAllI(threads_queue_t *tqp, msg_t msg) { - - while (queue_notempty(tqp)) { - thread_t *tp = queue_fifo_remove(tqp); - tp->p_u.rdymsg = msg; - chSchReadyI(tp); - } -} - /** @} */ diff --git a/os/hal/osal/chibios/osal.h b/os/hal/osal/chibios/osal.h index fa48f3aa6..b3d0fae2b 100644 --- a/os/hal/osal/chibios/osal.h +++ b/os/hal/osal/chibios/osal.h @@ -130,10 +130,12 @@ typedef uint32_t systime_t; typedef uint32_t rtcnt_t; #endif +#if 0 /** * @brief Type of a thread reference. */ typedef thread_t * thread_reference_t; +#endif #if 0 /** @@ -257,12 +259,6 @@ extern "C" { #endif void osalInit(void); void osalSysHalt(const char *reason); - msg_t osalThreadSuspendS(thread_reference_t *trp); - void osalThreadResumeI(thread_reference_t *trp, msg_t msg); - void osalThreadResumeS(thread_reference_t *trp, msg_t msg); - msg_t osalQueueGoSleepTimeoutS(threads_queue_t *tqp, systime_t time); - void osalQueueWakeupOneI(threads_queue_t *tqp, msg_t msg); - void osalQueueWakeupAllI(threads_queue_t *tqp, msg_t msg); #ifdef __cplusplus } #endif @@ -391,6 +387,117 @@ static inline void osalThreadSleep(systime_t time) { chThdSleep(time); } +/** + * @brief Sends the current thread sleeping and sets a reference variable. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @return The wake up message. + * + * @sclass + */ +static inline msg_t osalThreadSuspendS(thread_reference_t *trp) { + + return osalThreadSuspendS(trp); +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must not reschedule because it can be called from + * ISR context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @iclass + */ +static inline void osalThreadResumeI(thread_reference_t *trp, msg_t msg) { + + chThreadResumeI(trp, msg); +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @iclass + */ +static inline void osalThreadResumeS(thread_reference_t *trp, msg_t msg) { + + chThreadResumeS(trp, msg); +} + +/** + * @brief Initializes a threads queue object. + * + * @param[out] tqp pointer to the threads queue object + * + * @init + */ +static inline void osalQueueObjectInit(threads_queue_t *tqp) { + + queue_init(tqp); +} + +/** + * @brief Enqueues the caller thread. + * @details The caller thread is enqueued and put to sleep until it is + * dequeued or the specified timeouts expires. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] time 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. + * . + * @return The message from @p osalQueueWakeupOneI() or + * @p osalQueueWakeupAllI() functions. + * @retval RDY_TIMEOUT if the thread has not been dequeued within the + * specified timeout or if the function has been + * invoked with @p TIME_IMMEDIATE as timeout + * specification. + * + * @sclass + */ +static inline msg_t osalQueueGoSleepTimeoutS(threads_queue_t *tqp, systime_t time) { + + return chQueueGoSleepTimeoutS(tqp, time); +} + +/** + * @brief Dequeues and wakes up one thread from the queue, if any. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] msg the message code + * + * @iclass + */ +static inline void osalQueueWakeupOneI(threads_queue_t *tqp, msg_t msg) { + + chQueueWakeupOneI(tqp, msg); +} + +/** + * @brief Dequeues and wakes up all threads from the queue. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] msg the message code + * + * @iclass + */ +static inline void osalQueueWakeupAllI(threads_queue_t *tqp, msg_t msg) { + + chQueueWakeupAllI(tqp, msg); +} + /** * @brief Initializes an event flags object. * @@ -494,18 +601,6 @@ static inline void osalMutexUnlock(mutex_t *mp) { #endif } -/** - * @brief Initializes a threads queue object. - * - * @param[out] tqp pointer to the threads queue object - * - * @init - */ -static inline void osalQueueObjectInit(threads_queue_t *tqp) { - - queue_init(tqp); -} - #endif /* _OSAL_H_ */ /** @} */ diff --git a/os/rt/include/chlists.h b/os/rt/include/chlists.h index 69a42bcce..1384dc58f 100644 --- a/os/rt/include/chlists.h +++ b/os/rt/include/chlists.h @@ -20,9 +20,9 @@ /** * @file chlists.h - * @brief Thread queues/lists inlined code. + * @brief Thread queues and lists header. * - * @addtogroup internals + * @addtogroup queues_list * @{ */ @@ -72,6 +72,16 @@ /* External declarations. */ /*===========================================================================*/ +#ifdef __cplusplus +extern "C" { +#endif + msg_t chQueueGoSleepTimeoutS(threads_queue_t *tqp, systime_t time); + void chQueueWakeupOneI(threads_queue_t *tqp, msg_t msg); + void chQueueWakeupAllI(threads_queue_t *tqp, msg_t msg); +#ifdef __cplusplus +} +#endif + /*===========================================================================*/ /* Module inline functions. */ /*===========================================================================*/ @@ -192,4 +202,16 @@ static inline thread_t *queue_dequeue(thread_t *tp) { } #endif /* CH_CFG_OPTIMIZE_SPEED */ +/** + * @brief Initializes a threads queue object. + * + * @param[out] tqp pointer to the threads queue object + * + * @init + */ +static inline void chQueueObjectInit(threads_queue_t *tqp) { + + queue_init(tqp); +} + #endif /* _CHLISTS_H_ */ diff --git a/os/rt/include/chthreads.h b/os/rt/include/chthreads.h index d27de04a9..18fb962d4 100644 --- a/os/rt/include/chthreads.h +++ b/os/rt/include/chthreads.h @@ -41,20 +41,20 @@ #define CH_STATE_CURRENT 1 /**< @brief Currently running. */ #define CH_STATE_WTSTART 2 /**< @brief Created but not started. */ #define CH_STATE_SUSPENDED 3 /**< @brief Created in suspended state. */ -#define CH_STATE_WTSEM 4 /**< @brief Waiting on a semaphore. */ -#define CH_STATE_WTMTX 5 /**< @brief Waiting on a mutex. */ -#define CH_STATE_WTCOND 6 /**< @brief Waiting on a condition +#define CH_STATE_QUEUED 4 /**< @brief Waiting on an I/O queue. */ +#define CH_STATE_WTSEM 5 /**< @brief Waiting on a semaphore. */ +#define CH_STATE_WTMTX 6 /**< @brief Waiting on a mutex. */ +#define CH_STATE_WTCOND 7 /**< @brief Waiting on a condition variable. */ -#define CH_STATE_SLEEPING 7 /**< @brief Waiting in @p chThdSleep() +#define CH_STATE_SLEEPING 8 /**< @brief Waiting in @p chThdSleep() or @p chThdSleepUntil(). */ -#define CH_STATE_WTEXIT 8 /**< @brief Waiting in @p chThdWait(). */ -#define CH_STATE_WTOREVT 9 /**< @brief Waiting for an event. */ -#define CH_STATE_WTANDEVT 10 /**< @brief Waiting for several events. */ -#define CH_STATE_SNDMSGQ 11 /**< @brief Sending a message, in queue.*/ -#define CH_STATE_SNDMSG 12 /**< @brief Sent a message, waiting +#define CH_STATE_WTEXIT 9 /**< @brief Waiting in @p chThdWait(). */ +#define CH_STATE_WTOREVT 10 /**< @brief Waiting for an event. */ +#define CH_STATE_WTANDEVT 11 /**< @brief Waiting for several events. */ +#define CH_STATE_SNDMSGQ 12 /**< @brief Sending a message, in queue.*/ +#define CH_STATE_SNDMSG 13 /**< @brief Sent a message, waiting answer. */ -#define CH_STATE_WTMSG 13 /**< @brief Waiting for a message. */ -#define CH_STATE_WTQUEUE 14 /**< @brief Waiting on an I/O queue. */ +#define CH_STATE_WTMSG 14 /**< @brief Waiting for a message. */ #define CH_STATE_FINAL 15 /**< @brief Thread terminated. */ /** @@ -63,9 +63,9 @@ * indexed using the numeric thread state values. */ #define CH_STATE_NAMES \ - "READY", "WTSTART", "CURRENT", "SUSPENDED", "WTSEM", "WTMTX", "WTCOND", \ - "SLEEPING", "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", \ - "WTMSG", "WTQUEUE", "FINAL" + "READY", "WTSTART", "CURRENT", "SUSPENDED", "QUEUED", "WTSEM", "WTMTX", \ + "WTCOND", "SLEEPING", "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", \ + "SNDMSG", "WTMSG", "FINAL" /** @} */ /** @@ -93,6 +93,10 @@ /* Module data structures and types. */ /*===========================================================================*/ +/** + * @brief Type of a thread reference. + */ +typedef thread_t * thread_reference_t; /** * @brief Thread function. @@ -161,8 +165,12 @@ extern "C" { tprio_t prio, tfunc_t pf, void *arg); thread_t *chThdCreateStatic(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg); + thread_t *chThdStart(thread_t *tp); tprio_t chThdSetPriority(tprio_t newprio); - thread_t *chThdResume(thread_t *tp); + msg_t chThreadSuspendS(thread_reference_t *trp); + void chThreadResumeI(thread_reference_t *trp, msg_t msg); + void chThreadResumeS(thread_reference_t *trp, msg_t msg); + void chThreadResume(thread_reference_t *trp, msg_t msg); void chThdTerminate(thread_t *tp); void chThdSleep(systime_t time); void chThdSleepUntil(systime_t time); @@ -249,7 +257,7 @@ static inline bool chThdShouldTerminateX(void) { * * @param[in] tp pointer to the thread * - * @xclass + * @iclass */ static inline thread_t *chThdStartI(thread_t *tp) { diff --git a/os/rt/src/chlists.c b/os/rt/src/chlists.c index 0f492db5f..5bba30078 100644 --- a/os/rt/src/chlists.c +++ b/os/rt/src/chlists.c @@ -20,12 +20,9 @@ /** * @file chlists.c - * @brief Thread queues/lists code. + * @brief Thread queues and lists code. * - * @addtogroup internals - * @details All the functions present in this module, while public, are not - * OS APIs and should not be directly used in the user applications - * code. + * @addtogroup queues_list * @{ */ #include "ch.h" @@ -54,6 +51,80 @@ /* Module exported functions. */ /*===========================================================================*/ +/** + * @brief Enqueues the caller thread. + * @details The caller thread is enqueued and put to sleep until it is + * dequeued or the specified timeouts expires. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] time 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. + * . + * @return The message from @p osalQueueWakeupOneI() or + * @p osalQueueWakeupAllI() functions. + * @retval RDY_TIMEOUT if the thread has not been dequeued within the + * specified timeout or if the function has been + * invoked with @p TIME_IMMEDIATE as timeout + * specification. + * + * @sclass + */ +msg_t chQueueGoSleepTimeoutS(threads_queue_t *tqp, systime_t time) { + + if (TIME_IMMEDIATE == time) + return RDY_TIMEOUT; + + queue_insert(currp, tqp); + return chSchGoSleepTimeoutS(CH_STATE_QUEUED, time); +} + +/** + * @brief Dequeues and wakes up one thread from the queue, if any. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] msg the message code + * + * @iclass + */ +void chQueueWakeupOneI(threads_queue_t *tqp, msg_t msg) { + + if (queue_notempty(tqp)) { + thread_t *tp = queue_fifo_remove(tqp); + + chDbgAssert(tp->p_state == CH_STATE_QUEUED, + "not CH_STATE_QUEUED"); + + tp->p_u.rdymsg = msg; + chSchReadyI(tp); + } +} + +/** + * @brief Dequeues and wakes up all threads from the queue. + * + * @param[in] tqp pointer to the threads queue object + * @param[in] msg the message code + * + * @iclass + */ +void chQueueWakeupAllI(threads_queue_t *tqp, msg_t msg) { + + while (queue_notempty(tqp)) { + thread_t *tp = queue_fifo_remove(tqp); + + chDbgAssert(tp->p_state == CH_STATE_QUEUED, + "not CH_STATE_QUEUED"); + + tp->p_u.rdymsg = msg; + chSchReadyI(tp); + } +} + #if !CH_CFG_OPTIMIZE_SPEED || defined(__DOXYGEN__) /** * @brief Inserts a thread into a priority ordered queue. diff --git a/os/rt/src/chqueues.c b/os/rt/src/chqueues.c index 679d69337..c65eb06c6 100644 --- a/os/rt/src/chqueues.c +++ b/os/rt/src/chqueues.c @@ -65,30 +65,6 @@ /* Module local functions. */ /*===========================================================================*/ -/** - * @brief Puts the invoking thread into the queue's threads queue. - * - * @param[out] qp pointer to an @p io_queue_t structure - * @param[in] time the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return A message specifying how the invoking thread has been - * released from threads queue. - * @retval Q_OK is the normal exit, thread signaled. - * @retval Q_RESET if the queue has been reset. - * @retval Q_TIMEOUT if the queue operation timed out. - */ -static msg_t qwait(io_queue_t *qp, systime_t time) { - - if (TIME_IMMEDIATE == time) - return Q_TIMEOUT; - currp->p_u.wtobjp = qp; - queue_insert(currp, &qp->q_waiting); - return chSchGoSleepTimeoutS(CH_STATE_WTQUEUE, time); -} - /*===========================================================================*/ /* Module exported functions. */ /*===========================================================================*/ @@ -112,7 +88,7 @@ static msg_t qwait(io_queue_t *qp, systime_t time) { void chIQObjectInit(input_queue_t *iqp, uint8_t *bp, size_t size, qnotify_t infy, void *link) { - queue_init(&iqp->q_waiting); + chQueueObjectInit(&iqp->q_waiting); iqp->q_counter = 0; iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp; iqp->q_top = bp + size; @@ -137,8 +113,7 @@ void chIQResetI(input_queue_t *iqp) { iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer; iqp->q_counter = 0; - while (queue_notempty(&iqp->q_waiting)) - chSchReadyI(queue_fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_RESET; + chQueueWakeupAllI(&iqp->q_waiting, Q_RESET); } /** @@ -166,8 +141,7 @@ msg_t chIQPutI(input_queue_t *iqp, uint8_t b) { if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; - if (queue_notempty(&iqp->q_waiting)) - chSchReadyI(queue_fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_OK; + chQueueWakeupOneI(&iqp->q_waiting, Q_OK); return Q_OK; } @@ -201,7 +175,7 @@ msg_t chIQGetTimeout(input_queue_t *iqp, systime_t time) { while (chIQIsEmptyI(iqp)) { msg_t msg; - if ((msg = qwait((io_queue_t *)iqp, time)) < Q_OK) { + if ((msg = chQueueGoSleepTimeoutS(&iqp->q_waiting, time)) < Q_OK) { chSysUnlock(); return msg; } @@ -253,7 +227,7 @@ size_t chIQReadTimeout(input_queue_t *iqp, uint8_t *bp, nfy(iqp); while (chIQIsEmptyI(iqp)) { - if (qwait((io_queue_t *)iqp, time) != Q_OK) { + if (chQueueGoSleepTimeoutS(&iqp->q_waiting, time) != Q_OK) { chSysUnlock(); return r; } @@ -292,7 +266,7 @@ size_t chIQReadTimeout(input_queue_t *iqp, uint8_t *bp, void chOQObjectInit(output_queue_t *oqp, uint8_t *bp, size_t size, qnotify_t onfy, void *link) { - queue_init(&oqp->q_waiting); + chQueueObjectInit(&oqp->q_waiting); oqp->q_counter = size; oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp; oqp->q_top = bp + size; @@ -317,8 +291,7 @@ void chOQResetI(output_queue_t *oqp) { oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer; oqp->q_counter = chQSizeI(oqp); - while (queue_notempty(&oqp->q_waiting)) - chSchReadyI(queue_fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_RESET; + chQueueWakeupAllI(&oqp->q_waiting, Q_RESET); } /** @@ -349,7 +322,7 @@ msg_t chOQPutTimeout(output_queue_t *oqp, uint8_t b, systime_t time) { while (chOQIsFullI(oqp)) { msg_t msg; - if ((msg = qwait((io_queue_t *)oqp, time)) < Q_OK) { + if ((msg = chQueueGoSleepTimeoutS(&oqp->q_waiting, time)) < Q_OK) { chSysUnlock(); return msg; } @@ -390,8 +363,7 @@ msg_t chOQGetI(output_queue_t *oqp) { if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; - if (queue_notempty(&oqp->q_waiting)) - chSchReadyI(queue_fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK; + chQueueWakeupOneI(&oqp->q_waiting, Q_OK); return b; } @@ -430,7 +402,7 @@ size_t chOQWriteTimeout(output_queue_t *oqp, const uint8_t *bp, chSysLock(); while (true) { while (chOQIsFullI(oqp)) { - if (qwait((io_queue_t *)oqp, time) != Q_OK) { + if (chQueueGoSleepTimeoutS(&oqp->q_waiting, time) != Q_OK) { chSysUnlock(); return w; } diff --git a/os/rt/src/chschd.c b/os/rt/src/chschd.c index 9b7147a32..f03c5eff3 100644 --- a/os/rt/src/chschd.c +++ b/os/rt/src/chschd.c @@ -147,22 +147,17 @@ static void wakeup(void *p) { another thread with higher priority.*/ chSysUnlockFromISR(); return; -#if CH_CFG_USE_SEMAPHORES || CH_CFG_USE_QUEUES || \ - (CH_CFG_USE_CONDVARS && CH_CFG_USE_CONDVARS_TIMEOUT) #if CH_CFG_USE_SEMAPHORES case CH_STATE_WTSEM: chSemFastSignalI((semaphore_t *)tp->p_u.wtobjp); /* Falls into, intentional. */ #endif -#if CH_CFG_USE_QUEUES - case CH_STATE_WTQUEUE: -#endif #if CH_CFG_USE_CONDVARS && CH_CFG_USE_CONDVARS_TIMEOUT case CH_STATE_WTCOND: #endif + case CH_STATE_QUEUED: /* States requiring dequeuing.*/ queue_dequeue(tp); -#endif } tp->p_u.rdymsg = RDY_TIMEOUT; chSchReadyI(tp); diff --git a/os/rt/src/chthreads.c b/os/rt/src/chthreads.c index d6fbc880f..dbcd1f754 100644 --- a/os/rt/src/chthreads.c +++ b/os/rt/src/chthreads.c @@ -222,6 +222,21 @@ thread_t *chThdCreateStatic(void *wsp, size_t size, return tp; } +/** + * @brief Resumes a thread created with @p chThdCreateI(). + * + * @param[in] tp pointer to the thread + * + * @api + */ +thread_t *chThdStart(thread_t *tp) { + + chSysLock(); + tp = chThdStartI(tp); + chSysUnlock(); + return tp; +} + /** * @brief Changes the running thread priority level then reschedules if * necessary. @@ -255,26 +270,84 @@ tprio_t chThdSetPriority(tprio_t newprio) { } /** - * @brief Resumes a suspended thread. - * @pre The specified thread pointer must refer to an initialized thread - * in the @p CH_STATE_SUSPENDED state. - * @post The specified thread is immediately started or put in the ready - * list depending on the relative priority levels. - * @note Use this function to start threads created with @p chThdCreateI(). + * @brief Sends the current thread sleeping and sets a reference variable. + * @note This function must reschedule, it can only be called from thread + * context. * - * @param[in] tp pointer to the thread - * @return The pointer to the thread. + * @param[in] trp a pointer to a thread reference object + * @return The wake up message. + * + * @sclass + */ +msg_t chThreadSuspendS(thread_reference_t *trp) { + + chDbgAssert(*trp == NULL, "not NULL"); + + *trp = (thread_reference_t)chThdGetSelfX(); + chSchGoSleepS(CH_STATE_SUSPENDED); + return chThdGetSelfX()->p_msg; +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must not reschedule because it can be called from + * ISR context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @iclass + */ +void chThreadResumeI(thread_reference_t *trp, msg_t msg) { + + if (*trp != NULL) { + + chDbgAssert((*trp)->p_state == CH_STATE_SUSPENDED, + "not THD_STATE_SUSPENDED"); + + (*trp)->p_u.rdymsg = msg; + chSchReadyI(*trp); + *trp = NULL; + } +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @iclass + */ +void chThreadResumeS(thread_reference_t *trp, msg_t msg) { + + if (*trp != NULL) { + + chDbgAssert((*trp)->p_state == CH_STATE_SUSPENDED, + "not THD_STATE_SUSPENDED"); + + *trp = NULL; + chSchWakeupS(*trp, msg); + } +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code * * @api */ -thread_t *chThdResume(thread_t *tp) { +void chThreadResume(thread_reference_t *trp, msg_t msg) { chSysLock(); - chDbgAssert(tp->p_state == CH_STATE_SUSPENDED, - "thread not in CH_STATE_SUSPENDED state"); - chSchWakeupS(tp, RDY_OK); + chThreadResumeS(trp, msg); chSysUnlock(); - return tp; } /** diff --git a/test/testthd.c b/test/testthd.c index 34de252a8..522e54b9b 100644 --- a/test/testthd.c +++ b/test/testthd.c @@ -97,11 +97,11 @@ static void thd2_execute(void) { threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E"); threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A"); threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B"); - /* Done this way for coverage of chThdCreateI() and chThdResume().*/ + /* Done this way for coverage of chThdCreateI() and chThdStart().*/ chSysLock(); threads[2] = chThdCreateI(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C"); chSysUnlock(); - chThdResume(threads[2]); + chThdStart(threads[2]); test_wait_threads(); test_assert_sequence(1, "ABCDE"); }