debuggers.hg

changeset 22660:597e3fee23bc

credit2: Detect socket layout and assign one runqueue per socket

Because alloc_pdata() is called before the cpu layout information is
available, we grab a callback to the newly-created CPU_STARTING
notifier.

cpu 0 doesn't get a callback, so we simply hard-code it to runqueue 0.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
author Keir Fraser <keir@xen.org>
date Fri Dec 24 08:29:27 2010 +0000 (2010-12-24)
parents 3e7702cb31db
children 00fc33d9f691
files xen/common/sched_credit2.c
line diff
     1.1 --- a/xen/common/sched_credit2.c	Fri Dec 24 08:29:00 2010 +0000
     1.2 +++ b/xen/common/sched_credit2.c	Fri Dec 24 08:29:27 2010 +0000
     1.3 @@ -24,6 +24,7 @@
     1.4  #include <asm/atomic.h>
     1.5  #include <xen/errno.h>
     1.6  #include <xen/trace.h>
     1.7 +#include <xen/cpu.h>
     1.8  
     1.9  #if __i386__
    1.10  #define PRI_stime "lld"
    1.11 @@ -712,13 +713,15 @@ csched_vcpu_insert(const struct schedule
    1.12      printk("%s: Inserting d%dv%d\n",
    1.13             __func__, dom->domain_id, vc->vcpu_id);
    1.14  
    1.15 +    /* NB: On boot, idle vcpus are inserted before alloc_pdata() has
    1.16 +     * been called for that cpu.
    1.17 +     */
    1.18      if ( ! is_idle_vcpu(vc) )
    1.19      {
    1.20          /* FIXME: Do we need the private lock here? */
    1.21          list_add_tail(&svc->sdom_elem, &svc->sdom->vcpu);
    1.22  
    1.23          /* Add vcpu to runqueue of initial processor */
    1.24 -        /* FIXME: Abstract for multiple runqueues */
    1.25          vcpu_schedule_lock_irq(vc);
    1.26  
    1.27          runq_assign(ops, vc);
    1.28 @@ -1462,6 +1465,20 @@ static void init_pcpu(const struct sched
    1.29      /* Figure out which runqueue to put it in */
    1.30      rqi = 0;
    1.31  
    1.32 +    /* Figure out which runqueue to put it in */
    1.33 +    /* NB: cpu 0 doesn't get a STARTING callback, so we hard-code it to runqueue 0. */
    1.34 +    if ( cpu == 0 )
    1.35 +        rqi = 0;
    1.36 +    else
    1.37 +        rqi = cpu_to_socket(cpu);
    1.38 +
    1.39 +    if ( rqi < 0 )
    1.40 +    {
    1.41 +        printk("%s: cpu_to_socket(%d) returned %d!\n",
    1.42 +               __func__, cpu, rqi);
    1.43 +        BUG();
    1.44 +    }
    1.45 +
    1.46      rqd=prv->rqd + rqi;
    1.47  
    1.48      printk("Adding cpu %d to runqueue %d\n", cpu, rqi);
    1.49 @@ -1495,7 +1512,13 @@ static void init_pcpu(const struct sched
    1.50  static void *
    1.51  csched_alloc_pdata(const struct scheduler *ops, int cpu)
    1.52  {
    1.53 -    init_pcpu(ops, cpu);
    1.54 +    /* Check to see if the cpu is online yet */
    1.55 +    /* Note: cpu 0 doesn't get a STARTING callback */
    1.56 +    if ( cpu == 0 || cpu_to_socket(cpu) >= 0 )
    1.57 +        init_pcpu(ops, cpu);
    1.58 +    else
    1.59 +        printk("%s: cpu %d not online yet, deferring initializatgion\n",
    1.60 +               __func__, cpu);
    1.61  
    1.62      return (void *)1;
    1.63  }
    1.64 @@ -1543,6 +1566,41 @@ csched_free_pdata(const struct scheduler
    1.65  }
    1.66  
    1.67  static int
    1.68 +csched_cpu_starting(int cpu)
    1.69 +{
    1.70 +    struct scheduler *ops;
    1.71 +
    1.72 +    /* Hope this is safe from cpupools switching things around. :-) */
    1.73 +    ops = per_cpu(scheduler, cpu);
    1.74 +
    1.75 +    init_pcpu(ops, cpu);
    1.76 +
    1.77 +    return NOTIFY_DONE;
    1.78 +}
    1.79 +
    1.80 +static int cpu_credit2_callback(
    1.81 +    struct notifier_block *nfb, unsigned long action, void *hcpu)
    1.82 +{
    1.83 +    unsigned int cpu = (unsigned long)hcpu;
    1.84 +    int rc = 0;
    1.85 +
    1.86 +    switch ( action )
    1.87 +    {
    1.88 +    case CPU_STARTING:
    1.89 +        csched_cpu_starting(cpu);
    1.90 +        break;
    1.91 +    default:
    1.92 +        break;
    1.93 +    }
    1.94 +
    1.95 +    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
    1.96 +}
    1.97 +
    1.98 +static struct notifier_block cpu_credit2_nfb = {
    1.99 +    .notifier_call = cpu_credit2_callback
   1.100 +};
   1.101 +
   1.102 +static int
   1.103  csched_init(struct scheduler *ops)
   1.104  {
   1.105      int i;
   1.106 @@ -1552,15 +1610,20 @@ csched_init(struct scheduler *ops)
   1.107             " WARNING: This is experimental software in development.\n" \
   1.108             " Use at your own risk.\n");
   1.109  
   1.110 +    /* Basically no CPU information is available at this point; just
   1.111 +     * set up basic structures, and a callback when the CPU info is
   1.112 +     * available. */
   1.113 +
   1.114      prv = xmalloc(struct csched_private);
   1.115      if ( prv == NULL )
   1.116          return -ENOMEM;
   1.117      memset(prv, 0, sizeof(*prv));
   1.118      ops->sched_data = prv;
   1.119 -
   1.120      spin_lock_init(&prv->lock);
   1.121      INIT_LIST_HEAD(&prv->sdom);
   1.122  
   1.123 +    register_cpu_notifier(&cpu_credit2_nfb);
   1.124 +
   1.125      /* But un-initialize all runqueues */
   1.126      for ( i=0; i<NR_CPUS; i++)
   1.127      {