aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/xen/event.h
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-08-12 23:41:18 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-08-12 23:41:18 +0000
commita5d95ebe5d0445c2330a54304495a58e1c49d4d0 (patch)
tree5ee26107db13505c98dba848371cf5fb406427ea /xen/include/xen/event.h
parentf953ebc4f2e8263ddf82071f52d080bb58b34efc (diff)
downloadxen-a5d95ebe5d0445c2330a54304495a58e1c49d4d0.tar.gz
xen-a5d95ebe5d0445c2330a54304495a58e1c49d4d0.tar.bz2
xen-a5d95ebe5d0445c2330a54304495a58e1c49d4d0.zip
bitkeeper revision 1.1159.17.25 (411c001e5mj9D5ahE9xTur4qa1WK0Q)
Elaborate on concurrency issues when notifying an evtchn, and add an extra barrier.
Diffstat (limited to 'xen/include/xen/event.h')
-rw-r--r--xen/include/xen/event.h33
1 files changed, 18 insertions, 15 deletions
diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h
index e7ee55da02..1fcef0f03e 100644
--- a/xen/include/xen/event.h
+++ b/xen/include/xen/event.h
@@ -14,19 +14,6 @@
#include <asm/bitops.h>
/*
- * GENERIC SCHEDULING CALLBACK MECHANISMS
- */
-
-/* Schedule an asynchronous callback for the specified domain. */
-static inline void guest_async_callback(struct domain *d)
-{
- int running = test_bit(DF_RUNNING, &d->flags);
- domain_unblock(d);
- if ( running )
- smp_send_event_check_cpu(d->processor);
-}
-
-/*
* EVENT-CHANNEL NOTIFICATIONS
* NB. On x86, the atomic bit operations also act as memory barriers. There
* is therefore sufficiently strict ordering for this architecture -- others
@@ -36,13 +23,29 @@ static inline void guest_async_callback(struct domain *d)
static inline void evtchn_set_pending(struct domain *d, int port)
{
shared_info_t *s = d->shared_info;
+ int running;
+
+ /* These three operations must happen in strict order. */
if ( !test_and_set_bit(port, &s->evtchn_pending[0]) &&
!test_bit (port, &s->evtchn_mask[0]) &&
!test_and_set_bit(port>>5, &s->evtchn_pending_sel) )
{
/* The VCPU pending flag must be set /after/ update to evtchn-pend. */
- s->vcpu_data[0].evtchn_upcall_pending = 1;
- guest_async_callback(d);
+ set_bit(0, &s->vcpu_data[0].evtchn_upcall_pending);
+
+ /*
+ * NB1. 'flags' and 'processor' must be checked /after/ update of
+ * pending flag. These values may fluctuate (after all, we hold no
+ * locks) but the key insight is that each change will cause
+ * evtchn_upcall_pending to be polled.
+ *
+ * NB2. We save DF_RUNNING across the unblock to avoid a needless
+ * IPI for domains that we IPI'd to unblock.
+ */
+ running = test_bit(DF_RUNNING, &d->flags);
+ domain_unblock(d);
+ if ( running )
+ smp_send_event_check_cpu(d->processor);
}
}