Skip to content

Commit

Permalink
lib: cmsis_rtos_v2: Join and detach support
Browse files Browse the repository at this point in the history
Implements osThreadJoin and osThreadDetach.

This implementation uses a semaphore to signal when a thread is
exiting so any join operations are signalled to continue. It supports
multiple join operations on a single thread, and ensures joins are
aborted if a thread is detached.

Signed-off-by: Carlos Stuart <[email protected]>
  • Loading branch information
carlos-stuart authored and nashif committed Feb 8, 2019
1 parent 774a6c3 commit f5f450e
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 4 deletions.
87 changes: 84 additions & 3 deletions lib/cmsis_rtos_v2/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ static inline u32_t cmsis_to_zephyr_priority(u32_t c_prio)

static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3)
{
struct cv2_thread *tid = arg2;
void * (*fun_ptr)(void *) = arg3;

fun_ptr(arg1);

tid->has_joined = TRUE;
k_sem_give(&tid->join_guard);
}

void *is_cmsis_rtos_v2_thread(void *thread_id)
Expand Down Expand Up @@ -157,7 +161,7 @@ osThreadId_t osThreadNew(osThreadFunc_t threadfunc, void *arg,
this_thread_num = atomic_inc((atomic_t *)&thread_num);

tid = &cv2_thread_pool[this_thread_num];
tid->state = attr->attr_bits;
tid->attr_bits = attr->attr_bits;

if (attr->stack_mem == NULL) {
__ASSERT(CONFIG_CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE > 0,
Expand All @@ -184,13 +188,15 @@ osThreadId_t osThreadNew(osThreadFunc_t threadfunc, void *arg,

sys_dlist_append(&thread_list, &tid->node);

k_sem_init(&tid->join_guard, 0, 1);
tid->has_joined = FALSE;

(void)k_thread_create(&tid->z_thread,
stack, stack_size,
(k_thread_entry_t)zephyr_thread_wrapper,
(void *)arg, NULL, threadfunc,
(void *)arg, tid, threadfunc,
prio, 0, K_NO_WAIT);


if (attr->name == NULL) {
strncpy(tid->name, init_thread_attrs.name,
sizeof(tid->name) - 1);
Expand Down Expand Up @@ -417,6 +423,77 @@ osStatus_t osThreadResume(osThreadId_t thread_id)
return osOK;
}

/**
* @brief Detach a thread (thread storage can be reclaimed when thread
* terminates).
*/
osStatus_t osThreadDetach(osThreadId_t thread_id)
{
struct cv2_thread *tid = (struct cv2_thread *)thread_id;

if ((tid == NULL) || (is_cmsis_rtos_v2_thread(tid) == NULL)) {
return osErrorParameter;
}

if (k_is_in_isr()) {
return osErrorISR;
}

if (_is_thread_cmsis_inactive(&tid->z_thread)) {
return osErrorResource;
}

__ASSERT(tid->attr_bits != osThreadDetached,
"Thread already detached, behaviour undefined.");

tid->attr_bits = osThreadDetached;

k_sem_give(&tid->join_guard);

return osOK;
}

/**
* @brief Wait for specified thread to terminate.
*/
osStatus_t osThreadJoin(osThreadId_t thread_id)
{
struct cv2_thread *tid = (struct cv2_thread *)thread_id;
osStatus_t status = osError;

if ((tid == NULL) || (is_cmsis_rtos_v2_thread(tid) == NULL)) {
return osErrorParameter;
}

if (k_is_in_isr()) {
return osErrorISR;
}

if (_is_thread_cmsis_inactive(&tid->z_thread)) {
return osErrorResource;
}

if (tid->attr_bits != osThreadJoinable) {
return osErrorResource;
}

if (!tid->has_joined) {
if (k_sem_take(&tid->join_guard, K_FOREVER) != 0) {
__ASSERT(0, "Failed to take from join guard.");
}

k_sem_give(&tid->join_guard);
}

if (tid->has_joined && (tid->attr_bits == osThreadJoinable)) {
status = osOK;
} else {
status = osErrorResource;
}

return status;
}

/**
* @brief Terminate execution of current running thread.
*/
Expand All @@ -427,6 +504,8 @@ __NO_RETURN void osThreadExit(void)
__ASSERT(!k_is_in_isr(), "");
tid = osThreadGetId();

k_sem_give(&tid->join_guard);

k_thread_abort((k_tid_t)&tid->z_thread);

CODE_UNREACHABLE;
Expand All @@ -451,6 +530,8 @@ osStatus_t osThreadTerminate(osThreadId_t thread_id)
return osErrorResource;
}

k_sem_give(&tid->join_guard);

k_thread_abort((k_tid_t)&tid->z_thread);
return osOK;
}
Expand Down
4 changes: 3 additions & 1 deletion lib/cmsis_rtos_v2/wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ struct cv2_thread {
struct k_poll_event poll_event;
u32_t signal_results;
char name[16];
u32_t state;
u32_t attr_bits;
struct k_sem join_guard;
char has_joined;
};

struct cv2_timer {
Expand Down

0 comments on commit f5f450e

Please sign in to comment.