diff options
-rw-r--r-- | docs/ch.txt | 24 | ||||
-rw-r--r-- | docs/src/atomic.dox | 10 | ||||
-rw-r--r-- | docs/src/timing.dox | 42 | ||||
-rw-r--r-- | src/chschd.c | 8 | ||||
-rw-r--r-- | src/chthreads.c | 20 | ||||
-rw-r--r-- | src/include/threads.h | 1 | ||||
-rw-r--r-- | test/testsem.c | 1 |
7 files changed, 73 insertions, 33 deletions
diff --git a/docs/ch.txt b/docs/ch.txt index 0ae4eb61b..74436d6b5 100644 --- a/docs/ch.txt +++ b/docs/ch.txt @@ -192,7 +192,28 @@ *
* @section thread_states Threads States
* The image shows how threads can change their state in ChibiOS/RT.<br>
- * @image html states.png
+ * @dot
+ digraph example {
+ /*rankdir="LR";*/
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"];
+ start [label="Start", style="bold"];
+ run [label="Running"];
+ ready [label="Ready"];
+ suspend [label="Suspended"];
+ sleep [label="Sleeping"];
+ stop [label="Stop", style="bold"];
+ start -> suspend [label="chThdInit()", fontname=Helvetica, fontsize=8, constraint=false];
+ start -> run [label="chThdCreate()", fontname=Helvetica, fontsize=8];
+ start -> ready [label="chThdCreate()", fontname=Helvetica, fontsize=8];
+ run -> ready [dir="both", label="Reschedulation", fontname=Helvetica, fontsize=8];
+ suspend -> run [label="chThdResume()", fontname=Helvetica, fontsize=8];
+ suspend -> ready [label="chThdResume()", fontname=Helvetica, fontsize=8];
+ run -> sleep [label="chSchGoSleepS()", fontname=Helvetica, fontsize=8];
+ sleep -> run [label="chSchWakepS()", fontname=Helvetica, fontsize=8];
+ sleep -> ready [label="chSchWakepS()", fontname=Helvetica, fontsize=8];
+ run -> stop [label="chThdExit()", fontname=Helvetica, fontsize=8];
+ }
+ * @enddot
*
* @section priority Priority Levels
* Priorities in ChibiOS/RT are a contiguous numerical range but the initial
@@ -246,6 +267,7 @@ * - @subpage article_atomic
* - @subpage article_saveram
* - @subpage article_interrupts
+ * - @subpage article_timing
*/
/** @} */
diff --git a/docs/src/atomic.dox b/docs/src/atomic.dox index 22601d8d9..144d6bca0 100644 --- a/docs/src/atomic.dox +++ b/docs/src/atomic.dox @@ -12,17 +12,13 @@ chSemSignalI(&sem1);
chSemSignalI(&sem2);
- if (tp != NULL) {
- chThdResumeI(tp);
- tp = NULL;
- }
chSchRescheduleS();
chSysUnlock();
* @endcode
- * The above example performs a signal operation on two semaphores, optionally
- * resumes a thread, and performs a final reschedulation. The three operations
- * are performed atomically.<br>
+ * The above example performs a signal operation on two semaphores and
+ * performs a final reschedulation. The two operations are performed
+ * atomically.<br>
* An hypotetical @p chSemSignalSignalWait() operation could be implemented as
* follow:
* @code
diff --git a/docs/src/timing.dox b/docs/src/timing.dox new file mode 100644 index 000000000..e38fcb74c --- /dev/null +++ b/docs/src/timing.dox @@ -0,0 +1,42 @@ +/**
+ * @page article_timing Reliable timings using Threads
+ * @{
+ * One common task is to have threads do something at regular, scheduled,
+ * intervals.
+ * An obvious solution is to write something like this:
+ * @code
+msg_t my_thread(void *param) {
+
+ while (TRUE) {
+ do_something();
+ chThdSleepMilliseconds(1000); /* Fixed interval */
+ }
+}
+ * @endcode
+ * This example works well assuming that @p do_something() execution time is
+ * well below the system tick period and that @p my_thread() is not preempted
+ * by other threads inserting long intervals.<br>
+ * If the above conditions are not satisfied you may have @p do_something()
+ * executed at irregular intevals, as example:<br><br>
+ * T0...T0+1000...T0+2002...T0+3002...T0+4005...etc.<br><br>
+ * Also note that the error increases over time and this kind of behavior can
+ * lead anomalies really hard to debug.
+ * <h2>A better solution</h2>
+ * It is possible to rewrite the above code using absolute deadlines rather
+ * than fixed intervals:
+ * @code
+msg_t my_thread(void *param) {
+
+ systick_t time = chSysGetTime(); /* T0 */
+ while (TRUE) {
+ time += MS2ST(1000); /* Next deadline */
+ do_something();
+ chThdSleepUntil(time);
+ }
+}
+ * @endcode
+ * Using this code @p do_something() will always be executed at an absolute
+ * deadline time and the error will not accumulate over time regardless of
+ * the execution time and delays inserted by other threads.
+ */
+/** @} */
diff --git a/src/chschd.c b/src/chschd.c index e568ac64a..cc89682a8 100644 --- a/src/chschd.c +++ b/src/chschd.c @@ -102,11 +102,13 @@ static void wakeup(void *p) { #ifdef CH_USE_SEMAPHORES case PRWTSEM: chSemFastSignalI(tp->p_wtsemp); - /* Falls into, intentional.*/ + /* Falls into, intentional. */ #endif case PRWTCOND: - chSchReadyI(dequeue(tp))->p_rdymsg = RDY_TIMEOUT; - break; + case PRWTMTX: + /* States requiring dequeuing. */ + dequeue(tp); + /* Falls into, intentional. */ default: chSchReadyI(tp)->p_rdymsg = RDY_TIMEOUT; } diff --git a/src/chthreads.c b/src/chthreads.c index 355687423..28d969e46 100644 --- a/src/chthreads.c +++ b/src/chthreads.c @@ -215,26 +215,6 @@ void chThdSetPriority(tprio_t newprio) { } /** - * @brief Suspends the invoking thread. - * - * @param tpp pointer to a @p Thread pointer, the @p Thread pointer is set - * to point to the suspended process before it enters the - * @p PRSUSPENDED state. The variable pointed by this parameter - * must be set to @p NULL on entry. - * @note The resume operation is meant to be executed into an interrupt or timer - * handler. The handler is also responsible to clear the variable pointed - * by @p tpp after invoking @p chThdResumeI(). - */ -void chThdSuspend(Thread **tpp) { - - chSysLock(); - chDbgAssert(*tpp == NULL, "chthreads.c, chThdSuspend()"); - *tpp = currp; - chSchGoSleepS(PRSUSPENDED); - chSysUnlock(); -} - -/** * @brief Resumes a suspended thread. * * @param tp the pointer to the thread diff --git a/src/include/threads.h b/src/include/threads.h index 68f7f9bb9..5ca7dd0ce 100644 --- a/src/include/threads.h +++ b/src/include/threads.h @@ -183,7 +183,6 @@ extern "C" { #endif void chThdSetPriority(tprio_t newprio); Thread *chThdResume(Thread *tp); - void chThdSuspend(Thread **tpp); void chThdTerminate(Thread *tp); void chThdSleep(systime_t time); void chThdSleepUntil(systime_t time); diff --git a/test/testsem.c b/test/testsem.c index c9361a0bb..1ec0a7a13 100644 --- a/test/testsem.c +++ b/test/testsem.c @@ -94,7 +94,6 @@ static void sem2_execute(void) { test_assert(isempty(&sem1.s_queue), "queue not empty");
test_assert(&sem1.s_cnt != 0, "counter not zero");
}
- test_assert(chSemGetCounter(&sem1) == 0, "non zero counter");
test_assert_sequence("ABCDE");
test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
}
|