[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 2/4] lib/uksched: create and delete thread-local storage area
Most of the actual TLS setup is architecture-specific, so sched.c and thread.c call functions from a header file provided in arch/. Signed-off-by: Florian Schmidt <florian.schmidt@xxxxxxxxx> --- arch/x86/x86_64/include/uk/asm/thread.h | 64 +++++++++++++++++++++++++ include/uk/arch/thread.h | 40 ++++++++++++++++ lib/uksched/include/uk/sched.h | 3 ++ lib/uksched/include/uk/thread.h | 3 +- lib/uksched/sched.c | 54 ++++++++++++++------- lib/uksched/thread.c | 8 ++-- 6 files changed, 152 insertions(+), 20 deletions(-) create mode 100644 arch/x86/x86_64/include/uk/asm/thread.h create mode 100644 include/uk/arch/thread.h diff --git a/arch/x86/x86_64/include/uk/asm/thread.h b/arch/x86/x86_64/include/uk/asm/thread.h new file mode 100644 index 00000000..6e95848d --- /dev/null +++ b/arch/x86/x86_64/include/uk/asm/thread.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Florian Schmidt <florian.schmidt@xxxxxxxxx> + * + * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. + */ + +#ifndef __UKARCH_THREAD_H__ +#error Do not include this header directly +#endif + +extern char _tls_start[], _etdata[], _tls_end[]; + +static inline unsigned long tls_area_size(void) +{ + /* x86_64 ABI requires that fs:%0 contains the address of itself, to + * allow certain optimizations. Hence, the overall size of the size of + * the TLS area, plus 8 bytes. + */ + return _tls_end - _tls_start + 8; +} + +static inline unsigned int tls_area_align(void) +{ + return 8; +} + +static inline void tls_copy(void *tls_area) +{ + unsigned int tls_len = _tls_end - _tls_start; + unsigned int tls_data_len = _etdata - _tls_start; + unsigned int tls_bss_len = _tls_end - _etdata; + + memcpy(tls_area, _tls_start, tls_data_len); + memset(tls_area+tls_data_len, 0, tls_bss_len); + *((uintptr_t *)(tls_area+tls_len)) = (uintptr_t)(tls_area+tls_len); +} diff --git a/include/uk/arch/thread.h b/include/uk/arch/thread.h new file mode 100644 index 00000000..76fd3ad5 --- /dev/null +++ b/include/uk/arch/thread.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Florian Schmidt <florian.schmidt@xxxxxxxxx> + * + * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. + */ + +#ifndef __UKARCH_THREAD_H__ +#define __UKARCH_THREAD_H__ + +#include <uk/asm/thread.h> + +#endif /* __UKARCH_THREAD_H__ */ diff --git a/lib/uksched/include/uk/sched.h b/lib/uksched/include/uk/sched.h index cc5fbe93..3e21d8d8 100644 --- a/lib/uksched/include/uk/sched.h +++ b/lib/uksched/include/uk/sched.h @@ -50,6 +50,9 @@ struct uk_sched; struct uk_sched *uk_sched_default_init(struct uk_alloc *a); +extern char _tls_start[], _etdata[], _tls_end[]; +#define have_tls_area (_tls_end - _tls_start) + extern struct uk_sched *uk_sched_head; int uk_sched_register(struct uk_sched *s); struct uk_sched *uk_sched_get_default(void); diff --git a/lib/uksched/include/uk/thread.h b/lib/uksched/include/uk/thread.h index 71e39225..8cb3d6b6 100644 --- a/lib/uksched/include/uk/thread.h +++ b/lib/uksched/include/uk/thread.h @@ -50,6 +50,7 @@ struct uk_sched; struct uk_thread { const char *name; void *stack; + void *tls; void *ctx; UK_TAILQ_ENTRY(struct uk_thread) thread_list; uint32_t flags; @@ -106,7 +107,7 @@ struct uk_thread *uk_thread_current(void) int uk_thread_init(struct uk_thread *thread, struct ukplat_ctx_callbacks *cbs, struct uk_alloc *allocator, - const char *name, void *stack, + const char *name, void *stack, void *tls, void (*function)(void *), void *arg); void uk_thread_fini(struct uk_thread *thread, struct uk_alloc *allocator); diff --git a/lib/uksched/sched.c b/lib/uksched/sched.c index e0416736..c46db730 100644 --- a/lib/uksched/sched.c +++ b/lib/uksched/sched.c @@ -33,10 +33,12 @@ */ #include <stdlib.h> +#include <string.h> #include <uk/plat/config.h> #include <uk/plat/thread.h> #include <uk/alloc.h> #include <uk/sched.h> +#include <uk/arch/thread.h> #if CONFIG_LIBUKSCHEDCOOP #include <uk/schedcoop.h> #endif @@ -148,27 +150,42 @@ static void *create_stack(struct uk_alloc *allocator) return stack; } +static void *uk_thread_tls_create(struct uk_alloc *allocator) +{ + void *tls; + + if (uk_posix_memalign(allocator, &tls, + tls_area_align(), tls_area_size())) + return NULL; + tls_copy(tls); + return tls; +} + void uk_sched_idle_init(struct uk_sched *sched, void *stack, void (*function)(void *)) { struct uk_thread *idle; - int rc; + void *tls = NULL; UK_ASSERT(sched != NULL); - if (stack == NULL) - stack = create_stack(sched->allocator); - UK_ASSERT(stack != NULL); + if (!stack && !(stack = create_stack(sched->allocator))) + goto out_crash; + if (have_tls_area && !(tls = uk_thread_tls_create(sched->allocator))) + goto out_crash; idle = &sched->idle; - rc = uk_thread_init(idle, + if (uk_thread_init(idle, &sched->plat_ctx_cbs, sched->allocator, - "Idle", stack, function, NULL); - if (rc) - UK_CRASH("Error initializing idle thread."); + "Idle", stack, tls, function, NULL)) + goto out_crash; idle->sched = sched; + return; + +out_crash: + UK_CRASH("Error initializing the idle thread."); } struct uk_thread *uk_sched_thread_create(struct uk_sched *sched, @@ -177,7 +194,7 @@ struct uk_thread *uk_sched_thread_create(struct uk_sched *sched, { struct uk_thread *thread = NULL; void *stack = NULL; - int rc; + void *tls = NULL; thread = uk_malloc(sched->allocator, sizeof(struct uk_thread)); if (thread == NULL) { @@ -188,18 +205,17 @@ struct uk_thread *uk_sched_thread_create(struct uk_sched *sched, /* We can't use lazy allocation here * since the trap handler runs on the stack */ - stack = create_stack(sched->allocator); - if (stack == NULL) + if (!(stack = create_stack(sched->allocator))) + goto err; + if (have_tls_area && !(tls = uk_thread_tls_create(sched->allocator))) goto err; - rc = uk_thread_init(thread, + if (uk_thread_init(thread, &sched->plat_ctx_cbs, sched->allocator, - name, stack, function, arg); - if (rc) + name, stack, tls, function, arg)) goto err; - rc = uk_sched_thread_add(sched, thread, attr); - if (rc) + if (uk_sched_thread_add(sched, thread, attr)) goto err_add; return thread; @@ -207,6 +223,8 @@ struct uk_thread *uk_sched_thread_create(struct uk_sched *sched, err_add: uk_thread_fini(thread, sched->allocator); err: + if (tls) + uk_free(sched->allocator, tls); if (stack) uk_free(sched->allocator, stack); if (thread) @@ -219,11 +237,15 @@ void uk_sched_thread_destroy(struct uk_sched *sched, struct uk_thread *thread) { UK_ASSERT(sched != NULL); UK_ASSERT(thread != NULL); + UK_ASSERT(thread->stack != NULL); + UK_ASSERT(!have_tls_area || thread->tls != NULL); UK_ASSERT(is_exited(thread)); UK_TAILQ_REMOVE(&sched->exited_threads, thread, thread_list); uk_thread_fini(thread, sched->allocator); uk_pfree(sched->allocator, thread->stack, STACK_SIZE_PAGE_ORDER); + if (thread->tls) + uk_free(sched->allocator, thread->tls); uk_free(sched->allocator, thread); } diff --git a/lib/uksched/thread.c b/lib/uksched/thread.c index 7400baee..a97fad9e 100644 --- a/lib/uksched/thread.c +++ b/lib/uksched/thread.c @@ -88,13 +88,14 @@ struct _reent *__getreent(void) int uk_thread_init(struct uk_thread *thread, struct ukplat_ctx_callbacks *cbs, struct uk_alloc *allocator, - const char *name, void *stack, + const char *name, void *stack, void *tls, void (*function)(void *), void *arg) { unsigned long sp; UK_ASSERT(thread != NULL); UK_ASSERT(stack != NULL); + UK_ASSERT(!have_tls_area || tls != NULL); /* Save pointer to the thread on the stack to get current thread */ *((unsigned long *) stack) = (unsigned long) thread; @@ -108,6 +109,7 @@ int uk_thread_init(struct uk_thread *thread, thread->name = name; thread->stack = stack; + thread->tls = tls; /* Not runnable, not exited, not sleeping */ thread->flags = 0; @@ -121,8 +123,8 @@ int uk_thread_init(struct uk_thread *thread, reent_init(&thread->reent); #endif - uk_pr_info("Thread \"%s\": pointer: %p, stack: %p\n", - name, thread, thread->stack); + uk_pr_warn("Thread \"%s\": pointer: %p, stack: %p, tls: %p\n", + name, thread, thread->stack, thread->tls); return 0; } -- 2.21.0 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |