diff options
Diffstat (limited to 'os/rt/src/chthreads.c')
-rw-r--r-- | os/rt/src/chthreads.c | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/os/rt/src/chthreads.c b/os/rt/src/chthreads.c index 0fff76604..ed5b19e15 100644 --- a/os/rt/src/chthreads.c +++ b/os/rt/src/chthreads.c @@ -87,22 +87,27 @@ */
thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
- tp->prio = prio;
+ tp->prio = prio;
+ tp->state = CH_STATE_WTSTART;
+ tp->flags = CH_FLAG_MODE_STATIC;
#if CH_CFG_TIME_QUANTUM > 0
- tp->preempt = (tslices_t)CH_CFG_TIME_QUANTUM;
+ tp->preempt = (tslices_t)CH_CFG_TIME_QUANTUM;
#endif
#if CH_CFG_USE_MUTEXES == TRUE
- tp->realprio = prio;
- tp->mtxlist = NULL;
+ tp->realprio = prio;
+ tp->mtxlist = NULL;
#endif
#if CH_CFG_USE_EVENTS == TRUE
- tp->epending = (eventmask_t)0;
+ tp->epending = (eventmask_t)0;
#endif
#if CH_DBG_THREADS_PROFILING == TRUE
- tp->time = (systime_t)0;
+ tp->time = (systime_t)0;
+#endif
+#if CH_CFG_USE_DYNAMIC == TRUE
+ tp->refs = (trefs_t)1;
#endif
#if CH_CFG_USE_REGISTRY == TRUE
- tp->name = name;
+ tp->name = name;
REG_INSERT(tp);
#endif
#if CH_CFG_USE_WAITEXIT == TRUE
@@ -173,10 +178,6 @@ thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp) { tp = (thread_t *)((uint8_t *)tdp->wend -
MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN));
- /* Initial state.*/
- tp->state = CH_STATE_WTSTART;
- tp->flags = CH_FLAG_MODE_STATIC;
-
/* Stack boundary.*/
tp->stklimit = tdp->wbase;
@@ -380,6 +381,25 @@ tprio_t chThdSetPriority(tprio_t newprio) { }
/**
+ * @brief Requests a thread termination.
+ * @pre The target thread must be written to invoke periodically
+ * @p chThdShouldTerminate() and terminate cleanly if it returns
+ * @p true.
+ * @post The specified thread will terminate after detecting the termination
+ * condition.
+ *
+ * @param[in] tp pointer to the thread
+ *
+ * @api
+ */
+void chThdTerminate(thread_t *tp) {
+
+ chSysLock();
+ tp->flags |= CH_FLAG_TERMINATE;
+ chSysUnlock();
+}
+
+/**
* @brief Suspends the invoking thread for the specified time.
*
* @param[in] time the delay in system ticks, the special values are
@@ -501,14 +521,20 @@ void chThdExitS(msg_t msg) { thread_t *tp = currp;
tp->u.exitcode = msg;
+#if defined(CH_CFG_THREAD_EXIT_HOOK)
CH_CFG_THREAD_EXIT_HOOK(tp);
+#endif
#if CH_CFG_USE_WAITEXIT == TRUE
while (list_notempty(&tp->waiting)) {
(void) chSchReadyI(list_remove(&tp->waiting));
}
#endif
#if CH_CFG_USE_REGISTRY == TRUE
- REG_REMOVE(tp);
+ /* Static threads are immediately removed from the registry because
+ there is no memory to recover.*/
+ if ((tp->flags & CH_FLAG_MODE_MASK) == CH_FLAG_MODE_STATIC) {
+ REG_REMOVE(tp);
+ }
#endif
chSchGoSleepS(CH_STATE_FINAL);
@@ -520,12 +546,28 @@ void chThdExitS(msg_t msg) { /**
* @brief Blocks the execution of the invoking thread until the specified
* thread terminates then the exit code is returned.
+ * @details This function waits for the specified thread to terminate then
+ * decrements its reference counter, if the counter reaches zero then
+ * the thread working area is returned to the proper allocator.<br>
+ * The memory used by the exited thread is handled in different ways
+ * depending on the API that spawned the thread:
+ * - If the thread was spawned by @p chThdCreateStatic() or by
+ * @p chThdCreateI() then nothing happens and the thread working
+ * area is not released or modified in any way. This is the
+ * default, totally static, behavior.
+ * - If the thread was spawned by @p chThdCreateFromHeap() then
+ * the working area is returned to the system heap.
+ * - If the thread was spawned by @p chThdCreateFromMemoryPool()
+ * then the working area is returned to the owning memory pool.
+ * .
* @pre The configuration option @p CH_CFG_USE_WAITEXIT must be enabled in
* order to use this function.
* @post Enabling @p chThdWait() requires 2-4 (depending on the
* architecture) extra bytes in the @p thread_t structure.
* @post After invoking @p chThdWait() the thread pointer becomes invalid
* and must not be used as parameter for further system calls.
+ * @note If @p CH_CFG_USE_DYNAMIC is not specified this function just waits for
+ * the thread termination, no memory allocators are involved.
*
* @param[in] tp pointer to the thread
* @return The exit code from the terminated thread.
@@ -539,6 +581,9 @@ msg_t chThdWait(thread_t *tp) { chSysLock();
chDbgAssert(tp != currp, "waiting self");
+#if CH_CFG_USE_DYNAMIC == TRUE
+ chDbgAssert(tp->refs > (trefs_t)0, "not referenced");
+#endif
if (tp->state != CH_STATE_FINAL) {
list_insert(currp, &tp->waiting);
chSchGoSleepS(CH_STATE_WTEXIT);
@@ -546,6 +591,11 @@ msg_t chThdWait(thread_t *tp) { msg = tp->u.exitcode;
chSysUnlock();
+#if CH_CFG_USE_DYNAMIC == TRUE
+ /* Releasing a lock if it is a dynamic thread.*/
+ chThdRelease(tp);
+#endif
+
return msg;
}
#endif /* CH_CFG_USE_WAITEXIT */
|