Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kernel: userspace: dynamic thread stack support #59773

Merged
merged 6 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion include/zephyr/sys/kobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,33 @@ static inline void k_object_access_all_grant(const void *object)
* state, with the calling thread being granted permission on it. The memory
* for the object will be allocated out of the calling thread's resource pool.
*
* Currently, allocation of thread stacks is not supported.
* @note Thread stack object has to use k_object_alloc_size() since stacks may
* have different sizes.
*
* @param otype Requested kernel object type
* @return A pointer to the allocated kernel object, or NULL if memory wasn't
* available
*/
__syscall void *k_object_alloc(enum k_objects otype);

/**
* Allocate a kernel object of a designated type and a given size
*
* This will instantiate at runtime a kernel object of the specified type,
* returning a pointer to it. The object will be returned in an uninitialized
* state, with the calling thread being granted permission on it. The memory
* for the object will be allocated out of the calling thread's resource pool.
*
* This function is specially helpful for thread stack objects because
* their sizes can vary. Other objects should probably look k_object_alloc().
*
* @param otype Requested kernel object type
* @param size Requested kernel object size
* @return A pointer to the allocated kernel object, or NULL if memory wasn't
* available
*/
__syscall void *k_object_alloc_size(enum k_objects otype, size_t size);

/**
* Allocate memory and install as a generic kernel object
*
Expand Down Expand Up @@ -322,6 +341,15 @@ static inline void *z_impl_k_object_alloc(enum k_objects otype)
return NULL;
}

static inline void *z_impl_k_object_alloc_size(enum k_objects otype,
size_t size)
{
ARG_UNUSED(otype);
ARG_UNUSED(size);

return NULL;
}

static inline struct z_object *z_dynamic_object_aligned_create(size_t align,
size_t size)
{
Expand Down
58 changes: 37 additions & 21 deletions kernel/dynamic.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <zephyr/kernel/thread_stack.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/bitarray.h>
#include <zephyr/sys/kobject.h>
#include <zephyr/syscall_handler.h>

LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);

Expand Down Expand Up @@ -39,6 +41,8 @@ static k_thread_stack_t *z_thread_stack_alloc_pool(size_t size)
size_t offset;
k_thread_stack_t *stack;

size = Z_KERNEL_STACK_SIZE_ADJUST(size);

if (size > CONFIG_DYNAMIC_THREAD_STACK_SIZE) {
LOG_DBG("stack size %zu is > pool stack size %d", size,
CONFIG_DYNAMIC_THREAD_STACK_SIZE);
Expand All @@ -58,36 +62,40 @@ static k_thread_stack_t *z_thread_stack_alloc_pool(size_t size)
return stack;
}

k_thread_stack_t *z_impl_k_thread_stack_alloc(size_t size, int flags)
static k_thread_stack_t *stack_alloc_dyn(size_t size, int flags)
{
size_t align = 0;
size_t obj_size = 0;
k_thread_stack_t *stack = NULL;

#ifdef CONFIG_USERSPACE
if ((flags & K_USER) != 0) {
align = Z_THREAD_STACK_OBJ_ALIGN(size);
obj_size = Z_THREAD_STACK_SIZE_ADJUST(size);
} else
if ((flags & K_USER) == K_USER) {
#ifdef CONFIG_DYNAMIC_OBJECTS
return k_object_alloc_size(K_OBJ_THREAD_STACK_ELEMENT, size);
#else
/* Dynamic user stack needs a kobject, so if this option is not
* enabled we can't proceed.
*/
return NULL;
#endif
{
align = Z_KERNEL_STACK_OBJ_ALIGN;
obj_size = Z_KERNEL_STACK_SIZE_ADJUST(size);
}

return z_thread_stack_alloc_dyn(Z_KERNEL_STACK_OBJ_ALIGN,
Z_KERNEL_STACK_SIZE_ADJUST(size));
}

k_thread_stack_t *z_impl_k_thread_stack_alloc(size_t size, int flags)
{
k_thread_stack_t *stack = NULL;

if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_PREFER_ALLOC)) {
stack = z_thread_stack_alloc_dyn(align, obj_size);
stack = stack_alloc_dyn(size, flags);
if (stack == NULL && CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0) {
stack = z_thread_stack_alloc_pool(size);
}
} else if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_PREFER_POOL) &&
CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0) {
stack = z_thread_stack_alloc_pool(size);
if (stack == NULL && IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) {
stack = z_thread_stack_alloc_dyn(align, obj_size);
} else if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_PREFER_POOL)) {
if (CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0) {
stack = z_thread_stack_alloc_pool(size);
}

if ((stack == NULL) && IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) {
stack = stack_alloc_dyn(size, flags);
}
} else {
return NULL;
}

return stack;
Expand Down Expand Up @@ -144,7 +152,15 @@ int z_impl_k_thread_stack_free(k_thread_stack_t *stack)
}

if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) {
#ifdef CONFIG_USERSPACE
if (z_object_find(stack)) {
k_object_free(stack);
} else {
k_free(stack);
}
#else
k_free(stack);
#endif
} else {
LOG_ERR("Invalid stack %p", stack);
return -EINVAL;
Expand Down
Loading
Loading