ia64/xen-unstable

changeset 2219:c48fd545583a

bitkeeper revision 1.1159.17.25 (411c001e5mj9D5ahE9xTur4qa1WK0Q)

Elaborate on concurrency issues when notifying an evtchn, and add an
extra barrier.
author kaf24@scramble.cl.cam.ac.uk
date Thu Aug 12 23:41:18 2004 +0000 (2004-08-12)
parents bcf4ddddff97
children 7bac86571809 350a3acbb13f
files xen/include/xen/event.h
line diff
     1.1 --- a/xen/include/xen/event.h	Thu Aug 12 22:58:38 2004 +0000
     1.2 +++ b/xen/include/xen/event.h	Thu Aug 12 23:41:18 2004 +0000
     1.3 @@ -14,19 +14,6 @@
     1.4  #include <asm/bitops.h>
     1.5  
     1.6  /*
     1.7 - * GENERIC SCHEDULING CALLBACK MECHANISMS
     1.8 - */
     1.9 -
    1.10 -/* Schedule an asynchronous callback for the specified domain. */
    1.11 -static inline void guest_async_callback(struct domain *d)
    1.12 -{
    1.13 -    int running = test_bit(DF_RUNNING, &d->flags);
    1.14 -    domain_unblock(d);
    1.15 -    if ( running )
    1.16 -        smp_send_event_check_cpu(d->processor);
    1.17 -}
    1.18 -
    1.19 -/*
    1.20   * EVENT-CHANNEL NOTIFICATIONS
    1.21   * NB. On x86, the atomic bit operations also act as memory barriers. There
    1.22   * is therefore sufficiently strict ordering for this architecture -- others
    1.23 @@ -36,13 +23,29 @@ static inline void guest_async_callback(
    1.24  static inline void evtchn_set_pending(struct domain *d, int port)
    1.25  {
    1.26      shared_info_t *s = d->shared_info;
    1.27 +    int            running;
    1.28 +
    1.29 +    /* These three operations must happen in strict order. */
    1.30      if ( !test_and_set_bit(port,    &s->evtchn_pending[0]) &&
    1.31           !test_bit        (port,    &s->evtchn_mask[0])    &&
    1.32           !test_and_set_bit(port>>5, &s->evtchn_pending_sel) )
    1.33      {
    1.34          /* The VCPU pending flag must be set /after/ update to evtchn-pend. */
    1.35 -        s->vcpu_data[0].evtchn_upcall_pending = 1;
    1.36 -        guest_async_callback(d);
    1.37 +        set_bit(0, &s->vcpu_data[0].evtchn_upcall_pending);
    1.38 +
    1.39 +        /*
    1.40 +         * NB1. 'flags' and 'processor' must be checked /after/ update of
    1.41 +         * pending flag. These values may fluctuate (after all, we hold no
    1.42 +         * locks) but the key insight is that each change will cause
    1.43 +         * evtchn_upcall_pending to be polled.
    1.44 +         * 
    1.45 +         * NB2. We save DF_RUNNING across the unblock to avoid a needless
    1.46 +         * IPI for domains that we IPI'd to unblock.
    1.47 +         */
    1.48 +        running = test_bit(DF_RUNNING, &d->flags);
    1.49 +        domain_unblock(d);
    1.50 +        if ( running )
    1.51 +            smp_send_event_check_cpu(d->processor);
    1.52      }
    1.53  }
    1.54