Skip to content

Commit ac78bc7

Browse files
committed
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
2 parents 0dcb7b6 + 03cbc73 commit ac78bc7

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

kernel/sched/cputime.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@ void account_idle_time(cputime_t cputime)
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,
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)
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)
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,
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,
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)
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);

0 commit comments

Comments
 (0)