diff options
-rw-r--r-- | fs/exec.c | 3 | ||||
-rw-r--r-- | include/linux/sched.h | 10 | ||||
-rw-r--r-- | kernel/exit.c | 6 | ||||
-rw-r--r-- | kernel/fork.c | 1 | ||||
-rw-r--r-- | kernel/sys.c | 14 |
5 files changed, 34 insertions, 0 deletions
@@ -845,6 +845,9 @@ static int de_thread(struct task_struct *tsk) | |||
845 | sig->notify_count = 0; | 845 | sig->notify_count = 0; |
846 | 846 | ||
847 | no_thread_group: | 847 | no_thread_group: |
848 | if (current->mm) | ||
849 | setmax_mm_hiwater_rss(&sig->maxrss, current->mm); | ||
850 | |||
848 | exit_itimers(sig); | 851 | exit_itimers(sig); |
849 | flush_itimer_signals(); | 852 | flush_itimer_signals(); |
850 | 853 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 97b10da0a3ea..6448bbc6406b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -426,6 +426,15 @@ static inline unsigned long get_mm_hiwater_rss(struct mm_struct *mm) | |||
426 | return max(mm->hiwater_rss, get_mm_rss(mm)); | 426 | return max(mm->hiwater_rss, get_mm_rss(mm)); |
427 | } | 427 | } |
428 | 428 | ||
429 | static inline void setmax_mm_hiwater_rss(unsigned long *maxrss, | ||
430 | struct mm_struct *mm) | ||
431 | { | ||
432 | unsigned long hiwater_rss = get_mm_hiwater_rss(mm); | ||
433 | |||
434 | if (*maxrss < hiwater_rss) | ||
435 | *maxrss = hiwater_rss; | ||
436 | } | ||
437 | |||
429 | static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm) | 438 | static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm) |
430 | { | 439 | { |
431 | return max(mm->hiwater_vm, mm->total_vm); | 440 | return max(mm->hiwater_vm, mm->total_vm); |
@@ -612,6 +621,7 @@ struct signal_struct { | |||
612 | unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; | 621 | unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; |
613 | unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; | 622 | unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; |
614 | unsigned long inblock, oublock, cinblock, coublock; | 623 | unsigned long inblock, oublock, cinblock, coublock; |
624 | unsigned long maxrss, cmaxrss; | ||
615 | struct task_io_accounting ioac; | 625 | struct task_io_accounting ioac; |
616 | 626 | ||
617 | /* | 627 | /* |
diff --git a/kernel/exit.c b/kernel/exit.c index 61bb1761c7b8..60d6fdcc9265 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -947,6 +947,8 @@ NORET_TYPE void do_exit(long code) | |||
947 | if (group_dead) { | 947 | if (group_dead) { |
948 | hrtimer_cancel(&tsk->signal->real_timer); | 948 | hrtimer_cancel(&tsk->signal->real_timer); |
949 | exit_itimers(tsk->signal); | 949 | exit_itimers(tsk->signal); |
950 | if (tsk->mm) | ||
951 | setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm); | ||
950 | } | 952 | } |
951 | acct_collect(code, group_dead); | 953 | acct_collect(code, group_dead); |
952 | if (group_dead) | 954 | if (group_dead) |
@@ -1210,6 +1212,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1210 | if (likely(!traced) && likely(!task_detached(p))) { | 1212 | if (likely(!traced) && likely(!task_detached(p))) { |
1211 | struct signal_struct *psig; | 1213 | struct signal_struct *psig; |
1212 | struct signal_struct *sig; | 1214 | struct signal_struct *sig; |
1215 | unsigned long maxrss; | ||
1213 | 1216 | ||
1214 | /* | 1217 | /* |
1215 | * The resource counters for the group leader are in its | 1218 | * The resource counters for the group leader are in its |
@@ -1258,6 +1261,9 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
1258 | psig->coublock += | 1261 | psig->coublock += |
1259 | task_io_get_oublock(p) + | 1262 | task_io_get_oublock(p) + |
1260 | sig->oublock + sig->coublock; | 1263 | sig->oublock + sig->coublock; |
1264 | maxrss = max(sig->maxrss, sig->cmaxrss); | ||
1265 | if (psig->cmaxrss < maxrss) | ||
1266 | psig->cmaxrss = maxrss; | ||
1261 | task_io_accounting_add(&psig->ioac, &p->ioac); | 1267 | task_io_accounting_add(&psig->ioac, &p->ioac); |
1262 | task_io_accounting_add(&psig->ioac, &sig->ioac); | 1268 | task_io_accounting_add(&psig->ioac, &sig->ioac); |
1263 | spin_unlock_irq(&p->real_parent->sighand->siglock); | 1269 | spin_unlock_irq(&p->real_parent->sighand->siglock); |
diff --git a/kernel/fork.c b/kernel/fork.c index 1020977b57ca..7cf45812ce84 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -866,6 +866,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
866 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; | 866 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; |
867 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; | 867 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; |
868 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; | 868 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; |
869 | sig->maxrss = sig->cmaxrss = 0; | ||
869 | task_io_accounting_init(&sig->ioac); | 870 | task_io_accounting_init(&sig->ioac); |
870 | sig->sum_sched_runtime = 0; | 871 | sig->sum_sched_runtime = 0; |
871 | taskstats_tgid_init(sig); | 872 | taskstats_tgid_init(sig); |
diff --git a/kernel/sys.c b/kernel/sys.c index ea5c3bcac881..ebcb15611728 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1338,6 +1338,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
1338 | unsigned long flags; | 1338 | unsigned long flags; |
1339 | cputime_t utime, stime; | 1339 | cputime_t utime, stime; |
1340 | struct task_cputime cputime; | 1340 | struct task_cputime cputime; |
1341 | unsigned long maxrss = 0; | ||
1341 | 1342 | ||
1342 | memset((char *) r, 0, sizeof *r); | 1343 | memset((char *) r, 0, sizeof *r); |
1343 | utime = stime = cputime_zero; | 1344 | utime = stime = cputime_zero; |
@@ -1346,6 +1347,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
1346 | utime = task_utime(current); | 1347 | utime = task_utime(current); |
1347 | stime = task_stime(current); | 1348 | stime = task_stime(current); |
1348 | accumulate_thread_rusage(p, r); | 1349 | accumulate_thread_rusage(p, r); |
1350 | maxrss = p->signal->maxrss; | ||
1349 | goto out; | 1351 | goto out; |
1350 | } | 1352 | } |
1351 | 1353 | ||
@@ -1363,6 +1365,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
1363 | r->ru_majflt = p->signal->cmaj_flt; | 1365 | r->ru_majflt = p->signal->cmaj_flt; |
1364 | r->ru_inblock = p->signal->cinblock; | 1366 | r->ru_inblock = p->signal->cinblock; |
1365 | r->ru_oublock = p->signal->coublock; | 1367 | r->ru_oublock = p->signal->coublock; |
1368 | maxrss = p->signal->cmaxrss; | ||
1366 | 1369 | ||
1367 | if (who == RUSAGE_CHILDREN) | 1370 | if (who == RUSAGE_CHILDREN) |
1368 | break; | 1371 | break; |
@@ -1377,6 +1380,8 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
1377 | r->ru_majflt += p->signal->maj_flt; | 1380 | r->ru_majflt += p->signal->maj_flt; |
1378 | r->ru_inblock += p->signal->inblock; | 1381 | r->ru_inblock += p->signal->inblock; |
1379 | r->ru_oublock += p->signal->oublock; | 1382 | r->ru_oublock += p->signal->oublock; |
1383 | if (maxrss < p->signal->maxrss) | ||
1384 | maxrss = p->signal->maxrss; | ||
1380 | t = p; | 1385 | t = p; |
1381 | do { | 1386 | do { |
1382 | accumulate_thread_rusage(t, r); | 1387 | accumulate_thread_rusage(t, r); |
@@ -1392,6 +1397,15 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
1392 | out: | 1397 | out: |
1393 | cputime_to_timeval(utime, &r->ru_utime); | 1398 | cputime_to_timeval(utime, &r->ru_utime); |
1394 | cputime_to_timeval(stime, &r->ru_stime); | 1399 | cputime_to_timeval(stime, &r->ru_stime); |
1400 | |||
1401 | if (who != RUSAGE_CHILDREN) { | ||
1402 | struct mm_struct *mm = get_task_mm(p); | ||
1403 | if (mm) { | ||
1404 | setmax_mm_hiwater_rss(&maxrss, mm); | ||
1405 | mmput(mm); | ||
1406 | } | ||
1407 | } | ||
1408 | r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */ | ||
1395 | } | 1409 | } |
1396 | 1410 | ||
1397 | int getrusage(struct task_struct *p, int who, struct rusage __user *ru) | 1411 | int getrusage(struct task_struct *p, int who, struct rusage __user *ru) |