rtos: Return an error when a Thread is re-used

Calling Thread::start multiple times leads to undefined behavior since
the Thread class was not designed to handle being restarted.  Return an
error code if Thread::start is called a second time to prevent this
behavior.
pull/4025/head
Russ Butler 2017-03-01 14:37:55 -06:00 committed by Anna Bridge
parent bb6df591f0
commit edc473a526
2 changed files with 7 additions and 2 deletions

View File

@ -44,6 +44,7 @@ namespace rtos {
void Thread::constructor(osPriority priority, void Thread::constructor(osPriority priority,
uint32_t stack_size, unsigned char *stack_pointer) { uint32_t stack_size, unsigned char *stack_pointer) {
_tid = 0; _tid = 0;
_finished = false;
_dynamic_stack = (stack_pointer == NULL); _dynamic_stack = (stack_pointer == NULL);
#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
@ -74,7 +75,7 @@ void Thread::constructor(Callback<void()> task,
osStatus Thread::start(Callback<void()> task) { osStatus Thread::start(Callback<void()> task) {
_mutex.lock(); _mutex.lock();
if (_tid != 0) { if ((_tid != 0) || _finished) {
_mutex.unlock(); _mutex.unlock();
return osErrorParameter; return osErrorParameter;
} }
@ -117,6 +118,7 @@ osStatus Thread::terminate() {
osThreadId local_id = _tid; osThreadId local_id = _tid;
_join_sem.release(); _join_sem.release();
_tid = (osThreadId)NULL; _tid = (osThreadId)NULL;
_finished = true;
ret = osThreadTerminate(local_id); ret = osThreadTerminate(local_id);
@ -367,6 +369,7 @@ void Thread::_thunk(const void * thread_ptr)
t->_task(); t->_task();
t->_mutex.lock(); t->_mutex.lock();
t->_tid = (osThreadId)NULL; t->_tid = (osThreadId)NULL;
t->_finished = true;
t->_join_sem.release(); t->_join_sem.release();
// rtos will release the mutex automatically // rtos will release the mutex automatically
} }

View File

@ -197,6 +197,7 @@ public:
/** Starts a thread executing the specified function. /** Starts a thread executing the specified function.
@param task function to be executed by this thread. @param task function to be executed by this thread.
@return status code that indicates the execution status of the function. @return status code that indicates the execution status of the function.
@note a thread can only be started once
*/ */
osStatus start(mbed::Callback<void()> task); osStatus start(mbed::Callback<void()> task);
@ -344,9 +345,10 @@ private:
mbed::Callback<void()> _task; mbed::Callback<void()> _task;
osThreadId _tid; osThreadId _tid;
osThreadDef_t _thread_def; osThreadDef_t _thread_def;
bool _dynamic_stack;
Semaphore _join_sem; Semaphore _join_sem;
Mutex _mutex; Mutex _mutex;
bool _dynamic_stack;
bool _finished;
}; };
} }