On Thu, 26 Mar 2015 11:09:01 +0530 Viresh Kumar viresh.kumar@linaro.org wrote:
A delayed work to schedule vmstat_shepherd() is queued at periodic intervals for internal working of vmstat core. This work and its timer end up waking an idle cpu sometimes, as this always stays on CPU0.
Because we re-queue the work from its handler, idle_cpu() returns false and so the timer (used by delayed work) never migrates to any other CPU.
This may not be the desired behavior always as waking up an idle CPU to queue work on few other CPUs isn't good from power-consumption point of view.
In order to avoid waking up an idle core, we can replace schedule_delayed_work() with a normal work plus a separate timer. The timer handler will then queue the work after re-arming the timer. If the CPU was idle before the timer fired, idle_cpu() will mostly return true and the next timer shall be migrated to a non-idle CPU.
But the timer core has a limitation, when the timer is re-armed from its handler, timer core disables migration of that timer to other cores. Details of that limitation are present in kernel/time/timer.c:__mod_timer() routine.
Another simple yet effective solution can be to keep two timers with same handler and keep toggling between them, so that the above limitation doesn't hold true anymore.
This patch replaces schedule_delayed_work() with schedule_work() plus two timers. After this, it was seen that the timer and its do get migrated to other non-idle CPUs, when the local cpu is idle.
Shouldn't this be viewed as a shortcoming of the core timer code?
vmstat_shepherd() is merely rescheduling itself with schedule_delayed_work(). That's a dead bog simple operation and if it's producing suboptimal behaviour then we shouldn't be fixing it with elaborate workarounds in the caller?