[PATCH] m32r: Fix local-timer event handling
Hirokazu Takata [Tue, 2 Aug 2005 04:11:35 +0000 (21:11 -0700)]
There was a scheduling problem of the m32r SMP kernel; A process rarely
stopped and gave no responding but the other process have been handled by
the other CPU still lives, then if we did something in the other terminal
or something like that, the stopped process came back to life and continued
its operation...  (ex.  LMbench: lat_sig)

In the m32r SMP kernel, a local-timer event is delivered by using an
IPI(inter processor interrupts); LOCAL_TIMER_IPI.  And a function
smp_send_timer() is prepared to send the LOCAL_TIMER_IPI from the current
CPU to the other CPUs.

The funtion smp_send_timer() was placed and used in do_IRQ() in
former times (before 2.6.10-rc3-mm1 kernel), however, it was
unintentionally removed when arch/m32r/kernel/irq.c was modified to
employ the generic hardirq framework (CONFIG_GENERIC_HARDIRQ) in
my previous patch.

  [PATCH 2.6.10-rc3-mm1] m32r: Use generic hardirq framework
  http://www.ussg.iu.edu/hypermail/linux/kernel/0412.2/0358.html

The following patch fixes the above problem.

Signed-off-by: Hitoshi Yamamoto <hitoshiy@isl.melco.co.jp>
Signed-off-by: Hirokazu Takata <takata@linux-m32r.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

arch/m32r/kernel/time.c

index 3c47072..8a2b77b 100644 (file)
@@ -205,8 +205,7 @@ static long last_rtc_update = 0;
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static inline void
-do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 #ifndef CONFIG_SMP
        profile_tick(CPU_PROFILING, regs);
@@ -221,6 +220,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
         * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
+       write_seqlock(&xtime_lock);
        if ((time_status & STA_UNSYNC) == 0
                && xtime.tv_sec > last_rtc_update + 660
                && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
@@ -231,6 +231,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                else    /* do it again in 60 s */
                        last_rtc_update = xtime.tv_sec - 600;
        }
+       write_sequnlock(&xtime_lock);
        /* As we return to user mode fire off the other CPU schedulers..
           this is basically because we don't yet share IRQ's around.
           This message is rigged to be safe on the 386 - basically it's
@@ -238,14 +239,8 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 
 #ifdef CONFIG_SMP
        smp_local_timer_interrupt(regs);
+       smp_send_timer();
 #endif
-}
-
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       write_seqlock(&xtime_lock);
-       do_timer_interrupt(irq, NULL, regs);
-       write_sequnlock(&xtime_lock);
 
        return IRQ_HANDLED;
 }