From d26cf2dc332e1069ce322ea51896bad3424b1e40 Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Thu, 30 Mar 2017 13:07:02 -0700 Subject: [PATCH] kernel: add k_thread_create() API Unline k_thread_spawn(), the struct k_thread can live anywhere and not in the thread's stack region. This will be useful for memory protection scenarios where private kernel structures for a thread are not accessible by that thread, or we want to allow the thread to use all the stack space we gave it. This requires a change to the internal _new_thread() API as we need to provide a separate pointer for the k_thread. By default, we still create internal threads with the k_thread in stack memory. Forthcoming patches will change this, but we first need to make it easier to define k_thread memory of variable size depending on whether we need to store coprocessor state or not. Change-Id: I533bbcf317833ba67a771b356b6bbc6596bf60f5 Signed-off-by: Andrew Boie --- arch/arc/core/thread.c | 7 +-- arch/arm/core/thread.c | 5 +-- arch/arm/include/kernel_arch_func.h | 6 +-- arch/nios2/core/thread.c | 5 +-- arch/riscv32/core/thread.c | 7 ++- arch/x86/core/thread.c | 11 +++-- arch/xtensa/core/thread.c | 13 +++--- doc/kernel/other/float.rst | 8 ++-- doc/kernel/threads/lifecycle.rst | 35 +++++++-------- doc/kernel/threads/workqueues.rst | 8 ++-- include/kernel.h | 68 ++++++++++++++++++++++++----- kernel/include/kernel_structs.h | 17 +++----- kernel/include/nano_internal.h | 2 +- kernel/init.c | 18 +++++--- kernel/thread.c | 32 +++++++++----- kernel/work_q.c | 5 +-- 16 files changed, 147 insertions(+), 100 deletions(-) diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 0fec255a413..1c50755d4b1 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -54,7 +54,7 @@ struct init_stack_frame { * * @return N/A */ -void _new_thread(char *pStackMem, size_t stackSize, +void _new_thread(struct k_thread *thread, char *pStackMem, size_t stackSize, _thread_entry_t pEntry, void *parameter1, void *parameter2, void *parameter3, int priority, unsigned int options) @@ -64,12 +64,9 @@ void _new_thread(char *pStackMem, size_t stackSize, char *stackEnd = pStackMem + stackSize; struct init_stack_frame *pInitCtx; - struct k_thread *thread; - - thread = _new_thread_init(pStackMem, stackSize, priority, options); + _new_thread_init(thread, pStackMem, stackSize, priority, options); /* carve the thread entry struct from the "base" of the stack */ - pInitCtx = (struct init_stack_frame *)(STACK_ROUND_DOWN(stackEnd) - sizeof(struct init_stack_frame)); diff --git a/arch/arm/core/thread.c b/arch/arm/core/thread.c index 0e9f6f6568d..9ae5572b2a0 100644 --- a/arch/arm/core/thread.c +++ b/arch/arm/core/thread.c @@ -49,7 +49,7 @@ * @return N/A */ -void _new_thread(char *pStackMem, size_t stackSize, +void _new_thread(struct k_thread *thread, char *pStackMem, size_t stackSize, _thread_entry_t pEntry, void *parameter1, void *parameter2, void *parameter3, int priority, unsigned int options) @@ -62,9 +62,8 @@ void _new_thread(char *pStackMem, size_t stackSize, char *stackEnd = pStackMem + stackSize; struct __esf *pInitCtx; - struct k_thread *thread = (struct k_thread *) pStackMem; - thread = _new_thread_init(pStackMem, stackSize, priority, options); + _new_thread_init(thread, pStackMem, stackSize, priority, options); /* carve the thread entry struct from the "base" of the stack */ diff --git a/arch/arm/include/kernel_arch_func.h b/arch/arm/include/kernel_arch_func.h index 1b13cb0d203..eff05ccdfc5 100644 --- a/arch/arm/include/kernel_arch_func.h +++ b/arch/arm/include/kernel_arch_func.h @@ -38,8 +38,8 @@ static ALWAYS_INLINE void kernel_arch_init(void) } static ALWAYS_INLINE void -_arch_switch_to_main_thread(char *main_stack, size_t main_stack_size, - _thread_entry_t _main) +_arch_switch_to_main_thread(struct k_thread *main_thread, char *main_stack, + size_t main_stack_size, _thread_entry_t _main) { /* get high address of the stack, i.e. its start (stack grows down) */ char *start_of_main_stack; @@ -47,7 +47,7 @@ _arch_switch_to_main_thread(char *main_stack, size_t main_stack_size, start_of_main_stack = main_stack + main_stack_size; start_of_main_stack = (void *)STACK_ROUND_DOWN(start_of_main_stack); - _current = (void *)main_stack; + _current = main_thread; /* the ready queue cache already contains the main thread */ diff --git a/arch/nios2/core/thread.c b/arch/nios2/core/thread.c index c7ceead93c8..121132a2f13 100644 --- a/arch/nios2/core/thread.c +++ b/arch/nios2/core/thread.c @@ -31,17 +31,16 @@ struct init_stack_frame { }; -void _new_thread(char *stack_memory, size_t stack_size, +void _new_thread(struct k_thread *thread, char *stack_memory, size_t stack_size, _thread_entry_t thread_func, void *arg1, void *arg2, void *arg3, int priority, unsigned int options) { _ASSERT_VALID_PRIO(priority, thread_func); - struct k_thread *thread; struct init_stack_frame *iframe; - thread = _new_thread_init(stack_memory, stack_size, priority, options); + _new_thread_init(thread, stack_memory, stack_size, priority, options); /* Initial stack frame data, stored at the base of the stack */ iframe = (struct init_stack_frame *) diff --git a/arch/riscv32/core/thread.c b/arch/riscv32/core/thread.c index 557573f8530..7e4f6864025 100644 --- a/arch/riscv32/core/thread.c +++ b/arch/riscv32/core/thread.c @@ -15,17 +15,16 @@ void _thread_entry_wrapper(_thread_entry_t thread, void *arg2, void *arg3); -void _new_thread(char *stack_memory, size_t stack_size, - _thread_entry_t thread_func, +void _new_thread(struct k_thread *thread, char *stack_memory, + size_t stack_size, _thread_entry_t thread_func, void *arg1, void *arg2, void *arg3, int priority, unsigned int options) { _ASSERT_VALID_PRIO(priority, thread_func); - struct k_thread *thread; struct __esf *stack_init; - thread = _new_thread_init(stack_memory, stack_size, priority, options); + _new_thread_init(thread, stack_memory, stack_size, priority, options); /* Initial stack frame for thread */ stack_init = (struct __esf *) diff --git a/arch/x86/core/thread.c b/arch/x86/core/thread.c index 267085ab417..91b1c1e2515 100644 --- a/arch/x86/core/thread.c +++ b/arch/x86/core/thread.c @@ -39,6 +39,7 @@ void _thread_entry_wrapper(_thread_entry_t, void *, * * This function is called by _new_thread() to initialize tasks. * + * @param thread pointer to thread struct memory * @param pStackMem pointer to thread stack memory * @param stackSize size of a stack in bytes * @param priority thread priority @@ -180,9 +181,8 @@ __asm__("\t.globl _thread_entry\n" * This function is utilized to create execution threads for both fiber * threads and kernel tasks. * - * The k_thread structure is carved from the "end" of the specified - * thread stack memory. - * + * @param thread pointer to thread struct memory, including any space needed + * for extra coprocessor context * @param pStackmem the pointer to aligned stack memory * @param stackSize the stack size in bytes * @param pEntry thread entry point routine @@ -195,7 +195,7 @@ __asm__("\t.globl _thread_entry\n" * * @return opaque pointer to initialized k_thread structure */ -void _new_thread(char *pStackMem, size_t stackSize, +void _new_thread(struct k_thread *thread, char *pStackMem, size_t stackSize, _thread_entry_t pEntry, void *parameter1, void *parameter2, void *parameter3, int priority, unsigned int options) @@ -203,9 +203,8 @@ void _new_thread(char *pStackMem, size_t stackSize, _ASSERT_VALID_PRIO(priority, pEntry); unsigned long *pInitialThread; - struct k_thread *thread; - thread = _new_thread_init(pStackMem, stackSize, priority, options); + _new_thread_init(thread, pStackMem, stackSize, priority, options); /* carve the thread entry struct from the "base" of the stack */ diff --git a/arch/xtensa/core/thread.c b/arch/xtensa/core/thread.c index 2607a0087b4..9dd0791c621 100644 --- a/arch/xtensa/core/thread.c +++ b/arch/xtensa/core/thread.c @@ -16,9 +16,9 @@ extern void _xt_user_exit(void); /* - * @brief Initialize a new thread from its stack space + * @brief Initialize a new thread * - * The struct k_thread is put at the lower address of the stack. An + * Any coprocessor context data is put at the lower address of the stack. An * initial context, to be "restored" by __return_from_coop(), is put at * the other end of the stack, and thus reusable by the stack when not * needed anymore. @@ -29,6 +29,7 @@ extern void _xt_user_exit(void); * * is currently unused. * + * @param thread pointer to k_thread memory * @param pStackmem the pointer to aligned stack memory * @param stackSize the stack size in bytes * @param pEntry thread entry point routine @@ -41,23 +42,19 @@ extern void _xt_user_exit(void); * @return N/A */ -void _new_thread(char *pStack, size_t stackSize, +void _new_thread(struct k_thread *thread, char *pStack, size_t stackSize, void (*pEntry)(void *, void *, void *), void *p1, void *p2, void *p3, int priority, unsigned int options) { /* Align stack end to maximum alignment requirement. */ char *stackEnd = (char *)ROUND_DOWN(pStack + stackSize, 16); - /* k_thread is located at top of stack while frames are located at end - * of it - */ - struct k_thread *thread; #if XCHAL_CP_NUM > 0 u32_t *cpSA; char *cpStack; #endif - thread = _new_thread_init(pStack, stackSize, priority, options); + _new_thread_init(thread, pStack, stackSize, priority, options); #ifdef CONFIG_DEBUG printk("\nstackPtr = %p, stackSize = %d\n", pStack, stackSize); diff --git a/doc/kernel/other/float.rst b/doc/kernel/other/float.rst index cc6bc744e2c..156c6e4cf4c 100644 --- a/doc/kernel/other/float.rst +++ b/doc/kernel/other/float.rst @@ -100,15 +100,15 @@ tagged as an SSE user, or if the application wants to avoid the exception handling overhead involved in auto-tagging threads, it is possible to pre-tag a thread using one of the techniques listed below. -* A statically-spawned x86 thread can be pre-tagged by passing the +* A statically-created x86 thread can be pre-tagged by passing the :c:macro:`K_FP_REGS` or :c:macro:`K_SSE_REGS` option to :c:macro:`K_THREAD_DEFINE`. -* A dynamically-spawned x86 thread can be pre-tagged by passing the +* A dynamically-created x86 thread can be pre-tagged by passing the :c:macro:`K_FP_REGS` or :c:macro:`K_SSE_REGS` option to - :cpp:func:`k_thread_spawn()`. + :cpp:func:`k_thread_create()`. -* An already-spawned x86 thread can pre-tag itself once it has started +* An already-created x86 thread can pre-tag itself once it has started by passing the :c:macro:`K_FP_REGS` or :c:macro:`K_SSE_REGS` option to :cpp:func:`k_float_enable()`. diff --git a/doc/kernel/threads/lifecycle.rst b/doc/kernel/threads/lifecycle.rst index 194e2f742c4..f52ff7a8437 100644 --- a/doc/kernel/threads/lifecycle.rst +++ b/doc/kernel/threads/lifecycle.rst @@ -18,11 +18,13 @@ referenced by a :dfn:`thread id` that is assigned when the thread is spawned. A thread has the following key properties: -* A **stack area**, which is a region of memory used for the thread's - control block (of type :c:type:`struct k_thread`) and for its stack. +* A **stack area**, which is a region of memory used for the thread's stack. The **size** of the stack area can be tailored to conform to the actual needs of the thread's processing. +* A **thread control block** for private kernel bookkeeping of the thread's + metadata. This is an instance of type :c:type:`struct k_thread`. + * An **entry point function**, which is invoked when the thread is started. Up to 3 **argument values** can be passed to this function. @@ -38,13 +40,12 @@ A thread has the following key properties: .. _spawning_thread: -Thread Spawning +Thread Creation =============== -A thread must be spawned before it can be used. The kernel initializes -the control block portion of the thread's stack area, as well as one -end of the stack portion. The remainder of the thread's stack is typically -left uninitialized. +A thread must be created before it can be used. The kernel initializes +the thread control block as well as one end of the stack portion. The remainder +of the thread's stack is typically left uninitialized. Specifying a start delay of :c:macro:`K_NO_WAIT` instructs the kernel to start thread execution immediately. Alternatively, the kernel can be @@ -146,11 +147,9 @@ Implementation Spawning a Thread ================= -A thread is spawned by defining its stack area and then calling -:cpp:func:`k_thread_spawn()`. The stack area is an array of bytes -whose size must equal :c:macro:`K_THREAD_SIZEOF` plus the size -of the thread's stack. The stack area must be defined using the -:c:macro:`__stack` attribute to ensure it is properly aligned. +A thread is spawned by defining its stack area and its thread control block, +and then calling :cpp:func:`k_thread_create()`. The stack area must be defined +using the :c:macro:`__stack` attribute to ensure it is properly aligned. The thread spawning function returns its thread id, which can be used to reference the thread. @@ -165,14 +164,16 @@ The following code spawns a thread that starts immediately. extern void my_entry_point(void *, void *, void *); char __noinit __stack my_stack_area[MY_STACK_SIZE]; + struct k_thread my_thread_data; - k_tid_t my_tid = k_thread_spawn(my_stack_area, MY_STACK_SIZE, - my_entry_point, NULL, NULL, NULL, - MY_PRIORITY, 0, K_NO_WAIT); + k_tid_t my_tid = k_thread_create(&my_thread_data, my_stack_area, + MY_STACK_SIZE, my_entry_point, + NULL, NULL, NULL, + MY_PRIORITY, 0, K_NO_WAIT); Alternatively, a thread can be spawned at compile time by calling :c:macro:`K_THREAD_DEFINE`. Observe that the macro defines -the stack area and thread id variables automatically. +the stack area, control block, and thread id variables automatically. The following code has the same effect as the code segment above. @@ -231,7 +232,7 @@ APIs The following thread APIs are provided by :file:`kernel.h`: * :c:macro:`K_THREAD_DEFINE` -* :cpp:func:`k_thread_spawn()` +* :cpp:func:`k_thread_create()` * :cpp:func:`k_thread_cancel()` * :cpp:func:`k_thread_abort()` * :cpp:func:`k_thread_suspend()` diff --git a/doc/kernel/threads/workqueues.rst b/doc/kernel/threads/workqueues.rst index b27a042b78e..50786173b21 100644 --- a/doc/kernel/threads/workqueues.rst +++ b/doc/kernel/threads/workqueues.rst @@ -149,16 +149,14 @@ Defining a Workqueue A workqueue is defined using a variable of type :c:type:`struct k_work_q`. The workqueue is initialized by defining the stack area used by its thread -and then calling :cpp:func:`k_work_q_start()`. The stack area is an array -of bytes whose size must equal :c:macro:`K_THREAD_SIZEOF` plus the size -of the thread's stack. The stack area must be defined using the -:c:macro:`__stack` attribute to ensure it is properly aligned. +and then calling :cpp:func:`k_work_q_start()`. The stack area must be defined +using the :c:macro:`__stack` attribute to ensure it is properly aligned. The following code defines and initializes a workqueue. .. code-block:: c - #define MY_STACK_SIZE (K_THREAD_SIZEOF + 500) + #define MY_STACK_SIZE 512 #define MY_PRIORITY 5 char __noinit __stack my_stack_area[MY_STACK_SIZE]; diff --git a/include/kernel.h b/include/kernel.h index 51e60444351..407a9ad0828 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -355,6 +355,12 @@ typedef void (*k_thread_entry_t)(void *p1, void *p2, void *p3); * scheduler may preempt the current thread to allow the new thread to * execute. * + * Kernel data structures for bookkeeping and context storage for this thread + * will be placed at the beginning of the thread's stack memory region and may + * become corrupted if too much of the stack is used. This function has been + * deprecated in favor of k_thread_create() to give the user more control on + * where these data structures reside. + * * Thread options are architecture-specific, and can include K_ESSENTIAL, * K_FP_REGS, and K_SSE_REGS. Multiple options may be specified by separating * them using "|" (the logical OR operator). @@ -371,11 +377,49 @@ typedef void (*k_thread_entry_t)(void *p1, void *p2, void *p3); * * @return ID of new thread. */ -extern k_tid_t k_thread_spawn(char *stack, size_t stack_size, +extern __deprecated k_tid_t k_thread_spawn(char *stack, size_t stack_size, k_thread_entry_t entry, void *p1, void *p2, void *p3, int prio, u32_t options, s32_t delay); +/** + * @brief Create a thread. + * + * This routine initializes a thread, then schedules it for execution. + * + * The new thread may be scheduled for immediate execution or a delayed start. + * If the newly spawned thread does not have a delayed start the kernel + * scheduler may preempt the current thread to allow the new thread to + * execute. + * + * Thread options are architecture-specific, and can include K_ESSENTIAL, + * K_FP_REGS, and K_SSE_REGS. Multiple options may be specified by separating + * them using "|" (the logical OR operator). + * + * Historically, users often would use the beginning of the stack memory region + * to store the struct k_thread data, although corruption will occur if the + * stack overflows this region and stack protection features may not detect this + * situation. + * + * @param new_thread Pointer to uninitialized struct k_thread + * @param stack Pointer to the stack space. + * @param stack_size Stack size in bytes. + * @param entry Thread entry function. + * @param p1 1st entry point parameter. + * @param p2 2nd entry point parameter. + * @param p3 3rd entry point parameter. + * @param prio Thread priority. + * @param options Thread options. + * @param delay Scheduling delay (in milliseconds), or K_NO_WAIT (for no delay). + * + * @return ID of new thread. + */ +extern k_tid_t k_thread_create(struct k_thread *new_thread, char *stack, + size_t stack_size, + void (*entry)(void *, void *, void*), + void *p1, void *p2, void *p3, + int prio, u32_t options, s32_t delay); + /** * @brief Put the current thread to sleep. * @@ -469,10 +513,8 @@ extern void k_thread_abort(k_tid_t thread); #define _INACTIVE (-1) struct _static_thread_data { - union { - char *init_stack; - struct k_thread *thread; - }; + struct k_thread *init_thread; + char *init_stack; unsigned int init_stack_size; void (*init_entry)(void *, void *, void *); void *init_p1; @@ -485,11 +527,12 @@ struct _static_thread_data { u32_t init_groups; }; -#define _THREAD_INITIALIZER(stack, stack_size, \ +#define _THREAD_INITIALIZER(thread, stack, stack_size, \ entry, p1, p2, p3, \ prio, options, delay, abort, groups) \ { \ - {.init_stack = (stack)}, \ + .init_thread = (thread), \ + .init_stack = (stack), \ .init_stack_size = (stack_size), \ .init_entry = (void (*)(void *, void *, void *))entry, \ .init_p1 = (void *)p1, \ @@ -536,13 +579,15 @@ struct _static_thread_data { #define K_THREAD_DEFINE(name, stack_size, \ entry, p1, p2, p3, \ prio, options, delay) \ - char __noinit __stack _k_thread_obj_##name[stack_size]; \ + char __noinit __stack _k_thread_stack_##name[stack_size]; \ + struct k_thread _k_thread_obj_##name; \ struct _static_thread_data _k_thread_data_##name __aligned(4) \ __in_section(_static_thread_data, static, name) = \ - _THREAD_INITIALIZER(_k_thread_obj_##name, stack_size, \ + _THREAD_INITIALIZER(&_k_thread_obj_##name, \ + _k_thread_stack_##name, stack_size, \ entry, p1, p2, p3, prio, options, delay, \ - NULL, 0); \ - const k_tid_t name = (k_tid_t)_k_thread_obj_##name + NULL, 0); \ + const k_tid_t name = (k_tid_t)&_k_thread_obj_##name /** * @brief Get a thread's priority. @@ -1795,6 +1840,7 @@ typedef void (*k_work_handler_t)(struct k_work *work); struct k_work_q { struct k_fifo fifo; + struct k_thread thread; }; enum { diff --git a/kernel/include/kernel_structs.h b/kernel/include/kernel_structs.h index 3ab4fed5506..9caef3d365d 100644 --- a/kernel/include/kernel_structs.h +++ b/kernel/include/kernel_structs.h @@ -142,20 +142,19 @@ extern void _init_thread_base(struct _thread_base *thread_base, int priority, u32_t initial_state, unsigned int options); -static ALWAYS_INLINE struct k_thread *_new_thread_init(char *pStack, - size_t stackSize, - int prio, - unsigned int options) +static ALWAYS_INLINE void _new_thread_init(struct k_thread *thread, + char *pStack, size_t stackSize, + int prio, unsigned int options) { - struct k_thread *thread; +#if !defined(CONFIG_INIT_STACKS) && !defined(CONFIG_THREAD_STACK_INFO) + ARG_UNUSED(pStack); + ARG_UNUSED(stackSize); +#endif #ifdef CONFIG_INIT_STACKS memset(pStack, 0xaa, stackSize); #endif - /* Initialize various struct k_thread members */ - thread = (struct k_thread *)pStack; - _init_thread_base(&thread->base, prio, _THREAD_PRESTART, options); /* static threads overwrite it afterwards with real value */ @@ -171,8 +170,6 @@ static ALWAYS_INLINE struct k_thread *_new_thread_init(char *pStack, thread->stack_info.start = (u32_t)pStack; thread->stack_info.size = (u32_t)stackSize; #endif /* CONFIG_THREAD_STACK_INFO */ - - return thread; } #if defined(CONFIG_THREAD_MONITOR) diff --git a/kernel/include/nano_internal.h b/kernel/include/nano_internal.h index 691250e383d..2db27da7da7 100644 --- a/kernel/include/nano_internal.h +++ b/kernel/include/nano_internal.h @@ -43,7 +43,7 @@ FUNC_NORETURN void _Cstart(void); extern void _thread_entry(void (*)(void *, void *, void *), void *, void *, void *); -extern void _new_thread(char *pStack, size_t stackSize, +extern void _new_thread(struct k_thread *thread, char *pStack, size_t stackSize, void (*pEntry)(void *, void *, void *), void *p1, void *p2, void *p3, int prio, unsigned int options); diff --git a/kernel/init.c b/kernel/init.c index 63d27af1a0d..593e03f7f1d 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -81,8 +81,11 @@ u64_t __noinit __end_tick_tsc; char __noinit __stack _main_stack[MAIN_STACK_SIZE]; char __noinit __stack _idle_stack[IDLE_STACK_SIZE]; -k_tid_t const _main_thread = (k_tid_t)_main_stack; -k_tid_t const _idle_thread = (k_tid_t)_idle_stack; +static struct k_thread _main_thread_s; +static struct k_thread _idle_thread_s; + +k_tid_t const _main_thread = (k_tid_t)&_main_thread_s; +k_tid_t const _idle_thread = (k_tid_t)&_idle_thread_s; /* * storage space for the interrupt stack @@ -271,15 +274,15 @@ static void prepare_multithreading(struct k_thread *dummy_thread) */ _ready_q.cache = _main_thread; - _new_thread(_main_stack, MAIN_STACK_SIZE, - _main, NULL, NULL, NULL, + _new_thread(_main_thread, _main_stack, + MAIN_STACK_SIZE, _main, NULL, NULL, NULL, CONFIG_MAIN_THREAD_PRIORITY, K_ESSENTIAL); _mark_thread_as_started(_main_thread); _add_thread_to_ready_q(_main_thread); #ifdef CONFIG_MULTITHREADING - _new_thread(_idle_stack, IDLE_STACK_SIZE, - idle, NULL, NULL, NULL, + _new_thread(_idle_thread, _idle_stack, + IDLE_STACK_SIZE, idle, NULL, NULL, NULL, K_LOWEST_THREAD_PRIO, K_ESSENTIAL); _mark_thread_as_started(_idle_thread); _add_thread_to_ready_q(_idle_thread); @@ -295,7 +298,8 @@ static void prepare_multithreading(struct k_thread *dummy_thread) static void switch_to_main_thread(void) { #ifdef CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN - _arch_switch_to_main_thread(_main_stack, MAIN_STACK_SIZE, _main); + _arch_switch_to_main_thread(_main_thread, _main_stack, MAIN_STACK_SIZE, + _main); #else /* * Context switch to main task (entry function is _main()): the diff --git a/kernel/thread.c b/kernel/thread.c index 42828c0f3ac..c21b18cad32 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -208,21 +208,32 @@ static void schedule_new_thread(struct k_thread *thread, s32_t delay) #endif #ifdef CONFIG_MULTITHREADING + +k_tid_t k_thread_create(struct k_thread *new_thread, char *stack, + size_t stack_size, void (*entry)(void *, void *, void*), + void *p1, void *p2, void *p3, + int prio, u32_t options, s32_t delay) +{ + __ASSERT(!_is_in_isr(), "Threads may not be created in ISRs"); + _new_thread(new_thread, stack, stack_size, entry, p1, p2, p3, prio, + options); + + schedule_new_thread(new_thread, delay); + return new_thread; +} + + k_tid_t k_thread_spawn(char *stack, size_t stack_size, void (*entry)(void *, void *, void*), void *p1, void *p2, void *p3, int prio, u32_t options, s32_t delay) { - __ASSERT(!_is_in_isr(), ""); - struct k_thread *new_thread = (struct k_thread *)stack; - _new_thread(stack, stack_size, entry, p1, p2, p3, prio, options); - - schedule_new_thread(new_thread, delay); - - return new_thread; + return k_thread_create(new_thread, stack, stack_size, entry, p1, p2, + p3, prio, options, delay); } + #endif int k_thread_cancel(k_tid_t tid) @@ -264,7 +275,7 @@ void _k_thread_group_op(u32_t groups, void (*func)(struct k_thread *)) _FOREACH_STATIC_THREAD(thread_data) { if (is_in_any_group(thread_data, groups)) { key = irq_lock(); - func(thread_data->thread); + func(thread_data->init_thread); irq_unlock(key); } } @@ -359,6 +370,7 @@ void _init_static_threads(void) _FOREACH_STATIC_THREAD(thread_data) { _new_thread( + thread_data->init_thread, thread_data->init_stack, thread_data->init_stack_size, thread_data->init_entry, @@ -368,7 +380,7 @@ void _init_static_threads(void) thread_data->init_prio, thread_data->init_options); - thread_data->thread->init_data = thread_data; + thread_data->init_thread->init_data = thread_data; } _sched_lock(); @@ -385,7 +397,7 @@ void _init_static_threads(void) key = irq_lock(); _FOREACH_STATIC_THREAD(thread_data) { if (thread_data->init_delay != K_FOREVER) { - schedule_new_thread(thread_data->thread, + schedule_new_thread(thread_data->init_thread, thread_data->init_delay); } } diff --git a/kernel/work_q.c b/kernel/work_q.c index 4194702b70d..e4867a63c51 100644 --- a/kernel/work_q.c +++ b/kernel/work_q.c @@ -48,9 +48,8 @@ void k_work_q_start(struct k_work_q *work_q, char *stack, { k_fifo_init(&work_q->fifo); - k_thread_spawn(stack, stack_size, - work_q_main, work_q, 0, 0, - prio, 0, 0); + k_thread_create(&work_q->thread, stack, stack_size, work_q_main, + work_q, 0, 0, prio, 0, 0); } #ifdef CONFIG_SYS_CLOCK_EXISTS