diff options
author | Richard Braun <rbraun@sceen.net> | 2014-05-06 20:49:26 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2014-05-06 20:49:26 +0200 |
commit | b11e4e9411cb0a4e99c370a4ff9a275540036aae (patch) | |
tree | 72064536d69b40727b1309f78da341b456a3c8f5 /kern/thread.c | |
parent | edae23a2cd2800dff9806309854fb46f12d408d7 (diff) |
x86/tcb: make tcb_init initialize thread-local data
For now, there is no thread-local data to actually initialize, but the
interface is there to allow it. The main goal of this change is to avoid
the need of complex startup synchronization by allocating thread-local
data at thread creation time.
Diffstat (limited to 'kern/thread.c')
-rw-r--r-- | kern/thread.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/kern/thread.c b/kern/thread.c index ef340054..b66d7303 100644 --- a/kern/thread.c +++ b/kern/thread.c @@ -1421,13 +1421,14 @@ thread_init_sched(struct thread *thread, unsigned short priority) thread_sched_ops[thread->sched_class].init_thread(thread, priority); } -static void +static int thread_init(struct thread *thread, void *stack, const struct thread_attr *attr, void (*fn)(void *), void *arg) { struct thread *caller; struct task *task; struct cpumap *cpumap; + int error; caller = thread_self(); @@ -1445,7 +1446,6 @@ thread_init(struct thread *thread, void *stack, const struct thread_attr *attr, * Locking the run queue increases the preemption counter once more, * making its value 2. */ - tcb_init(&thread->tcb, stack, thread_main); thread->flags = 0; thread->runq = NULL; thread->state = THREAD_SLEEPING; @@ -1462,7 +1462,18 @@ thread_init(struct thread *thread, void *stack, const struct thread_attr *attr, thread->fn = fn; thread->arg = arg; + /* + * This call may initialize thread-local data, do it once the thread is + * mostly initialized. + */ + error = tcb_init(&thread->tcb, stack, thread_main); + + if (error) + return error; + task_add_thread(task, thread); + + return 0; } static struct thread_runq * @@ -1712,7 +1723,11 @@ thread_setup_idler(struct thread_runq *runq) thread_attr_init(&attr, name); thread_attr_set_cpumap(&attr, cpumap); thread_attr_set_policy(&attr, THREAD_SCHED_POLICY_IDLE); - thread_init(idler, stack, &attr, thread_idle, runq); + error = thread_init(idler, stack, &attr, thread_idle, runq); + + if (error) + panic("thread: unable to initialize idler thread"); + cpumap_destroy(cpumap); /* An idler thread needs special tuning */ @@ -1777,7 +1792,10 @@ thread_create(struct thread **threadp, const struct thread_attr *attr, goto error_stack; } - thread_init(thread, stack, attr, fn, arg); + error = thread_init(thread, stack, attr, fn, arg); + + if (error) + goto error_init; /* * The new thread address must be written before the thread is started @@ -1789,6 +1807,8 @@ thread_create(struct thread **threadp, const struct thread_attr *attr, return 0; +error_init: + kmem_cache_free(&thread_stack_cache, stack); error_stack: kmem_cache_free(&thread_cache, thread); error_thread: |