Merge pull request #1785 from geky/thread-lifetime

Add lifetime management to threads
pull/1802/head
Martin Kojtal 2016-06-01 11:42:28 +01:00
commit 2db84dadcb
2 changed files with 85 additions and 12 deletions

View File

@ -32,34 +32,82 @@ extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id);
namespace rtos {
Thread::Thread(void (*task)(void const *argument), void *argument,
osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) {
Thread::Thread(osPriority priority,
uint32_t stack_size, unsigned char *stack_pointer):
_tid(0), _dynamic_stack(stack_pointer == NULL) {
#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
_thread_def.pthread = task;
_thread_def.tpriority = priority;
_thread_def.stacksize = stack_size;
if (stack_pointer != NULL) {
_thread_def.stack_pointer = (uint32_t*)stack_pointer;
_dynamic_stack = false;
} else {
_thread_def.stack_pointer = new uint32_t[stack_size/sizeof(uint32_t)];
if (_thread_def.stack_pointer == NULL)
_thread_def.stack_pointer = (uint32_t*)stack_pointer;
#endif
}
Thread::Thread(void (*task)(void const *argument), void *argument,
osPriority priority, uint32_t stack_size, unsigned char *stack_pointer):
_tid(0), _dynamic_stack(stack_pointer == NULL) {
#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
_thread_def.tpriority = priority;
_thread_def.stacksize = stack_size;
_thread_def.stack_pointer = (uint32_t*)stack_pointer;
#endif
switch (start(task, argument)) {
case osErrorResource:
error("OS ran out of threads!\n");
break;
case osErrorParameter:
error("Thread already running!\n");
break;
case osErrorNoMemory:
error("Error allocating the stack memory\n");
_dynamic_stack = true;
default:
break;
}
}
osStatus Thread::start(void (*task)(void const *argument), void *argument) {
if (_tid != NULL) {
return osErrorParameter;
}
#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
_thread_def.pthread = task;
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)
return osErrorNoMemory;
}
//Fill the stack with a magic word for maximum usage checking
for (uint32_t i = 0; i < (stack_size / sizeof(uint32_t)); i++) {
for (uint32_t i = 0; i < (_thread_def.stacksize / sizeof(uint32_t)); i++) {
_thread_def.stack_pointer[i] = 0xE25A2EA5;
}
#endif
_tid = osThreadCreate(&_thread_def, argument);
if (_tid == NULL) {
if (_dynamic_stack) delete[] (_thread_def.stack_pointer);
return osErrorResource;
}
return osOK;
}
osStatus Thread::terminate() {
return osThreadTerminate(_tid);
}
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;
}
}
}
osStatus Thread::set_priority(osPriority priority) {
return osThreadSetPriority(_tid, priority);
}

View File

@ -30,6 +30,15 @@ namespace rtos {
/** The Thread class allow defining, creating, and controlling thread functions in the system. */
class Thread {
public:
/** Allocate a new thread without starting execution
@param priority initial priority of the thread function. (default: osPriorityNormal).
@param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE).
@param stack_pointer pointer to the stack area to be used by this thread (default: NULL).
*/
Thread(osPriority priority=osPriorityNormal,
uint32_t stack_size=DEFAULT_STACK_SIZE,
unsigned char *stack_pointer=NULL);
/** Create a new thread, and start it executing the specified function.
@param task function to be executed by this thread.
@param argument pointer that is passed to the thread function as start argument. (default: NULL).
@ -42,6 +51,19 @@ public:
uint32_t stack_size=DEFAULT_STACK_SIZE,
unsigned char *stack_pointer=NULL);
/** Starts a thread executing the specified function.
@param task function to be executed by this thread.
@param argument pointer that is passed to the thread function as start argument. (default: NULL).
@return status code that indicates the execution status of the function.
*/
osStatus start(void (*task)(void const *argument), void *argument=NULL);
/** Wait for thread to terminate
@return status code that indicates the execution status of the function.
@note not callable from interrupt
*/
osStatus join();
/** Terminate execution of a thread and remove it from Active Threads
@return status code that indicates the execution status of the function.
*/
@ -113,17 +135,20 @@ public:
@param signals wait until all specified signal flags set or 0 for any single signal flag.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return event flag information or error code.
@note not callable from interrupt
*/
static osEvent signal_wait(int32_t signals, uint32_t millisec=osWaitForever);
/** Wait for a specified time period in millisec:
@param millisec time delay value
@return status code that indicates the execution status of the function.
@note not callable from interrupt
*/
static osStatus wait(uint32_t millisec);
/** Pass control to next thread that is in state READY.
@return status code that indicates the execution status of the function.
@note not callable from interrupt
*/
static osStatus yield();