On 30 March 2015 at 18:17, Peter Zijlstra peterz@infradead.org wrote:
No, I means something else with that. We can remove the tvec_base::running_timer field. Everything that uses that can use tbase_running() AFAICT.
Okay, there is one instance which still needs it.
migrate_timers():
BUG_ON(old_base->running_timer);
What I wasn't sure about it is if we get can drop this statement or not. If we decide not to drop it, then we can convert running_timer into a bool.
Drop yes, racy not so much I think.
diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 2d3f5c504939..1394f9540348 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1189,12 +1189,39 @@ static inline void __run_timers(struct tvec_base *base) cascade(base, &base->tv5, INDEX(3)); ++base->timer_jiffies; list_replace_init(base->tv1.vec + index, head);
+again: while (!list_empty(head)) { void (*fn)(unsigned long); unsigned long data; bool irqsafe;
timer = list_first_entry(head, struct timer_list,entry);
timer = list_first_entry(head, struct timer_list, entry);
if (unlikely(tbase_running(timer))) {
/* Only one timer on the list, force wait. */
if (unlikely(head->next == head->prev)) {
spin_unlock(&base->lock);
/*
* The only way to get here is if the
* handler requeued itself on another
* base, this guarantees the timer will
* not go away.
*/
while (tbase_running(timer))
cpu_relax();
spin_lock(&base->lock);
} else {
/*
* Otherwise, rotate the list and try
* someone else.
*/
list_move_tail(&timer->entry, head);
}
goto again;
}
fn = timer->function; data = timer->data; irqsafe = tbase_get_irqsafe(timer->base);
Yeah, so I have written something similar only. Wasn't sure about what you wrote earlier. Thanks for the clarification.