[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] Process event channels notifications in round-robin order.



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.