ia64/xen-unstable

changeset 13011:360eb996fa38

[XEN] Improve scheduler cap mechanism
Somewhat unbastardize the scheduler cap mechanism. We now cleanly
pause and unpause running VCPUs of capped out domains instead of
using sub-idle priorities. This also improves the precision of
caps a bit.
Signed-off-by: Emmanuel Ackaouy <ack@xensource.com>
author Emmanuel Ackaouy <ack@xensource.com>
date Wed Dec 13 16:13:26 2006 +0000 (2006-12-13)
parents c79f9d788204
children 903f80054bca
files xen/common/domain.c xen/common/sched_credit.c xen/include/xen/sched.h
line diff
     1.1 --- a/xen/common/domain.c	Wed Dec 13 10:20:20 2006 -0500
     1.2 +++ b/xen/common/domain.c	Wed Dec 13 16:13:26 2006 +0000
     1.3 @@ -350,18 +350,27 @@ void domain_destroy(struct domain *d)
     1.4      send_guest_global_virq(dom0, VIRQ_DOM_EXC);
     1.5  }
     1.6  
     1.7 -void vcpu_pause(struct vcpu *v)
     1.8 +static void vcpu_pause_setup(struct vcpu *v)
     1.9  {
    1.10 -    ASSERT(v != current);
    1.11 -
    1.12      spin_lock(&v->pause_lock);
    1.13      if ( v->pause_count++ == 0 )
    1.14          set_bit(_VCPUF_paused, &v->vcpu_flags);
    1.15      spin_unlock(&v->pause_lock);
    1.16 +}
    1.17  
    1.18 +void vcpu_pause(struct vcpu *v)
    1.19 +{
    1.20 +    ASSERT(v != current);
    1.21 +    vcpu_pause_setup(v);
    1.22      vcpu_sleep_sync(v);
    1.23  }
    1.24  
    1.25 +void vcpu_pause_nosync(struct vcpu *v)
    1.26 +{
    1.27 +    vcpu_pause_setup(v);
    1.28 +    vcpu_sleep_nosync(v);
    1.29 +}
    1.30 +
    1.31  void vcpu_unpause(struct vcpu *v)
    1.32  {
    1.33      int wake;
     2.1 --- a/xen/common/sched_credit.c	Wed Dec 13 10:20:20 2006 -0500
     2.2 +++ b/xen/common/sched_credit.c	Wed Dec 13 16:13:26 2006 +0000
     2.3 @@ -56,7 +56,12 @@
     2.4  #define CSCHED_PRI_TS_UNDER     -1      /* time-share w/ credits */
     2.5  #define CSCHED_PRI_TS_OVER      -2      /* time-share w/o credits */
     2.6  #define CSCHED_PRI_IDLE         -64     /* idle */
     2.7 -#define CSCHED_PRI_TS_PARKED    -65     /* time-share w/ capped credits */
     2.8 +
     2.9 +
    2.10 +/*
    2.11 + * Flags
    2.12 + */
    2.13 +#define CSCHED_FLAG_VCPU_PARKED 0x0001  /* VCPU over capped credits */
    2.14  
    2.15  
    2.16  /*
    2.17 @@ -100,6 +105,8 @@
    2.18      _MACRO(vcpu_wake_onrunq)                \
    2.19      _MACRO(vcpu_wake_runnable)              \
    2.20      _MACRO(vcpu_wake_not_runnable)          \
    2.21 +    _MACRO(vcpu_park)                       \
    2.22 +    _MACRO(vcpu_unpark)                     \
    2.23      _MACRO(tickle_local_idler)              \
    2.24      _MACRO(tickle_local_over)               \
    2.25      _MACRO(tickle_local_under)              \
    2.26 @@ -190,6 +197,7 @@ struct csched_vcpu {
    2.27      struct csched_dom *sdom;
    2.28      struct vcpu *vcpu;
    2.29      atomic_t credit;
    2.30 +    uint16_t flags;
    2.31      int16_t pri;
    2.32  #ifdef CSCHED_STATS
    2.33      struct {
    2.34 @@ -579,12 +587,11 @@ csched_vcpu_init(struct vcpu *vc)
    2.35      svc->sdom = sdom;
    2.36      svc->vcpu = vc;
    2.37      atomic_set(&svc->credit, 0);
    2.38 +    svc->flags = 0U;
    2.39      svc->pri = is_idle_domain(dom) ? CSCHED_PRI_IDLE : CSCHED_PRI_TS_UNDER;
    2.40      CSCHED_VCPU_STATS_RESET(svc);
    2.41      vc->sched_priv = svc;
    2.42  
    2.43 -    CSCHED_VCPU_CHECK(vc);
    2.44 -
    2.45      /* Allocate per-PCPU info */
    2.46      if ( unlikely(!CSCHED_PCPU(vc->processor)) )
    2.47      {
    2.48 @@ -593,7 +600,6 @@ csched_vcpu_init(struct vcpu *vc)
    2.49      }
    2.50  
    2.51      CSCHED_VCPU_CHECK(vc);
    2.52 -
    2.53      return 0;
    2.54  }
    2.55  
    2.56 @@ -673,9 +679,16 @@ csched_vcpu_wake(struct vcpu *vc)
    2.57       * This allows wake-to-run latency sensitive VCPUs to preempt
    2.58       * more CPU resource intensive VCPUs without impacting overall 
    2.59       * system fairness.
    2.60 +     *
    2.61 +     * The one exception is for VCPUs of capped domains unpausing
    2.62 +     * after earning credits they had overspent. We don't boost
    2.63 +     * those.
    2.64       */
    2.65 -    if ( svc->pri == CSCHED_PRI_TS_UNDER )
    2.66 +    if ( svc->pri == CSCHED_PRI_TS_UNDER &&
    2.67 +         !(svc->flags & CSCHED_FLAG_VCPU_PARKED) )
    2.68 +    {
    2.69          svc->pri = CSCHED_PRI_TS_BOOST;
    2.70 +    }
    2.71  
    2.72      /* Put the VCPU on the runq and tickle CPUs */
    2.73      __runq_insert(cpu, svc);
    2.74 @@ -749,11 +762,8 @@ csched_dom_init(struct domain *dom)
    2.75  static void
    2.76  csched_dom_destroy(struct domain *dom)
    2.77  {
    2.78 -    struct csched_dom * const sdom = CSCHED_DOM(dom);
    2.79 -
    2.80      CSCHED_STAT_CRANK(dom_destroy);
    2.81 -
    2.82 -    xfree(sdom);
    2.83 +    xfree(CSCHED_DOM(dom));
    2.84  }
    2.85  
    2.86  /*
    2.87 @@ -942,11 +952,19 @@ csched_acct(void)
    2.88               */
    2.89              if ( credit < 0 )
    2.90              {
    2.91 -                if ( sdom->cap != 0U && credit < -credit_cap )
    2.92 -                    svc->pri = CSCHED_PRI_TS_PARKED;
    2.93 -                else
    2.94 -                    svc->pri = CSCHED_PRI_TS_OVER;
    2.95 +                svc->pri = CSCHED_PRI_TS_OVER;
    2.96  
    2.97 +                /* Park running VCPUs of capped-out domains */
    2.98 +                if ( sdom->cap != 0U &&
    2.99 +                     credit < -credit_cap &&
   2.100 +                     !(svc->flags & CSCHED_FLAG_VCPU_PARKED) )
   2.101 +                {
   2.102 +                    CSCHED_STAT_CRANK(vcpu_park);
   2.103 +                    vcpu_pause_nosync(svc->vcpu);
   2.104 +                    svc->flags |= CSCHED_FLAG_VCPU_PARKED;
   2.105 +                }
   2.106 +
   2.107 +                /* Lower bound on credits */
   2.108                  if ( credit < -CSCHED_CREDITS_PER_TSLICE )
   2.109                  {
   2.110                      CSCHED_STAT_CRANK(acct_min_credit);
   2.111 @@ -958,6 +976,20 @@ csched_acct(void)
   2.112              {
   2.113                  svc->pri = CSCHED_PRI_TS_UNDER;
   2.114  
   2.115 +                /* Unpark any capped domains whose credits go positive */
   2.116 +                if ( svc->flags & CSCHED_FLAG_VCPU_PARKED)
   2.117 +                {
   2.118 +                    /*
   2.119 +                     * It's important to unset the flag AFTER the unpause()
   2.120 +                     * call to make sure the VCPU's priority is not boosted
   2.121 +                     * if it is woken up here.
   2.122 +                     */
   2.123 +                    CSCHED_STAT_CRANK(vcpu_unpark);
   2.124 +                    vcpu_unpause(svc->vcpu);
   2.125 +                    svc->flags &= ~CSCHED_FLAG_VCPU_PARKED;
   2.126 +                }
   2.127 +
   2.128 +                /* Upper bound on credits means VCPU stops earning */
   2.129                  if ( credit > CSCHED_CREDITS_PER_TSLICE )
   2.130                  {
   2.131                      __csched_vcpu_acct_stop_locked(svc);
   2.132 @@ -1031,10 +1063,10 @@ csched_runq_steal(int peer_cpu, int cpu,
   2.133              speer = __runq_elem(iter);
   2.134  
   2.135              /*
   2.136 -             * If next available VCPU here is not of higher priority
   2.137 -             * than ours, this PCPU is useless to us.
   2.138 +             * If next available VCPU here is not of strictly higher
   2.139 +             * priority than ours, this PCPU is useless to us.
   2.140               */
   2.141 -            if ( speer->pri <= CSCHED_PRI_IDLE || speer->pri <= pri )
   2.142 +            if ( speer->pri <= pri )
   2.143                  break;
   2.144  
   2.145              /* Is this VCPU is runnable on our PCPU? */
   2.146 @@ -1181,10 +1213,11 @@ csched_dump_vcpu(struct csched_vcpu *svc
   2.147  {
   2.148      struct csched_dom * const sdom = svc->sdom;
   2.149  
   2.150 -    printk("[%i.%i] pri=%i cpu=%i",
   2.151 +    printk("[%i.%i] pri=%i flags=%x cpu=%i",
   2.152              svc->vcpu->domain->domain_id,
   2.153              svc->vcpu->vcpu_id,
   2.154              svc->pri,
   2.155 +            svc->flags,
   2.156              svc->vcpu->processor);
   2.157  
   2.158      if ( sdom )
     3.1 --- a/xen/include/xen/sched.h	Wed Dec 13 10:20:20 2006 -0500
     3.2 +++ b/xen/include/xen/sched.h	Wed Dec 13 16:13:26 2006 +0000
     3.3 @@ -437,6 +437,7 @@ static inline int vcpu_runnable(struct v
     3.4  }
     3.5  
     3.6  void vcpu_pause(struct vcpu *v);
     3.7 +void vcpu_pause_nosync(struct vcpu *v);
     3.8  void domain_pause(struct domain *d);
     3.9  void vcpu_unpause(struct vcpu *v);
    3.10  void domain_unpause(struct domain *d);