aboutsummaryrefslogtreecommitdiffstats
path: root/os/nil
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2018-10-21 06:23:41 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2018-10-21 06:23:41 +0000
commitafd9deb6f7b1b9e08a47cb2ca9d30f48546f776b (patch)
tree675d75c5a7142ad781f9a4a883ee6702bf07fdb8 /os/nil
parentd6b07697901d5b87354f38ef694a64ec9520e734 (diff)
downloadChibiOS-afd9deb6f7b1b9e08a47cb2ca9d30f48546f776b.tar.gz
ChibiOS-afd9deb6f7b1b9e08a47cb2ca9d30f48546f776b.tar.bz2
ChibiOS-afd9deb6f7b1b9e08a47cb2ca9d30f48546f776b.zip
Fixed bugs #982 and #983.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12374 110e8d01-0319-4d1e-a829-52ad28d1bb01
Diffstat (limited to 'os/nil')
-rw-r--r--os/nil/include/ch.h8
-rw-r--r--os/nil/src/ch.c159
2 files changed, 85 insertions, 82 deletions
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.
*