# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxx>
# Date 1196433331 0
# Node ID 7fe1c6d02a2bd8d38b6a8b529f166990e4cd1dc3
# Parent fd879c0688bf123a85dcfa371f863da3542ab8af
Process event channels notifications in round-robin order.
Avoids fairness issue resulting from domain 0 processing lowest
numbered event channel first.
Bugzilla #1115 "Event channel port scanning unfair".
From: Scott Rixner <rixner@xxxxxxxx>
From: Diego Ongaro <dieo.ongaro@xxxxxxxx>
From: Alan L. Cox <alc@xxxxxxxx>
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
---
drivers/xen/core/evtchn.c | 60 ++++++++++++++++++++++++++++++++++++----------
1 files changed, 48 insertions(+), 12 deletions(-)
diff -r fd879c0688bf -r 7fe1c6d02a2b drivers/xen/core/evtchn.c
--- a/drivers/xen/core/evtchn.c Fri Nov 23 16:26:56 2007 +0000
+++ b/drivers/xen/core/evtchn.c Fri Nov 30 14:35:31 2007 +0000
@@ -225,11 +225,14 @@ static DEFINE_PER_CPU(unsigned int, upca
/* NB. Interrupts are disabled on entry. */
asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
{
- unsigned long l1, l2;
- unsigned int l1i, l2i, port, count;
- int irq, cpu = smp_processor_id();
- shared_info_t *s = HYPERVISOR_shared_info;
- vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
+ unsigned long l1, l2;
+ unsigned long masked_l1, masked_l2;
+ unsigned int l1i, l2i, port, count;
+ static unsigned int last_processed_l1i = BITS_PER_LONG - 1,
last_processed_l2i = BITS_PER_LONG - 1;
+ int irq, cpu = smp_processor_id();
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
+
do {
/* Avoid a callback storm when we reenable delivery. */
@@ -244,13 +247,36 @@ asmlinkage void evtchn_do_upcall(struct
rmb();
#endif
l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+
+ l1i = last_processed_l1i;
+ l2i = last_processed_l2i;
+
while (l1 != 0) {
- l1i = __ffs(l1);
- l1 &= ~(1UL << l1i);
-
- while ((l2 = active_evtchns(cpu, s, l1i)) != 0) {
- l2i = __ffs(l2);
-
+
+ l1i = (l1i + 1) % BITS_PER_LONG;
+ masked_l1 = l1 & ((~0UL) << l1i);
+
+ if (masked_l1 == 0) { /* if we masked out all events,
wrap around to the beginning */
+ l1i = BITS_PER_LONG - 1;
+ l2i = BITS_PER_LONG - 1;
+ continue;
+ }
+ l1i = __ffs(masked_l1);
+
+ do {
+ l2 = active_evtchns(cpu, s, l1i);
+
+ l2i = (l2i + 1) % BITS_PER_LONG;
+ masked_l2 = l2 & ((~0UL) << l2i);
+
+ if (masked_l2 == 0) { /* if we masked out all
events, move on */
+ l2i = BITS_PER_LONG - 1;
+ break;
+ }
+
+ l2i = __ffs(masked_l2);
+
+ /* process port */
port = (l1i * BITS_PER_LONG) + l2i;
if ((irq = evtchn_to_irq[port]) != -1)
do_IRQ(irq, regs);
@@ -258,7 +284,17 @@ asmlinkage void evtchn_do_upcall(struct
exit_idle();
evtchn_device_upcall(port);
}
- }
+
+ /* if this is the final port processed, we'll
pick up here+1 next time */
+ last_processed_l1i = l1i;
+ last_processed_l2i = l2i;
+
+ } while (l2i != BITS_PER_LONG - 1);
+
+ l2 = active_evtchns(cpu, s, l1i);
+ if (l2 == 0) /* we handled all ports, so we can clear
the selector bit */
+ l1 &= ~(1UL << l1i);
+
}
/* If there were nested callbacks then we have more to do. */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|