Skip to content

Add lifetime management to threads #1785

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 59 additions & 11 deletions rtos/rtos/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,82 @@ extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id);

namespace rtos {

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.tpriority = priority;
_thread_def.stacksize = stack_size;
_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) {
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
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);
}
Expand Down
25 changes: 25 additions & 0 deletions rtos/rtos/Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -42,6 +51,19 @@ class Thread {
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.
*/
Expand Down Expand Up @@ -113,17 +135,20 @@ class Thread {
@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();

Expand Down