Enhanced dynamic support.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8948 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
3e6e47ee7d
commit
c2a407c4d5
|
@ -49,6 +49,10 @@
|
||||||
#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_WAITEXIT"
|
#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_WAITEXIT"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CH_CFG_USE_REGISTRY == FALSE
|
||||||
|
#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_REGISTRY"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (CH_CFG_USE_HEAP == FALSE) && (CH_CFG_USE_MEMPOOLS == FALSE)
|
#if (CH_CFG_USE_HEAP == FALSE) && (CH_CFG_USE_MEMPOOLS == FALSE)
|
||||||
#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_HEAP and/or CH_CFG_USE_MEMPOOLS"
|
#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_HEAP and/or CH_CFG_USE_MEMPOOLS"
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,8 +75,6 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
thread_t *chThdAddRef(thread_t *tp);
|
|
||||||
void chThdRelease(thread_t *tp);
|
|
||||||
#if CH_CFG_USE_HEAP == TRUE
|
#if CH_CFG_USE_HEAP == TRUE
|
||||||
thread_t *chThdCreateFromHeap(memory_heap_t *heapp, size_t size,
|
thread_t *chThdCreateFromHeap(memory_heap_t *heapp, size_t size,
|
||||||
const char *name, tprio_t prio,
|
const char *name, tprio_t prio,
|
||||||
|
|
|
@ -235,7 +235,7 @@ struct ch_thread {
|
||||||
* @brief Various thread flags.
|
* @brief Various thread flags.
|
||||||
*/
|
*/
|
||||||
tmode_t flags;
|
tmode_t flags;
|
||||||
#if (CH_CFG_USE_DYNAMIC == TRUE) || defined(__DOXYGEN__)
|
#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief References to this thread.
|
* @brief References to this thread.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -181,6 +181,13 @@ extern "C" {
|
||||||
thread_t *chThdCreateStatic(void *wsp, size_t size,
|
thread_t *chThdCreateStatic(void *wsp, size_t size,
|
||||||
tprio_t prio, tfunc_t pf, void *arg);
|
tprio_t prio, tfunc_t pf, void *arg);
|
||||||
thread_t *chThdStart(thread_t *tp);
|
thread_t *chThdStart(thread_t *tp);
|
||||||
|
thread_t *chThdAddRef(thread_t *tp);
|
||||||
|
void chThdRelease(thread_t *tp);
|
||||||
|
void chThdExit(msg_t msg);
|
||||||
|
void chThdExitS(msg_t msg);
|
||||||
|
#if CH_CFG_USE_WAITEXIT == TRUE
|
||||||
|
msg_t chThdWait(thread_t *tp);
|
||||||
|
#endif
|
||||||
tprio_t chThdSetPriority(tprio_t newprio);
|
tprio_t chThdSetPriority(tprio_t newprio);
|
||||||
void chThdTerminate(thread_t *tp);
|
void chThdTerminate(thread_t *tp);
|
||||||
msg_t chThdSuspendS(thread_reference_t *trp);
|
msg_t chThdSuspendS(thread_reference_t *trp);
|
||||||
|
@ -195,11 +202,6 @@ extern "C" {
|
||||||
void chThdSleepUntil(systime_t time);
|
void chThdSleepUntil(systime_t time);
|
||||||
systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next);
|
systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next);
|
||||||
void chThdYield(void);
|
void chThdYield(void);
|
||||||
void chThdExit(msg_t msg);
|
|
||||||
void chThdExitS(msg_t msg);
|
|
||||||
#if CH_CFG_USE_WAITEXIT == TRUE
|
|
||||||
msg_t chThdWait(thread_t *tp);
|
|
||||||
#endif
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -54,78 +54,6 @@
|
||||||
/* Module exported functions. */
|
/* Module exported functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adds a reference to a thread object.
|
|
||||||
* @pre The configuration option @p CH_CFG_USE_DYNAMIC must be enabled in
|
|
||||||
* order to use this function.
|
|
||||||
*
|
|
||||||
* @param[in] tp pointer to the thread
|
|
||||||
* @return The same thread pointer passed as parameter
|
|
||||||
* representing the new reference.
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
thread_t *chThdAddRef(thread_t *tp) {
|
|
||||||
|
|
||||||
chSysLock();
|
|
||||||
chDbgAssert(tp->refs < (trefs_t)255, "too many references");
|
|
||||||
tp->refs++;
|
|
||||||
chSysUnlock();
|
|
||||||
|
|
||||||
return tp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Releases a reference to a thread object.
|
|
||||||
* @details If the references counter reaches zero <b>and</b> the thread
|
|
||||||
* is in the @p CH_STATE_FINAL state then the thread's memory is
|
|
||||||
* returned to the proper allocator.
|
|
||||||
* @pre The configuration option @p CH_CFG_USE_DYNAMIC must be enabled in
|
|
||||||
* order to use this function.
|
|
||||||
* @note Static threads are not affected.
|
|
||||||
*
|
|
||||||
* @param[in] tp pointer to the thread
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
void chThdRelease(thread_t *tp) {
|
|
||||||
trefs_t refs;
|
|
||||||
|
|
||||||
chSysLock();
|
|
||||||
chDbgAssert(tp->refs > (trefs_t)0, "not referenced");
|
|
||||||
tp->refs--;
|
|
||||||
refs = tp->refs;
|
|
||||||
chSysUnlock();
|
|
||||||
|
|
||||||
/* If the references counter reaches zero and the thread is in its
|
|
||||||
terminated state then the memory can be returned to the proper
|
|
||||||
allocator. Of course static threads are not affected.*/
|
|
||||||
if ((refs == (trefs_t)0) && (tp->state == CH_STATE_FINAL)) {
|
|
||||||
switch (tp->flags & CH_FLAG_MODE_MASK) {
|
|
||||||
#if CH_CFG_USE_HEAP == TRUE
|
|
||||||
case CH_FLAG_MODE_HEAP:
|
|
||||||
#if CH_CFG_USE_REGISTRY == TRUE
|
|
||||||
REG_REMOVE(tp);
|
|
||||||
#endif
|
|
||||||
chHeapFree(chthdGetStackLimitX(tp));
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if CH_CFG_USE_MEMPOOLS == TRUE
|
|
||||||
case CH_FLAG_MODE_MPOOL:
|
|
||||||
#if CH_CFG_USE_REGISTRY == TRUE
|
|
||||||
REG_REMOVE(tp);
|
|
||||||
#endif
|
|
||||||
chPoolFree(tp->mpool, chthdGetStackLimitX(tp));
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
/* Nothing to do for static threads, those are removed from the
|
|
||||||
registry on exit.*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
|
#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new thread allocating the memory from the heap.
|
* @brief Creates a new thread allocating the memory from the heap.
|
||||||
|
|
|
@ -103,10 +103,8 @@ thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
|
||||||
#if CH_DBG_THREADS_PROFILING == TRUE
|
#if CH_DBG_THREADS_PROFILING == TRUE
|
||||||
tp->time = (systime_t)0;
|
tp->time = (systime_t)0;
|
||||||
#endif
|
#endif
|
||||||
#if CH_CFG_USE_DYNAMIC == TRUE
|
|
||||||
tp->refs = (trefs_t)1;
|
|
||||||
#endif
|
|
||||||
#if CH_CFG_USE_REGISTRY == TRUE
|
#if CH_CFG_USE_REGISTRY == TRUE
|
||||||
|
tp->refs = (trefs_t)1;
|
||||||
tp->name = name;
|
tp->name = name;
|
||||||
REG_INSERT(tp);
|
REG_INSERT(tp);
|
||||||
#endif
|
#endif
|
||||||
|
@ -145,6 +143,10 @@ void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v) {
|
||||||
* @brief Creates a new thread into a static memory area.
|
* @brief Creates a new thread into a static memory area.
|
||||||
* @details The new thread is initialized but not inserted in the ready list,
|
* @details The new thread is initialized but not inserted in the ready list,
|
||||||
* the initial state is @p CH_STATE_WTSTART.
|
* the initial state is @p CH_STATE_WTSTART.
|
||||||
|
* @post The created thread has a reference counter set to one, it is
|
||||||
|
* caller responsibility to call @p chThdRelease() or @p chthdWait()
|
||||||
|
* in order to release the reference. The thread persists in the
|
||||||
|
* registry until its reference counter reaches zero.
|
||||||
* @post The initialized thread can be subsequently started by invoking
|
* @post The initialized thread can be subsequently started by invoking
|
||||||
* @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
|
* @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
|
||||||
* depending on the execution context.
|
* depending on the execution context.
|
||||||
|
@ -193,6 +195,10 @@ thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp) {
|
||||||
* @brief Creates a new thread into a static memory area.
|
* @brief Creates a new thread into a static memory area.
|
||||||
* @details The new thread is initialized but not inserted in the ready list,
|
* @details The new thread is initialized but not inserted in the ready list,
|
||||||
* the initial state is @p CH_STATE_WTSTART.
|
* the initial state is @p CH_STATE_WTSTART.
|
||||||
|
* @post The created thread has a reference counter set to one, it is
|
||||||
|
* caller responsibility to call @p chThdRelease() or @p chthdWait()
|
||||||
|
* in order to release the reference. The thread persists in the
|
||||||
|
* registry until its reference counter reaches zero.
|
||||||
* @post The initialized thread can be subsequently started by invoking
|
* @post The initialized thread can be subsequently started by invoking
|
||||||
* @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
|
* @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
|
||||||
* depending on the execution context.
|
* depending on the execution context.
|
||||||
|
@ -224,6 +230,10 @@ thread_t *chThdCreateSuspended(const thread_descriptor_t *tdp) {
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new thread into a static memory area.
|
* @brief Creates a new thread into a static memory area.
|
||||||
* @details The new thread is initialized and make ready to execute.
|
* @details The new thread is initialized and make ready to execute.
|
||||||
|
* @post The created thread has a reference counter set to one, it is
|
||||||
|
* caller responsibility to call @p chThdRelease() or @p chthdWait()
|
||||||
|
* in order to release the reference. The thread persists in the
|
||||||
|
* registry until its reference counter reaches zero.
|
||||||
* @post The initialized thread can be subsequently started by invoking
|
* @post The initialized thread can be subsequently started by invoking
|
||||||
* @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
|
* @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
|
||||||
* depending on the execution context.
|
* depending on the execution context.
|
||||||
|
@ -247,6 +257,10 @@ thread_t *chThdCreateI(const thread_descriptor_t *tdp) {
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new thread into a static memory area.
|
* @brief Creates a new thread into a static memory area.
|
||||||
* @details The new thread is initialized and make ready to execute.
|
* @details The new thread is initialized and make ready to execute.
|
||||||
|
* @post The created thread has a reference counter set to one, it is
|
||||||
|
* caller responsibility to call @p chThdRelease() or @p chthdWait()
|
||||||
|
* in order to release the reference. The thread persists in the
|
||||||
|
* registry until its reference counter reaches zero.
|
||||||
* @note A thread can terminate by calling @p chThdExit() or by simply
|
* @note A thread can terminate by calling @p chThdExit() or by simply
|
||||||
* returning from its main function.
|
* returning from its main function.
|
||||||
*
|
*
|
||||||
|
@ -275,6 +289,10 @@ thread_t *chThdCreate(const thread_descriptor_t *tdp) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new thread into a static memory area.
|
* @brief Creates a new thread into a static memory area.
|
||||||
|
* @post The created thread has a reference counter set to one, it is
|
||||||
|
* caller responsibility to call @p chThdRelease() or @p chthdWait()
|
||||||
|
* in order to release the reference. The thread persists in the
|
||||||
|
* registry until its reference counter reaches zero.
|
||||||
* @note A thread can terminate by calling @p chThdExit() or by simply
|
* @note A thread can terminate by calling @p chThdExit() or by simply
|
||||||
* returning from its main function.
|
* returning from its main function.
|
||||||
*
|
*
|
||||||
|
@ -346,6 +364,186 @@ thread_t *chThdStart(thread_t *tp) {
|
||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a reference to a thread object.
|
||||||
|
* @pre The configuration option @p CH_CFG_USE_DYNAMIC must be enabled in
|
||||||
|
* order to use this function.
|
||||||
|
*
|
||||||
|
* @param[in] tp pointer to the thread
|
||||||
|
* @return The same thread pointer passed as parameter
|
||||||
|
* representing the new reference.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
thread_t *chThdAddRef(thread_t *tp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chDbgAssert(tp->refs < (trefs_t)255, "too many references");
|
||||||
|
tp->refs++;
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases a reference to a thread object.
|
||||||
|
* @details If the references counter reaches zero <b>and</b> the thread
|
||||||
|
* is in the @p CH_STATE_FINAL state then the thread's memory is
|
||||||
|
* returned to the proper allocator and the thread is removed
|
||||||
|
* from the registry.<br>
|
||||||
|
* Threads whose counter reaches zero and are still active become
|
||||||
|
* "detached" and will be removed from registry on termination.
|
||||||
|
* @pre The configuration option @p CH_CFG_USE_DYNAMIC must be enabled in
|
||||||
|
* order to use this function.
|
||||||
|
* @note Static threads are not affected.
|
||||||
|
*
|
||||||
|
* @param[in] tp pointer to the thread
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void chThdRelease(thread_t *tp) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chDbgAssert(tp->refs > (trefs_t)0, "not referenced");
|
||||||
|
tp->refs--;
|
||||||
|
|
||||||
|
/* If the references counter reaches zero and the thread is in its
|
||||||
|
terminated state then the memory can be returned to the proper
|
||||||
|
allocator.*/
|
||||||
|
if ((tp->refs == (trefs_t)0) && (tp->state == CH_STATE_FINAL)) {
|
||||||
|
REG_REMOVE(tp);
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
|
#if CH_CFG_USE_DYNAMIC == TRUE
|
||||||
|
switch (tp->flags & CH_FLAG_MODE_MASK) {
|
||||||
|
#if CH_CFG_USE_HEAP == TRUE
|
||||||
|
case CH_FLAG_MODE_HEAP:
|
||||||
|
chHeapFree(chthdGetStackLimitX(tp));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if CH_CFG_USE_MEMPOOLS == TRUE
|
||||||
|
case CH_FLAG_MODE_MPOOL:
|
||||||
|
chPoolFree(tp->mpool, chthdGetStackLimitX(tp));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
/* Nothing else to do for static threads.*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
#endif /* CH_CFG_USE_DYNAMIC == TRUE */
|
||||||
|
}
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Terminates the current thread.
|
||||||
|
* @details The thread goes in the @p CH_STATE_FINAL state holding the
|
||||||
|
* specified exit status code, other threads can retrieve the
|
||||||
|
* exit status code by invoking the function @p chThdWait().
|
||||||
|
* @post Eventual code after this function will never be executed,
|
||||||
|
* this function never returns. The compiler has no way to
|
||||||
|
* know this so do not assume that the compiler would remove
|
||||||
|
* the dead code.
|
||||||
|
*
|
||||||
|
* @param[in] msg thread exit code
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void chThdExit(msg_t msg) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chThdExitS(msg);
|
||||||
|
/* The thread never returns here.*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Terminates the current thread.
|
||||||
|
* @details The thread goes in the @p CH_STATE_FINAL state holding the
|
||||||
|
* specified exit status code, other threads can retrieve the
|
||||||
|
* exit status code by invoking the function @p chThdWait().
|
||||||
|
* @post Exiting a thread that does not have references (detached)
|
||||||
|
* causes the thread to remain in the registry. It can only
|
||||||
|
* be removed by performing a registry scan operation.
|
||||||
|
* @post Eventual code after this function will never be executed,
|
||||||
|
* this function never returns. The compiler has no way to
|
||||||
|
* know this so do not assume that the compiler would remove
|
||||||
|
* the dead code.
|
||||||
|
*
|
||||||
|
* @param[in] msg thread exit code
|
||||||
|
*
|
||||||
|
* @sclass
|
||||||
|
*/
|
||||||
|
void chThdExitS(msg_t msg) {
|
||||||
|
thread_t *tp = currp;
|
||||||
|
|
||||||
|
/* Storing exit message.*/
|
||||||
|
tp->u.exitcode = msg;
|
||||||
|
|
||||||
|
/* Exit handler hook.*/
|
||||||
|
CH_CFG_THREAD_EXIT_HOOK(tp);
|
||||||
|
|
||||||
|
#if CH_CFG_USE_WAITEXIT == TRUE
|
||||||
|
/* Waking up any waiting thread.*/
|
||||||
|
while (list_notempty(&tp->waiting)) {
|
||||||
|
(void) chSchReadyI(list_remove(&tp->waiting));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Going into final state.*/
|
||||||
|
chSchGoSleepS(CH_STATE_FINAL);
|
||||||
|
|
||||||
|
/* The thread never returns here.*/
|
||||||
|
chDbgAssert(false, "zombies apocalypse");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @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 and
|
||||||
|
* the thread is removed from registry.
|
||||||
|
* @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.
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
msg_t chThdWait(thread_t *tp) {
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
chDbgCheck(tp != NULL);
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chDbgAssert(tp != currp, "waiting self");
|
||||||
|
#if CH_CFG_USE_REGISTRY == TRUE
|
||||||
|
chDbgAssert(tp->refs > (trefs_t)0, "no references");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (tp->state != CH_STATE_FINAL) {
|
||||||
|
list_insert(currp, &tp->waiting);
|
||||||
|
chSchGoSleepS(CH_STATE_WTEXIT);
|
||||||
|
}
|
||||||
|
msg = tp->u.exitcode;
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
|
#if CH_CFG_USE_REGISTRY == TRUE
|
||||||
|
/* Releasing a reference to the thread.*/
|
||||||
|
chThdRelease(tp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
#endif /* CH_CFG_USE_WAITEXIT */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Changes the running thread priority level then reschedules if
|
* @brief Changes the running thread priority level then reschedules if
|
||||||
* necessary.
|
* necessary.
|
||||||
|
@ -482,124 +680,6 @@ void chThdYield(void) {
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Terminates the current thread.
|
|
||||||
* @details The thread goes in the @p CH_STATE_FINAL state holding the
|
|
||||||
* specified exit status code, other threads can retrieve the
|
|
||||||
* exit status code by invoking the function @p chThdWait().
|
|
||||||
* @post Eventual code after this function will never be executed,
|
|
||||||
* this function never returns. The compiler has no way to
|
|
||||||
* know this so do not assume that the compiler would remove
|
|
||||||
* the dead code.
|
|
||||||
*
|
|
||||||
* @param[in] msg thread exit code
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
void chThdExit(msg_t msg) {
|
|
||||||
|
|
||||||
chSysLock();
|
|
||||||
chThdExitS(msg);
|
|
||||||
/* The thread never returns here.*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Terminates the current thread.
|
|
||||||
* @details The thread goes in the @p CH_STATE_FINAL state holding the
|
|
||||||
* specified exit status code, other threads can retrieve the
|
|
||||||
* exit status code by invoking the function @p chThdWait().
|
|
||||||
* @post Eventual code after this function will never be executed,
|
|
||||||
* this function never returns. The compiler has no way to
|
|
||||||
* know this so do not assume that the compiler would remove
|
|
||||||
* the dead code.
|
|
||||||
*
|
|
||||||
* @param[in] msg thread exit code
|
|
||||||
*
|
|
||||||
* @sclass
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* The thread never returns here.*/
|
|
||||||
chDbgAssert(false, "zombies apocalypse");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
|
|
||||||
/**
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
msg_t chThdWait(thread_t *tp) {
|
|
||||||
msg_t msg;
|
|
||||||
|
|
||||||
chDbgCheck(tp != NULL);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends the current thread sleeping and sets a reference variable.
|
* @brief Sends the current thread sleeping and sets a reference variable.
|
||||||
* @note This function must reschedule, it can only be called from thread
|
* @note This function must reschedule, it can only be called from thread
|
||||||
|
|
|
@ -24,12 +24,14 @@ a series of important new features.
|
||||||
|
|
||||||
- Common ports architecture.
|
- Common ports architecture.
|
||||||
- Ability to use the new shared RTOS components.
|
- Ability to use the new shared RTOS components.
|
||||||
|
- New threading API, now creating static threads is even faster.
|
||||||
|
- Extended priority range from 1..127 to 1..255.
|
||||||
|
- Enhanced dynamic threading, safer and easier to use.
|
||||||
|
- Enhanced Registry, it is now possible to find threads by name, by pointer
|
||||||
|
or by working area.
|
||||||
- Enhanced trace buffer, it is able to store events regarding not just threads
|
- Enhanced trace buffer, it is able to store events regarding not just threads
|
||||||
but also IRQs, halts and user events. The trace record now stores both the
|
but also IRQs, halts and user events. The trace record now stores both the
|
||||||
"slow" system time and a RT stamp for increased accuracy.
|
"slow" system time and a RT stamp for increased accuracy.
|
||||||
- Enhanced Registry, it is now possible to find threads by name or by pointer.
|
|
||||||
- New threading API, now creating static threads is even faster.
|
|
||||||
- Extended priority range to 1..255.
|
|
||||||
- New kernel hooks for a more flexible code instrumentation.
|
- New kernel hooks for a more flexible code instrumentation.
|
||||||
- Experimental NASA OSAL implementation.
|
- Experimental NASA OSAL implementation.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue