summaryrefslogtreecommitdiff
path: root/kern/thread.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-07-30 17:58:09 +0200
committerRichard Braun <rbraun@sceen.net>2017-07-30 17:59:04 +0200
commitb9411198e3853793b4f9cf10af65587875f5f478 (patch)
tree95b5f451b5eb3375eb7e8051c9df6721adba7dbd /kern/thread.c
parent7dad3346fcbe327eb14aa2902e8cbc8bbe40b05d (diff)
kern/thread: replace the reaper with deferred works
Diffstat (limited to 'kern/thread.c')
-rw-r--r--kern/thread.c83
1 files changed, 13 insertions, 70 deletions
diff --git a/kern/thread.c b/kern/thread.c
index 8e5b2b52..29173d94 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -339,15 +339,8 @@ static unsigned int thread_nr_keys __read_mostly;
*/
static thread_dtor_fn_t thread_dtors[THREAD_KEYS_MAX] __read_mostly;
-/*
- * List of threads pending for destruction by the reaper.
- */
-static struct mutex thread_reap_lock;
-static struct condition thread_reap_cond;
-static struct list thread_reap_list;
-
struct thread_zombie {
- struct list node;
+ struct work work;
struct thread *thread;
};
@@ -2002,55 +1995,6 @@ thread_join_common(struct thread *thread)
}
static void
-thread_reap(void *arg)
-{
- struct thread_zombie *zombie;
- struct list zombies;
-
- (void)arg;
-
- for (;;) {
- mutex_lock(&thread_reap_lock);
-
- while (list_empty(&thread_reap_list)) {
- condition_wait(&thread_reap_cond, &thread_reap_lock);
- }
-
- list_set_head(&zombies, &thread_reap_list);
- list_init(&thread_reap_list);
-
- mutex_unlock(&thread_reap_lock);
-
- while (!list_empty(&zombies)) {
- zombie = list_first_entry(&zombies, struct thread_zombie, node);
- list_remove(&zombie->node);
- thread_join_common(zombie->thread);
- }
- }
-
- /* Never reached */
-}
-
-static void __init
-thread_setup_reaper(void)
-{
- struct thread_attr attr;
- struct thread *thread;
- int error;
-
- mutex_init(&thread_reap_lock);
- condition_init(&thread_reap_cond);
- list_init(&thread_reap_list);
-
- thread_attr_init(&attr, THREAD_KERNEL_PREFIX "thread_reap");
- error = thread_create(&thread, &attr, thread_reap, NULL);
-
- if (error) {
- panic("thread: unable to create reaper thread");
- }
-}
-
-static void
thread_balance_idle_tick(struct thread_runq *runq)
{
assert(runq->idle_balance_ticks != 0);
@@ -2333,8 +2277,6 @@ thread_setup(void)
CPU_DATA_ALIGN, NULL, 0);
#endif /* X15_THREAD_STACK_GUARD */
- thread_setup_reaper();
-
cpumap_for_each(&thread_active_runqs, cpu) {
thread_setup_runq(percpu_ptr(thread_runq, cpu));
}
@@ -2418,6 +2360,15 @@ error_thread:
return error;
}
+static void
+thread_reap(struct work *work)
+{
+ struct thread_zombie *zombie;
+
+ zombie = structof(work, struct thread_zombie, work);
+ thread_join_common(zombie->thread);
+}
+
void
thread_exit(void)
{
@@ -2431,25 +2382,17 @@ thread_exit(void)
if (thread_test_flag(thread, THREAD_DETACHED)) {
zombie.thread = thread;
- mutex_lock(&thread_reap_lock);
- list_insert_tail(&thread_reap_list, &zombie.node);
- condition_signal(&thread_reap_cond);
- mutex_unlock(&thread_reap_lock);
+ work_init(&zombie.work, thread_reap);
+ work_schedule(&zombie.work, 0);
}
mutex_lock(&thread->join_lock);
thread->exited = 1;
condition_signal(&thread->join_cond);
- /*
- * Disable preemption before releasing the mutex to make sure the current
- * thread becomes dead as soon as possible. This is important because the
- * joining thread actively polls the thread state before destroying it.
- */
- thread_preempt_disable();
-
mutex_unlock(&thread->join_lock);
+ thread_preempt_disable();
runq = thread_runq_local();
spinlock_lock_intr_save(&runq->lock, &flags);