cmsis_rtos_v1: fix thread instances management.
add a bitarray into struct osThreadDef_t to indicate whether the thread is used or not, then we can get the first available thread by searching this array when creating a new thread, and update this array to add a free thread when terminating a thread. Signed-off-by: Chen Peng1 <peng1.chen@intel.com>
This commit is contained in:
parent
40f4091d44
commit
0f63d1135c
6 changed files with 62 additions and 4 deletions
|
@ -67,6 +67,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <kernel.h>
|
||||
#include <sys/bitarray.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
@ -172,6 +173,8 @@ typedef struct os_thread_def {
|
|||
struct k_poll_signal *poll_signal;
|
||||
struct k_poll_event *poll_event;
|
||||
int32_t signal_results;
|
||||
///< a bitarray used to indicate whether the thread is used or not, 0: unused, 1: used
|
||||
void *status_mask;
|
||||
} osThreadDef_t;
|
||||
|
||||
/// Timer Definition structure contains timer parameters.
|
||||
|
@ -288,8 +291,11 @@ static K_THREAD_STACK_ARRAY_DEFINE(stacks_##name, instances, CONFIG_CMSIS_THREAD
|
|||
static struct k_thread cm_thread_##name[instances]; \
|
||||
static struct k_poll_signal wait_signal_##name; \
|
||||
static struct k_poll_event wait_events_##name; \
|
||||
static SYS_BITARRAY_DEFINE(bitarray_##name, instances); \
|
||||
static osThreadDef_t os_thread_def_##name = \
|
||||
{ (name), (priority), (instances), (stacksz), (void *)(stacks_##name), (cm_thread_##name), (&wait_signal_##name), (&wait_events_##name), 0 }
|
||||
{ (name), (priority), (instances), (stacksz), (void *)(stacks_##name), \
|
||||
(cm_thread_##name), (&wait_signal_##name), \
|
||||
(&wait_events_##name), 0, (void *)(&bitarray_##name)}
|
||||
#endif
|
||||
|
||||
/// Access a Thread definition.
|
||||
|
|
|
@ -1460,6 +1460,10 @@ static inline void unpend_all(_wait_q_t *wait_q)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMSIS_RTOS_V1
|
||||
extern void z_thread_cmsis_status_mask_clear(struct k_thread *thread);
|
||||
#endif
|
||||
|
||||
static void end_thread(struct k_thread *thread)
|
||||
{
|
||||
/* We hold the lock, and the thread is known not to be running
|
||||
|
@ -1482,6 +1486,10 @@ static void end_thread(struct k_thread *thread)
|
|||
|
||||
z_thread_monitor_exit(thread);
|
||||
|
||||
#ifdef CONFIG_CMSIS_RTOS_V1
|
||||
z_thread_cmsis_status_mask_clear(thread);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
z_mem_domain_exit_thread(thread);
|
||||
z_thread_perms_all_clear(thread);
|
||||
|
|
|
@ -5,6 +5,7 @@ config CMSIS_RTOS_V1
|
|||
bool "CMSIS RTOS v1 API"
|
||||
depends on THREAD_CUSTOM_DATA
|
||||
depends on POLL
|
||||
depends on THREAD_STACK_INFO
|
||||
help
|
||||
This enables CMSIS RTOS v1 API support. This is an OS-integration
|
||||
layer which allows applications using CMSIS RTOS APIs to build on
|
||||
|
|
|
@ -34,6 +34,23 @@ static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3)
|
|||
fun_ptr(arg1);
|
||||
}
|
||||
|
||||
/* clear related bit in cmsis thread status bitarray
|
||||
* when terminating a thread
|
||||
*/
|
||||
void z_thread_cmsis_status_mask_clear(struct k_thread *thread)
|
||||
{
|
||||
uint32_t offset, instance;
|
||||
|
||||
osThreadDef_t *thread_def = (osThreadDef_t *)(thread->custom_data);
|
||||
|
||||
if (thread_def != NULL) {
|
||||
/* get thread instance index according to stack address */
|
||||
offset = thread->stack_info.start - (uintptr_t)thread_def->stack_mem;
|
||||
instance = offset / K_THREAD_STACK_LEN(CONFIG_CMSIS_THREAD_MAX_STACK_SIZE);
|
||||
sys_bitarray_clear_bit((sys_bitarray_t *)(thread_def->status_mask), instance);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new thread.
|
||||
*/
|
||||
|
@ -43,6 +60,8 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg)
|
|||
uint32_t prio;
|
||||
k_tid_t tid;
|
||||
uint32_t stacksz;
|
||||
int ret;
|
||||
size_t instance;
|
||||
|
||||
k_thread_stack_t
|
||||
(*stk_ptr)[K_THREAD_STACK_LEN(CONFIG_CMSIS_THREAD_MAX_STACK_SIZE)];
|
||||
|
@ -67,6 +86,13 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg)
|
|||
(thread_def->tpriority <= osPriorityRealtime),
|
||||
"invalid priority\n");
|
||||
|
||||
/* get an available thread instance */
|
||||
ret = sys_bitarray_alloc((sys_bitarray_t *)(thread_def->status_mask),
|
||||
1, &instance);
|
||||
if (ret != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stacksz = thread_def->stacksize;
|
||||
if (stacksz == 0U) {
|
||||
stacksz = CONFIG_CMSIS_THREAD_MAX_STACK_SIZE;
|
||||
|
@ -77,17 +103,22 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg)
|
|||
K_POLL_MODE_NOTIFY_ONLY, thread_def->poll_signal);
|
||||
|
||||
cm_thread = thread_def->cm_thread;
|
||||
atomic_dec((atomic_t *)&thread_def->instances);
|
||||
stk_ptr = thread_def->stack_mem;
|
||||
prio = cmsis_to_zephyr_priority(thread_def->tpriority);
|
||||
k_thread_custom_data_set((void *)thread_def);
|
||||
|
||||
tid = k_thread_create(&cm_thread[thread_def->instances],
|
||||
stk_ptr[thread_def->instances], stacksz,
|
||||
tid = k_thread_create(&cm_thread[instance],
|
||||
stk_ptr[instance], stacksz,
|
||||
(k_thread_entry_t)zephyr_thread_wrapper,
|
||||
(void *)arg, NULL, thread_def->pthread,
|
||||
prio, 0, K_NO_WAIT);
|
||||
|
||||
/* make custom_data pointer of thread point to its source thread_def,
|
||||
* then we can use it to release thread instances
|
||||
* when terminating threads
|
||||
*/
|
||||
tid->custom_data = (void *)thread_def;
|
||||
|
||||
return ((osThreadId)tid);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,3 +6,4 @@ CONFIG_MAX_THREAD_BYTES=4
|
|||
CONFIG_IRQ_OFFLOAD=y
|
||||
CONFIG_CMSIS_THREAD_MAX_STACK_SIZE=2048
|
||||
CONFIG_SMP=n
|
||||
CONFIG_THREAD_STACK_INFO=y
|
||||
|
|
|
@ -26,6 +26,7 @@ osThreadDef(thread_inst_check, osPriorityNormal, 3, STACKSZ);
|
|||
void test_thread_instances(void)
|
||||
{
|
||||
osThreadId id1, id2, id3, id4;
|
||||
osStatus status;
|
||||
|
||||
id1 = osThreadCreate(osThread(thread_inst_check), NULL);
|
||||
zassert_true(id1 != NULL, "Failed creating thread_inst_check");
|
||||
|
@ -38,4 +39,14 @@ void test_thread_instances(void)
|
|||
|
||||
id4 = osThreadCreate(osThread(thread_inst_check), NULL);
|
||||
zassert_true(id4 == NULL, "Something wrong with thread instances");
|
||||
|
||||
status = osThreadTerminate(id2);
|
||||
zassert_true(status == osOK, "Error terminating thread_inst_check");
|
||||
|
||||
/* after terminating thread id2, when creating a new thread,
|
||||
* it should re-use the available thread instance of id2.
|
||||
*/
|
||||
id4 = osThreadCreate(osThread(thread_inst_check), NULL);
|
||||
zassert_true(id4 != NULL, "Failed creating thread_inst_check");
|
||||
zassert_true(id2 == id4, "Error creating thread_inst_check");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue