|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v2 5/6] 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>
---
lib/uksched/include/uk/sched.h | 3 +++
lib/uksched/include/uk/thread.h | 3 ++-
lib/uksched/sched.c | 35 ++++++++++++++++++++++++++++++---
lib/uksched/thread.c | 8 +++++---
4 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/lib/uksched/include/uk/sched.h b/lib/uksched/include/uk/sched.h
index f9dc16d0..5674cc96 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..a2505479 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/tls.h>
#if CONFIG_LIBUKSCHEDCOOP
#include <uk/schedcoop.h>
#endif
@@ -148,27 +150,45 @@ 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, ukarch_tls_area_align(),
+ ukarch_tls_area_size()))
+ return NULL;
+ ukarch_tls_area_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 (have_tls_area() && !(tls = uk_thread_tls_create(sched->allocator)))
+ goto out_crash;
idle = &sched->idle;
rc = uk_thread_init(idle,
&sched->plat_ctx_cbs, sched->allocator,
- "Idle", stack, function, NULL);
+ "Idle", stack, tls, function, NULL);
if (rc)
- UK_CRASH("Error initializing idle thread.");
+ 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,
@@ -178,6 +198,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) {
@@ -191,10 +212,12 @@ struct uk_thread *uk_sched_thread_create(struct uk_sched
*sched,
stack = create_stack(sched->allocator);
if (stack == NULL)
goto err;
+ if (have_tls_area() && !(tls = uk_thread_tls_create(sched->allocator)))
+ goto err;
rc = uk_thread_init(thread,
&sched->plat_ctx_cbs, sched->allocator,
- name, stack, function, arg);
+ name, stack, tls, function, arg);
if (rc)
goto err;
@@ -207,6 +230,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 +244,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..7d7ee016 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_info("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 |