diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-12 23:41:18 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-12 23:41:18 +0000 |
commit | a5d95ebe5d0445c2330a54304495a58e1c49d4d0 (patch) | |
tree | 5ee26107db13505c98dba848371cf5fb406427ea /xen/include/xen/event.h | |
parent | f953ebc4f2e8263ddf82071f52d080bb58b34efc (diff) | |
download | xen-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.h | 33 |
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); } } |