fork
Diff: rtos/Thread.cpp
- Revision:
- 123:58563e6cba1e
- Parent:
- 119:19af2d39a542
--- a/rtos/Thread.cpp Wed Nov 09 12:22:14 2016 -0600 +++ b/rtos/Thread.cpp Mon Nov 14 17:14:42 2016 -0600 @@ -19,10 +19,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "Thread.h" +#include "rtos/Thread.h" #include "mbed.h" -#include "rtos_idle.h" +#include "rtos/rtos_idle.h" // rt_tid2ptcb is an internal function which we exposed to get TCB for thread id #undef NULL //Workaround for conflicting macros in rt_TypeDef.h and stdio.h @@ -30,6 +30,15 @@ extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id); + +static void (*terminate_hook)(osThreadId id) = 0; +extern "C" void thread_terminate_hook(osThreadId id) +{ + if (terminate_hook != (void (*)(osThreadId))NULL) { + terminate_hook(id); + } +} + namespace rtos { void Thread::constructor(osPriority priority, @@ -74,10 +83,7 @@ _thread_def.pthread = Thread::_thunk; if (_thread_def.stack_pointer == NULL) { _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)]; - if (_thread_def.stack_pointer == NULL) { - _mutex.unlock(); - return osErrorNoMemory; - } + MBED_ASSERT(_thread_def.stack_pointer != NULL); } //Fill the stack with a magic word for maximum usage checking @@ -88,8 +94,12 @@ _task = task; _tid = osThreadCreate(&_thread_def, this); if (_tid == NULL) { - if (_dynamic_stack) delete[] (_thread_def.stack_pointer); + if (_dynamic_stack) { + delete[] (_thread_def.stack_pointer); + _thread_def.stack_pointer = (uint32_t*)NULL; + } _mutex.unlock(); + _join_sem.release(); return osErrorResource; } @@ -101,11 +111,14 @@ osStatus ret; _mutex.lock(); - ret = osThreadTerminate(_tid); + // Set the Thread's tid to NULL and + // release the semaphore before terminating + // since this thread could be terminating itself + osThreadId local_id = _tid; + _join_sem.release(); _tid = (osThreadId)NULL; - // Wake threads joining the terminated thread - _join_sem.release(); + ret = osThreadTerminate(local_id); _mutex.unlock(); return ret; @@ -116,6 +129,14 @@ if (ret < 0) { return osErrorOS; } + + // The semaphore has been released so this thread is being + // terminated or has been terminated. Once the mutex has + // been locked it is ensured that the thread is deleted. + _mutex.lock(); + MBED_ASSERT(NULL == _tid); + _mutex.unlock(); + // Release sem so any other threads joining this thread wake up _join_sem.release(); return osOK; @@ -325,12 +346,17 @@ rtos_attach_idle_hook(fptr); } +void Thread::attach_terminate_hook(void (*fptr)(osThreadId id)) { + terminate_hook = fptr; +} + Thread::~Thread() { // terminate is thread safe terminate(); #ifdef __MBED_CMSIS_RTOS_CM if (_dynamic_stack) { delete[] (_thread_def.stack_pointer); + _thread_def.stack_pointer = (uint32_t*)NULL; } #endif }