Commit d4979c79 authored by Ingo Molnar's avatar Ingo Molnar

[PATCH] timer cleanups

This is my latest timer patchset, it makes del_timer_sync() a bit more
robust wrt.  code that re-adds timers from the timer handler.

Other changes in the patch:

 - clean up cascading a bit.

 - do not save flags in __run_timer_list - we enter from an irqs-enabled
   tasklet.
parent 469d2810
......@@ -266,29 +266,31 @@ int del_timer(timer_t *timer)
int del_timer_sync(timer_t *timer)
{
tvec_base_t *base = tvec_bases;
int i, ret;
int i, ret = 0;
ret = del_timer(timer);
del_again:
ret += del_timer(timer);
for (i = 0; i < NR_CPUS; i++) {
for (i = 0; i < NR_CPUS; i++, base++) {
if (!cpu_online(i))
continue;
if (base->running_timer == timer) {
while (base->running_timer == timer) {
cpu_relax();
preempt_disable();
preempt_enable();
preempt_check_resched();
}
break;
}
base++;
}
if (timer_pending(timer))
goto del_again;
return ret;
}
#endif
static void cascade(tvec_base_t *base, tvec_t *tv)
static int cascade(tvec_base_t *base, tvec_t *tv)
{
/* cascade all the timers from tv up one level */
struct list_head *head, *curr, *next;
......@@ -310,7 +312,8 @@ static void cascade(tvec_base_t *base, tvec_t *tv)
curr = next;
}
INIT_LIST_HEAD(head);
tv->index = (tv->index + 1) & TVN_MASK;
return tv->index = (tv->index + 1) & TVN_MASK;
}
/***
......@@ -322,26 +325,18 @@ static void cascade(tvec_base_t *base, tvec_t *tv)
*/
static inline void __run_timers(tvec_base_t *base)
{
unsigned long flags;
spin_lock_irqsave(&base->lock, flags);
spin_lock_irq(&base->lock);
while ((long)(jiffies - base->timer_jiffies) >= 0) {
struct list_head *head, *curr;
/*
* Cascade timers:
*/
if (!base->tv1.index) {
cascade(base, &base->tv2);
if (base->tv2.index == 1) {
cascade(base, &base->tv3);
if (base->tv3.index == 1) {
cascade(base, &base->tv4);
if (base->tv4.index == 1)
cascade(base, &base->tv5);
}
}
}
if (!base->tv1.index &&
(cascade(base, &base->tv2) == 1) &&
(cascade(base, &base->tv3) == 1) &&
cascade(base, &base->tv4) == 1)
cascade(base, &base->tv5);
repeat:
head = base->tv1.vec + base->tv1.index;
curr = head->next;
......@@ -360,7 +355,10 @@ static inline void __run_timers(tvec_base_t *base)
base->running_timer = timer;
#endif
spin_unlock_irq(&base->lock);
fn(data);
if (!fn)
printk("Bad: timer %p has NULL fn. (data: %08lx)\n", timer, data);
else
fn(data);
spin_lock_irq(&base->lock);
goto repeat;
}
......@@ -370,7 +368,7 @@ static inline void __run_timers(tvec_base_t *base)
#if CONFIG_SMP
base->running_timer = NULL;
#endif
spin_unlock_irqrestore(&base->lock, flags);
spin_unlock_irq(&base->lock);
}
/******************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment