xen/poll-single-port.patch

164 lines
5.3 KiB
Diff

Index: xen-3.3.1-testing/xen/common/domain.c
===================================================================
--- xen-3.3.1-testing.orig/xen/common/domain.c
+++ xen-3.3.1-testing/xen/common/domain.c
@@ -209,6 +209,7 @@ struct domain *domain_create(
atomic_set(&d->refcnt, 1);
spin_lock_init(&d->domain_lock);
spin_lock_init(&d->page_alloc_lock);
+ spin_lock_init(&d->poll_lock);
spin_lock_init(&d->shutdown_lock);
spin_lock_init(&d->hypercall_deadlock_mutex);
INIT_LIST_HEAD(&d->page_list);
@@ -653,7 +654,7 @@ void vcpu_reset(struct vcpu *v)
v->fpu_initialised = 0;
v->fpu_dirtied = 0;
- v->is_polling = 0;
+ v->poll_evtchn = 0;
v->is_initialised = 0;
v->nmi_pending = 0;
v->mce_pending = 0;
Index: xen-3.3.1-testing/xen/common/event_channel.c
===================================================================
--- xen-3.3.1-testing.orig/xen/common/event_channel.c
+++ xen-3.3.1-testing/xen/common/event_channel.c
@@ -545,6 +545,7 @@ out:
static int evtchn_set_pending(struct vcpu *v, int port)
{
struct domain *d = v->domain;
+ unsigned long flags;
/*
* The following bit operations must happen in strict order.
@@ -564,19 +565,36 @@ static int evtchn_set_pending(struct vcp
}
/* Check if some VCPU might be polling for this event. */
- if ( unlikely(d->is_polling) )
+ if ( likely(!d->is_polling) )
+ return 0;
+
+ spin_lock_irqsave(&d->poll_lock, flags);
+
+ if ( likely(d->is_polling) )
{
- d->is_polling = 0;
+ bool_t is_polling = 0;
+
+ d->is_polling = -1;
smp_mb(); /* check vcpu poll-flags /after/ clearing domain poll-flag */
for_each_vcpu ( d, v )
{
- if ( !v->is_polling )
+ int poll_evtchn = v->poll_evtchn;
+
+ if ( !poll_evtchn )
+ continue;
+ if ( poll_evtchn > 0 && poll_evtchn != port )
+ {
+ is_polling = 1;
continue;
- v->is_polling = 0;
+ }
+ v->poll_evtchn = 0;
vcpu_unblock(v);
}
+ cmpxchg(&d->is_polling, -1, is_polling);
}
+ spin_unlock_irqrestore(&d->poll_lock, flags);
+
return 0;
}
Index: xen-3.3.1-testing/xen/common/schedule.c
===================================================================
--- xen-3.3.1-testing.orig/xen/common/schedule.c
+++ xen-3.3.1-testing/xen/common/schedule.c
@@ -348,7 +348,7 @@ static long do_poll(struct sched_poll *s
return -EFAULT;
set_bit(_VPF_blocked, &v->pause_flags);
- v->is_polling = 1;
+ v->poll_evtchn = -1;
d->is_polling = 1;
/* Check for events /after/ setting flags: avoids wakeup waiting race. */
@@ -369,6 +369,9 @@ static long do_poll(struct sched_poll *s
goto out;
}
+ if ( i == 1 )
+ v->poll_evtchn = port;
+
if ( sched_poll->timeout != 0 )
set_timer(&v->poll_timer, sched_poll->timeout);
@@ -378,7 +381,7 @@ static long do_poll(struct sched_poll *s
return 0;
out:
- v->is_polling = 0;
+ v->poll_evtchn = 0;
clear_bit(_VPF_blocked, &v->pause_flags);
return rc;
}
@@ -760,10 +763,10 @@ static void poll_timer_fn(void *data)
{
struct vcpu *v = data;
- if ( !v->is_polling )
+ if ( !v->poll_evtchn )
return;
- v->is_polling = 0;
+ v->poll_evtchn = 0;
vcpu_unblock(v);
}
Index: xen-3.3.1-testing/xen/include/xen/sched.h
===================================================================
--- xen-3.3.1-testing.orig/xen/include/xen/sched.h
+++ xen-3.3.1-testing/xen/include/xen/sched.h
@@ -106,8 +106,6 @@ struct vcpu
bool_t fpu_initialised;
/* Has the FPU been used since it was last saved? */
bool_t fpu_dirtied;
- /* Is this VCPU polling any event channels (SCHEDOP_poll)? */
- bool_t is_polling;
/* Initialization completed for this VCPU? */
bool_t is_initialised;
/* Currently running on a CPU? */
@@ -137,6 +135,11 @@ struct vcpu
unsigned long pause_flags;
atomic_t pause_count;
+ /* Is this VCPU polling any event channels (SCHEDOP_poll)?
+ * Positive values indicate a single, negative values multiple channels
+ * being polled. */
+ int poll_evtchn;
+
/* IRQ-safe virq_lock protects against delivering VIRQ to stale evtchn. */
u16 virq_to_evtchn[NR_VIRQS];
spinlock_t virq_lock;
@@ -210,7 +213,7 @@ struct domain
/* Is this guest being debugged by dom0? */
bool_t debugger_attached;
/* Are any VCPUs polling event channels (SCHEDOP_poll)? */
- bool_t is_polling;
+ signed char is_polling;
/* Is this guest dying (i.e., a zombie)? */
enum { DOMDYING_alive, DOMDYING_dying, DOMDYING_dead } is_dying;
/* Domain is paused by controller software? */
@@ -218,6 +221,9 @@ struct domain
/* Domain's VCPUs are pinned 1:1 to physical CPUs? */
bool_t is_pinned;
+ /* Protects is_polling modification in evtchn_set_pending(). */
+ spinlock_t poll_lock;
+
/* Guest has shut down (inc. reason code)? */
spinlock_t shutdown_lock;
bool_t is_shutting_down; /* in process of shutting down? */