{
unsigned long l1, l2;
unsigned long masked_l1, masked_l2;
- unsigned int l1i, l2i, port, count;
+ unsigned int l1i, l2i, start_l1i, start_l2i, port, count, i;
int irq;
unsigned int cpu = smp_processor_id();
shared_info_t *s = HYPERVISOR_shared_info;
#endif
l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
- l1i = per_cpu(current_l1i, cpu);
- l2i = per_cpu(current_l2i, cpu);
+ start_l1i = l1i = per_cpu(current_l1i, cpu);
+ start_l2i = per_cpu(current_l2i, cpu);
- while (l1 != 0) {
+ for (i = 0; l1 != 0; i++) {
masked_l1 = l1 & ((~0UL) << l1i);
/* If we masked out all events, wrap to beginning. */
if (masked_l1 == 0) {
}
l1i = __ffs(masked_l1);
+ l2 = active_evtchns(cpu, s, l1i);
+ l2i = 0; /* usually scan entire word from start */
+ if (l1i == start_l1i) {
+ /* We scan the starting word in two parts. */
+ if (i == 0)
+ /* 1st time: start in the middle */
+ l2i = start_l2i;
+ else
+ /* 2nd time: mask bits done already */
+ l2 &= (1ul << start_l2i) - 1;
+ }
+
do {
- l2 = active_evtchns(cpu, s, l1i);
masked_l2 = l2 & ((~0UL) << l2i);
if (masked_l2 == 0)
break;
} while (l2i != 0);
- l2 = active_evtchns(cpu, s, l1i);
- /* If we handled all ports, clear the selector bit. */
- if (l2 == 0)
+ /* Scan start_l1i twice; all others once. */
+ if ((l1i != start_l1i) || (i != 0))
l1 &= ~(1UL << l1i);
l1i = (l1i + 1) % BITS_PER_LONG;