While removing hrtimers, in __remove_hrtimer(), we may call hrtimer_force_reprogram() to reprogram clockevent device. And right after calling hrtimer_force_reprogram() we update 'cpu_base->active_bases' to reflect which clock-bases have pending timers.
hrtimer_force_reprogram() iterates over all clock-bases, of a particular cpu-base, to find hrtimer that will expire next.
Next commit will update hrtimer_force_reprogram() to use newly created for_each_active_base() routine which is dependent on the updated value of ->active_bases.
If timer being removed was the last one queued, then we will try to find next expiry for an empty clock-base as ->active_bases isn't updated yet. timerqueue_getnext() will return NULL and we will get 'NULL pointer dereference' error from hrtimer_force_reprogram().
To fix this, update ->active_bases before calling hrtimer_force_reprogram().
Reviewed-by: Preeti U Murthy preeti@linux.vnet.ibm.com Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- kernel/hrtimer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 3ab2899..aff97db 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -925,6 +925,9 @@ static void __remove_hrtimer(struct hrtimer *timer,
next_timer = timerqueue_getnext(&base->active); timerqueue_del(&base->active, &timer->node); + if (!timerqueue_getnext(&base->active)) + base->cpu_base->active_bases &= ~(1 << base->index); + if (&timer->node == next_timer) { #ifdef CONFIG_HIGH_RES_TIMERS /* Reprogram the clock event device. if enabled */ @@ -938,8 +941,6 @@ static void __remove_hrtimer(struct hrtimer *timer, } #endif } - if (!timerqueue_getnext(&base->active)) - base->cpu_base->active_bases &= ~(1 << base->index); out: timer->state = newstate; }