Official mbed Real Time Operating System based on the RTX implementation of the CMSIS-RTOS API open standard.
Dependents: Assignment_3__Embedded_Software
Fork of mbed-rtos by
Diff: rtos/Thread.cpp
- Revision:
- 119:19af2d39a542
- Parent:
- 118:6635230e06ba
- Child:
- 123:58563e6cba1e
--- a/rtos/Thread.cpp Mon Jul 25 14:12:24 2016 +0100 +++ b/rtos/Thread.cpp Wed Aug 10 16:09:20 2016 +0100 @@ -63,16 +63,21 @@ } osStatus Thread::start(Callback<void()> task) { + _mutex.lock(); + if (_tid != 0) { + _mutex.unlock(); return osErrorParameter; } #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) - _thread_def.pthread = (void (*)(const void *))Callback<void()>::thunk; + _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) + if (_thread_def.stack_pointer == NULL) { + _mutex.unlock(); return osErrorNoMemory; + } } //Fill the stack with a magic word for maximum usage checking @@ -81,67 +86,122 @@ } #endif _task = task; - _tid = osThreadCreate(&_thread_def, &_task); + _tid = osThreadCreate(&_thread_def, this); if (_tid == NULL) { if (_dynamic_stack) delete[] (_thread_def.stack_pointer); + _mutex.unlock(); return osErrorResource; } + + _mutex.unlock(); return osOK; } osStatus Thread::terminate() { - return osThreadTerminate(_tid); + osStatus ret; + _mutex.lock(); + + ret = osThreadTerminate(_tid); + _tid = (osThreadId)NULL; + + // Wake threads joining the terminated thread + _join_sem.release(); + + _mutex.unlock(); + return ret; } osStatus Thread::join() { - while (true) { - uint8_t state = get_state(); - if (state == Thread::Inactive || state == osErrorParameter) { - return osOK; - } - - osStatus status = yield(); - if (status != osOK) { - return status; - } + int32_t ret = _join_sem.wait(); + if (ret < 0) { + return osErrorOS; } + // Release sem so any other threads joining this thread wake up + _join_sem.release(); + return osOK; } osStatus Thread::set_priority(osPriority priority) { - return osThreadSetPriority(_tid, priority); + osStatus ret; + _mutex.lock(); + + ret = osThreadSetPriority(_tid, priority); + + _mutex.unlock(); + return ret; } osPriority Thread::get_priority() { - return osThreadGetPriority(_tid); + osPriority ret; + _mutex.lock(); + + ret = osThreadGetPriority(_tid); + + _mutex.unlock(); + return ret; } int32_t Thread::signal_set(int32_t signals) { + // osSignalSet is thread safe as long as the underlying + // thread does not get terminated or return from main return osSignalSet(_tid, signals); } int32_t Thread::signal_clr(int32_t signals) { + // osSignalClear is thread safe as long as the underlying + // thread does not get terminated or return from main return osSignalClear(_tid, signals); } Thread::State Thread::get_state() { #if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM) #ifdef CMSIS_OS_RTX - return ((State)_thread_def.tcb.state); + State status = Deleted; + _mutex.lock(); + + if (_tid != NULL) { + status = (State)_thread_def.tcb.state; + } + + _mutex.unlock(); + return status; #endif #else - uint8_t status; - status = osThreadGetState(_tid); - return ((State)status); + State status = Deleted; + _mutex.lock(); + + if (_tid != NULL) { + status = (State)osThreadGetState(_tid); + } + + _mutex.unlock(); + return status; #endif } uint32_t Thread::stack_size() { #ifndef __MBED_CMSIS_RTOS_CA9 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) - return _thread_def.tcb.priv_stack; + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + size = _thread_def.tcb.priv_stack; + } + + _mutex.unlock(); + return size; #else - P_TCB tcb = rt_tid2ptcb(_tid); - return tcb->priv_stack; + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + P_TCB tcb = rt_tid2ptcb(_tid); + size = tcb->priv_stack; + } + + _mutex.unlock(); + return size; #endif #else return 0; @@ -151,12 +211,28 @@ uint32_t Thread::free_stack() { #ifndef __MBED_CMSIS_RTOS_CA9 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) - uint32_t bottom = (uint32_t)_thread_def.tcb.stack; - return _thread_def.tcb.tsk_stack - bottom; + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + uint32_t bottom = (uint32_t)_thread_def.tcb.stack; + size = _thread_def.tcb.tsk_stack - bottom; + } + + _mutex.unlock(); + return size; #else - P_TCB tcb = rt_tid2ptcb(_tid); - uint32_t bottom = (uint32_t)tcb->stack; - return tcb->tsk_stack - bottom; + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + P_TCB tcb = rt_tid2ptcb(_tid); + uint32_t bottom = (uint32_t)tcb->stack; + size = tcb->tsk_stack - bottom; + } + + _mutex.unlock(); + return size; #endif #else return 0; @@ -166,12 +242,28 @@ uint32_t Thread::used_stack() { #ifndef __MBED_CMSIS_RTOS_CA9 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) - uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack; - return top - _thread_def.tcb.tsk_stack; + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack; + size = top - _thread_def.tcb.tsk_stack; + } + + _mutex.unlock(); + return size; #else - P_TCB tcb = rt_tid2ptcb(_tid); - uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack; - return top - tcb->tsk_stack; + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + P_TCB tcb = rt_tid2ptcb(_tid); + uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack; + size = top - tcb->tsk_stack; + } + + _mutex.unlock(); + return size; #endif #else return 0; @@ -181,16 +273,32 @@ uint32_t Thread::max_stack() { #ifndef __MBED_CMSIS_RTOS_CA9 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) - uint32_t high_mark = 0; - while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5) - high_mark++; - return _thread_def.tcb.priv_stack - (high_mark * 4); + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + uint32_t high_mark = 0; + while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5) + high_mark++; + size = _thread_def.tcb.priv_stack - (high_mark * 4); + } + + _mutex.unlock(); + return size; #else - P_TCB tcb = rt_tid2ptcb(_tid); - uint32_t high_mark = 0; - while (tcb->stack[high_mark] == 0xE25A2EA5) - high_mark++; - return tcb->priv_stack - (high_mark * 4); + uint32_t size = 0; + _mutex.lock(); + + if (_tid != NULL) { + P_TCB tcb = rt_tid2ptcb(_tid); + uint32_t high_mark = 0; + while (tcb->stack[high_mark] == 0xE25A2EA5) + high_mark++; + size = tcb->priv_stack - (high_mark * 4); + } + + _mutex.unlock(); + return size; #endif #else return 0; @@ -218,6 +326,7 @@ } Thread::~Thread() { + // terminate is thread safe terminate(); #ifdef __MBED_CMSIS_RTOS_CM if (_dynamic_stack) { @@ -226,4 +335,14 @@ #endif } +void Thread::_thunk(const void * thread_ptr) +{ + Thread *t = (Thread*)thread_ptr; + t->_task(); + t->_mutex.lock(); + t->_tid = (osThreadId)NULL; + t->_join_sem.release(); + // rtos will release the mutex automatically } + +}