diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 85a83c831856..2d8be7ebb0f7 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -40,13 +40,13 @@ | |||
40 | #include <linux/cn_proc.h> | 40 | #include <linux/cn_proc.h> |
41 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
42 | #include <linux/futex.h> | 42 | #include <linux/futex.h> |
43 | #include <linux/compat.h> | ||
44 | #include <linux/pipe_fs_i.h> | 43 | #include <linux/pipe_fs_i.h> |
45 | #include <linux/audit.h> /* for audit_free() */ | 44 | #include <linux/audit.h> /* for audit_free() */ |
46 | #include <linux/resource.h> | 45 | #include <linux/resource.h> |
47 | #include <linux/blkdev.h> | 46 | #include <linux/blkdev.h> |
48 | #include <linux/task_io_accounting_ops.h> | 47 | #include <linux/task_io_accounting_ops.h> |
49 | #include <linux/tracehook.h> | 48 | #include <linux/tracehook.h> |
49 | #include <trace/sched.h> | ||
50 | 50 | ||
51 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
52 | #include <asm/unistd.h> | 52 | #include <asm/unistd.h> |
@@ -112,8 +112,6 @@ static void __exit_signal(struct task_struct *tsk) | |||
112 | * We won't ever get here for the group leader, since it | 112 | * We won't ever get here for the group leader, since it |
113 | * will have been the last reference on the signal_struct. | 113 | * will have been the last reference on the signal_struct. |
114 | */ | 114 | */ |
115 | sig->utime = cputime_add(sig->utime, task_utime(tsk)); | ||
116 | sig->stime = cputime_add(sig->stime, task_stime(tsk)); | ||
117 | sig->gtime = cputime_add(sig->gtime, task_gtime(tsk)); | 115 | sig->gtime = cputime_add(sig->gtime, task_gtime(tsk)); |
118 | sig->min_flt += tsk->min_flt; | 116 | sig->min_flt += tsk->min_flt; |
119 | sig->maj_flt += tsk->maj_flt; | 117 | sig->maj_flt += tsk->maj_flt; |
@@ -122,7 +120,6 @@ static void __exit_signal(struct task_struct *tsk) | |||
122 | sig->inblock += task_io_get_inblock(tsk); | 120 | sig->inblock += task_io_get_inblock(tsk); |
123 | sig->oublock += task_io_get_oublock(tsk); | 121 | sig->oublock += task_io_get_oublock(tsk); |
124 | task_io_accounting_add(&sig->ioac, &tsk->ioac); | 122 | task_io_accounting_add(&sig->ioac, &tsk->ioac); |
125 | sig->sum_sched_runtime += tsk->se.sum_exec_runtime; | ||
126 | sig = NULL; /* Marker for below. */ | 123 | sig = NULL; /* Marker for below. */ |
127 | } | 124 | } |
128 | 125 | ||
@@ -143,13 +140,21 @@ static void __exit_signal(struct task_struct *tsk) | |||
143 | if (sig) { | 140 | if (sig) { |
144 | flush_sigqueue(&sig->shared_pending); | 141 | flush_sigqueue(&sig->shared_pending); |
145 | taskstats_tgid_free(sig); | 142 | taskstats_tgid_free(sig); |
143 | /* | ||
144 | * Make sure ->signal can't go away under rq->lock, | ||
145 | * see account_group_exec_runtime(). | ||
146 | */ | ||
147 | task_rq_unlock_wait(tsk); | ||
146 | __cleanup_signal(sig); | 148 | __cleanup_signal(sig); |
147 | } | 149 | } |
148 | } | 150 | } |
149 | 151 | ||
150 | static void delayed_put_task_struct(struct rcu_head *rhp) | 152 | static void delayed_put_task_struct(struct rcu_head *rhp) |
151 | { | 153 | { |
152 | put_task_struct(container_of(rhp, struct task_struct, rcu)); | 154 | struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); |
155 | |||
156 | trace_sched_process_free(tsk); | ||
157 | put_task_struct(tsk); | ||
153 | } | 158 | } |
154 | 159 | ||
155 | 160 | ||
@@ -640,24 +645,23 @@ retry: | |||
640 | assign_new_owner: | 645 | assign_new_owner: |
641 | BUG_ON(c == p); | 646 | BUG_ON(c == p); |
642 | get_task_struct(c); | 647 | get_task_struct(c); |
648 | read_unlock(&tasklist_lock); | ||
649 | down_write(&mm->mmap_sem); | ||
643 | /* | 650 | /* |
644 | * The task_lock protects c->mm from changing. | 651 | * The task_lock protects c->mm from changing. |
645 | * We always want mm->owner->mm == mm | 652 | * We always want mm->owner->mm == mm |
646 | */ | 653 | */ |
647 | task_lock(c); | 654 | task_lock(c); |
648 | /* | ||
649 | * Delay read_unlock() till we have the task_lock() | ||
650 | * to ensure that c does not slip away underneath us | ||
651 | */ | ||
652 | read_unlock(&tasklist_lock); | ||
653 | if (c->mm != mm) { | 655 | if (c->mm != mm) { |
654 | task_unlock(c); | 656 | task_unlock(c); |
657 | up_write(&mm->mmap_sem); | ||
655 | put_task_struct(c); | 658 | put_task_struct(c); |
656 | goto retry; | 659 | goto retry; |
657 | } | 660 | } |
658 | cgroup_mm_owner_callbacks(mm->owner, c); | 661 | cgroup_mm_owner_callbacks(mm->owner, c); |
659 | mm->owner = c; | 662 | mm->owner = c; |
660 | task_unlock(c); | 663 | task_unlock(c); |
664 | up_write(&mm->mmap_sem); | ||
661 | put_task_struct(c); | 665 | put_task_struct(c); |
662 | } | 666 | } |
663 | #endif /* CONFIG_MM_OWNER */ | 667 | #endif /* CONFIG_MM_OWNER */ |
@@ -1054,14 +1058,6 @@ NORET_TYPE void do_exit(long code) | |||
1054 | exit_itimers(tsk->signal); | 1058 | exit_itimers(tsk->signal); |
1055 | } | 1059 | } |
1056 | acct_collect(code, group_dead); | 1060 | acct_collect(code, group_dead); |
1057 | #ifdef CONFIG_FUTEX | ||
1058 | if (unlikely(tsk->robust_list)) | ||
1059 | exit_robust_list(tsk); | ||
1060 | #ifdef CONFIG_COMPAT | ||
1061 | if (unlikely(tsk->compat_robust_list)) | ||
1062 | compat_exit_robust_list(tsk); | ||
1063 | #endif | ||
1064 | #endif | ||
1065 | if (group_dead) | 1061 | if (group_dead) |
1066 | tty_audit_exit(); | 1062 | tty_audit_exit(); |
1067 | if (unlikely(tsk->audit_context)) | 1063 | if (unlikely(tsk->audit_context)) |
@@ -1074,6 +1070,8 @@ NORET_TYPE void do_exit(long code) | |||
1074 | 1070 | ||
1075 | if (group_dead) | 1071 | if (group_dead) |
1076 | acct_process(); | 1072 | acct_process(); |
1073 | trace_sched_process_exit(tsk); | ||
1074 | |||
1077 | exit_sem(tsk); | 1075 | exit_sem(tsk); |
1078 | exit_files(tsk); | 1076 | exit_files(tsk); |
1079 | exit_fs(tsk); | 1077 | exit_fs(tsk); |
@@ -1302,6 +1300,7 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
1302 | if (likely(!traced)) { | 1300 | if (likely(!traced)) { |
1303 | struct signal_struct *psig; | 1301 | struct signal_struct *psig; |
1304 | struct signal_struct *sig; | 1302 | struct signal_struct *sig; |
1303 | struct task_cputime cputime; | ||
1305 | 1304 | ||
1306 | /* | 1305 | /* |
1307 | * The resource counters for the group leader are in its | 1306 | * The resource counters for the group leader are in its |
@@ -1317,20 +1316,23 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
1317 | * need to protect the access to p->parent->signal fields, | 1316 | * need to protect the access to p->parent->signal fields, |
1318 | * as other threads in the parent group can be right | 1317 | * as other threads in the parent group can be right |
1319 | * here reaping other children at the same time. | 1318 | * here reaping other children at the same time. |
1319 | * | ||
1320 | * We use thread_group_cputime() to get times for the thread | ||
1321 | * group, which consolidates times for all threads in the | ||
1322 | * group including the group leader. | ||
1320 | */ | 1323 | */ |
1321 | spin_lock_irq(&p->parent->sighand->siglock); | 1324 | spin_lock_irq(&p->parent->sighand->siglock); |
1322 | psig = p->parent->signal; | 1325 | psig = p->parent->signal; |
1323 | sig = p->signal; | 1326 | sig = p->signal; |
1327 | thread_group_cputime(p, &cputime); | ||
1324 | psig->cutime = | 1328 | psig->cutime = |
1325 | cputime_add(psig->cutime, | 1329 | cputime_add(psig->cutime, |
1326 | cputime_add(p->utime, | 1330 | cputime_add(cputime.utime, |
1327 | cputime_add(sig->utime, | 1331 | sig->cutime)); |
1328 | sig->cutime))); | ||
1329 | psig->cstime = | 1332 | psig->cstime = |
1330 | cputime_add(psig->cstime, | 1333 | cputime_add(psig->cstime, |
1331 | cputime_add(p->stime, | 1334 | cputime_add(cputime.stime, |
1332 | cputime_add(sig->stime, | 1335 | sig->cstime)); |
1333 | sig->cstime))); | ||
1334 | psig->cgtime = | 1336 | psig->cgtime = |
1335 | cputime_add(psig->cgtime, | 1337 | cputime_add(psig->cgtime, |
1336 | cputime_add(p->gtime, | 1338 | cputime_add(p->gtime, |
@@ -1675,6 +1677,8 @@ static long do_wait(enum pid_type type, struct pid *pid, int options, | |||
1675 | struct task_struct *tsk; | 1677 | struct task_struct *tsk; |
1676 | int retval; | 1678 | int retval; |
1677 | 1679 | ||
1680 | trace_sched_process_wait(pid); | ||
1681 | |||
1678 | add_wait_queue(¤t->signal->wait_chldexit,&wait); | 1682 | add_wait_queue(¤t->signal->wait_chldexit,&wait); |
1679 | repeat: | 1683 | repeat: |
1680 | /* | 1684 | /* |