[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 04 of 16] credit2: Refactor runqueue initialization



Several refactorizations:
* Add prv->initialized cpu mask
* Replace prv->runq_count with active_queue mask
* Replace rqd->cpu_min,cpu_mask with  active cpu mask
* Put locks in the runqueue structure, rather than borrowing the existing
cpu locks
* init() initializes all runqueues to NULL, inactive, and maps all pcpus to 
runqueue -q
* alloc_pcpu() will add cpus to runqueues, "activating" the runqueue if
necessary.  All cpus are currently assigned to runqueue 0.

End-to-end behavior of the system should remain largely the same.

Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>

diff -r 666ca1dd3ca7 -r b4aeb2f27741 xen/common/sched_credit2.c
--- a/xen/common/sched_credit2.c        Thu Dec 23 12:24:29 2010 +0000
+++ b/xen/common/sched_credit2.c        Thu Dec 23 12:24:48 2010 +0000
@@ -176,10 +176,14 @@
  */
 struct csched_runqueue_data {
     int id;
+
+    spinlock_t lock;      /* Lock for this runqueue. */
+    cpumask_t active;      /* CPUs enabled for this runqueue */
+
     struct list_head runq; /* Ordered list of runnable vms */
     struct list_head svc;  /* List of all vcpus assigned to this runqueue */
     int max_weight;
-    int cpu_min, cpu_max;  /* Range of physical cpus this runqueue runs */
+
     cpumask_t idle,        /* Currently idle */
         tickled;           /* Another cpu in the queue is already targeted for 
this one */
 };
@@ -189,12 +193,12 @@
  */
 struct csched_private {
     spinlock_t lock;
-    uint32_t ncpus;
-
+    cpumask_t initialized; /* CPU is initialized for this pool */
+    
     struct list_head sdom; /* Used mostly for dump keyhandler. */
 
     int runq_map[NR_CPUS];
-    uint32_t runq_count;
+    cpumask_t active_queues; /* Queues which may have active cpus */
     struct csched_runqueue_data rqd[NR_CPUS];
 };
 
@@ -341,7 +345,7 @@
     int i, ipid=-1;
     s_time_t lowest=(1<<30);
     struct csched_runqueue_data *rqd = RQD(ops, cpu);
-    cpumask_t *online, mask;
+    cpumask_t mask;
     struct csched_vcpu * cur;
 
     d2printk("rqt d%dv%d cd%dv%d\n",
@@ -374,9 +378,7 @@
 
     /* Otherwise, look for the non-idle cpu with the lowest credit,
      * skipping cpus which have been tickled but not scheduled yet */
-    online = CSCHED_CPUONLINE(per_cpu(cpupool, cpu));
-
-    cpus_andnot(mask, *online, rqd->idle);
+    cpus_andnot(mask, rqd->active, rqd->idle);
     cpus_andnot(mask, mask, rqd->tickled);
 
     for_each_cpu_mask(i, mask)
@@ -997,7 +999,7 @@
     const struct scheduler *ops, s_time_t now, bool_t tasklet_work_scheduled)
 {
     const int cpu = smp_processor_id();
-    struct csched_runqueue_data *rqd = RQD(ops, cpu);
+    struct csched_runqueue_data *rqd;
     struct csched_vcpu * const scurr = CSCHED_VCPU(current);
     struct csched_vcpu *snext = NULL;
     struct task_slice ret;
@@ -1010,6 +1012,10 @@
              scurr->vcpu->vcpu_id,
              now);
 
+    BUG_ON(!cpu_isset(cpu, CSCHED_PRIV(ops)->initialized));
+
+    rqd = RQD(ops, cpu);
+    BUG_ON(!cpu_isset(cpu, rqd->active));
 
     /* Protected by runqueue lock */
 
@@ -1166,14 +1172,22 @@
 {
     struct list_head *iter_sdom, *iter_svc;
     struct csched_private *prv = CSCHED_PRIV(ops);
-    int loop;
+    int i, loop;
 
-    printk("info:\n"
-           "\tncpus              = %u\n"
+    printk("Active queues: %d\n"
            "\tdefault-weight     = %d\n",
-           prv->ncpus,
+           cpus_weight(prv->active_queues),
            CSCHED_DEFAULT_WEIGHT);
+    for_each_cpu_mask(i, prv->active_queues)
+    {
+        printk("Runqueue %d:\n"
+               "\tncpus              = %u\n"
+               "\tmax_weight         = %d\n",
+               i,
+               cpus_weight(prv->rqd[i].active),
+               prv->rqd[i].max_weight);
 
+    }
     /* FIXME: Locking! */
 
     printk("Domain info:\n");
@@ -1199,16 +1213,82 @@
     }
 }
 
-static void
-csched_free_pdata(const struct scheduler *ops, void *pcpu, int cpu)
+static void activate_runqueue(struct csched_private *prv, int rqi)
 {
-    unsigned long flags;
+    struct csched_runqueue_data *rqd;
+
+    rqd = prv->rqd + rqi;
+
+    BUG_ON(!cpus_empty(rqd->active));
+
+    rqd->max_weight = 1;
+    rqd->id = rqi;
+    INIT_LIST_HEAD(&rqd->svc);
+    INIT_LIST_HEAD(&rqd->runq);
+    spin_lock_init(&rqd->lock);
+
+    cpu_set(rqi, prv->active_queues);
+}
+
+static void deactivate_runqueue(struct csched_private *prv, int rqi)
+{
+    struct csched_runqueue_data *rqd;
+
+    rqd = prv->rqd + rqi;
+
+    BUG_ON(!cpus_empty(rqd->active));
+    
+    rqd->id = -1;
+
+    cpu_clear(rqi, prv->active_queues);
+}
+
+static void init_pcpu(const struct scheduler *ops, int cpu)
+{
+    int rqi, old_rqi, flags;
     struct csched_private *prv = CSCHED_PRIV(ops);
+    struct csched_runqueue_data *rqd;
+    spinlock_t *old_lock;
 
     spin_lock_irqsave(&prv->lock, flags);
-    prv->ncpus--;
-    cpu_clear(cpu, RQD(ops, cpu)->idle);
-    printk("Removing cpu %d to pool (%d total)\n", cpu, prv->ncpus);
+
+    if ( cpu_isset(cpu, prv->initialized) )
+    {
+        printk("%s: Strange, cpu %d already initialized!\n", __func__, cpu);
+        spin_unlock_irqrestore(&prv->lock, flags);
+        return;
+    }
+
+    old_rqi = prv->runq_map[cpu];
+
+    /* Figure out which runqueue to put it in */
+    rqi = 0;
+
+    rqd=prv->rqd + rqi;
+
+    printk("Adding cpu %d to runqueue %d\n", cpu, rqi);
+    if ( ! cpu_isset(rqi, prv->active_queues) )
+    {
+        printk(" First cpu on runqueue, activating\n");
+        activate_runqueue(prv, rqi);
+    }
+    
+    /* IRQs already disabled */
+    old_lock=pcpu_schedule_lock(cpu);
+
+    /* Move spinlock to new runq lock.  */
+    per_cpu(schedule_data, cpu).schedule_lock = &rqd->lock;
+
+    /* Set the runqueue map */
+    prv->runq_map[cpu]=rqi;
+    
+    cpu_set(cpu, rqd->idle);
+    cpu_set(cpu, rqd->active);
+
+    spin_unlock(old_lock);
+
+    cpu_set(cpu, prv->initialized);
+
     spin_unlock_irqrestore(&prv->lock, flags);
 
     return;
@@ -1217,33 +1297,51 @@
 static void *
 csched_alloc_pdata(const struct scheduler *ops, int cpu)
 {
-    spinlock_t *new_lock;
-    spinlock_t *old_lock = per_cpu(schedule_data, cpu).schedule_lock;
-    unsigned long flags;
-    struct csched_private *prv = CSCHED_PRIV(ops);
-
-    spin_lock_irqsave(old_lock, flags);
-    new_lock = &per_cpu(schedule_data, prv->runq_map[cpu])._lock;
-    per_cpu(schedule_data, cpu).schedule_lock = new_lock;
-    spin_unlock_irqrestore(old_lock, flags);
-
-    spin_lock_irqsave(&prv->lock, flags);
-    prv->ncpus++;
-    cpu_set(cpu, RQD(ops, cpu)->idle);
-    printk("Adding cpu %d to pool (%d total)\n", cpu, prv->ncpus);
-    spin_unlock_irqrestore(&prv->lock, flags);
+    init_pcpu(ops, cpu);
 
     return (void *)1;
 }
 
 static void
-make_runq_map(struct csched_private *prv)
+csched_free_pdata(const struct scheduler *ops, void *pcpu, int cpu)
 {
-    /* FIXME: Read pcpu layout and do this properly */
-    prv->runq_count = 1;
-    prv->rqd[0].cpu_min = 0;
-    prv->rqd[0].cpu_max = NR_CPUS;
-    memset(prv->runq_map, 0, sizeof(prv->runq_map));
+    unsigned long flags;
+    struct csched_private *prv = CSCHED_PRIV(ops);
+    struct csched_runqueue_data *rqd;
+    int rqi;
+
+    spin_lock_irqsave(&prv->lock, flags);
+
+    BUG_ON( !cpu_isset(cpu, prv->initialized));
+    
+    /* Find the old runqueue and remove this cpu from it */
+    rqi = prv->runq_map[cpu];
+
+    rqd = prv->rqd + rqi;
+
+    /* No need to save IRQs here, they're already disabled */
+    spin_lock(&rqd->lock);
+
+    BUG_ON(!cpu_isset(cpu, rqd->idle));
+
+    printk("Removing cpu %d from runqueue %d\n", cpu, rqi);
+
+    cpu_clear(cpu, rqd->idle);
+    cpu_clear(cpu, rqd->active);
+
+    if ( cpus_empty(rqd->active) )
+    {
+        printk(" No cpus left on runqueue, disabling\n");
+        deactivate_runqueue(prv, rqi);
+    }
+
+    spin_unlock(&rqd->lock);
+
+    cpu_clear(cpu, prv->initialized);
+
+    spin_unlock_irqrestore(&prv->lock, flags);
+
+    return;
 }
 
 static int
@@ -1265,18 +1363,11 @@
     spin_lock_init(&prv->lock);
     INIT_LIST_HEAD(&prv->sdom);
 
-    prv->ncpus = 0;
-
-    make_runq_map(prv);
-
-    for ( i=0; i<prv->runq_count ; i++ )
+    /* But un-initialize all runqueues */
+    for ( i=0; i<NR_CPUS; i++)
     {
-        struct csched_runqueue_data *rqd = prv->rqd + i;
-
-        rqd->max_weight = 1;
-        rqd->id = i;
-        INIT_LIST_HEAD(&rqd->svc);
-        INIT_LIST_HEAD(&rqd->runq);
+        prv->runq_map[i] = -1;
+        prv->rqd[i].id = -1;
     }
 
     return 0;

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.