aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c43
1 files changed, 17 insertions, 26 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 7f2683a10ac4..ceffc67b564a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -55,15 +55,14 @@
55#include <asm/unistd.h> 55#include <asm/unistd.h>
56#include <asm/pgtable.h> 56#include <asm/pgtable.h>
57#include <asm/mmu_context.h> 57#include <asm/mmu_context.h>
58#include "cred-internals.h"
59 58
60static void exit_mm(struct task_struct * tsk); 59static void exit_mm(struct task_struct * tsk);
61 60
62static void __unhash_process(struct task_struct *p) 61static void __unhash_process(struct task_struct *p, bool group_dead)
63{ 62{
64 nr_threads--; 63 nr_threads--;
65 detach_pid(p, PIDTYPE_PID); 64 detach_pid(p, PIDTYPE_PID);
66 if (thread_group_leader(p)) { 65 if (group_dead) {
67 detach_pid(p, PIDTYPE_PGID); 66 detach_pid(p, PIDTYPE_PGID);
68 detach_pid(p, PIDTYPE_SID); 67 detach_pid(p, PIDTYPE_SID);
69 68
@@ -80,10 +79,9 @@ static void __unhash_process(struct task_struct *p)
80static void __exit_signal(struct task_struct *tsk) 79static void __exit_signal(struct task_struct *tsk)
81{ 80{
82 struct signal_struct *sig = tsk->signal; 81 struct signal_struct *sig = tsk->signal;
82 bool group_dead = thread_group_leader(tsk);
83 struct sighand_struct *sighand; 83 struct sighand_struct *sighand;
84 84 struct tty_struct *uninitialized_var(tty);
85 BUG_ON(!sig);
86 BUG_ON(!atomic_read(&sig->count));
87 85
88 sighand = rcu_dereference_check(tsk->sighand, 86 sighand = rcu_dereference_check(tsk->sighand,
89 rcu_read_lock_held() || 87 rcu_read_lock_held() ||
@@ -91,14 +89,16 @@ static void __exit_signal(struct task_struct *tsk)
91 spin_lock(&sighand->siglock); 89 spin_lock(&sighand->siglock);
92 90
93 posix_cpu_timers_exit(tsk); 91 posix_cpu_timers_exit(tsk);
94 if (atomic_dec_and_test(&sig->count)) 92 if (group_dead) {
95 posix_cpu_timers_exit_group(tsk); 93 posix_cpu_timers_exit_group(tsk);
96 else { 94 tty = sig->tty;
95 sig->tty = NULL;
96 } else {
97 /* 97 /*
98 * If there is any task waiting for the group exit 98 * If there is any task waiting for the group exit
99 * then notify it: 99 * then notify it:
100 */ 100 */
101 if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) 101 if (sig->notify_count > 0 && !--sig->notify_count)
102 wake_up_process(sig->group_exit_task); 102 wake_up_process(sig->group_exit_task);
103 103
104 if (tsk == sig->curr_target) 104 if (tsk == sig->curr_target)
@@ -124,32 +124,24 @@ static void __exit_signal(struct task_struct *tsk)
124 sig->oublock += task_io_get_oublock(tsk); 124 sig->oublock += task_io_get_oublock(tsk);
125 task_io_accounting_add(&sig->ioac, &tsk->ioac); 125 task_io_accounting_add(&sig->ioac, &tsk->ioac);
126 sig->sum_sched_runtime += tsk->se.sum_exec_runtime; 126 sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
127 sig = NULL; /* Marker for below. */
128 } 127 }
129 128
130 __unhash_process(tsk); 129 sig->nr_threads--;
130 __unhash_process(tsk, group_dead);
131 131
132 /* 132 /*
133 * Do this under ->siglock, we can race with another thread 133 * Do this under ->siglock, we can race with another thread
134 * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals. 134 * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
135 */ 135 */
136 flush_sigqueue(&tsk->pending); 136 flush_sigqueue(&tsk->pending);
137
138 tsk->signal = NULL;
139 tsk->sighand = NULL; 137 tsk->sighand = NULL;
140 spin_unlock(&sighand->siglock); 138 spin_unlock(&sighand->siglock);
141 139
142 __cleanup_sighand(sighand); 140 __cleanup_sighand(sighand);
143 clear_tsk_thread_flag(tsk,TIF_SIGPENDING); 141 clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
144 if (sig) { 142 if (group_dead) {
145 flush_sigqueue(&sig->shared_pending); 143 flush_sigqueue(&sig->shared_pending);
146 taskstats_tgid_free(sig); 144 tty_kref_put(tty);
147 /*
148 * Make sure ->signal can't go away under rq->lock,
149 * see account_group_exec_runtime().
150 */
151 task_rq_unlock_wait(tsk);
152 __cleanup_signal(sig);
153 } 145 }
154} 146}
155 147
@@ -857,12 +849,9 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
857 849
858 tsk->exit_state = signal == DEATH_REAP ? EXIT_DEAD : EXIT_ZOMBIE; 850 tsk->exit_state = signal == DEATH_REAP ? EXIT_DEAD : EXIT_ZOMBIE;
859 851
860 /* mt-exec, de_thread() is waiting for us */ 852 /* mt-exec, de_thread() is waiting for group leader */
861 if (thread_group_leader(tsk) && 853 if (unlikely(tsk->signal->notify_count < 0))
862 tsk->signal->group_exit_task &&
863 tsk->signal->notify_count < 0)
864 wake_up_process(tsk->signal->group_exit_task); 854 wake_up_process(tsk->signal->group_exit_task);
865
866 write_unlock_irq(&tasklist_lock); 855 write_unlock_irq(&tasklist_lock);
867 856
868 tracehook_report_death(tsk, signal, cookie, group_dead); 857 tracehook_report_death(tsk, signal, cookie, group_dead);
@@ -1003,8 +992,10 @@ NORET_TYPE void do_exit(long code)
1003 992
1004 exit_notify(tsk, group_dead); 993 exit_notify(tsk, group_dead);
1005#ifdef CONFIG_NUMA 994#ifdef CONFIG_NUMA
995 task_lock(tsk);
1006 mpol_put(tsk->mempolicy); 996 mpol_put(tsk->mempolicy);
1007 tsk->mempolicy = NULL; 997 tsk->mempolicy = NULL;
998 task_unlock(tsk);
1008#endif 999#endif
1009#ifdef CONFIG_FUTEX 1000#ifdef CONFIG_FUTEX
1010 if (unlikely(current->pi_state_cache)) 1001 if (unlikely(current->pi_state_cache))