]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/uksched: Introduce the per-thread auxiliary stack
authorSergiu Moga <sergiu@unikraft.io>
Tue, 31 Oct 2023 16:49:00 +0000 (18:49 +0200)
committerSergiu Moga <sergiu@unikraft.io>
Sat, 25 Nov 2023 11:06:50 +0000 (13:06 +0200)
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 <sergiu@unikraft.io>
lib/posix-process/clone.c
lib/uksched/include/uk/sched.h
lib/uksched/include/uk/sched_impl.h
lib/uksched/include/uk/thread.h
lib/uksched/sched.c
lib/uksched/thread.c
lib/ukschedcoop/schedcoop.c

index 56a14e7750be0f4f6210d7580c8dc88439cfbc31..6aa8adbedd3a204ab74959b1bd087177b67afdf3 100644 (file)
@@ -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)
index 7d1a05c69b5c34b0492e696e9baf653e1c33a6db..444077839ed890e810c5556d84f7b9a5daa62923 100644 (file)
@@ -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)                            \
index 613f585f12935027cd0421ca2fb4aa9220983b42..63f5d3c6f550e04fbfbdcdc0a757c0a2b81e28d2 100644 (file)
@@ -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); \
index 270f54ec04b6e3c3c4d37489b7c164c673237a23..cfa8eee6119612d49390aea517ea2793021cf342 100644 (file)
@@ -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,
index 9ab93ff42b8216ef85f41faa77df7c5cd4669a5d..7cbcc863e49dfde521620948687da9b3edb3cb18 100644 (file)
@@ -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;
index 008f95c5479c84fdc9b47439f047526e9ba58dd0..8c5cd982a2902dea4a0d74c7ce85a95287de5e80 100644 (file)
@@ -44,6 +44,7 @@
 #include <uk/print.h>
 #include <uk/assert.h>
 #include <uk/arch/tls.h>
+#include <uk/plat/memory.h>
 
 #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);
 }
index e476884343b2524a5af4e47aa09b0e9782806b35..ed5a4293051688d465835e082b496cd1354020da 100644 (file)
@@ -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",