aboutsummaryrefslogtreecommitdiffstats
path: root/os/nil
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2017-04-11 09:23:49 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2017-04-11 09:23:49 +0000
commitca129dc5b437343cb35b38206363a9b5940971af (patch)
treecd9791a0ff49651d6917dcffb6ac03019bc6ab5d /os/nil
parent7b2d689e16bc11ce37cb21308f8b80d3827d910c (diff)
downloadChibiOS-ca129dc5b437343cb35b38206363a9b5940971af.tar.gz
ChibiOS-ca129dc5b437343cb35b38206363a9b5940971af.tar.bz2
ChibiOS-ca129dc5b437343cb35b38206363a9b5940971af.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10154 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/nil')
-rw-r--r--os/nil/include/ch.h53
-rw-r--r--os/nil/src/ch.c126
2 files changed, 137 insertions, 42 deletions
diff --git a/os/nil/include/ch.h b/os/nil/include/ch.h
index cb32383cb..f21527c2d 100644
--- a/os/nil/include/ch.h
+++ b/os/nil/include/ch.h
@@ -111,12 +111,12 @@
executing. */
#define NIL_STATE_SLEEPING (tstate_t)1 /**< @brief Thread sleeping. */
#define NIL_STATE_SUSP (tstate_t)2 /**< @brief Thread suspended. */
-#define NIL_STATE_WTSEM (tstate_t)3 /**< @brief On semaphore. */
+#define NIL_STATE_WTQUEUE (tstate_t)3 /**< @brief On queue or semaph. */
#define NIL_STATE_WTOREVT (tstate_t)4 /**< @brief Waiting for events. */
#define NIL_THD_IS_READY(tr) ((tr)->state == NIL_STATE_READY)
#define NIL_THD_IS_SLEEPING(tr) ((tr)->state == NIL_STATE_SLEEPING)
#define NIL_THD_IS_SUSP(tr) ((tr)->state == NIL_STATE_SUSP)
-#define NIL_THD_IS_WTSEM(tr) ((tr)->state == NIL_STATE_WTSEM)
+#define NIL_THD_IS_WTQUEUE(tr) ((tr)->state == NIL_STATE_WTQUEUE)
#define NIL_THD_IS_WTOREVT(tr) ((tr)->state == NIL_STATE_WTOREVT)
/** @} */
@@ -474,18 +474,25 @@ typedef struct nil_thread thread_t;
#include "chcore.h"
-#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
- * @brief Type of a structure representing a semaphore.
+ * @brief Structure representing a queue of threads.
*/
-typedef struct nil_semaphore semaphore_t;
+struct nil_threads_queue {
+ volatile cnt_t cnt; /**< @brief Threads Queue counter. */
+};
/**
- * @brief Structure representing a counting semaphore.
+ * @brief Type of a queue of threads.
*/
-struct nil_semaphore {
- volatile cnt_t cnt; /**< @brief Semaphore counter. */
-};
+typedef struct nil_threads_queue threads_queue_t;
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a structure representing a semaphore.
+ * @note Semaphores are implemented on thread queues, the object is the
+ * same, the behavior is slightly different.
+ */
+typedef threads_queue_t semaphore_t;
#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
/**
@@ -526,9 +533,7 @@ struct nil_thread {
msg_t msg; /**< @brief Wake-up message. */
void *p; /**< @brief Generic pointer. */
thread_reference_t *trp; /**< @brief Pointer to thread reference.*/
-#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
- semaphore_t *semp; /**< @brief Pointer to semaphore. */
-#endif
+ threads_queue_t *tqp; /**< @brief Pointer to thread queue. */
#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
eventmask_t ewmask; /**< @brief Enabled events mask. */
#endif
@@ -1126,6 +1131,27 @@ struct nil_system {
(void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, (abstime) - \
chVTGetSystemTimeX())
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+#define chThdQueueObjectInit(tqp) ((tqp)->cnt = (cnt_t)0)
+
+/**
+ * @brief Evaluates to @p true if the specified queue is empty.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+#define chThdQueueIsEmptyI(tqp) ((bool)(tqp->cnt >= (cnt_t)0))
+
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Initializes a semaphore with the specified counter value.
@@ -1341,6 +1367,9 @@ extern "C" {
void chThdResumeI(thread_reference_t *trp, msg_t msg);
void chThdSleep(systime_t timeout);
void chThdSleepUntil(systime_t abstime);
+ void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);
#if CH_CFG_USE_SEMAPHORES == TRUE
msg_t chSemWaitTimeout(semaphore_t *sp, systime_t timeout);
msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout);
diff --git a/os/nil/src/ch.c b/os/nil/src/ch.c
index 7fdf6812f..faf725164 100644
--- a/os/nil/src/ch.c
+++ b/os/nil/src/ch.c
@@ -328,10 +328,10 @@ void chSysTimerHandlerI(void) {
/* Did the timer reach zero?*/
if (--tp->timeout == (systime_t)0) {
- /* Timeout on semaphores requires a special handling because the
- semaphore counter must be incremented.*/
+ /* Timeout on queues/semaphores requires a special handling because
+ the counter must be incremented.*/
/*lint -save -e9013 [15.7] There is no else because it is not needed.*/
- if (NIL_THD_IS_WTSEM(tp)) {
+ if (NIL_THD_IS_WTQUEUE(tp)) {
tp->u1.semp->cnt++;
}
else if (NIL_THD_IS_SUSP(tp)) {
@@ -367,20 +367,16 @@ void chSysTimerHandlerI(void) {
tp->timeout = timeout;
if (timeout == (systime_t)0) {
-#if CH_CFG_USE_SEMAPHORES == TRUE
- /* Timeout on semaphores requires a special handling because the
- semaphore counter must be incremented.*/
- if (NIL_THD_IS_WTSEM(tp)) {
- tp->u1.semp->cnt++;
+ /* Timeout on thread queues requires a special handling because the
+ counter must be incremented.*/
+ if (NIL_THD_IS_WTQUEUE(tp)) {
+ tp->u1.tqp->cnt++;
}
else {
-#endif
if (NIL_THD_IS_SUSP(tp)) {
*tp->u1.trp = NULL;
}
-#if CH_CFG_USE_SEMAPHORES == TRUE
}
-#endif
(void) chSchReadyI(tp, MSG_TIMEOUT);
}
else {
@@ -761,6 +757,90 @@ void chThdSleepUntil(systime_t abstime) {
chSysUnlock();
}
+/**
+ * @brief Dequeues and wakes up one thread from the threads queue object.
+ * @details Dequeues one thread from the queue without checking if the queue
+ * is empty.
+ * @pre The queue must contain at least an object.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+ thread_reference_t tr = nil.threads;
+
+ chDbgAssert(tqp->cnt > (cnt_t)0, "empty queue");
+
+ while (true) {
+ /* Is this thread waiting on this queue?*/
+ if (tr->u1.tqp == tqp) {
+ tqp->cnt++;
+
+ chDbgAssert(NIL_THD_IS_WTQUEUE(tr), "not waiting");
+
+ (void) chSchReadyI(tr, msg);
+ return;
+ }
+ tr++;
+
+ chDbgAssert(tr < &nil.threads[CH_CFG_NUM_THREADS],
+ "pointer out of range");
+ }
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the threads queue object,
+ * if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ chDbgCheckClassI();
+ chDbgCheck(tqp != NULL);
+
+ if (tqp->cnt <= (cnt_t)0) {
+ chThdDoDequeueNextI(tqp, msg);
+ }
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the threads queue object.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @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++;
+ }
+}
+
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Performs a wait operation on a semaphore with timeout specification.
@@ -823,8 +903,8 @@ msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout) {
return MSG_TIMEOUT;
}
sp->cnt = cnt - (cnt_t)1;
- nil.current->u1.semp = sp;
- return chSchGoSleepTimeoutS(NIL_STATE_WTSEM, timeout);
+ nil.current->u1.tqp = (threads_queue_t *)sp;
+ return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
}
sp->cnt = cnt - (cnt_t)1;
return MSG_OK;
@@ -862,21 +942,7 @@ void chSemSignalI(semaphore_t *sp) {
chDbgCheck(sp != NULL);
if (++sp->cnt <= (cnt_t)0) {
- thread_reference_t tr = nil.threads;
- while (true) {
- /* Is this thread waiting on this semaphore?*/
- if (tr->u1.semp == sp) {
-
- chDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting");
-
- (void) chSchReadyI(tr, MSG_OK);
- return;
- }
- tr++;
-
- chDbgAssert(tr < &nil.threads[CH_CFG_NUM_THREADS],
- "pointer out of range");
- }
+ chThdDoDequeueNextI((threads_queue_t *)sp, MSG_OK);
}
}
@@ -932,9 +998,9 @@ void chSemResetI(semaphore_t *sp, cnt_t n) {
"pointer out of range");
/* Is this thread waiting on this semaphore?*/
- if (tp->u1.semp == sp) {
+ if (tp->u1.tqp == (threads_queue_t *)sp) {
- chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting");
+ chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting");
cnt++;
(void) chSchReadyI(tp, MSG_RESET);