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

[Xen-changelog] [xen-unstable] cpupool: Simplify locking, use refcounts for cpupool liveness.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxx>
# Date 1290766077 0
# Node ID aee9a8f63aaefb1a3801eea2f7d9cddfeb5486df
# Parent  79b71c77907b80772ee8cba0c5bbf8e444e61226
cpupool: Simplify locking, use refcounts for cpupool liveness.

Signed-off-by: Keir Fraser <keir@xxxxxxx>
---
 xen/common/cpupool.c       |   82 +++++++++++++++++++++++++--------------------
 xen/common/schedule.c      |    9 +---
 xen/include/xen/sched-if.h |    1 
 3 files changed, 49 insertions(+), 43 deletions(-)

diff -r 79b71c77907b -r aee9a8f63aae xen/common/cpupool.c
--- a/xen/common/cpupool.c      Wed Nov 24 10:20:03 2010 +0000
+++ b/xen/common/cpupool.c      Fri Nov 26 10:07:57 2010 +0000
@@ -31,11 +31,7 @@ static struct cpupool *cpupool_cpu_movin
 static struct cpupool *cpupool_cpu_moving = NULL;
 static cpumask_t cpupool_locked_cpus = CPU_MASK_NONE;
 
-/* cpupool lock: be carefull, this lock is sometimes released on another cpu
- *               as it was obtained!
- */
 static DEFINE_SPINLOCK(cpupool_lock);
-static DEFINE_SPINLOCK(cpupool_ctl_lock);
 
 DEFINE_PER_CPU(struct cpupool *, cpupool);
 
@@ -61,30 +57,37 @@ static struct cpupool *cpupool_find_by_i
 {
     struct cpupool **q;
 
+    ASSERT(spin_is_locked(&cpupool_lock));
+
     for_each_cpupool(q)
-    {
-        if ( (*q)->cpupool_id == id )
-            return *q;
-        if ( (*q)->cpupool_id > id )
-            break;
-    }
-    return exact ? NULL : *q;
+        if ( (*q)->cpupool_id >= id )
+            break;
+
+    return (!exact || ((*q)->cpupool_id == id)) ? *q : NULL;
+}
+
+static struct cpupool *__cpupool_get_by_id(int poolid, int exact)
+{
+    struct cpupool *c;
+    spin_lock(&cpupool_lock);
+    c = cpupool_find_by_id(poolid, exact);
+    if ( c != NULL )
+        atomic_inc(&c->refcnt);
+    spin_unlock(&cpupool_lock);
+    return c;
 }
 
 struct cpupool *cpupool_get_by_id(int poolid)
 {
-    struct cpupool *c;
-    /* cpupool_ctl_lock protects against concurrent pool destruction */
-    spin_lock(&cpupool_ctl_lock);
-    c = cpupool_find_by_id(poolid, 1);
-    if ( c == NULL )
-        spin_unlock(&cpupool_ctl_lock);
-    return c;
+    return __cpupool_get_by_id(poolid, 1);
 }
 
 void cpupool_put(struct cpupool *pool)
 {
-    spin_unlock(&cpupool_ctl_lock);
+    if ( !atomic_dec_and_test(&pool->refcnt) )
+        return;
+    scheduler_free(pool->sched);
+    free_cpupool_struct(pool);
 }
 
 /*
@@ -107,6 +110,9 @@ static struct cpupool *cpupool_create(
         return NULL;
     memset(c, 0, sizeof(*c));
 
+    /* One reference for caller, one reference for cpupool_destroy(). */
+    atomic_set(&c->refcnt, 2);
+
     cpupool_dprintk("cpupool_create(pool=%d,sched=%u)\n", poolid, sched_id);
 
     spin_lock(&cpupool_lock);
@@ -183,9 +189,10 @@ static int cpupool_destroy(struct cpupoo
     }
     *q = c->next;
     spin_unlock(&cpupool_lock);
+
+    cpupool_put(c);
+
     cpupool_dprintk("cpupool_destroy(pool=%d)\n", c->cpupool_id);
-    scheduler_free(c->sched);
-    free_cpupool_struct(c);
     return 0;
 }
 
@@ -203,6 +210,7 @@ static int cpupool_assign_cpu_locked(str
     if (cpupool_moving_cpu == cpu)
     {
         cpupool_moving_cpu = -1;
+        cpupool_put(cpupool_cpu_moving);
         cpupool_cpu_moving = NULL;
     }
     cpu_set(cpu, c->cpu_valid);
@@ -217,6 +225,7 @@ static long cpupool_unassign_cpu_helper(
     cpupool_dprintk("cpupool_unassign_cpu(pool=%d,cpu=%d) ret %ld\n",
                     cpupool_id, cpu, ret);
 
+    spin_lock(&cpupool_lock);
     ret = cpu_disable_scheduler(cpu);
     cpu_set(cpu, cpupool_free_cpus);
     if ( !ret )
@@ -224,6 +233,7 @@ static long cpupool_unassign_cpu_helper(
         schedule_cpu_switch(cpu, NULL);
         per_cpu(cpupool, cpu) = NULL;
         cpupool_moving_cpu = -1;
+        cpupool_put(cpupool_cpu_moving);
         cpupool_cpu_moving = NULL;
     }
     spin_unlock(&cpupool_lock);
@@ -287,8 +297,11 @@ int cpupool_unassign_cpu(struct cpupool 
             goto out;
     }
     cpupool_moving_cpu = cpu;
+    atomic_inc(&c->refcnt);
     cpupool_cpu_moving = c;
     cpu_clear(cpu, c->cpu_valid);
+    spin_unlock(&cpupool_lock);
+
     work_cpu = smp_processor_id();
     if ( work_cpu == cpu )
     {
@@ -395,8 +408,6 @@ int cpupool_do_sysctl(struct xen_sysctl_
     int ret;
     struct cpupool *c;
 
-    spin_lock(&cpupool_ctl_lock);
-
     switch ( op->op )
     {
 
@@ -408,30 +419,35 @@ int cpupool_do_sysctl(struct xen_sysctl_
             CPUPOOLID_NONE: op->cpupool_id;
         c = cpupool_create(poolid, op->sched_id, &ret);
         if ( c != NULL )
+        {
             op->cpupool_id = c->cpupool_id;
+            cpupool_put(c);
+        }
     }
     break;
 
     case XEN_SYSCTL_CPUPOOL_OP_DESTROY:
     {
-        c = cpupool_find_by_id(op->cpupool_id, 1);
+        c = cpupool_get_by_id(op->cpupool_id);
         ret = -ENOENT;
         if ( c == NULL )
             break;
         ret = cpupool_destroy(c);
+        cpupool_put(c);
     }
     break;
 
     case XEN_SYSCTL_CPUPOOL_OP_INFO:
     {
-        c = cpupool_find_by_id(op->cpupool_id, 0);
+        c = __cpupool_get_by_id(op->cpupool_id, 0);
         ret = -ENOENT;
         if ( c == NULL )
             break;
         op->cpupool_id = c->cpupool_id;
         op->sched_id = c->sched->sched_id;
         op->n_dom = c->n_dom;
-        ret = cpumask_to_xenctl_cpumap(&(op->cpumap), &(c->cpu_valid));
+        ret = cpumask_to_xenctl_cpumap(&op->cpumap, &c->cpu_valid);
+        cpupool_put(c);
     }
     break;
 
@@ -467,20 +483,15 @@ int cpupool_do_sysctl(struct xen_sysctl_
     {
         unsigned cpu;
 
-        c = cpupool_find_by_id(op->cpupool_id, 0);
+        c = __cpupool_get_by_id(op->cpupool_id, 0);
         ret = -ENOENT;
         if ( c == NULL )
             break;
         cpu = op->cpu;
         if ( cpu == XEN_SYSCTL_CPUPOOL_PAR_ANY )
             cpu = last_cpu(c->cpu_valid);
-        ret = -EINVAL;
-        if ( cpu >= NR_CPUS )
-            break;
-        /* caution: cpupool_unassign_cpu uses continue_hypercall_on_cpu and
-         * will continue after the local return
-         */
-        ret = cpupool_unassign_cpu(c, cpu);
+        ret = (cpu < NR_CPUS) ? cpupool_unassign_cpu(c, cpu) : -EINVAL;
+        cpupool_put(c);
     }
     break;
 
@@ -539,8 +550,6 @@ int cpupool_do_sysctl(struct xen_sysctl_
         ret = -ENOSYS;
         break;
     }
-
-    spin_unlock(&cpupool_ctl_lock);
 
     return ret;
 }
@@ -605,6 +614,7 @@ static int __init cpupool_presmp_init(vo
     void *cpu = (void *)(long)smp_processor_id();
     cpupool0 = cpupool_create(0, 0, &err);
     BUG_ON(cpupool0 == NULL);
+    cpupool_put(cpupool0);
     cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
     register_cpu_notifier(&cpu_nfb);
     return 0;
diff -r 79b71c77907b -r aee9a8f63aae xen/common/schedule.c
--- a/xen/common/schedule.c     Wed Nov 24 10:20:03 2010 +0000
+++ b/xen/common/schedule.c     Fri Nov 26 10:07:57 2010 +0000
@@ -999,13 +999,8 @@ long sched_adjust_global(struct xen_sysc
     if ( pool == NULL )
         return -ESRCH;
 
-    if ( op->sched_id != pool->sched->sched_id )
-    {
-        cpupool_put(pool);
-        return -EINVAL;
-    }
-
-    rc = SCHED_OP(pool->sched, adjust_global, op);
+    rc = ((op->sched_id == pool->sched->sched_id)
+          ? SCHED_OP(pool->sched, adjust_global, op) : -EINVAL);
 
     cpupool_put(pool);
 
diff -r 79b71c77907b -r aee9a8f63aae xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h        Wed Nov 24 10:20:03 2010 +0000
+++ b/xen/include/xen/sched-if.h        Fri Nov 26 10:07:57 2010 +0000
@@ -133,6 +133,7 @@ struct cpupool
     struct cpupool   *next;
     unsigned int     n_dom;
     struct scheduler *sched;
+    atomic_t         refcnt;
 };
 
 #endif /* __XEN_SCHED_IF_H__ */

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


 


Rackspace

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