aboutsummaryrefslogtreecommitdiffstats
path: root/os/rt
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-08-17 11:04:57 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-08-17 11:04:57 +0000
commit4f49b546b101841d523df17806bea67b269a2a85 (patch)
tree4690183f1989a0caff203b688c0dbdf25f9c26d6 /os/rt
parentbfa3ba9f00d263a15d6d6b2dec2aa0b81058df27 (diff)
downloadChibiOS-4f49b546b101841d523df17806bea67b269a2a85.tar.gz
ChibiOS-4f49b546b101841d523df17806bea67b269a2a85.tar.bz2
ChibiOS-4f49b546b101841d523df17806bea67b269a2a85.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6167 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/rt')
-rw-r--r--os/rt/include/chlists.h26
-rw-r--r--os/rt/include/chthreads.h40
-rw-r--r--os/rt/src/chlists.c81
-rw-r--r--os/rt/src/chqueues.c48
-rw-r--r--os/rt/src/chschd.c7
-rw-r--r--os/rt/src/chthreads.c99
6 files changed, 221 insertions, 80 deletions
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
@@ -223,6 +223,21 @@ thread_t *chThdCreateStatic(void *wsp, size_t size,
}
/**
+ * @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.
* @note The function returns the real thread priority regardless of the
@@ -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;
}
/**