diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index ee515683b92d..93cee3671332 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> |
11 | #include <linux/smp_lock.h> | 11 | #include <linux/smp_lock.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/capability.h> | ||
13 | #include <linux/completion.h> | 14 | #include <linux/completion.h> |
14 | #include <linux/personality.h> | 15 | #include <linux/personality.h> |
15 | #include <linux/tty.h> | 16 | #include <linux/tty.h> |
@@ -29,6 +30,7 @@ | |||
29 | #include <linux/syscalls.h> | 30 | #include <linux/syscalls.h> |
30 | #include <linux/signal.h> | 31 | #include <linux/signal.h> |
31 | #include <linux/cn_proc.h> | 32 | #include <linux/cn_proc.h> |
33 | #include <linux/mutex.h> | ||
32 | 34 | ||
33 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
34 | #include <asm/unistd.h> | 36 | #include <asm/unistd.h> |
@@ -72,7 +74,6 @@ repeat: | |||
72 | __ptrace_unlink(p); | 74 | __ptrace_unlink(p); |
73 | BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children)); | 75 | BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children)); |
74 | __exit_signal(p); | 76 | __exit_signal(p); |
75 | __exit_sighand(p); | ||
76 | /* | 77 | /* |
77 | * Note that the fastpath in sys_times depends on __exit_signal having | 78 | * Note that the fastpath in sys_times depends on __exit_signal having |
78 | * updated the counters before a task is removed from the tasklist of | 79 | * updated the counters before a task is removed from the tasklist of |
@@ -192,7 +193,7 @@ int is_orphaned_pgrp(int pgrp) | |||
192 | return retval; | 193 | return retval; |
193 | } | 194 | } |
194 | 195 | ||
195 | static inline int has_stopped_jobs(int pgrp) | 196 | static int has_stopped_jobs(int pgrp) |
196 | { | 197 | { |
197 | int retval = 0; | 198 | int retval = 0; |
198 | struct task_struct *p; | 199 | struct task_struct *p; |
@@ -229,7 +230,7 @@ static inline int has_stopped_jobs(int pgrp) | |||
229 | * | 230 | * |
230 | * NOTE that reparent_to_init() gives the caller full capabilities. | 231 | * NOTE that reparent_to_init() gives the caller full capabilities. |
231 | */ | 232 | */ |
232 | static inline void reparent_to_init(void) | 233 | static void reparent_to_init(void) |
233 | { | 234 | { |
234 | write_lock_irq(&tasklist_lock); | 235 | write_lock_irq(&tasklist_lock); |
235 | 236 | ||
@@ -243,7 +244,9 @@ static inline void reparent_to_init(void) | |||
243 | /* Set the exit signal to SIGCHLD so we signal init on exit */ | 244 | /* Set the exit signal to SIGCHLD so we signal init on exit */ |
244 | current->exit_signal = SIGCHLD; | 245 | current->exit_signal = SIGCHLD; |
245 | 246 | ||
246 | if ((current->policy == SCHED_NORMAL) && (task_nice(current) < 0)) | 247 | if ((current->policy == SCHED_NORMAL || |
248 | current->policy == SCHED_BATCH) | ||
249 | && (task_nice(current) < 0)) | ||
247 | set_user_nice(current, 0); | 250 | set_user_nice(current, 0); |
248 | /* cpus_allowed? */ | 251 | /* cpus_allowed? */ |
249 | /* rt_priority? */ | 252 | /* rt_priority? */ |
@@ -258,7 +261,7 @@ static inline void reparent_to_init(void) | |||
258 | 261 | ||
259 | void __set_special_pids(pid_t session, pid_t pgrp) | 262 | void __set_special_pids(pid_t session, pid_t pgrp) |
260 | { | 263 | { |
261 | struct task_struct *curr = current; | 264 | struct task_struct *curr = current->group_leader; |
262 | 265 | ||
263 | if (curr->signal->session != session) { | 266 | if (curr->signal->session != session) { |
264 | detach_pid(curr, PIDTYPE_SID); | 267 | detach_pid(curr, PIDTYPE_SID); |
@@ -366,7 +369,7 @@ void daemonize(const char *name, ...) | |||
366 | 369 | ||
367 | EXPORT_SYMBOL(daemonize); | 370 | EXPORT_SYMBOL(daemonize); |
368 | 371 | ||
369 | static inline void close_files(struct files_struct * files) | 372 | static void close_files(struct files_struct * files) |
370 | { | 373 | { |
371 | int i, j; | 374 | int i, j; |
372 | struct fdtable *fdt; | 375 | struct fdtable *fdt; |
@@ -540,7 +543,7 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re | |||
540 | p->real_parent = reaper; | 543 | p->real_parent = reaper; |
541 | } | 544 | } |
542 | 545 | ||
543 | static inline void reparent_thread(task_t *p, task_t *father, int traced) | 546 | static void reparent_thread(task_t *p, task_t *father, int traced) |
544 | { | 547 | { |
545 | /* We don't want people slaying init. */ | 548 | /* We don't want people slaying init. */ |
546 | if (p->exit_signal != -1) | 549 | if (p->exit_signal != -1) |
@@ -604,7 +607,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) | |||
604 | * group, and if no such member exists, give it to | 607 | * group, and if no such member exists, give it to |
605 | * the global child reaper process (ie "init") | 608 | * the global child reaper process (ie "init") |
606 | */ | 609 | */ |
607 | static inline void forget_original_parent(struct task_struct * father, | 610 | static void forget_original_parent(struct task_struct * father, |
608 | struct list_head *to_release) | 611 | struct list_head *to_release) |
609 | { | 612 | { |
610 | struct task_struct *p, *reaper = father; | 613 | struct task_struct *p, *reaper = father; |
@@ -842,7 +845,7 @@ fastcall NORET_TYPE void do_exit(long code) | |||
842 | } | 845 | } |
843 | group_dead = atomic_dec_and_test(&tsk->signal->live); | 846 | group_dead = atomic_dec_and_test(&tsk->signal->live); |
844 | if (group_dead) { | 847 | if (group_dead) { |
845 | del_timer_sync(&tsk->signal->real_timer); | 848 | hrtimer_cancel(&tsk->signal->real_timer); |
846 | exit_itimers(tsk->signal); | 849 | exit_itimers(tsk->signal); |
847 | acct_process(code); | 850 | acct_process(code); |
848 | } | 851 | } |
@@ -870,6 +873,10 @@ fastcall NORET_TYPE void do_exit(long code) | |||
870 | mpol_free(tsk->mempolicy); | 873 | mpol_free(tsk->mempolicy); |
871 | tsk->mempolicy = NULL; | 874 | tsk->mempolicy = NULL; |
872 | #endif | 875 | #endif |
876 | /* | ||
877 | * If DEBUG_MUTEXES is on, make sure we are holding no locks: | ||
878 | */ | ||
879 | mutex_debug_check_no_locks_held(tsk); | ||
873 | 880 | ||
874 | /* PF_DEAD causes final put_task_struct after we schedule. */ | 881 | /* PF_DEAD causes final put_task_struct after we schedule. */ |
875 | preempt_disable(); | 882 | preempt_disable(); |
@@ -926,7 +933,6 @@ do_group_exit(int exit_code) | |||
926 | /* Another thread got here before we took the lock. */ | 933 | /* Another thread got here before we took the lock. */ |
927 | exit_code = sig->group_exit_code; | 934 | exit_code = sig->group_exit_code; |
928 | else { | 935 | else { |
929 | sig->flags = SIGNAL_GROUP_EXIT; | ||
930 | sig->group_exit_code = exit_code; | 936 | sig->group_exit_code = exit_code; |
931 | zap_other_threads(current); | 937 | zap_other_threads(current); |
932 | } | 938 | } |
@@ -1068,6 +1074,9 @@ static int wait_task_zombie(task_t *p, int noreap, | |||
1068 | } | 1074 | } |
1069 | 1075 | ||
1070 | if (likely(p->real_parent == p->parent) && likely(p->signal)) { | 1076 | if (likely(p->real_parent == p->parent) && likely(p->signal)) { |
1077 | struct signal_struct *psig; | ||
1078 | struct signal_struct *sig; | ||
1079 | |||
1071 | /* | 1080 | /* |
1072 | * The resource counters for the group leader are in its | 1081 | * The resource counters for the group leader are in its |
1073 | * own task_struct. Those for dead threads in the group | 1082 | * own task_struct. Those for dead threads in the group |
@@ -1084,24 +1093,26 @@ static int wait_task_zombie(task_t *p, int noreap, | |||
1084 | * here reaping other children at the same time. | 1093 | * here reaping other children at the same time. |
1085 | */ | 1094 | */ |
1086 | spin_lock_irq(&p->parent->sighand->siglock); | 1095 | spin_lock_irq(&p->parent->sighand->siglock); |
1087 | p->parent->signal->cutime = | 1096 | psig = p->parent->signal; |
1088 | cputime_add(p->parent->signal->cutime, | 1097 | sig = p->signal; |
1098 | psig->cutime = | ||
1099 | cputime_add(psig->cutime, | ||
1089 | cputime_add(p->utime, | 1100 | cputime_add(p->utime, |
1090 | cputime_add(p->signal->utime, | 1101 | cputime_add(sig->utime, |
1091 | p->signal->cutime))); | 1102 | sig->cutime))); |
1092 | p->parent->signal->cstime = | 1103 | psig->cstime = |
1093 | cputime_add(p->parent->signal->cstime, | 1104 | cputime_add(psig->cstime, |
1094 | cputime_add(p->stime, | 1105 | cputime_add(p->stime, |
1095 | cputime_add(p->signal->stime, | 1106 | cputime_add(sig->stime, |
1096 | p->signal->cstime))); | 1107 | sig->cstime))); |
1097 | p->parent->signal->cmin_flt += | 1108 | psig->cmin_flt += |
1098 | p->min_flt + p->signal->min_flt + p->signal->cmin_flt; | 1109 | p->min_flt + sig->min_flt + sig->cmin_flt; |
1099 | p->parent->signal->cmaj_flt += | 1110 | psig->cmaj_flt += |
1100 | p->maj_flt + p->signal->maj_flt + p->signal->cmaj_flt; | 1111 | p->maj_flt + sig->maj_flt + sig->cmaj_flt; |
1101 | p->parent->signal->cnvcsw += | 1112 | psig->cnvcsw += |
1102 | p->nvcsw + p->signal->nvcsw + p->signal->cnvcsw; | 1113 | p->nvcsw + sig->nvcsw + sig->cnvcsw; |
1103 | p->parent->signal->cnivcsw += | 1114 | psig->cnivcsw += |
1104 | p->nivcsw + p->signal->nivcsw + p->signal->cnivcsw; | 1115 | p->nivcsw + sig->nivcsw + sig->cnivcsw; |
1105 | spin_unlock_irq(&p->parent->sighand->siglock); | 1116 | spin_unlock_irq(&p->parent->sighand->siglock); |
1106 | } | 1117 | } |
1107 | 1118 | ||