History

Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull scheduler fixes from Ingo Molnar: "Two cputime fixes - hopefully the last ones" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/cputime: Resync steal time when guest & host lose sync sched/cputime: Fix NO_HZ_FULL getrusage() monotonicity regression

Linus Torvalds committed 10 years ago

Commit ac78bc72 parents 0dcb7b6 03cbc731 file · +25 −8Browse files

Unified · Split

kernel/sched/cputime.c+25−8
@@ -263,6 +263,11 @@ void account_idle_time(cputime_t cputime) · 262 unmodified lines
263263 cpustat[CPUTIME_IDLE] += (__force u64) cputime;
264264 }
265265
266+/*
267+ * When a guest is interrupted for a longer amount of time, missed clock
268+ * ticks are not redelivered later. Due to that, this function may on
269+ * occasion account more time than the calling functions think elapsed.
270+ */
266271 static __always_inline cputime_t steal_account_process_time(cputime_t maxtime)
267272 {
268273 #ifdef CONFIG_PARAVIRT
@@ -371,7 +376,7 @@ static void irqtime_account_process_tick(struct task_struct *p, int user_tick, · 102 unmodified lines
371376 * idle, or potentially user or system time. Due to rounding,
372377 * other time can exceed ticks occasionally.
373378 */
374− other = account_other_time(cputime);
379+ other = account_other_time(ULONG_MAX);
375380 if (other >= cputime)
376381 return;
377382 cputime -= other;
@@ -486,7 +491,7 @@ void account_process_tick(struct task_struct *p, int user_tick) · 108 unmodified lines
486491 }
487492
488493 cputime = cputime_one_jiffy;
489− steal = steal_account_process_time(cputime);
494+ steal = steal_account_process_time(ULONG_MAX);
490495
491496 if (steal >= cputime)
492497 return;
@@ -516,7 +521,7 @@ void account_idle_ticks(unsigned long ticks) · 23 unmodified lines
516521 }
517522
518523 cputime = jiffies_to_cputime(ticks);
519− steal = steal_account_process_time(cputime);
524+ steal = steal_account_process_time(ULONG_MAX);
520525
521526 if (steal >= cputime)
522527 return;
@@ -614,19 +619,25 @@ static void cputime_adjust(struct task_cputime *curr, · 91 unmodified lines
614619 stime = curr->stime;
615620 utime = curr->utime;
616621
617− if (utime == 0) {
618− stime = rtime;
622+ /*
623+ * If either stime or both stime and utime are 0, assume all runtime is
624+ * userspace. Once a task gets some ticks, the monotonicy code at
625+ * 'update' will ensure things converge to the observed ratio.
626+ */
627+ if (stime == 0) {
628+ utime = rtime;
619629 goto update;
620630 }
621631
622− if (stime == 0) {
623− utime = rtime;
632+ if (utime == 0) {
633+ stime = rtime;
624634 goto update;
625635 }
626636
627637 stime = scale_stime((__force u64)stime, (__force u64)rtime,
628638 (__force u64)(stime + utime));
629639
640+update:
630641 /*
631642 * Make sure stime doesn't go backwards; this preserves monotonicity
632643 * for utime because rtime is monotonic.
@@ -649,7 +660,6 @@ static void cputime_adjust(struct task_cputime *curr, · 16 unmodified lines
649660 stime = rtime - utime;
650661 }
651662
652−update:
653663 prev->stime = stime;
654664 prev->utime = utime;
655665 out:
@@ -694,6 +704,13 @@ static cputime_t get_vtime_delta(struct task_struct *tsk) · 38 unmodified lines
694704 unsigned long now = READ_ONCE(jiffies);
695705 cputime_t delta, other;
696706
707+ /*
708+ * Unlike tick based timing, vtime based timing never has lost
709+ * ticks, and no need for steal time accounting to make up for
710+ * lost ticks. Vtime accounts a rounded version of actual
711+ * elapsed time. Limit account_other_time to prevent rounding
712+ * errors from causing elapsed vtime to go negative.
713+ */
697714 delta = jiffies_to_cputime(now - tsk->vtime_snap);
698715 other = account_other_time(delta);
699716 WARN_ON_ONCE(tsk->vtime_snap_whence == VTIME_INACTIVE);