aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched')
-rw-r--r--kernel/sched/cputime.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 49b7cfe98f7a..2b57031afc19 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -602,9 +602,12 @@ static void cputime_adjust(struct task_cputime *curr,
* If the tick based count grows faster than the scheduler one,
* the result of the scaling may go backward.
* Let's enforce monotonicity.
+ * Atomic exchange protects against concurrent cputime_adjust().
*/
- prev->stime = max(prev->stime, stime);
- prev->utime = max(prev->utime, utime);
+ while (stime > (rtime = ACCESS_ONCE(prev->stime)))
+ cmpxchg(&prev->stime, rtime, stime);
+ while (utime > (rtime = ACCESS_ONCE(prev->utime)))
+ cmpxchg(&prev->utime, rtime, utime);
out:
*ut = prev->utime;