lib: cmsis_rtos_v2: Dynamic thread stacks
Implemented dynamic thread stacks for CMSIS threads by declaring an array of default sized thread stacks. Allocation cannot be done on the heap as some architectures require strict alignment for stacks so the macro must be used to define the stack to ensure most compatibility. Added a Kconfig variable to limit the number of dynamic threads on the system (they also count towards total CMSIS thread count). This is so a developer can have fine grained control over how many dynamic threads can be allocated because all their stacks must be allocated up front so could use a lot of memory needlessly if oversubscribed. The default value is 0 which effectively disabled dynamic threads but also reduces the memory impact to almost none. Fixed an assert bug where thread_num was being tested against the maximum allowed CMSIS threads - it previous checked for less than or equal which actually (due to when the increment happens) allowed there to be one more thread. The check now correctly uses less than and only allowed up to the defined maximum. Signed-off-by: Carlos Stuart <carlosstuart1970@gmail.com>
This commit is contained in:
parent
db24367652
commit
d4eb2c9014
2 changed files with 93 additions and 25 deletions
|
@ -27,12 +27,28 @@ config CMSIS_V2_THREAD_MAX_COUNT
|
|||
There's a limitation on the number of threads due to memory
|
||||
related constraints.
|
||||
|
||||
config CMSIS_V2_THREAD_DYNAMIC_MAX_COUNT
|
||||
int "Maximum dynamic thread count in CMSIS RTOS V2 application"
|
||||
default 0
|
||||
range 0 255
|
||||
help
|
||||
Mention max number of dynamic threads in CMSIS RTOS V2 compliant
|
||||
application. There's a limitation on the number of threads due to memory
|
||||
related constraints. Dynamic threads are a subset of all other CMSIS
|
||||
threads i.e. they also count towards that maximum too.
|
||||
|
||||
config CMSIS_V2_THREAD_MAX_STACK_SIZE
|
||||
int "Max stack size threads can be allocated in CMSIS RTOS V2 application"
|
||||
default 512
|
||||
help
|
||||
Mention max stack size threads can be allocated in CMSIS RTOS V2 application.
|
||||
|
||||
config CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE
|
||||
int "Dynamic stack size threads are allocated in CMSIS RTOS V2 application"
|
||||
default 0
|
||||
help
|
||||
Mention dynamic stack size threads are allocated in CMSIS RTOS V2 application.
|
||||
|
||||
config CMSIS_V2_TIMER_MAX_COUNT
|
||||
int "Maximum timer count in CMSIS RTOS V2 application"
|
||||
default 5
|
||||
|
|
|
@ -12,9 +12,26 @@
|
|||
#include <misc/stack.h>
|
||||
#include "wrapper.h"
|
||||
|
||||
static const osThreadAttr_t init_thread_attrs = {
|
||||
.name = "ZephyrThread",
|
||||
.attr_bits = osThreadDetached,
|
||||
.cb_mem = NULL,
|
||||
.cb_size = 0,
|
||||
.stack_mem = NULL,
|
||||
.stack_size = 0,
|
||||
.priority = osPriorityNormal,
|
||||
.tz_module = 0,
|
||||
.reserved = 0,
|
||||
};
|
||||
|
||||
static sys_dlist_t thread_list;
|
||||
static struct cv2_thread cv2_thread_pool[CONFIG_CMSIS_V2_THREAD_MAX_COUNT];
|
||||
static u32_t thread_num;
|
||||
static u32_t thread_num_dynamic;
|
||||
|
||||
static K_THREAD_STACK_ARRAY_DEFINE(cv2_thread_stack_pool, \
|
||||
CONFIG_CMSIS_V2_THREAD_DYNAMIC_MAX_COUNT, \
|
||||
CONFIG_CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE);
|
||||
|
||||
static inline int _is_thread_cmsis_inactive(struct k_thread *thread)
|
||||
{
|
||||
|
@ -83,36 +100,70 @@ osThreadId_t osThreadNew(osThreadFunc_t threadfunc, void *arg,
|
|||
s32_t prio;
|
||||
struct cv2_thread *tid;
|
||||
static u32_t one_time;
|
||||
|
||||
BUILD_ASSERT_MSG(osPriorityISR <= CONFIG_NUM_PREEMPT_PRIORITIES,
|
||||
"Configure NUM_PREEMPT_PRIORITIES to at least osPriorityISR");
|
||||
|
||||
__ASSERT(attr->stack_size <= CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE,
|
||||
"invalid stack size\n");
|
||||
|
||||
__ASSERT(thread_num <= CONFIG_CMSIS_V2_THREAD_MAX_COUNT,
|
||||
"Exceeded max number of threads\n");
|
||||
|
||||
__ASSERT(attr != NULL,
|
||||
"Zephyr requirement: Pass attributes explicitly for ThreadNew\n");
|
||||
|
||||
/* Zephyr needs valid stack to be specified when this API is called */
|
||||
__ASSERT(attr->stack_mem, "");
|
||||
__ASSERT(attr->stack_size, "");
|
||||
|
||||
__ASSERT((attr->priority >= osPriorityIdle) &&
|
||||
(attr->priority <= osPriorityISR),
|
||||
"invalid priority\n");
|
||||
void *stack;
|
||||
size_t stack_size;
|
||||
u32_t this_thread_num;
|
||||
u32_t this_thread_num_dynamic;
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (thread_num >= CONFIG_CMSIS_V2_THREAD_MAX_COUNT) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (attr == NULL) {
|
||||
attr = &init_thread_attrs;
|
||||
}
|
||||
|
||||
if ((attr->stack_mem == NULL) && (thread_num_dynamic >=
|
||||
CONFIG_CMSIS_V2_THREAD_DYNAMIC_MAX_COUNT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BUILD_ASSERT_MSG(osPriorityISR <= CONFIG_NUM_PREEMPT_PRIORITIES,
|
||||
"Configure NUM_PREEMPT_PRIORITIES to at least osPriorityISR");
|
||||
|
||||
BUILD_ASSERT_MSG(CONFIG_CMSIS_V2_THREAD_DYNAMIC_MAX_COUNT <=
|
||||
CONFIG_CMSIS_V2_THREAD_MAX_COUNT,
|
||||
"Number of dynamic threads cannot exceed max number of threads.");
|
||||
|
||||
BUILD_ASSERT_MSG(CONFIG_CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE <=
|
||||
CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE,
|
||||
"Default dynamic thread stack size cannot exceed max stack size");
|
||||
|
||||
__ASSERT(attr->stack_size <= CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE,
|
||||
"invalid stack size\n");
|
||||
|
||||
__ASSERT((attr->priority >= osPriorityIdle) &&
|
||||
(attr->priority <= osPriorityISR),
|
||||
"invalid priority\n");
|
||||
|
||||
if (attr->stack_mem != NULL) {
|
||||
if (attr->stack_size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
prio = cmsis_to_zephyr_priority(attr->priority);
|
||||
|
||||
tid = &cv2_thread_pool[thread_num];
|
||||
tid->state = attr->attr_bits;/* detached/joinable */
|
||||
atomic_inc((atomic_t *)&thread_num);
|
||||
this_thread_num = atomic_inc((atomic_t *)&thread_num);
|
||||
|
||||
tid = &cv2_thread_pool[this_thread_num];
|
||||
tid->state = attr->attr_bits;
|
||||
|
||||
if (attr->stack_mem == NULL) {
|
||||
__ASSERT(CONFIG_CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE > 0,
|
||||
"dynamic stack size must be configured to be non-zero\n");
|
||||
this_thread_num_dynamic =
|
||||
atomic_inc((atomic_t *)&thread_num_dynamic);
|
||||
stack_size = CONFIG_CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE;
|
||||
stack = cv2_thread_stack_pool[this_thread_num_dynamic];
|
||||
} else {
|
||||
stack_size = attr->stack_size;
|
||||
stack = attr->stack_mem;
|
||||
}
|
||||
|
||||
k_poll_signal_init(&tid->poll_signal);
|
||||
k_poll_event_init(&tid->poll_event, K_POLL_TYPE_SIGNAL,
|
||||
|
@ -128,12 +179,13 @@ osThreadId_t osThreadNew(osThreadFunc_t threadfunc, void *arg,
|
|||
sys_dlist_append(&thread_list, &tid->node);
|
||||
|
||||
(void)k_thread_create(&tid->z_thread,
|
||||
attr->stack_mem, attr->stack_size,
|
||||
stack, stack_size,
|
||||
(k_thread_entry_t)zephyr_thread_wrapper,
|
||||
(void *)arg, NULL, threadfunc,
|
||||
prio, 0, K_NO_WAIT);
|
||||
|
||||
k_thread_name_set(&tid->z_thread, attr->name);
|
||||
memcpy(tid->name, attr->name, 16);
|
||||
k_thread_name_set(&tid->z_thread, tid->name);
|
||||
|
||||
return (osThreadId_t)tid;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue