From: Sergiu Moga Date: Tue, 31 Oct 2023 16:49:00 +0000 (+0200) Subject: lib/uksched: Introduce the per-thread auxiliary stack X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=cbc0a3bf7dbc47be37051233f5dcdb56afbcabfd;p=unikraft%2Funikraft.git lib/uksched: Introduce the per-thread auxiliary stack Add a new field to `struct uk_thread` that can represent a secondary stack that can be used as a backup stack. This can become very useful in cases such as when wanting to defer exception handling without creating another thread. For example, we want to return from an exception into a function inside the same thread to be able to do deferred I/O outside exception context without contaminating the original stack that was present before the trap. We can avoid polluting the original stack by using this auxiliary stack instead. Update each thread creation/deletion method's signature and implementation accordingly. Signed-off-by: Sergiu Moga --- diff --git a/lib/posix-process/clone.c b/lib/posix-process/clone.c index 56a14e775..6aa8adbed 100644 --- a/lib/posix-process/clone.c +++ b/lib/posix-process/clone.c @@ -400,6 +400,7 @@ static int _clone(struct clone_args *cl_args, size_t cl_args_len, (void *) cl_args->tls); child = uk_thread_create_container2(s->a, (__uptr) cl_args->stack, + 0, (__uptr) cl_args->tls, true, /* TLS is an UKTLS */ false, /* We want ECTX */ @@ -423,6 +424,7 @@ static int _clone(struct clone_args *cl_args, size_t cl_args_len, } child = uk_thread_create_container(s->a, NULL, 0, /* Stack is given */ + NULL, 0, s->a_uktls, false, /* We want ECTX */ (t->name) ? strdup(t->name) diff --git a/lib/uksched/include/uk/sched.h b/lib/uksched/include/uk/sched.h index 7d1a05c69..444077839 100644 --- a/lib/uksched/include/uk/sched.h +++ b/lib/uksched/include/uk/sched.h @@ -94,6 +94,7 @@ struct uk_sched { struct uk_thread_list exited_threads; struct uk_alloc *a; /**< default allocator for struct uk_thread */ struct uk_alloc *a_stack; /**< default allocator for stacks */ + struct uk_alloc *a_auxstack; /**< default allocator for aux stacks */ struct uk_alloc *a_uktls; /**< default allocator for TLS+ectx */ struct uk_sched *next; }; @@ -177,6 +178,9 @@ int uk_sched_start(struct uk_sched *sched); * @param stack_len * Size of the thread stack. If set to 0, a default stack size is used * for the stack allocation. + * @param auxstack_len + * Size of the thread auxiliary stack. If set to 0, a default stack size is + * used for the stack allocation. * @param no_uktls * If set, no memory is allocated for a TLS. Functions must not use * any TLS variables. @@ -198,6 +202,7 @@ int uk_sched_start(struct uk_sched *sched); struct uk_thread *uk_sched_thread_create_fn0(struct uk_sched *s, uk_thread_fn0_t fn0, size_t stack_len, + size_t auxstack_len, bool no_uktls, bool no_ectx, const char *name, @@ -212,6 +217,7 @@ struct uk_thread *uk_sched_thread_create_fn1(struct uk_sched *s, uk_thread_fn1_t fn1, void *argp, size_t stack_len, + size_t auxstack_len, bool no_uktls, bool no_ectx, const char *name, @@ -226,6 +232,7 @@ struct uk_thread *uk_sched_thread_create_fn2(struct uk_sched *s, uk_thread_fn2_t fn2, void *argp0, void *argp1, size_t stack_len, + size_t auxstack_len, bool no_uktls, bool no_ectx, const char *name, @@ -235,7 +242,7 @@ struct uk_thread *uk_sched_thread_create_fn2(struct uk_sched *s, /* Shortcut for creating a thread with default settings */ #define uk_sched_thread_create(s, fn1, argp, name) \ uk_sched_thread_create_fn1((s), (fn1), (void *) (argp), \ - 0x0, false, false, \ + 0x0, 0x0, false, false, \ (name), NULL, NULL) #define uk_sched_foreach_thread(sched, itr) \ diff --git a/lib/uksched/include/uk/sched_impl.h b/lib/uksched/include/uk/sched_impl.h index 613f585f1..63f5d3c6f 100644 --- a/lib/uksched/include/uk/sched_impl.h +++ b/lib/uksched/include/uk/sched_impl.h @@ -68,6 +68,7 @@ int uk_sched_register(struct uk_sched *s); \ (s)->a = (def_allocator); \ (s)->a_stack = (def_allocator); \ + (s)->a_auxstack = (def_allocator); \ (s)->a_uktls = (def_allocator); \ UK_TAILQ_INIT(&(s)->thread_list); \ UK_TAILQ_INIT(&(s)->exited_threads); \ diff --git a/lib/uksched/include/uk/thread.h b/lib/uksched/include/uk/thread.h index 270f54ec0..cfa8eee61 100644 --- a/lib/uksched/include/uk/thread.h +++ b/lib/uksched/include/uk/thread.h @@ -59,6 +59,7 @@ struct uk_thread { struct ukarch_ectx *ectx; /**< Extended context (FPU, VPU, ...) */ uintptr_t tlsp; /**< Current active TLS pointer */ __uptr uktlsp; /**< Unikraft TLS pointer */ + __uptr auxsp; /**< Unikraft Auxiliary Stack Pointer */ UK_TAILQ_ENTRY(struct uk_thread) queue; uint32_t flags; @@ -71,6 +72,8 @@ struct uk_thread { struct uk_alloc *stack_a; void *uktls; struct uk_alloc *uktls_a; + void *auxstack; + struct uk_alloc *auxstack_a; } _mem; /**< Associated allocs (internal!) */ uk_thread_gc_t _gc_fn; /**< Extra gc function (internal!) */ void *_gc_argp; /**< Argument for gc fn (internal!) */ @@ -197,6 +200,8 @@ void uk_thread_set_exited(struct uk_thread *t); * UK_THREADF_RUNNABLE is set. * @param sp * Stack pointer + * @param auxsp + * Auxiliary stack pointer * @param tlsp * Architecture pointer to TLS. If set to NULL, the thread cannot * access thread-local variables. @@ -222,6 +227,7 @@ void uk_thread_set_exited(struct uk_thread *t); int uk_thread_init_bare(struct uk_thread *t, uintptr_t ip, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -243,6 +249,8 @@ int uk_thread_init_bare(struct uk_thread *t, * Thread entry function (required) * @param sp * Architecture stack pointer (stack is required) + * @param auxsp + * Auxiliary stack pointer * @param tlsp * Architecture pointer to TLS. If set to NULL, the thread cannot * access thread-local variables. @@ -268,6 +276,7 @@ int uk_thread_init_bare(struct uk_thread *t, int uk_thread_init_bare_fn0(struct uk_thread *t, uk_thread_fn0_t fn, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -283,6 +292,7 @@ int uk_thread_init_bare_fn1(struct uk_thread *t, uk_thread_fn1_t fn, void *argp, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -298,6 +308,7 @@ int uk_thread_init_bare_fn2(struct uk_thread *t, uk_thread_fn2_t fn, void *argp0, void *argp1, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -319,6 +330,11 @@ int uk_thread_init_bare_fn2(struct uk_thread *t, * @param stack_len * Size of the thread stack. If set to 0, a default stack size is used * for the allocation. + * @param a_auxstack + * Reference to an allocator for allocating an auxiliary stack + * @param auxstack_len + * Size of the thread auxiliary stack. If set to 0, a default stack size is + * used for the allocation. * @param a_uktls * Reference to an allocator for allocating (Unikraft) thread local storage. * In case `custom_ectx` is not set, space for extended CPU context state @@ -348,6 +364,8 @@ int uk_thread_init_fn0(struct uk_thread *t, uk_thread_fn0_t fn, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool custom_ectx, struct ukarch_ectx *ectx, @@ -364,6 +382,8 @@ int uk_thread_init_fn1(struct uk_thread *t, void *argp, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool custom_ectx, struct ukarch_ectx *ectx, @@ -380,6 +400,8 @@ int uk_thread_init_fn2(struct uk_thread *t, void *argp0, void *argp1, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool custom_ectx, struct ukarch_ectx *ectx, @@ -398,6 +420,8 @@ int uk_thread_init_fn2(struct uk_thread *t, * `UK_THREADF_RUNNABLE` is set. * @param sp * Stack pointer + * @param auxsp + * Auxiliary stack pointer * @param tlsp * Architecture pointer to TLS. If set to NULL, the thread cannot * access thread-local variables @@ -422,6 +446,7 @@ int uk_thread_init_fn2(struct uk_thread *t, struct uk_thread *uk_thread_create_bare(struct uk_alloc *a, uintptr_t ip, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, bool no_ectx, @@ -443,6 +468,11 @@ struct uk_thread *uk_thread_create_bare(struct uk_alloc *a, * @param stack_len * Size of the thread stack. If set to 0, a default stack size is used * for the stack allocation. + * @param a_auxstack + * Reference to an allocator for allocating an auxiliary stack + * @param auxstack_len + * Size of the thread auxiliary stack. If set to 0, a default stack size is + * used for the allocation. * @param a_uktls * Reference to an allocator for allocating (Unikraft) thread local storage. * If `NULL` is passed, a thread without TLS is allocated. @@ -464,6 +494,8 @@ struct uk_thread *uk_thread_create_bare(struct uk_alloc *a, struct uk_thread *uk_thread_create_container(struct uk_alloc *a, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, @@ -481,6 +513,8 @@ struct uk_thread *uk_thread_create_container(struct uk_alloc *a, * Reference t o an allocator (required) * @param sp * Stack pointer + * @param auxsp + * Auxiliary stack pointer * @param tlsp * Architecture pointer to TLS. If set to NULL, the thread cannot * access thread-local variables @@ -504,6 +538,7 @@ struct uk_thread *uk_thread_create_container(struct uk_alloc *a, */ struct uk_thread *uk_thread_create_container2(struct uk_alloc *a, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, bool no_ectx, @@ -537,6 +572,11 @@ void uk_thread_container_init_fn2(struct uk_thread *t, uk_thread_fn2_t fn, * @param stack_len * Size of the thread stack. If set to 0, a default stack size is used * for the stack allocation. + * @param a_auxstack + * Reference to an allocator for allocating an auxiliary stack + * @param auxstack_len + * Size of the thread auxiliary stack. If set to 0, a default stack size is + * used for the allocation. * @param a_uktls * Reference to an allocator for allocating (Unikraft) thread local storage. * If `NULL` is passed, a thread without TLS is allocated. @@ -559,6 +599,8 @@ struct uk_thread *uk_thread_create_fn0(struct uk_alloc *a, uk_thread_fn0_t fn, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, @@ -573,6 +615,8 @@ struct uk_thread *uk_thread_create_fn1(struct uk_alloc *a, uk_thread_fn1_t fn, void *argp, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, @@ -588,6 +632,8 @@ struct uk_thread *uk_thread_create_fn2(struct uk_alloc *a, void *argp0, void *argp1, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, diff --git a/lib/uksched/sched.c b/lib/uksched/sched.c index 9ab93ff42..7cbcc863e 100644 --- a/lib/uksched/sched.c +++ b/lib/uksched/sched.c @@ -66,6 +66,7 @@ int uk_sched_register(struct uk_sched *s) struct uk_thread *uk_sched_thread_create_fn0(struct uk_sched *s, uk_thread_fn0_t fn0, size_t stack_len, + size_t auxstack_len, bool no_uktls, bool no_ectx, const char *name, @@ -77,6 +78,7 @@ struct uk_thread *uk_sched_thread_create_fn0(struct uk_sched *s, UK_ASSERT(s); UK_ASSERT(s->a_stack); + UK_ASSERT(s->a_auxstack); if (!no_uktls && !s->a_uktls) goto err_out; @@ -84,6 +86,7 @@ struct uk_thread *uk_sched_thread_create_fn0(struct uk_sched *s, t = uk_thread_create_fn0(s->a, fn0, s->a_stack, stack_len, + s->a_auxstack, auxstack_len, no_uktls ? NULL : s->a_uktls, no_ectx, name, @@ -108,6 +111,7 @@ struct uk_thread *uk_sched_thread_create_fn1(struct uk_sched *s, uk_thread_fn1_t fn1, void *argp, size_t stack_len, + size_t auxstack_len, bool no_uktls, bool no_ectx, const char *name, @@ -119,6 +123,7 @@ struct uk_thread *uk_sched_thread_create_fn1(struct uk_sched *s, UK_ASSERT(s); UK_ASSERT(s->a_stack); + UK_ASSERT(s->a_auxstack); if (!no_uktls && !s->a_uktls) goto err_out; @@ -126,6 +131,7 @@ struct uk_thread *uk_sched_thread_create_fn1(struct uk_sched *s, t = uk_thread_create_fn1(s->a, fn1, argp, s->a_stack, stack_len, + s->a_auxstack, auxstack_len, no_uktls ? NULL : s->a_uktls, no_ectx, name, @@ -150,6 +156,7 @@ struct uk_thread *uk_sched_thread_create_fn2(struct uk_sched *s, uk_thread_fn2_t fn2, void *argp0, void *argp1, size_t stack_len, + size_t auxstack_len, bool no_uktls, bool no_ectx, const char *name, @@ -161,6 +168,7 @@ struct uk_thread *uk_sched_thread_create_fn2(struct uk_sched *s, UK_ASSERT(s); UK_ASSERT(s->a_stack); + UK_ASSERT(s->a_auxstack); if (!no_uktls && !s->a_uktls) goto err_out; @@ -168,6 +176,7 @@ struct uk_thread *uk_sched_thread_create_fn2(struct uk_sched *s, t = uk_thread_create_fn2(s->a, fn2, argp0, argp1, s->a_stack, stack_len, + s->a_auxstack, auxstack_len, no_uktls ? NULL : s->a_uktls, no_ectx, name, @@ -205,7 +214,8 @@ int uk_sched_start(struct uk_sched *s) */ tlsp = ukplat_tlsp_get(); main_thread = uk_thread_create_bare(s->a, - 0x0, 0x0, tlsp, !(!tlsp), false, + 0x0, 0x0, 0x0, + tlsp, !(!tlsp), false, "init", NULL, NULL); if (!main_thread) { ret = -ENOMEM; diff --git a/lib/uksched/thread.c b/lib/uksched/thread.c index 008f95c54..8c5cd982a 100644 --- a/lib/uksched/thread.c +++ b/lib/uksched/thread.c @@ -44,6 +44,7 @@ #include #include #include +#include #if CONFIG_LIBUKSCHED_TCB_INIT && !CONFIG_UKARCH_TLS_HAVE_TCB #error CONFIG_LIBUKSCHED_TCB_INIT requires that a TLS contains reserved space for a TCB @@ -224,6 +225,7 @@ void uk_thread_set_exited(struct uk_thread *t) } static void _uk_thread_struct_init(struct uk_thread *t, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -243,6 +245,15 @@ static void _uk_thread_struct_init(struct uk_thread *t, t->dtor = dtor; t->exec_time = 0; + if (!auxsp) + auxsp = ukplat_auxsp_alloc(uk_alloc_get_default(), +#if CONFIG_LIBUKVMEM + uk_vas_get_active(), +#endif /* CONFIG_LIBUKVMEM */ + 0); /* Default auxsp size */ + + t->auxsp = auxsp; + if (tlsp && is_uktls) { t->flags |= UK_THREADF_UKTLS; t->uktlsp = tlsp; @@ -260,6 +271,7 @@ static void _uk_thread_struct_init(struct uk_thread *t, int uk_thread_init_bare(struct uk_thread *t, uintptr_t ip, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -270,7 +282,8 @@ int uk_thread_init_bare(struct uk_thread *t, UK_ASSERT(t); UK_ASSERT(t != uk_thread_current()); - _uk_thread_struct_init(t, tlsp, is_uktls, ectx, name, priv, dtor); + _uk_thread_struct_init(t, auxsp, tlsp, is_uktls, ectx, name, priv, + dtor); ukarch_ctx_init_bare(&t->ctx, sp, ip); if (ip) @@ -282,6 +295,7 @@ int uk_thread_init_bare(struct uk_thread *t, int uk_thread_init_bare_fn0(struct uk_thread *t, uk_thread_fn0_t fn, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -294,7 +308,8 @@ int uk_thread_init_bare_fn0(struct uk_thread *t, UK_ASSERT(sp); /* stack pointer is required for ctx_entry */ UK_ASSERT(fn); - _uk_thread_struct_init(t, tlsp, is_uktls, ectx, name, priv, dtor); + _uk_thread_struct_init(t, auxsp, tlsp, is_uktls, ectx, name, priv, + dtor); ukarch_ctx_init_entry0(&t->ctx, sp, 0, (ukarch_ctx_entry0) fn); uk_thread_set_runnable(t); @@ -306,6 +321,7 @@ int uk_thread_init_bare_fn1(struct uk_thread *t, uk_thread_fn1_t fn, void *argp, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -318,7 +334,8 @@ int uk_thread_init_bare_fn1(struct uk_thread *t, UK_ASSERT(sp); /* stack pointer is required for ctx_entry */ UK_ASSERT(fn); - _uk_thread_struct_init(t, tlsp, is_uktls, ectx, name, priv, dtor); + _uk_thread_struct_init(t, auxsp, tlsp, is_uktls, ectx, name, priv, + dtor); ukarch_ctx_init_entry1(&t->ctx, sp, 0, (ukarch_ctx_entry1) fn, (long) argp); @@ -331,6 +348,7 @@ int uk_thread_init_bare_fn2(struct uk_thread *t, uk_thread_fn2_t fn, void *argp0, void *argp1, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, struct ukarch_ectx *ectx, @@ -343,7 +361,8 @@ int uk_thread_init_bare_fn2(struct uk_thread *t, UK_ASSERT(sp); /* stack pointer is required for ctx_entry */ UK_ASSERT(fn); - _uk_thread_struct_init(t, tlsp, is_uktls, ectx, name, priv, dtor); + _uk_thread_struct_init(t, auxsp, tlsp, is_uktls, ectx, name, priv, + dtor); ukarch_ctx_init_entry2(&t->ctx, sp, 0, (ukarch_ctx_entry2) fn, (long) argp0, (long) argp1); @@ -356,6 +375,8 @@ int uk_thread_init_bare_fn2(struct uk_thread *t, static int _uk_thread_struct_init_alloc(struct uk_thread *t, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool custom_ectx, struct ukarch_ectx *ectx, @@ -365,6 +386,7 @@ static int _uk_thread_struct_init_alloc(struct uk_thread *t, { void *stack = NULL; void *tls = NULL; + void *auxstack = 0x0; uintptr_t tlsp = 0x0; int rc; @@ -376,6 +398,18 @@ static int _uk_thread_struct_init_alloc(struct uk_thread *t, } } + if (a_auxstack && auxstack_len) { + auxstack = (void *)ukplat_auxsp_alloc(a_auxstack, +#if CONFIG_LIBUKVMEM + uk_vas_get_active(), +#endif /* CONFIG_LIBUKVMEM */ + auxstack_len); + if (unlikely(!auxstack)) { + rc = -ENOMEM; + goto err_free_stack; + } + } + if (a_uktls) { if (!custom_ectx) { /* Allocate TLS and ectx together */ @@ -407,7 +441,9 @@ static int _uk_thread_struct_init_alloc(struct uk_thread *t, tlsp = ukarch_tls_tlsp(tls); } - _uk_thread_struct_init(t, tlsp, !(!tlsp), ectx, name, priv, dtor); + _uk_thread_struct_init(t, (__uptr)auxstack, tlsp, !(!tlsp), ectx, + name, priv, + dtor); /* Set uk_thread fields related to stack and TLS */ if (stack) { @@ -415,6 +451,11 @@ static int _uk_thread_struct_init_alloc(struct uk_thread *t, t->_mem.stack_a = a_stack; } + if (auxstack) { + t->_mem.auxstack = auxstack; + t->_mem.auxstack_a = a_auxstack; + } + if (tls) { ukarch_tls_area_init(tls); @@ -463,12 +504,19 @@ void _uk_thread_struct_free_alloc(struct uk_thread *t) t->_mem.stack_a = NULL; t->_mem.stack = NULL; } + if (t->auxsp) { + uk_free(t->_mem.auxstack_a, t->_mem.auxstack); + t->_mem.auxstack_a = NULL; + t->_mem.auxstack = NULL; + } } int uk_thread_init_fn0(struct uk_thread *t, uk_thread_fn0_t fn, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool custom_ectx, struct ukarch_ectx *ectx, @@ -482,7 +530,9 @@ int uk_thread_init_fn0(struct uk_thread *t, UK_ASSERT(t != uk_thread_current()); UK_ASSERT(fn); - ret = _uk_thread_struct_init_alloc(t, a_stack, stack_len, + ret = _uk_thread_struct_init_alloc(t, + a_stack, stack_len, + a_auxstack, auxstack_len, a_uktls, custom_ectx, ectx, name, priv, dtor); if (ret < 0) @@ -509,6 +559,8 @@ int uk_thread_init_fn1(struct uk_thread *t, void *argp, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool custom_ectx, struct ukarch_ectx *ectx, @@ -522,7 +574,9 @@ int uk_thread_init_fn1(struct uk_thread *t, UK_ASSERT(t != uk_thread_current()); UK_ASSERT(fn); - ret = _uk_thread_struct_init_alloc(t, a_stack, stack_len, + ret = _uk_thread_struct_init_alloc(t, + a_stack, stack_len, + a_auxstack, auxstack_len, a_uktls, custom_ectx, ectx, name, priv, dtor); if (ret < 0) @@ -549,6 +603,8 @@ int uk_thread_init_fn2(struct uk_thread *t, void *argp0, void *argp1, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool custom_ectx, struct ukarch_ectx *ectx, @@ -562,7 +618,9 @@ int uk_thread_init_fn2(struct uk_thread *t, UK_ASSERT(t != uk_thread_current()); UK_ASSERT(fn); - ret = _uk_thread_struct_init_alloc(t, a_stack, stack_len, + ret = _uk_thread_struct_init_alloc(t, + a_stack, stack_len, + a_auxstack, auxstack_len, a_uktls, custom_ectx, ectx, name, priv, dtor); if (ret < 0) @@ -588,6 +646,7 @@ err_out: struct uk_thread *uk_thread_create_bare(struct uk_alloc *a, uintptr_t ip, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, bool no_ectx, @@ -608,7 +667,7 @@ struct uk_thread *uk_thread_create_bare(struct uk_alloc *a, if (!t) return NULL; - uk_thread_init_bare(t, ip, sp, tlsp, is_uktls, + uk_thread_init_bare(t, ip, sp, auxsp, tlsp, is_uktls, (struct ukarch_ectx *) ALIGN_UP((uintptr_t) t + sizeof(*t), ukarch_ectx_align()), @@ -624,6 +683,8 @@ struct uk_thread *uk_thread_create_bare(struct uk_alloc *a, struct uk_thread *uk_thread_create_container(struct uk_alloc *a, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, @@ -653,9 +714,12 @@ struct uk_thread *uk_thread_create_container(struct uk_alloc *a, ukarch_ectx_align()); stack_len = (!!stack_len) ? stack_len : STACK_SIZE; + auxstack_len = (!!auxstack_len) ? auxstack_len : + CONFIG_UKPLAT_AUXSP_SIZE; if (_uk_thread_struct_init_alloc(t, a_stack, stack_len, + a_auxstack, auxstack_len, a_uktls, !(!ectx), ectx, @@ -691,6 +755,7 @@ err_out: */ struct uk_thread *uk_thread_create_container2(struct uk_alloc *a, uintptr_t sp, + uintptr_t auxsp, uintptr_t tlsp, bool is_uktls, bool no_ectx, @@ -720,7 +785,8 @@ struct uk_thread *uk_thread_create_container2(struct uk_alloc *a, + sizeof(*t), ukarch_ectx_align()); - _uk_thread_struct_init(t, tlsp, is_uktls, ectx, name, priv, dtor); + _uk_thread_struct_init(t, auxsp, tlsp, is_uktls, ectx, name, priv, + dtor); t->_mem.t_a = a; /* Minimal context initialization where the stack pointer @@ -799,6 +865,8 @@ struct uk_thread *uk_thread_create_fn0(struct uk_alloc *a, uk_thread_fn0_t fn, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, @@ -812,6 +880,7 @@ struct uk_thread *uk_thread_create_fn0(struct uk_alloc *a, t = uk_thread_create_container(a, a_stack, stack_len, + a_auxstack, auxstack_len, a_uktls, no_ectx, name, priv, dtor); if (!t) @@ -829,6 +898,8 @@ struct uk_thread *uk_thread_create_fn1(struct uk_alloc *a, void *argp, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, @@ -842,6 +913,7 @@ struct uk_thread *uk_thread_create_fn1(struct uk_alloc *a, t = uk_thread_create_container(a, a_stack, stack_len, + a_auxstack, auxstack_len, a_uktls, no_ectx, name, priv, dtor); if (!t) @@ -859,6 +931,8 @@ struct uk_thread *uk_thread_create_fn2(struct uk_alloc *a, void *argp0, void *argp1, struct uk_alloc *a_stack, size_t stack_len, + struct uk_alloc *a_auxstack, + size_t auxstack_len, struct uk_alloc *a_uktls, bool no_ectx, const char *name, @@ -872,6 +946,7 @@ struct uk_thread *uk_thread_create_fn2(struct uk_alloc *a, t = uk_thread_create_container(a, a_stack, stack_len, + a_auxstack, auxstack_len, a_uktls, no_ectx, name, priv, dtor); if (!t) @@ -888,8 +963,10 @@ void uk_thread_release(struct uk_thread *t) { struct uk_alloc *a; struct uk_alloc *stack_a; + struct uk_alloc *auxstack_a; struct uk_alloc *tls_a; void *stack; + void *auxstack; void *tls; UK_ASSERT(t); @@ -904,9 +981,11 @@ void uk_thread_release(struct uk_thread *t) */ a = t->_mem.t_a; stack_a = t->_mem.stack_a; - stack = t->_mem.stack; - tls_a = t->_mem.uktls_a; - tls = t->_mem.uktls; + stack = t->_mem.stack; + auxstack_a = t->_mem.auxstack_a; + auxstack = t->_mem.auxstack; + tls_a = t->_mem.uktls_a; + tls = t->_mem.uktls; #if CONFIG_LIBUKSCHED_TCB_INIT if (tls_a && tls) @@ -920,6 +999,8 @@ void uk_thread_release(struct uk_thread *t) uk_free(tls_a, tls); if (stack_a && stack) uk_free(stack_a, stack); + if (auxstack_a && auxstack) + uk_free(auxstack_a, auxstack); if (a) uk_free(a, t); } diff --git a/lib/ukschedcoop/schedcoop.c b/lib/ukschedcoop/schedcoop.c index e47688434..ed5a42930 100644 --- a/lib/ukschedcoop/schedcoop.c +++ b/lib/ukschedcoop/schedcoop.c @@ -302,6 +302,7 @@ struct uk_sched *uk_schedcoop_create(struct uk_alloc *a) rc = uk_thread_init_fn1(&c->idle, idle_thread_fn, (void *) c, a, STACK_SIZE, + a, 0, /* Default auxiliary stack size */ a, false, NULL, "idle",