doc: kernel: threads: add dynamic thread stack docs

Add documentation to indicate that, aside from static thread
stack allocation, Zephyr supports dynamically allocated thread
stacks.

Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
This commit is contained in:
Chris Friedt 2025-04-05 16:45:40 -04:00 committed by Benjamin Cabé
commit c46f7f54e8
2 changed files with 43 additions and 13 deletions

View file

@ -189,8 +189,12 @@ require their regions to be of some power of two in size, and aligned to its
own size. own size.
Because of this, portable code can't simply pass an arbitrary character buffer Because of this, portable code can't simply pass an arbitrary character buffer
to :c:func:`k_thread_create`. Special macros exist to instantiate stacks, to :c:func:`k_thread_create`. Special macros exist to instantiate stacks
prefixed with ``K_KERNEL_STACK`` and ``K_THREAD_STACK``. statically, prefixed with ``K_KERNEL_STACK`` and ``K_THREAD_STACK``.
Additionally, stacks may be instantiated dynamically using
:c:func:`k_thread_stack_alloc` and subsequently freed with
:c:func:`k_thread_stack_free`.
Kernel-only Stacks Kernel-only Stacks
================== ==================
@ -411,8 +415,9 @@ Spawning a Thread
A thread is spawned by defining its stack area and its thread control block, A thread is spawned by defining its stack area and its thread control block,
and then calling :c:func:`k_thread_create`. and then calling :c:func:`k_thread_create`.
The stack area must be defined using :c:macro:`K_THREAD_STACK_DEFINE` or The stack area may be statically allocated using
:c:macro:`K_KERNEL_STACK_DEFINE` to ensure it is properly set up in memory. :c:macro:`K_THREAD_STACK_DEFINE` or :c:macro:`K_KERNEL_STACK_DEFINE` to ensure
it is properly set up in memory.
The size parameter for the stack must be one of three values: The size parameter for the stack must be one of three values:
@ -426,6 +431,9 @@ The size parameter for the stack must be one of three values:
macros, the return value of :c:macro:`K_KERNEL_STACK_SIZEOF()` for that macros, the return value of :c:macro:`K_KERNEL_STACK_SIZEOF()` for that
object. object.
Alternatively, the stack area may be dynamically allocated using
:c:func:`k_thread_stack_alloc` and freed using :c:func:`k_thread_stack_free`.
The thread spawning function returns its thread id, which can be used The thread spawning function returns its thread id, which can be used
to reference the thread. to reference the thread.
@ -470,6 +478,25 @@ The following code has the same effect as the code segment above.
thread immediately. The corresponding parameter to :c:macro:`K_THREAD_DEFINE` thread immediately. The corresponding parameter to :c:macro:`K_THREAD_DEFINE`
is a duration in integral milliseconds, so the equivalent argument is 0. is a duration in integral milliseconds, so the equivalent argument is 0.
The following code dynamically allocates a thread stack, waits until the thread
has joined, and then frees the dynamically allocated thread stack.
.. code-block:: c
extern void my_entry_point(void *, void *, void *);
k_tid_t my_tid;
void *my_stack_area;
my_stack_area = k_thread_stack_alloc(CONFIG_DYNAMIC_THREAD_STACK_SIZE);
my_tid = k_thread_create(&my_thread_data, my_stack_area,
CONFIG_DYNAMIC_THREAD_STACK_SIZE,
my_entry_point,
NULL, NULL, NULL,
MY_PRIORITY, 0, K_NO_WAIT);
k_thread_join(my_tid, K_FOREVER);
k_thread_stack_free(my_stack_area);
User Mode Constraints User Mode Constraints
--------------------- ---------------------

View file

@ -332,14 +332,15 @@ void k_thread_foreach_unlocked_filter_by_cpu(unsigned int cpu,
/** /**
* @brief Dynamically allocate a thread stack. * @brief Dynamically allocate a thread stack.
* *
* Dynamically allocate a thread stack either from a pool of thread stacks of size * Dynamically allocate a thread stack either from a pool of thread stacks of
* @kconfig{CONFIG_DYNAMIC_THREAD_POOL_SIZE}, or from the system heap. Order is determined by the * size @kconfig{CONFIG_DYNAMIC_THREAD_POOL_SIZE}, or from the system heap.
* kconfig{CONFIG_DYNAMIC_THREAD_PREFER_ALLOC} and @kconfig{CONFIG_DYNAMIC_THREAD_PREFER_POOL} * Order is determined by the @kconfig{CONFIG_DYNAMIC_THREAD_PREFER_ALLOC} and
* options. Thread stacks from the pool are of maximum size * @kconfig{CONFIG_DYNAMIC_THREAD_PREFER_POOL} options. Thread stacks from the
* @kconfig{CONFIG_DYNAMIC_THREAD_STACK_SIZE}. * pool are of maximum size @kconfig{CONFIG_DYNAMIC_THREAD_STACK_SIZE}.
* *
* Relevant stack creation flags include: * @note When no longer required, thread stacks allocated with
* - @ref K_USER allocate a userspace thread (requires @kconfig{CONFIG_USERSPACE}) * `k_thread_stack_alloc()` must be freed with @ref k_thread_stack_free to
* avoid leaking memory.
* *
* @param size Stack size in bytes. * @param size Stack size in bytes.
* @param flags Stack creation flags, or 0. * @param flags Stack creation flags, or 0.
@ -347,6 +348,9 @@ void k_thread_foreach_unlocked_filter_by_cpu(unsigned int cpu,
* @retval the allocated thread stack on success. * @retval the allocated thread stack on success.
* @retval NULL on failure. * @retval NULL on failure.
* *
* Relevant stack creation flags include:
* - @ref K_USER allocate a userspace thread (requires @kconfig{CONFIG_USERSPACE})
*
* @see @kconfig{CONFIG_DYNAMIC_THREAD} * @see @kconfig{CONFIG_DYNAMIC_THREAD}
*/ */
__syscall k_thread_stack_t *k_thread_stack_alloc(size_t size, int flags); __syscall k_thread_stack_t *k_thread_stack_alloc(size_t size, int flags);
@ -389,8 +393,7 @@ __syscall int k_thread_stack_free(k_thread_stack_t *stack);
* enabled. * enabled.
* *
* Alternatively, the stack may be dynamically allocated using * Alternatively, the stack may be dynamically allocated using
* @ref k_thread_stack_alloc. If this is the case, then the stack should * @ref k_thread_stack_alloc.
* be freed using @ref k_thread_stack_free after joining the thread.
* *
* The stack_size parameter has constraints. It must either be: * The stack_size parameter has constraints. It must either be:
* *