[XEN] Various softirq cleanups. Main one is to always
authorkfraser@dhcp93.uk.xensource.com <kfraser@dhcp93.uk.xensource.com>
Fri, 30 Jun 2006 12:25:43 +0000 (13:25 +0100)
committerkfraser@dhcp93.uk.xensource.com <kfraser@dhcp93.uk.xensource.com>
Fri, 30 Jun 2006 12:25:43 +0000 (13:25 +0100)
call smp_processor_id() after any softirq, as rescheduling
may cause us to move to another processor on ia64
(spotted by Isaku Yamahata). Also get rid of many direct
callers of do_softirq() by creating new function
process_pending_timers().
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/domain.c
xen/arch/x86/smpboot.c
xen/common/page_alloc.c
xen/common/softirq.c
xen/common/timer.c
xen/drivers/char/console.c
xen/include/xen/timer.h

index b4ad1a7a811d27ad4c65fe2ae4ce8e4a3784f8d0..3b8abf4893f13de04be63057885f033f4f5bacce 100644 (file)
@@ -67,16 +67,11 @@ static void default_idle(void)
 
 void idle_loop(void)
 {
-    int cpu = smp_processor_id();
-
     for ( ; ; )
     {
         page_scrub_schedule_work();
-
         default_idle();
-
-        if ( softirq_pending(cpu) )
-            do_softirq();
+        do_softirq();
     }
 }
 
index f75c01f7b2d60ca0ef83b279b8b3d5a7a6b59333..a78ed07d2643f5eb5ca8f40657f9d67648eb10ee 100644 (file)
@@ -1197,8 +1197,7 @@ int __devinit __cpu_up(unsigned int cpu)
        cpu_set(cpu, smp_commenced_mask);
        while (!cpu_isset(cpu, cpu_online_map)) {
                mb();
-               if (softirq_pending(0))
-                       do_softirq();
+               process_pending_timers();
        }
        return 0;
 }
index 9a20eaf8747cce07cdd74ba213a66ddb0ef0f4e6..fc5cc76ac38786501672bdc340ba3e78e39d39c5 100644 (file)
@@ -388,7 +388,6 @@ void scrub_heap_pages(void)
 {
     void *p;
     unsigned long pfn;
-    int cpu = smp_processor_id();
 
     printk("Scrubbing Free RAM: ");
 
@@ -398,8 +397,7 @@ void scrub_heap_pages(void)
         if ( (pfn % ((100*1024*1024)/PAGE_SIZE)) == 0 )
             printk(".");
 
-        if ( unlikely(softirq_pending(cpu)) )
-            do_softirq();
+        process_pending_timers();
 
         /* Quick lock-free check. */
         if ( allocated_in_map(pfn) )
index f8a2c3780ca51f142385a01cfd1990af1df1f170..fb220694fe8f32d7408ac4bac5d130f81228e9fd 100644 (file)
@@ -23,17 +23,23 @@ static softirq_handler softirq_handlers[NR_SOFTIRQS];
 
 asmlinkage void do_softirq(void)
 {
-    unsigned int i, cpu = smp_processor_id();
+    unsigned int i, cpu;
     unsigned long pending;
 
-    pending = softirq_pending(cpu);
-    ASSERT(pending != 0);
+    for ( ; ; )
+    {
+        /*
+         * Initialise @cpu on every iteration: SCHEDULE_SOFTIRQ may move
+         * us to another processor.
+         */
+        cpu = smp_processor_id();
+        if ( (pending = softirq_pending(cpu)) == 0 )
+            break;
 
-    do {
         i = find_first_set_bit(pending);
         clear_bit(i, &softirq_pending(cpu));
         (*softirq_handlers[i])();
-    } while ( (pending = softirq_pending(cpu)) != 0 );
+    }
 }
 
 void open_softirq(int nr, softirq_handler handler)
index 10985fdd8b8899fd2c2cb03049b4cbb36043b36e..eb5636b51f1efdad9117c7401cf7da16d81dd6be 100644 (file)
@@ -327,6 +327,15 @@ static void timer_softirq_action(void)
 }
 
 
+void process_pending_timers(void)
+{
+    unsigned int cpu = smp_processor_id();
+    ASSERT(!in_irq() && local_irq_is_enabled());
+    if ( test_and_clear_bit(TIMER_SOFTIRQ, &softirq_pending(cpu)) )
+        timer_softirq_action();
+}
+
+
 static void dump_timerq(unsigned char key)
 {
     struct timer *t;
index 2765d4e2e0f24c3024cd686525fa7a95923f0bcd..3bc2659d83cf77cef0f5695c6d0c6a5713ddd55f 100644 (file)
@@ -528,8 +528,7 @@ void console_endboot(void)
             printk("%d... ", 3-i);
             for ( j = 0; j < 100; j++ )
             {
-                if ( softirq_pending(smp_processor_id()) )
-                    do_softirq();
+                process_pending_timers();
                 mdelay(10);
             }
         }
index f0c9b7e8a5fc30e3fc4e9917369a2852b3de2e87..495e81c4c3f371008b7d054d30cdf6337d6575dd 100644 (file)
@@ -88,6 +88,12 @@ extern void migrate_timer(struct timer *timer, unsigned int new_cpu);
  */
 extern void kill_timer(struct timer *timer);
 
+/*
+ * Process pending timers on this CPU. This should be called periodically
+ * when performing work that prevents softirqs from running in a timely manner.
+ */
+extern void process_pending_timers(void);
+
 /*
  * Bootstrap initialisation. Must be called before any other timer function.
  */