diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index e61891f80123..546774a31a66 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/init_task.h> | 49 | #include <linux/init_task.h> |
50 | #include <linux/perf_event.h> | 50 | #include <linux/perf_event.h> |
51 | #include <trace/events/sched.h> | 51 | #include <trace/events/sched.h> |
52 | #include <linux/hw_breakpoint.h> | ||
52 | 53 | ||
53 | #include <asm/uaccess.h> | 54 | #include <asm/uaccess.h> |
54 | #include <asm/unistd.h> | 55 | #include <asm/unistd.h> |
@@ -67,10 +68,10 @@ static void __unhash_process(struct task_struct *p) | |||
67 | detach_pid(p, PIDTYPE_SID); | 68 | detach_pid(p, PIDTYPE_SID); |
68 | 69 | ||
69 | list_del_rcu(&p->tasks); | 70 | list_del_rcu(&p->tasks); |
71 | list_del_init(&p->sibling); | ||
70 | __get_cpu_var(process_counts)--; | 72 | __get_cpu_var(process_counts)--; |
71 | } | 73 | } |
72 | list_del_rcu(&p->thread_group); | 74 | list_del_rcu(&p->thread_group); |
73 | list_del_init(&p->sibling); | ||
74 | } | 75 | } |
75 | 76 | ||
76 | /* | 77 | /* |
@@ -110,9 +111,9 @@ static void __exit_signal(struct task_struct *tsk) | |||
110 | * We won't ever get here for the group leader, since it | 111 | * We won't ever get here for the group leader, since it |
111 | * will have been the last reference on the signal_struct. | 112 | * will have been the last reference on the signal_struct. |
112 | */ | 113 | */ |
113 | sig->utime = cputime_add(sig->utime, task_utime(tsk)); | 114 | sig->utime = cputime_add(sig->utime, tsk->utime); |
114 | sig->stime = cputime_add(sig->stime, task_stime(tsk)); | 115 | sig->stime = cputime_add(sig->stime, tsk->stime); |
115 | sig->gtime = cputime_add(sig->gtime, task_gtime(tsk)); | 116 | sig->gtime = cputime_add(sig->gtime, tsk->gtime); |
116 | sig->min_flt += tsk->min_flt; | 117 | sig->min_flt += tsk->min_flt; |
117 | sig->maj_flt += tsk->maj_flt; | 118 | sig->maj_flt += tsk->maj_flt; |
118 | sig->nvcsw += tsk->nvcsw; | 119 | sig->nvcsw += tsk->nvcsw; |
@@ -359,10 +360,8 @@ void __set_special_pids(struct pid *pid) | |||
359 | { | 360 | { |
360 | struct task_struct *curr = current->group_leader; | 361 | struct task_struct *curr = current->group_leader; |
361 | 362 | ||
362 | if (task_session(curr) != pid) { | 363 | if (task_session(curr) != pid) |
363 | change_pid(curr, PIDTYPE_SID, pid); | 364 | change_pid(curr, PIDTYPE_SID, pid); |
364 | proc_sid_connector(curr); | ||
365 | } | ||
366 | 365 | ||
367 | if (task_pgrp(curr) != pid) | 366 | if (task_pgrp(curr) != pid) |
368 | change_pid(curr, PIDTYPE_PGID, pid); | 367 | change_pid(curr, PIDTYPE_PGID, pid); |
@@ -737,12 +736,9 @@ static struct task_struct *find_new_reaper(struct task_struct *father) | |||
737 | /* | 736 | /* |
738 | * Any that need to be release_task'd are put on the @dead list. | 737 | * Any that need to be release_task'd are put on the @dead list. |
739 | */ | 738 | */ |
740 | static void reparent_thread(struct task_struct *father, struct task_struct *p, | 739 | static void reparent_leader(struct task_struct *father, struct task_struct *p, |
741 | struct list_head *dead) | 740 | struct list_head *dead) |
742 | { | 741 | { |
743 | if (p->pdeath_signal) | ||
744 | group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p); | ||
745 | |||
746 | list_move_tail(&p->sibling, &p->real_parent->children); | 742 | list_move_tail(&p->sibling, &p->real_parent->children); |
747 | 743 | ||
748 | if (task_detached(p)) | 744 | if (task_detached(p)) |
@@ -781,12 +777,18 @@ static void forget_original_parent(struct task_struct *father) | |||
781 | reaper = find_new_reaper(father); | 777 | reaper = find_new_reaper(father); |
782 | 778 | ||
783 | list_for_each_entry_safe(p, n, &father->children, sibling) { | 779 | list_for_each_entry_safe(p, n, &father->children, sibling) { |
784 | p->real_parent = reaper; | 780 | struct task_struct *t = p; |
785 | if (p->parent == father) { | 781 | do { |
786 | BUG_ON(task_ptrace(p)); | 782 | t->real_parent = reaper; |
787 | p->parent = p->real_parent; | 783 | if (t->parent == father) { |
788 | } | 784 | BUG_ON(task_ptrace(t)); |
789 | reparent_thread(father, p, &dead_children); | 785 | t->parent = t->real_parent; |
786 | } | ||
787 | if (t->pdeath_signal) | ||
788 | group_send_sig_info(t->pdeath_signal, | ||
789 | SEND_SIG_NOINFO, t); | ||
790 | } while_each_thread(p, t); | ||
791 | reparent_leader(father, p, &dead_children); | ||
790 | } | 792 | } |
791 | write_unlock_irq(&tasklist_lock); | 793 | write_unlock_irq(&tasklist_lock); |
792 | 794 | ||
@@ -934,7 +936,7 @@ NORET_TYPE void do_exit(long code) | |||
934 | * an exiting task cleaning up the robust pi futexes. | 936 | * an exiting task cleaning up the robust pi futexes. |
935 | */ | 937 | */ |
936 | smp_mb(); | 938 | smp_mb(); |
937 | spin_unlock_wait(&tsk->pi_lock); | 939 | raw_spin_unlock_wait(&tsk->pi_lock); |
938 | 940 | ||
939 | if (unlikely(in_atomic())) | 941 | if (unlikely(in_atomic())) |
940 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", | 942 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", |
@@ -972,7 +974,7 @@ NORET_TYPE void do_exit(long code) | |||
972 | exit_thread(); | 974 | exit_thread(); |
973 | cgroup_exit(tsk, 1); | 975 | cgroup_exit(tsk, 1); |
974 | 976 | ||
975 | if (group_dead && tsk->signal->leader) | 977 | if (group_dead) |
976 | disassociate_ctty(1); | 978 | disassociate_ctty(1); |
977 | 979 | ||
978 | module_put(task_thread_info(tsk)->exec_domain->module); | 980 | module_put(task_thread_info(tsk)->exec_domain->module); |
@@ -980,6 +982,10 @@ NORET_TYPE void do_exit(long code) | |||
980 | proc_exit_connector(tsk); | 982 | proc_exit_connector(tsk); |
981 | 983 | ||
982 | /* | 984 | /* |
985 | * FIXME: do that only when needed, using sched_exit tracepoint | ||
986 | */ | ||
987 | flush_ptrace_hw_breakpoint(tsk); | ||
988 | /* | ||
983 | * Flush inherited counters to the parent - before the parent | 989 | * Flush inherited counters to the parent - before the parent |
984 | * gets woken up by child-exit notifications. | 990 | * gets woken up by child-exit notifications. |
985 | */ | 991 | */ |
@@ -1006,7 +1012,7 @@ NORET_TYPE void do_exit(long code) | |||
1006 | tsk->flags |= PF_EXITPIDONE; | 1012 | tsk->flags |= PF_EXITPIDONE; |
1007 | 1013 | ||
1008 | if (tsk->io_context) | 1014 | if (tsk->io_context) |
1009 | exit_io_context(); | 1015 | exit_io_context(tsk); |
1010 | 1016 | ||
1011 | if (tsk->splice_pipe) | 1017 | if (tsk->splice_pipe) |
1012 | __free_pipe_info(tsk->splice_pipe); | 1018 | __free_pipe_info(tsk->splice_pipe); |
@@ -1207,6 +1213,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1207 | struct signal_struct *psig; | 1213 | struct signal_struct *psig; |
1208 | struct signal_struct *sig; | 1214 | struct signal_struct *sig; |
1209 | unsigned long maxrss; | 1215 | unsigned long maxrss; |
1216 | cputime_t tgutime, tgstime; | ||
1210 | 1217 | ||
1211 | /* | 1218 | /* |
1212 | * The resource counters for the group leader are in its | 1219 | * The resource counters for the group leader are in its |
@@ -1222,20 +1229,23 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1222 | * need to protect the access to parent->signal fields, | 1229 | * need to protect the access to parent->signal fields, |
1223 | * as other threads in the parent group can be right | 1230 | * as other threads in the parent group can be right |
1224 | * here reaping other children at the same time. | 1231 | * here reaping other children at the same time. |
1232 | * | ||
1233 | * We use thread_group_times() to get times for the thread | ||
1234 | * group, which consolidates times for all threads in the | ||
1235 | * group including the group leader. | ||
1225 | */ | 1236 | */ |
1237 | thread_group_times(p, &tgutime, &tgstime); | ||
1226 | spin_lock_irq(&p->real_parent->sighand->siglock); | 1238 | spin_lock_irq(&p->real_parent->sighand->siglock); |
1227 | psig = p->real_parent->signal; | 1239 | psig = p->real_parent->signal; |
1228 | sig = p->signal; | 1240 | sig = p->signal; |
1229 | psig->cutime = | 1241 | psig->cutime = |
1230 | cputime_add(psig->cutime, | 1242 | cputime_add(psig->cutime, |
1231 | cputime_add(p->utime, | 1243 | cputime_add(tgutime, |
1232 | cputime_add(sig->utime, | 1244 | sig->cutime)); |
1233 | sig->cutime))); | ||
1234 | psig->cstime = | 1245 | psig->cstime = |
1235 | cputime_add(psig->cstime, | 1246 | cputime_add(psig->cstime, |
1236 | cputime_add(p->stime, | 1247 | cputime_add(tgstime, |
1237 | cputime_add(sig->stime, | 1248 | sig->cstime)); |
1238 | sig->cstime))); | ||
1239 | psig->cgtime = | 1249 | psig->cgtime = |
1240 | cputime_add(psig->cgtime, | 1250 | cputime_add(psig->cgtime, |
1241 | cputime_add(p->gtime, | 1251 | cputime_add(p->gtime, |
@@ -1544,14 +1554,9 @@ static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk) | |||
1544 | struct task_struct *p; | 1554 | struct task_struct *p; |
1545 | 1555 | ||
1546 | list_for_each_entry(p, &tsk->children, sibling) { | 1556 | list_for_each_entry(p, &tsk->children, sibling) { |
1547 | /* | 1557 | int ret = wait_consider_task(wo, 0, p); |
1548 | * Do not consider detached threads. | 1558 | if (ret) |
1549 | */ | 1559 | return ret; |
1550 | if (!task_detached(p)) { | ||
1551 | int ret = wait_consider_task(wo, 0, p); | ||
1552 | if (ret) | ||
1553 | return ret; | ||
1554 | } | ||
1555 | } | 1560 | } |
1556 | 1561 | ||
1557 | return 0; | 1562 | return 0; |