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 | /* |
