aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-03-17 19:37:20 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-24 17:57:32 -0400
commit229664bee6126e01f8662976a5fe2e79813b77c8 (patch)
tree1e7d2fc69bae4a941952c00fa20f5746d07c0256 /arch
parentee8fa1c67f0b873a324960f0ca9fa1d7e49aa86b (diff)
xen: short-cut for recursive event handling
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/xen/events.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/arch/x86/xen/events.c b/arch/x86/xen/events.c
index f73b53bd65b7..85bac298b3cb 100644
--- a/arch/x86/xen/events.c
+++ b/arch/x86/xen/events.c
@@ -517,29 +517,43 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
517 int cpu = get_cpu(); 517 int cpu = get_cpu();
518 struct shared_info *s = HYPERVISOR_shared_info; 518 struct shared_info *s = HYPERVISOR_shared_info;
519 struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); 519 struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
520 unsigned long pending_words; 520 static DEFINE_PER_CPU(unsigned, nesting_count);
521 unsigned count;
521 522
522 vcpu_info->evtchn_upcall_pending = 0; 523 do {
524 unsigned long pending_words;
523 525
524 /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ 526 vcpu_info->evtchn_upcall_pending = 0;
525 pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
526 while (pending_words != 0) {
527 unsigned long pending_bits;
528 int word_idx = __ffs(pending_words);
529 pending_words &= ~(1UL << word_idx);
530 527
531 while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) { 528 if (__get_cpu_var(nesting_count)++)
532 int bit_idx = __ffs(pending_bits); 529 goto out;
533 int port = (word_idx * BITS_PER_LONG) + bit_idx;
534 int irq = evtchn_to_irq[port];
535 530
536 if (irq != -1) { 531 /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
537 regs->orig_ax = ~irq; 532 pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
538 do_IRQ(regs); 533 while (pending_words != 0) {
534 unsigned long pending_bits;
535 int word_idx = __ffs(pending_words);
536 pending_words &= ~(1UL << word_idx);
537
538 while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
539 int bit_idx = __ffs(pending_bits);
540 int port = (word_idx * BITS_PER_LONG) + bit_idx;
541 int irq = evtchn_to_irq[port];
542
543 if (irq != -1) {
544 regs->orig_ax = ~irq;
545 do_IRQ(regs);
546 }
539 } 547 }
540 } 548 }
541 }
542 549
550 BUG_ON(!irqs_disabled());
551
552 count = __get_cpu_var(nesting_count);
553 __get_cpu_var(nesting_count) = 0;
554 } while(count != 1);
555
556out:
543 put_cpu(); 557 put_cpu();
544} 558}
545 559