Skip to content

Commit f5f450e

Browse files
carlos-stuartnashif
authored andcommitted
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 <[email protected]>
1 parent 774a6c3 commit f5f450e

File tree

2 files changed

+87
-4
lines changed

2 files changed

+87
-4
lines changed

lib/cmsis_rtos_v2/thread.c

+84-3
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,13 @@ static inline u32_t cmsis_to_zephyr_priority(u32_t c_prio)
5252

5353
static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3)
5454
{
55+
struct cv2_thread *tid = arg2;
5556
void * (*fun_ptr)(void *) = arg3;
5657

5758
fun_ptr(arg1);
59+
60+
tid->has_joined = TRUE;
61+
k_sem_give(&tid->join_guard);
5862
}
5963

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

159163
tid = &cv2_thread_pool[this_thread_num];
160-
tid->state = attr->attr_bits;
164+
tid->attr_bits = attr->attr_bits;
161165

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

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

191+
k_sem_init(&tid->join_guard, 0, 1);
192+
tid->has_joined = FALSE;
193+
187194
(void)k_thread_create(&tid->z_thread,
188195
stack, stack_size,
189196
(k_thread_entry_t)zephyr_thread_wrapper,
190-
(void *)arg, NULL, threadfunc,
197+
(void *)arg, tid, threadfunc,
191198
prio, 0, K_NO_WAIT);
192199

193-
194200
if (attr->name == NULL) {
195201
strncpy(tid->name, init_thread_attrs.name,
196202
sizeof(tid->name) - 1);
@@ -417,6 +423,77 @@ osStatus_t osThreadResume(osThreadId_t thread_id)
417423
return osOK;
418424
}
419425

426+
/**
427+
* @brief Detach a thread (thread storage can be reclaimed when thread
428+
* terminates).
429+
*/
430+
osStatus_t osThreadDetach(osThreadId_t thread_id)
431+
{
432+
struct cv2_thread *tid = (struct cv2_thread *)thread_id;
433+
434+
if ((tid == NULL) || (is_cmsis_rtos_v2_thread(tid) == NULL)) {
435+
return osErrorParameter;
436+
}
437+
438+
if (k_is_in_isr()) {
439+
return osErrorISR;
440+
}
441+
442+
if (_is_thread_cmsis_inactive(&tid->z_thread)) {
443+
return osErrorResource;
444+
}
445+
446+
__ASSERT(tid->attr_bits != osThreadDetached,
447+
"Thread already detached, behaviour undefined.");
448+
449+
tid->attr_bits = osThreadDetached;
450+
451+
k_sem_give(&tid->join_guard);
452+
453+
return osOK;
454+
}
455+
456+
/**
457+
* @brief Wait for specified thread to terminate.
458+
*/
459+
osStatus_t osThreadJoin(osThreadId_t thread_id)
460+
{
461+
struct cv2_thread *tid = (struct cv2_thread *)thread_id;
462+
osStatus_t status = osError;
463+
464+
if ((tid == NULL) || (is_cmsis_rtos_v2_thread(tid) == NULL)) {
465+
return osErrorParameter;
466+
}
467+
468+
if (k_is_in_isr()) {
469+
return osErrorISR;
470+
}
471+
472+
if (_is_thread_cmsis_inactive(&tid->z_thread)) {
473+
return osErrorResource;
474+
}
475+
476+
if (tid->attr_bits != osThreadJoinable) {
477+
return osErrorResource;
478+
}
479+
480+
if (!tid->has_joined) {
481+
if (k_sem_take(&tid->join_guard, K_FOREVER) != 0) {
482+
__ASSERT(0, "Failed to take from join guard.");
483+
}
484+
485+
k_sem_give(&tid->join_guard);
486+
}
487+
488+
if (tid->has_joined && (tid->attr_bits == osThreadJoinable)) {
489+
status = osOK;
490+
} else {
491+
status = osErrorResource;
492+
}
493+
494+
return status;
495+
}
496+
420497
/**
421498
* @brief Terminate execution of current running thread.
422499
*/
@@ -427,6 +504,8 @@ __NO_RETURN void osThreadExit(void)
427504
__ASSERT(!k_is_in_isr(), "");
428505
tid = osThreadGetId();
429506

507+
k_sem_give(&tid->join_guard);
508+
430509
k_thread_abort((k_tid_t)&tid->z_thread);
431510

432511
CODE_UNREACHABLE;
@@ -451,6 +530,8 @@ osStatus_t osThreadTerminate(osThreadId_t thread_id)
451530
return osErrorResource;
452531
}
453532

533+
k_sem_give(&tid->join_guard);
534+
454535
k_thread_abort((k_tid_t)&tid->z_thread);
455536
return osOK;
456537
}

lib/cmsis_rtos_v2/wrapper.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ struct cv2_thread {
2020
struct k_poll_event poll_event;
2121
u32_t signal_results;
2222
char name[16];
23-
u32_t state;
23+
u32_t attr_bits;
24+
struct k_sem join_guard;
25+
char has_joined;
2426
};
2527

2628
struct cv2_timer {

0 commit comments

Comments
 (0)