Re: RT and Cascade interrupts

Trond Myklebust
2005-06-01T23:09:40Z

[-- Attachment #1: Type: text/plain, Size: 424 bytes --]

on den 01.06.2005 Klokka 18:51 (-0400) skreiv Trond Myklebust:
> Could you then apply the following debugging patch? It should warn you
> in case something happens to corrupt base->running_timer (something
> which would screw up del_timer_sync()). I'm not sure that can happen,
> but it might be worth checking.

Oops. You don't want to return without releasing the spinlock. This
patch should be better...

Cheers,
Trond

[-- Attachment #2: linux-2.6.12-rt-warn.dif --]
[-- Type: text/plain, Size: 1673 bytes --]

timer.c | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletion(-)

Index: linux-2.6.12-rc5-rt-V0.7.47-15/kernel/timer.c
===================================================================
--- linux-2.6.12-rc5-rt-V0.7.47-15.orig/kernel/timer.c
+++ linux-2.6.12-rc5-rt-V0.7.47-15/kernel/timer.c
@@ -436,7 +436,7 @@ static int cascade(tvec_base_t *base, tv

static inline void __run_timers(tvec_base_t *base)
{
- struct timer_list *timer;
+ struct timer_list *timer = NULL;

spin_lock_irq(&base->lock);
while (time_after_eq(jiffies, base->timer_jiffies)) {
@@ -444,6 +444,10 @@ static inline void __run_timers(tvec_bas
struct list_head *head = &work_list;
int index = base->timer_jiffies & TVR_MASK;

+ if (unlikely(base->running_timer != timer)) {
+ printk("BUG in line %d: __run_timers() is non-reentrant!\n", __LINE__);
+ goto out;
+ }
if (softirq_need_resched()) {
/* running_timer might be stale: */
set_running_timer(base, NULL);
@@ -459,6 +463,10 @@ static inline void __run_timers(tvec_bas
* valid. Any new jiffy will be taken care of in
* subsequent loops:
*/
+ if (unlikely(base->running_timer != timer)) {
+ printk("BUG in line %d: __run_timers() is non-reentrant!\n", __LINE__);
+ goto out;
+ }
}
/*
* Cascade timers:
@@ -498,7 +506,12 @@ repeat:
goto repeat;
}
}
+ if (unlikely(base->running_timer != timer)) {
+ printk("BUG in line %d: __run_timers() is non-reentrant!\n", __LINE__);
+ goto out;
+ }
set_running_timer(base, NULL);
+out:
spin_unlock_irq(&base->lock);
// if (waitqueue_active(&base->wait_running_timer))
wake_up(&base->wait_for_running_timer);