Aguila
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
}
+
+}
