summaryrefslogtreecommitdiff
path: root/kern/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'kern/thread.c')
-rw-r--r--kern/thread.c28
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: