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>
This commit is contained in:
Родитель
ee8fa1c67f
Коммит
229664bee6
|
@ -517,29 +517,43 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
|
||||||
int cpu = get_cpu();
|
int cpu = get_cpu();
|
||||||
struct shared_info *s = HYPERVISOR_shared_info;
|
struct shared_info *s = HYPERVISOR_shared_info;
|
||||||
struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
|
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. */
|
vcpu_info->evtchn_upcall_pending = 0;
|
||||||
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) {
|
if (__get_cpu_var(nesting_count)++)
|
||||||
int bit_idx = __ffs(pending_bits);
|
goto out;
|
||||||
int port = (word_idx * BITS_PER_LONG) + bit_idx;
|
|
||||||
int irq = evtchn_to_irq[port];
|
|
||||||
|
|
||||||
if (irq != -1) {
|
/* NB. No need for a barrier here -- XCHG is a barrier on x86. */
|
||||||
regs->orig_ax = ~irq;
|
pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
|
||||||
do_IRQ(regs);
|
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();
|
put_cpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче