not bound to the polling VCPU.
Signed-off-by: Keir Fraser <keir@xensource.com>
{
evtchn_notify(v);
}
- else if ( unlikely(test_bit(_VCPUF_blocked, &v->vcpu_flags) &&
- !local_event_delivery_is_enabled()) )
+
+ /* Check if some VCPU might be polling for this event. */
+ if ( unlikely(test_bit(_DOMF_polling, &d->domain_flags)) &&
+ likely(test_and_clear_bit(_DOMF_polling, &d->domain_flags)) )
{
- /*
- * Blocked and masked will usually mean that the VCPU executed
- * SCHEDOP_poll. Kick the VCPU in case this port is in its poll list.
- */
- vcpu_unblock(v);
+ for_each_vcpu ( d, v )
+ if ( test_and_clear_bit(_VCPUF_polling, &v->vcpu_flags) )
+ vcpu_unblock(v);
}
}
}
-void evtchn_notify_reserved_port(struct domain *d, int port)
-{
- struct evtchn *chn = evtchn_from_port(d, port);
- evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);
-}
-
-
int evtchn_init(struct domain *d)
{
spin_lock_init(&d->evtchn_lock);
if ( !guest_handle_okay(sched_poll->ports, sched_poll->nr_ports) )
return -EFAULT;
- /* Ensure that events are disabled: tested by evtchn_set_pending(). */
- if ( local_event_delivery_is_enabled() )
- return -EINVAL;
-
+ /* These operations must occur in order. */
set_bit(_VCPUF_blocked, &v->vcpu_flags);
+ set_bit(_VCPUF_polling, &v->vcpu_flags);
+ set_bit(_DOMF_polling, &v->domain->domain_flags);
- /* Check for events /after/ blocking: avoids wakeup waiting race. */
+ /* Check for events /after/ setting flags: avoids wakeup waiting race. */
for ( i = 0; i < sched_poll->nr_ports; i++ )
{
rc = -EFAULT;
stop_timer(&v->poll_timer);
out:
+ clear_bit(_VCPUF_polling, &v->vcpu_flags);
clear_bit(_VCPUF_blocked, &v->vcpu_flags);
return rc;
}
static void poll_timer_fn(void *data)
{
struct vcpu *v = data;
- vcpu_unblock(v);
+ if ( test_and_clear_bit(_VCPUF_polling, &v->vcpu_flags) )
+ vcpu_unblock(v);
}
/* Initialise the data structures. */
/* Initialization completed. */
#define _VCPUF_initialised 4
#define VCPUF_initialised (1UL<<_VCPUF_initialised)
- /* VCPU is not-runnable */
+ /* VCPU is offline. */
#define _VCPUF_down 5
#define VCPUF_down (1UL<<_VCPUF_down)
/* NMI callback pending for this VCPU? */
/* Avoid NMI reentry by allowing NMIs to be masked for short periods. */
#define _VCPUF_nmi_masked 9
#define VCPUF_nmi_masked (1UL<<_VCPUF_nmi_masked)
+ /* VCPU is polling a set of event channels (SCHEDOP_poll). */
+#define _VCPUF_polling 10
+#define VCPUF_polling (1UL<<_VCPUF_polling)
/*
* Per-domain flags (domain_flags).
/* Domain is being debugged by controller software. */
#define _DOMF_debugging 4
#define DOMF_debugging (1UL<<_DOMF_debugging)
+ /* Are any VCPUs polling event channels (SCHEDOP_poll)? */
+#define _DOMF_polling 5
+#define DOMF_polling (1UL<<_DOMF_polling)
static inline int vcpu_runnable(struct vcpu *v)
{