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.