lib: cmsis_rtos_v2: Join and detach support
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 <carlosstuart1970@gmail.com>
This commit is contained in:
parent
774a6c31b3
commit
f5f450eeee
2 changed files with 87 additions and 4 deletions
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue