xen: short-cut for recursive event handling
authorJeremy Fitzhardinge <jeremy@goop.org>
Mon, 17 Mar 2008 23:37:20 +0000 (16:37 -0700)
committerIngo Molnar <mingo@elte.hu>
Thu, 24 Apr 2008 21:57:32 +0000 (23:57 +0200)
If an event comes in while events are currently being processed, then
just increment the counter and have the outer event loop reprocess the
pending events.  This prevents unbounded recursion on heavy event
loads (of course massive event storms will cause infinite loops).

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/xen/events.c

index f73b53bd65b76991b0e53015a261a9657ce23a4c..85bac298b3cb901240276959d5bd4f6e3a065947 100644 (file)
@@ -517,29 +517,43 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
        int cpu = get_cpu();
        struct shared_info *s = HYPERVISOR_shared_info;
        struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
-       unsigned long pending_words;
+       static DEFINE_PER_CPU(unsigned, nesting_count);
+       unsigned count;
 
-       vcpu_info->evtchn_upcall_pending = 0;
+       do {
+               unsigned long pending_words;
 
-       /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
-       pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
-       while (pending_words != 0) {
-               unsigned long pending_bits;
-               int word_idx = __ffs(pending_words);
-               pending_words &= ~(1UL << word_idx);
+               vcpu_info->evtchn_upcall_pending = 0;
 
-               while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
-                       int bit_idx = __ffs(pending_bits);
-                       int port = (word_idx * BITS_PER_LONG) + bit_idx;
-                       int irq = evtchn_to_irq[port];
+               if (__get_cpu_var(nesting_count)++)
+                       goto out;
 
-                       if (irq != -1) {
-                               regs->orig_ax = ~irq;
-                               do_IRQ(regs);
+               /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
+               pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
+               while (pending_words != 0) {
+                       unsigned long pending_bits;
+                       int word_idx = __ffs(pending_words);
+                       pending_words &= ~(1UL << word_idx);
+
+                       while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
+                               int bit_idx = __ffs(pending_bits);
+                               int port = (word_idx * BITS_PER_LONG) + bit_idx;
+                               int irq = evtchn_to_irq[port];
+
+                               if (irq != -1) {
+                                       regs->orig_ax = ~irq;
+                                       do_IRQ(regs);
+                               }
                        }
                }
-       }
 
+               BUG_ON(!irqs_disabled());
+
+               count = __get_cpu_var(nesting_count);
+               __get_cpu_var(nesting_count) = 0;
+       } while(count != 1);
+
+out:
        put_cpu();
 }