linux/kernel/time
Frederic Weisbecker 2b17c545a4 nohz: Fix one jiffy count too far in idle cputime
When we stop the tick in idle, we save the current jiffies value
in ts->idle_jiffies. This snapshot is substracted from the later
value of jiffies when the tick is restarted and the resulting
delta is accounted as idle cputime. This is how we handle the
idle cputime accounting without the tick.

But sometimes we need to schedule the next tick to some time in
the future instead of completely stopping it. In this case, a
tick may happen before we restart the periodic behaviour and
from that tick we account one jiffy to idle cputime as usual but
we also increment the ts->idle_jiffies snapshot by one so that
when we compute the delta to account, we substract the one jiffy
we just accounted.

To prepare for stopping the tick outside idle, we introduced a
check that prevents from fixing up that ts->idle_jiffies if we
are not running the idle task. But we use idle_cpu() for that
and this is a problem if we run the tick while another CPU
remotely enqueues a ttwu to our runqueue:

CPU 0:                            CPU 1:

tick_sched_timer() {              ttwu_queue_remote()
       if (idle_cpu(CPU 0))
           ts->idle_jiffies++;
}

Here, idle_cpu() notes that &rq->wake_list is not empty and
hence won't consider the CPU as idle. As a result,
ts->idle_jiffies won't be incremented. But this is wrong because
we actually account the current jiffy to idle cputime. And that
jiffy won't get substracted from the nohz time delta. So in the
end, this jiffy is accounted twice.

Fix this by changing idle_cpu(smp_processor_id()) with
is_idle_task(current). This way the jiffy is substracted
correctly even if a ttwu operation is enqueued on the CPU.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: <stable@vger.kernel.org> # 3.5+
Link: http://lkml.kernel.org/r/1349308004-3482-1-git-send-email-fweisbec@gmail.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2012-10-05 10:22:20 +02:00
..
alarmtimer.c alarmtimer: Provide accessor to alarmtimer rtc device 2012-04-20 14:56:36 -07:00
clockevents.c clockevents: Make clockevents_config() a global symbol 2012-05-25 01:44:51 +02:00
clocksource.c kernel-time: fix s/then/than/ spelling errors 2012-03-23 16:49:21 -07:00
jiffies.c time/jiffies: Rename ACTHZ to SHIFTED_HZ 2012-07-31 17:09:12 +02:00
Kconfig timers: Fixup the Kconfig consolidation fallout 2012-05-21 23:43:46 +02:00
Makefile timers: Introduce in-kernel alarm-timer interface 2011-04-26 14:01:44 -07:00
ntp.c time/jiffies: Rename ACTHZ to SHIFTED_HZ 2012-07-31 17:09:12 +02:00
posix-clock.c kernel: Fix files explicitly needing EXPORT_SYMBOL infrastructure 2011-10-31 19:30:05 -04:00
tick-broadcast.c tick: Fix the spurious broadcast timer ticks after resume 2012-04-19 21:27:50 +02:00
tick-common.c clockevents: Make minimum delay adjustments configurable 2011-09-08 11:10:56 +02:00
tick-internal.h clockevents: Make minimum delay adjustments configurable 2011-09-08 11:10:56 +02:00
tick-oneshot.c clockevents: Make minimum delay adjustments configurable 2011-09-08 11:10:56 +02:00
tick-sched.c nohz: Fix one jiffy count too far in idle cputime 2012-10-05 10:22:20 +02:00
timecompare.c time: Use ARRAY_SIZE macro in timecompare.c 2010-10-21 17:30:06 +02:00
timeconv.c time: add function to convert between calendar time and broken-down time for universal use 2009-09-24 07:20:56 -07:00
timekeeping.c time: Fix timeekeping_get_ns overflow on 32bit systems 2012-09-13 17:39:14 +02:00
timer_list.c nohz: Rename ts->idle_tick to ts->last_tick 2012-06-11 20:07:17 +02:00
timer_stats.c locking, timer_stats: Annotate table_lock as raw 2011-09-13 11:12:00 +02:00