From a6eed37d26ba0ca617e8e1f3b3eca31449a26fdb Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Fri, 26 Feb 2016 10:28:00 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8950 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/common/abstractions/nasa_osal/src/osapi.c | 22 +++++++++++++--------- os/rt/src/chthreads.c | 21 ++++++++++++++++++--- 2 files changed, 31 insertions(+), 12 deletions(-) (limited to 'os') diff --git a/os/common/abstractions/nasa_osal/src/osapi.c b/os/common/abstractions/nasa_osal/src/osapi.c index a367c339b..0a805a99a 100644 --- a/os/common/abstractions/nasa_osal/src/osapi.c +++ b/os/common/abstractions/nasa_osal/src/osapi.c @@ -1311,7 +1311,8 @@ int32 OS_TaskCreate(uint32 *task_id, /* Checking if this working area is already in use by some thread, the error code is not very appropriate but this case seems to not be coveded by the specification.*/ - if ((tp = chRegFindThreadByWorkingArea((stkalign_t *)stack_pointer)) != NULL) { + tp = chRegFindThreadByWorkingArea((stkalign_t *)stack_pointer); + if (tp != NULL) { /* Releasing the thread reference.*/ chThdRelease(tp); return OS_ERR_NO_FREE_IDS; @@ -1339,8 +1340,10 @@ int32 OS_TaskCreate(uint32 *task_id, NULL }; - /* Creating the task.*/ + /* Creating the task and detaching it, other APIs will have to gain a + reference using the registry API.*/ tp = chThdCreate(&td); + chThdRelease(tp); /* Storing the task id.*/ *task_id = (uint32)tp; @@ -1377,8 +1380,9 @@ int32 OS_TaskInstallDeleteHandler(void *function_pointer) { */ int32 OS_TaskDelete(uint32 task_id) { thread_t *tp = (thread_t *)task_id; + funcptr_t fp; - /* Check for thread validity.*/ + /* Check for thread validity, getting a reference.*/ if (chRegFindThreadByPointer(tp) == NULL) { return OS_ERR_INVALID_ID; } @@ -1386,17 +1390,17 @@ int32 OS_TaskDelete(uint32 task_id) { /* Asking for thread termination.*/ chThdTerminate(tp); - /* Waiting for termination.*/ + /* Getting the delete handler while the thread is still referenced.*/ + fp = (funcptr_t)tp->osal_delete_handler; + + /* Waiting for termination, releasing the reference.*/ chThdWait(tp); /* Calling the delete handler, if defined.*/ - if (tp->osal_delete_handler != NULL) { - ((funcptr_t)(tp->osal_delete_handler))(); + if (fp != NULL) { + fp(); } - /* Releasing the thread reference.*/ - chThdRelease(tp); - return OS_SUCCESS; } diff --git a/os/rt/src/chthreads.c b/os/rt/src/chthreads.c index e809fbb13..943ca7d7c 100644 --- a/os/rt/src/chthreads.c +++ b/os/rt/src/chthreads.c @@ -462,9 +462,9 @@ void chThdExit(msg_t msg) { * @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 Exiting a non-static 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 @@ -490,6 +490,21 @@ void chThdExitS(msg_t msg) { } #endif +#if CH_CFG_USE_REGISTRY == TRUE + /* Static threads with no references are immediately removed from the + registry because there is no memory to recover.*/ +#if CH_CFG_USE_DYNAMIC == TRUE + if ((tp->refs == (trefs_t)0) && + (tp->flags & CH_FLAG_MODE_MASK) == CH_FLAG_MODE_STATIC) { + REG_REMOVE(tp); + } +#else + if (tp->refs == (trefs_t)0) { + REG_REMOVE(tp); + } +#endif +#endif + /* Going into final state.*/ chSchGoSleepS(CH_STATE_FINAL); -- cgit v1.2.3