diff --git a/include/kernel.h b/include/kernel.h index 482b9ad77bf..87e60cdf05d 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -166,38 +166,89 @@ struct _static_thread_data { struct k_thread *thread; }; unsigned int init_stack_size; + int32_t init_delay; }; -#define K_THREAD_INITIALIZER(stack, stack_size, \ - entry, p1, p2, p3, \ - abort, prio, groups) \ - { \ - .init_groups = (groups), \ - .init_prio = (prio), \ - .init_entry = (void (*)(void *, void *, void *))entry, \ - .init_p1 = (void *)p1, \ - .init_p2 = (void *)p2, \ - .init_p3 = (void *)p3, \ - .init_abort = abort, \ - .init_stack = (stack), \ - .init_stack_size = (stack_size), \ +/* + * Common macro used by both K_THREAD_INITIALIZER() + * and _MDEF_THREAD_INITIALIZER(). + */ +#define _THREAD_INITIALIZER(stack, stack_size, \ + entry, p1, p2, p3, \ + abort, prio) \ + .init_prio = (prio), \ + .init_entry = (void (*)(void *, void *, void *))entry, \ + .init_p1 = (void *)p1, \ + .init_p2 = (void *)p2, \ + .init_p3 = (void *)p3, \ + .init_abort = abort, \ + .init_stack = (stack), \ + .init_stack_size = (stack_size), + +/** + * @brief Thread initializer macro + * + * This macro is to only be used with statically defined threads that were not + * defined in the MDEF file. As such the associated threads can not belong to + * any thread group. + */ +#define K_THREAD_INITIALIZER(stack, stack_size, \ + entry, p1, p2, p3, \ + abort, prio, delay) \ + { \ + _THREAD_INITIALIZER(stack, stack_size, \ + entry, p1, p2, p3, \ + abort, prio) \ + .init_groups = 0, \ + .init_delay = (delay), \ } -/* - * Define thread initializer object and initialize it - * NOTE: For thread group functions thread initializers must be organized - * in array and thus should not have gaps between them. - * On x86 by default compiler aligns them by 32 byte boundary. To prevent - * this 32-bit alignment in specified here. - * _static_thread_data structure sise needs to be kept 32-bit aligned as well +/** + * @brief Thread initializer macro + * + * This macro is to only be used with statically defined threads that were + * defined with legacy APIs (including the MDEF file). As such the associated + * threads may belong to one or more thread groups. */ -#define K_THREAD_DEFINE(name, stack_size, \ - entry, p1, p2, p3, \ - abort, prio, groups) \ - char __noinit __stack _k_thread_obj_##name[stack_size]; \ - struct _static_thread_data _k_thread_data_##name __aligned(4) \ - __in_section(_k_task_list, private, task) = \ - K_THREAD_INITIALIZER(_k_thread_obj_##name, stack_size, \ +#define _MDEF_THREAD_INITIALIZER(stack, stack_size, \ + entry, p1, p2, p3, \ + abort, prio, groups) \ + { \ + _THREAD_INITIALIZER(stack, stack_size, \ + entry, p1, p2, p3, \ + abort, prio) \ + .init_groups = (groups), \ + .init_delay = K_FOREVER, \ + } + +/** + * @brief Define thread initializer and initialize it. + * + * @internal It has been observed that the x86 compiler by default aligns + * these _static_thread_data structures to 32-byte boundaries, thereby + * wasting space. To work around this, force a 4-byte alignment. + */ +#define K_THREAD_DEFINE(name, stack_size, \ + entry, p1, p2, p3, \ + abort, prio, delay) \ + char __noinit __stack _k_thread_obj_##name[stack_size]; \ + struct _static_thread_data _k_thread_data_##name __aligned(4) \ + __in_section(_k_task_list, private, task) = \ + K_THREAD_INITIALIZER(_k_thread_obj_##name, stack_size, \ + entry, p1, p2, p3, abort, prio, delay) + +/** + * @brief Define thread initializer for MDEF defined thread and initialize it. + * + * @ref K_THREAD_DEFINE + */ +#define _MDEF_THREAD_DEFINE(name, stack_size, \ + entry, p1, p2, p3, \ + abort, prio, groups) \ + char __noinit __stack _k_thread_obj_##name[stack_size]; \ + struct _static_thread_data _k_thread_data_##name __aligned(4) \ + __in_section(_k_task_list, private, task) = \ + _MDEF_THREAD_INITIALIZER(_k_thread_obj_##name, stack_size, \ entry, p1, p2, p3, abort, prio, groups) extern int k_thread_priority_get(k_tid_t thread); diff --git a/include/legacy.h b/include/legacy.h index 10cb27fd46d..f08216ebc1f 100644 --- a/include/legacy.h +++ b/include/legacy.h @@ -84,7 +84,7 @@ typedef int nano_context_type_t; char __noinit __stack _k_thread_obj_##name[stack_size]; \ struct _static_thread_data _k_thread_data_##name __aligned(4) \ __in_section(_k_task_list, private, task) = \ - K_THREAD_INITIALIZER(_k_thread_obj_##name, stack_size, \ + _MDEF_THREAD_INITIALIZER(_k_thread_obj_##name, stack_size, \ entry, NULL, NULL, NULL, \ NULL, prio, (uint32_t)(groups)); \ k_tid_t const name = (k_tid_t)_k_thread_obj_##name diff --git a/kernel/unified/thread.c b/kernel/unified/thread.c index 28f30eecef8..06e247aa160 100644 --- a/kernel/unified/thread.c +++ b/kernel/unified/thread.c @@ -424,6 +424,8 @@ void _k_thread_single_abort(struct k_thread *thread) void _init_static_threads(void) { + unsigned int key; + _FOREACH_STATIC_THREAD(thread_data) { _new_thread( thread_data->init_stack, @@ -438,7 +440,29 @@ void _init_static_threads(void) thread_data->thread->init_data = thread_data; } + + k_sched_lock(); + /* Start all (legacy) threads that are part of the EXE group */ _k_thread_group_op(K_THREAD_GROUP_EXE, _k_thread_single_start); + + /* + * Non-legacy static threads may be started immediately or after a + * previously specified delay. Even though the scheduler is locked, + * ticks can still be delivered and processed. Lock interrupts so + * that the countdown until execution begins from the same tick. + * + * Note that static threads defined using the legacy API have a + * delay of K_FOREVER. + */ + key = irq_lock(); + _FOREACH_STATIC_THREAD(thread_data) { + if (thread_data->init_delay != K_FOREVER) { + schedule_new_thread(thread_data->thread, + thread_data->init_delay); + } + } + irq_unlock(key); + k_sched_unlock(); } uint32_t _k_thread_group_mask_get(struct k_thread *thread) diff --git a/scripts/sysgen b/scripts/sysgen index b05acb0a111..8d9cce32c0a 100755 --- a/scripts/sysgen +++ b/scripts/sysgen @@ -448,7 +448,7 @@ def kernel_main_c_tasks_unified(): kernel_main_c_out("EXTERN_C void %s(void);\n" % abort) kernel_main_c_out( - "K_THREAD_DEFINE(%s, %u, %s, %s, %s, %s, %s, %d, 0x%x);\n" % + "_MDEF_THREAD_DEFINE(%s, %u, %s, %s, %s, %s, %s, %d, 0x%x);\n" % (name, int(stack_size), entry, params[0], params[1], params[2], abort, int(prio), int(groups)))