# HG changeset patch
# User kaushik
# Date 1264744731 21600
# Node ID 12c3dcae53baf45665266614d4b589875c819355
# Parent 91224343eeee460c9aafdaadc1bdedab54e92256
Search a snapshot of level 2 bits for pending upcalls.
Using only a snapshot of level 1 bits can lead to unfairness
in some cases. Consider the case where two upcalls are marked
pending after a snapshot of level 1 bits is taken. One of these
two upcalls can still be processed if the corresponding level 1
bit was already set.
This is not a perfect solution since its still possible for a level 2
bit to be set before a level 2 snapshot is taken (unless both
snapshots are taken atomically).
Signed-off-by: Kaushik Kumar Ram <kaushik@xxxxxxxx>
diff -r 91224343eeee -r 12c3dcae53ba drivers/xen/core/evtchn.c
--- a/drivers/xen/core/evtchn.c Thu Jan 21 15:05:02 2010 +0000
+++ b/drivers/xen/core/evtchn.c Thu Jan 28 23:58:51 2010 -0600
@@ -243,6 +243,8 @@ asmlinkage void evtchn_do_upcall(struct
unsigned int cpu = smp_processor_id();
shared_info_t *s = HYPERVISOR_shared_info;
vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
+ int i;
+ unsigned long local_l2[sizeof(unsigned long) * 8];
exit_idle();
irq_enter();
@@ -260,6 +262,10 @@ asmlinkage void evtchn_do_upcall(struct
wmb();
#endif
l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+
+ for(i = 0; i < BITS_PER_LONG; i++) {
+ local_l2[i] = active_evtchns(cpu, s, i);
+ }
l1i = per_cpu(last_processed_l1i, cpu);
l2i = per_cpu(last_processed_l2i, cpu);
@@ -277,7 +283,7 @@ asmlinkage void evtchn_do_upcall(struct
l1i = __ffs(masked_l1);
do {
- l2 = active_evtchns(cpu, s, l1i);
+ l2 = local_l2[l1i];
l2i = (l2i + 1) % BITS_PER_LONG;
masked_l2 = l2 & ((~0UL) << l2i);
@@ -296,13 +302,15 @@ asmlinkage void evtchn_do_upcall(struct
else
evtchn_device_upcall(port);
+ clear_bit(l2i, &local_l2[l1i]);
+
/* if this is the final port processed, we'll
pick up here+1 next time */
per_cpu(last_processed_l1i, cpu) = l1i;
per_cpu(last_processed_l2i, cpu) = l2i;
} while (l2i != BITS_PER_LONG - 1);
- l2 = active_evtchns(cpu, s, l1i);
+ l2 = local_l2[l1i];
if (l2 == 0) /* we handled all ports, so we can clear
the selector bit */
l1 &= ~(1UL << l1i);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|