From: Nick Piggin Some fixes for unsynchronised TSCs. A task's timestamp may have been set by another CPU. Although we try to adjust this correctly with the timestamp_last_tick field, there is no guarantee this will be exactly right. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton --- 25-akpm/kernel/sched.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletion(-) diff -puN kernel/sched.c~sched-timestamp-fixes kernel/sched.c --- 25/kernel/sched.c~sched-timestamp-fixes 2005-02-24 19:54:44.000000000 -0800 +++ 25-akpm/kernel/sched.c 2005-02-24 19:54:44.000000000 -0800 @@ -650,6 +650,7 @@ static inline void __activate_idle_task( static void recalc_task_prio(task_t *p, unsigned long long now) { + /* Caller must always ensure 'now >= p->timestamp' */ unsigned long long __sleep_time = now - p->timestamp; unsigned long sleep_time; @@ -2663,8 +2664,10 @@ need_resched_nonpreemptible: schedstat_inc(rq, sched_cnt); now = sched_clock(); - if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG)) + if (likely((long long)now - prev->timestamp < NS_MAX_SLEEP_AVG)) run_time = now - prev->timestamp; + if (unlikely((long long)now - prev->timestamp < 0)) + run_time = 0; else run_time = NS_MAX_SLEEP_AVG; @@ -2742,6 +2745,8 @@ go_idle: if (!rt_task(next) && next->activated > 0) { unsigned long long delta = now - next->timestamp; + if (unlikely((long long)now - next->timestamp < 0)) + delta = 0; if (next->activated == 1) delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128; _