From f63b060f455d99c3b046881803497f39c62fd3b0 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 25 Jul 2008 01:47:44 -0700 Subject: [PATCH] --- yaml --- r: 105941 b: refs/heads/master c: b564daf806d492dd4f7afe9b6c83b8d35d137669 h: refs/heads/master i: 105939: c2ea9cc879a968f1fd7979d2562e3e44fb1de445 v: v3 --- [refs] | 2 +- trunk/fs/exec.c | 2 ++ trunk/include/linux/mm_types.h | 6 ++++++ trunk/kernel/exit.c | 15 ++++++++++++--- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 3791ff347a7c..9b2e68e679c2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9d5b327bf198d2720666de958dcc2ae219d86952 +refs/heads/master: b564daf806d492dd4f7afe9b6c83b8d35d137669 diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index b8ee842d93cd..fe2873b8037f 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -1604,6 +1604,8 @@ static int coredump_wait(int exit_code, struct core_state *core_state) init_completion(&mm->core_done); init_completion(&core_state->startup); + core_state->dumper.task = tsk; + core_state->dumper.next = NULL; core_waiters = zap_threads(tsk, mm, core_state, exit_code); up_write(&mm->mmap_sem); diff --git a/trunk/include/linux/mm_types.h b/trunk/include/linux/mm_types.h index ae99a28ba6ae..4d0d0abc79fe 100644 --- a/trunk/include/linux/mm_types.h +++ b/trunk/include/linux/mm_types.h @@ -159,8 +159,14 @@ struct vm_area_struct { #endif }; +struct core_thread { + struct task_struct *task; + struct core_thread *next; +}; + struct core_state { atomic_t nr_threads; + struct core_thread dumper; struct completion startup; }; diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 63d82957baae..b66f0d55c791 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -664,6 +664,7 @@ void mm_update_next_owner(struct mm_struct *mm) static void exit_mm(struct task_struct * tsk) { struct mm_struct *mm = tsk->mm; + struct core_state *core_state; mm_release(tsk, mm); if (!mm) @@ -676,11 +677,19 @@ static void exit_mm(struct task_struct * tsk) * group with ->mm != NULL. */ down_read(&mm->mmap_sem); - if (mm->core_state) { + core_state = mm->core_state; + if (core_state) { + struct core_thread self; up_read(&mm->mmap_sem); - if (atomic_dec_and_test(&mm->core_state->nr_threads)) - complete(&mm->core_state->startup); + self.task = tsk; + self.next = xchg(&core_state->dumper.next, &self); + /* + * Implies mb(), the result of xchg() must be visible + * to core_state->dumper. + */ + if (atomic_dec_and_test(&core_state->nr_threads)) + complete(&core_state->startup); wait_for_completion(&mm->core_done); down_read(&mm->mmap_sem);