Messages in this thread Patch in this message |  | | | Date | Wed, 27 Oct 2004 10:44:01 +0200 | | From | Ingo Molnar <> | | Subject | Re: [patch] Real-Time Preemption, -RT-2.6.9-mm1-V0 |
| |
* Ingo Molnar <mingo@elte.hu> wrote:
> > Oct 26 21:43:56 porky kernel: BUG: sleeping function called from > > invalid context amlat(3963) at kernel/mutex.c:28 > > Oct 26 21:43:56 porky kernel: in_atomic():1 [00000001], irqs_disabled():1 > > Oct 26 21:43:56 porky kernel: [<c011c7da>] __might_sleep+0xca/0xe0 (12) > > Oct 26 21:43:56 porky kernel: [<c0137d89>] _mutex_lock+0x39/0x50 (36) > > Oct 26 21:43:56 porky kernel: [<c0137df6>] _mutex_lock_irqsave+0x16/0x20 (24) > > Oct 26 21:43:56 porky kernel: [<c012977d>] __mod_timer+0x4d/0x1f0 (12) > > Oct 26 21:43:56 porky kernel: [<c01f6535>] rtc_do_ioctl+0x185/0x970 (44) > > does the quick hack below help?
here's a more complete fix.
Ingo
--- linux/drivers/char/rtc.c.orig +++ linux/drivers/char/rtc.c @@ -177,7 +177,7 @@ static unsigned long rtc_max_user_freq = /* * rtc_task_lock nests inside rtc_lock. */ -static DECLARE_SPINLOCK(rtc_task_lock); +static DECLARE_RAW_SPINLOCK(rtc_task_lock); static rtc_task_t *rtc_callback = NULL; #endif @@ -238,10 +238,17 @@ irqreturn_t rtc_interrupt(int irq, void rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); } - if (rtc_status & RTC_TIMER_ON) + if (rtc_status & RTC_TIMER_ON) { + spin_unlock (&rtc_lock); + /* + * We do the mod_timer outside of the lock because + * it may reschedule under PREEMPT_REALTIME. As long + * as we read the flag race-free it is not a problem + * if two mod_timer()s race: + */ mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100); - - spin_unlock (&rtc_lock); + } else + spin_unlock (&rtc_lock); /* Now do the rest of the actions */ spin_lock(&rtc_task_lock); @@ -1094,17 +1101,19 @@ static void rtc_dropped_irq(unsigned lon return; } - /* Just in case someone disabled the timer from behind our back... */ - if (rtc_status & RTC_TIMER_ON) - mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100); - rtc_irq_data += ((rtc_freq/HZ)<<8); rtc_irq_data &= ~0xff; rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ freq = rtc_freq; - spin_unlock_irq(&rtc_lock); + /* Just in case someone disabled the timer from behind our back... */ + if (rtc_status & RTC_TIMER_ON) { + spin_unlock_irq(&rtc_lock); + mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100); + } else + spin_unlock_irq(&rtc_lock); + printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|  |