aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-03-29 19:58:22 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-29 19:58:22 -0500
commit79072f38909e3d9883317238887460c39ddcc4cb (patch)
tree28369f5a844535ff836565eefd62695b0e890fa3 /kernel/exit.c
parent200d5a7684cc49ef4be40e832daf3f217e70dfbb (diff)
parent55d8ca4f8094246da6e71889a4e04bfafaa78b10 (diff)
Merge branch 'upstream'
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c141
1 files changed, 92 insertions, 49 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index d1e8d500a7e1..bc0ec674d3f4 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -29,8 +29,11 @@
29#include <linux/cpuset.h> 29#include <linux/cpuset.h>
30#include <linux/syscalls.h> 30#include <linux/syscalls.h>
31#include <linux/signal.h> 31#include <linux/signal.h>
32#include <linux/posix-timers.h>
32#include <linux/cn_proc.h> 33#include <linux/cn_proc.h>
33#include <linux/mutex.h> 34#include <linux/mutex.h>
35#include <linux/futex.h>
36#include <linux/compat.h>
34 37
35#include <asm/uaccess.h> 38#include <asm/uaccess.h>
36#include <asm/unistd.h> 39#include <asm/unistd.h>
@@ -48,15 +51,80 @@ static void __unhash_process(struct task_struct *p)
48{ 51{
49 nr_threads--; 52 nr_threads--;
50 detach_pid(p, PIDTYPE_PID); 53 detach_pid(p, PIDTYPE_PID);
51 detach_pid(p, PIDTYPE_TGID);
52 if (thread_group_leader(p)) { 54 if (thread_group_leader(p)) {
53 detach_pid(p, PIDTYPE_PGID); 55 detach_pid(p, PIDTYPE_PGID);
54 detach_pid(p, PIDTYPE_SID); 56 detach_pid(p, PIDTYPE_SID);
55 if (p->pid) 57
56 __get_cpu_var(process_counts)--; 58 list_del_init(&p->tasks);
59 __get_cpu_var(process_counts)--;
57 } 60 }
61 list_del_rcu(&p->thread_group);
62 remove_parent(p);
63}
58 64
59 REMOVE_LINKS(p); 65/*
66 * This function expects the tasklist_lock write-locked.
67 */
68static void __exit_signal(struct task_struct *tsk)
69{
70 struct signal_struct *sig = tsk->signal;
71 struct sighand_struct *sighand;
72
73 BUG_ON(!sig);
74 BUG_ON(!atomic_read(&sig->count));
75
76 rcu_read_lock();
77 sighand = rcu_dereference(tsk->sighand);
78 spin_lock(&sighand->siglock);
79
80 posix_cpu_timers_exit(tsk);
81 if (atomic_dec_and_test(&sig->count))
82 posix_cpu_timers_exit_group(tsk);
83 else {
84 /*
85 * If there is any task waiting for the group exit
86 * then notify it:
87 */
88 if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
89 wake_up_process(sig->group_exit_task);
90 sig->group_exit_task = NULL;
91 }
92 if (tsk == sig->curr_target)
93 sig->curr_target = next_thread(tsk);
94 /*
95 * Accumulate here the counters for all threads but the
96 * group leader as they die, so they can be added into
97 * the process-wide totals when those are taken.
98 * The group leader stays around as a zombie as long
99 * as there are other threads. When it gets reaped,
100 * the exit.c code will add its counts into these totals.
101 * We won't ever get here for the group leader, since it
102 * will have been the last reference on the signal_struct.
103 */
104 sig->utime = cputime_add(sig->utime, tsk->utime);
105 sig->stime = cputime_add(sig->stime, tsk->stime);
106 sig->min_flt += tsk->min_flt;
107 sig->maj_flt += tsk->maj_flt;
108 sig->nvcsw += tsk->nvcsw;
109 sig->nivcsw += tsk->nivcsw;
110 sig->sched_time += tsk->sched_time;
111 sig = NULL; /* Marker for below. */
112 }
113
114 __unhash_process(tsk);
115
116 tsk->signal = NULL;
117 tsk->sighand = NULL;
118 spin_unlock(&sighand->siglock);
119 rcu_read_unlock();
120
121 __cleanup_sighand(sighand);
122 clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
123 flush_sigqueue(&tsk->pending);
124 if (sig) {
125 flush_sigqueue(&sig->shared_pending);
126 __cleanup_signal(sig);
127 }
60} 128}
61 129
62void release_task(struct task_struct * p) 130void release_task(struct task_struct * p)
@@ -65,21 +133,14 @@ void release_task(struct task_struct * p)
65 task_t *leader; 133 task_t *leader;
66 struct dentry *proc_dentry; 134 struct dentry *proc_dentry;
67 135
68repeat: 136repeat:
69 atomic_dec(&p->user->processes); 137 atomic_dec(&p->user->processes);
70 spin_lock(&p->proc_lock); 138 spin_lock(&p->proc_lock);
71 proc_dentry = proc_pid_unhash(p); 139 proc_dentry = proc_pid_unhash(p);
72 write_lock_irq(&tasklist_lock); 140 write_lock_irq(&tasklist_lock);
73 if (unlikely(p->ptrace)) 141 ptrace_unlink(p);
74 __ptrace_unlink(p);
75 BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children)); 142 BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
76 __exit_signal(p); 143 __exit_signal(p);
77 /*
78 * Note that the fastpath in sys_times depends on __exit_signal having
79 * updated the counters before a task is removed from the tasklist of
80 * the process by __unhash_process.
81 */
82 __unhash_process(p);
83 144
84 /* 145 /*
85 * If we are the last non-leader member of the thread 146 * If we are the last non-leader member of the thread
@@ -114,21 +175,6 @@ repeat:
114 goto repeat; 175 goto repeat;
115} 176}
116 177
117/* we are using it only for SMP init */
118
119void unhash_process(struct task_struct *p)
120{
121 struct dentry *proc_dentry;
122
123 spin_lock(&p->proc_lock);
124 proc_dentry = proc_pid_unhash(p);
125 write_lock_irq(&tasklist_lock);
126 __unhash_process(p);
127 write_unlock_irq(&tasklist_lock);
128 spin_unlock(&p->proc_lock);
129 proc_pid_flush(proc_dentry);
130}
131
132/* 178/*
133 * This checks not only the pgrp, but falls back on the pid if no 179 * This checks not only the pgrp, but falls back on the pid if no
134 * satisfactory pgrp is found. I dunno - gdb doesn't work correctly 180 * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
@@ -236,10 +282,10 @@ static void reparent_to_init(void)
236 282
237 ptrace_unlink(current); 283 ptrace_unlink(current);
238 /* Reparent to init */ 284 /* Reparent to init */
239 REMOVE_LINKS(current); 285 remove_parent(current);
240 current->parent = child_reaper; 286 current->parent = child_reaper;
241 current->real_parent = child_reaper; 287 current->real_parent = child_reaper;
242 SET_LINKS(current); 288 add_parent(current);
243 289
244 /* Set the exit signal to SIGCHLD so we signal init on exit */ 290 /* Set the exit signal to SIGCHLD so we signal init on exit */
245 current->exit_signal = SIGCHLD; 291 current->exit_signal = SIGCHLD;
@@ -345,9 +391,9 @@ void daemonize(const char *name, ...)
345 exit_mm(current); 391 exit_mm(current);
346 392
347 set_special_pids(1, 1); 393 set_special_pids(1, 1);
348 down(&tty_sem); 394 mutex_lock(&tty_mutex);
349 current->signal->tty = NULL; 395 current->signal->tty = NULL;
350 up(&tty_sem); 396 mutex_unlock(&tty_mutex);
351 397
352 /* Block and flush all signals */ 398 /* Block and flush all signals */
353 sigfillset(&blocked); 399 sigfillset(&blocked);
@@ -536,13 +582,13 @@ static void exit_mm(struct task_struct * tsk)
536 mmput(mm); 582 mmput(mm);
537} 583}
538 584
539static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_reaper) 585static inline void choose_new_parent(task_t *p, task_t *reaper)
540{ 586{
541 /* 587 /*
542 * Make sure we're not reparenting to ourselves and that 588 * Make sure we're not reparenting to ourselves and that
543 * the parent is not a zombie. 589 * the parent is not a zombie.
544 */ 590 */
545 BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE); 591 BUG_ON(p == reaper || reaper->exit_state);
546 p->real_parent = reaper; 592 p->real_parent = reaper;
547} 593}
548 594
@@ -567,9 +613,9 @@ static void reparent_thread(task_t *p, task_t *father, int traced)
567 * anyway, so let go of it. 613 * anyway, so let go of it.
568 */ 614 */
569 p->ptrace = 0; 615 p->ptrace = 0;
570 list_del_init(&p->sibling); 616 remove_parent(p);
571 p->parent = p->real_parent; 617 p->parent = p->real_parent;
572 list_add_tail(&p->sibling, &p->parent->children); 618 add_parent(p);
573 619
574 /* If we'd notified the old parent about this child's death, 620 /* If we'd notified the old parent about this child's death,
575 * also notify the new parent. 621 * also notify the new parent.
@@ -643,7 +689,7 @@ static void forget_original_parent(struct task_struct * father,
643 689
644 if (father == p->real_parent) { 690 if (father == p->real_parent) {
645 /* reparent with a reaper, real father it's us */ 691 /* reparent with a reaper, real father it's us */
646 choose_new_parent(p, reaper, child_reaper); 692 choose_new_parent(p, reaper);
647 reparent_thread(p, father, 0); 693 reparent_thread(p, father, 0);
648 } else { 694 } else {
649 /* reparent ptraced task to its real parent */ 695 /* reparent ptraced task to its real parent */
@@ -664,7 +710,7 @@ static void forget_original_parent(struct task_struct * father,
664 } 710 }
665 list_for_each_safe(_p, _n, &father->ptrace_children) { 711 list_for_each_safe(_p, _n, &father->ptrace_children) {
666 p = list_entry(_p,struct task_struct,ptrace_list); 712 p = list_entry(_p,struct task_struct,ptrace_list);
667 choose_new_parent(p, reaper, child_reaper); 713 choose_new_parent(p, reaper);
668 reparent_thread(p, father, 1); 714 reparent_thread(p, father, 1);
669 } 715 }
670} 716}
@@ -805,7 +851,7 @@ fastcall NORET_TYPE void do_exit(long code)
805 panic("Aiee, killing interrupt handler!"); 851 panic("Aiee, killing interrupt handler!");
806 if (unlikely(!tsk->pid)) 852 if (unlikely(!tsk->pid))
807 panic("Attempted to kill the idle task!"); 853 panic("Attempted to kill the idle task!");
808 if (unlikely(tsk->pid == 1)) 854 if (unlikely(tsk == child_reaper))
809 panic("Attempted to kill init!"); 855 panic("Attempted to kill init!");
810 856
811 if (unlikely(current->ptrace & PT_TRACE_EXIT)) { 857 if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
@@ -852,6 +898,12 @@ fastcall NORET_TYPE void do_exit(long code)
852 exit_itimers(tsk->signal); 898 exit_itimers(tsk->signal);
853 acct_process(code); 899 acct_process(code);
854 } 900 }
901 if (unlikely(tsk->robust_list))
902 exit_robust_list(tsk);
903#ifdef CONFIG_COMPAT
904 if (unlikely(tsk->compat_robust_list))
905 compat_exit_robust_list(tsk);
906#endif
855 exit_mm(tsk); 907 exit_mm(tsk);
856 908
857 exit_sem(tsk); 909 exit_sem(tsk);
@@ -912,13 +964,6 @@ asmlinkage long sys_exit(int error_code)
912 do_exit((error_code&0xff)<<8); 964 do_exit((error_code&0xff)<<8);
913} 965}
914 966
915task_t fastcall *next_thread(const task_t *p)
916{
917 return pid_task(p->pids[PIDTYPE_TGID].pid_list.next, PIDTYPE_TGID);
918}
919
920EXPORT_SYMBOL(next_thread);
921
922/* 967/*
923 * Take down every thread in the group. This is called by fatal signals 968 * Take down every thread in the group. This is called by fatal signals
924 * as well as by sys_exit_group (below). 969 * as well as by sys_exit_group (below).
@@ -933,7 +978,6 @@ do_group_exit(int exit_code)
933 else if (!thread_group_empty(current)) { 978 else if (!thread_group_empty(current)) {
934 struct signal_struct *const sig = current->signal; 979 struct signal_struct *const sig = current->signal;
935 struct sighand_struct *const sighand = current->sighand; 980 struct sighand_struct *const sighand = current->sighand;
936 read_lock(&tasklist_lock);
937 spin_lock_irq(&sighand->siglock); 981 spin_lock_irq(&sighand->siglock);
938 if (sig->flags & SIGNAL_GROUP_EXIT) 982 if (sig->flags & SIGNAL_GROUP_EXIT)
939 /* Another thread got here before we took the lock. */ 983 /* Another thread got here before we took the lock. */
@@ -943,7 +987,6 @@ do_group_exit(int exit_code)
943 zap_other_threads(current); 987 zap_other_threads(current);
944 } 988 }
945 spin_unlock_irq(&sighand->siglock); 989 spin_unlock_irq(&sighand->siglock);
946 read_unlock(&tasklist_lock);
947 } 990 }
948 991
949 do_exit(exit_code); 992 do_exit(exit_code);
@@ -1273,7 +1316,7 @@ bail_ref:
1273 1316
1274 /* move to end of parent's list to avoid starvation */ 1317 /* move to end of parent's list to avoid starvation */
1275 remove_parent(p); 1318 remove_parent(p);
1276 add_parent(p, p->parent); 1319 add_parent(p);
1277 1320
1278 write_unlock_irq(&tasklist_lock); 1321 write_unlock_irq(&tasklist_lock);
1279 1322