# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1276758147 -3600
# Node ID dab8676e97ce7a95c0777e58eee4b1b03bfc5322
# Parent 0695a5cdcb42d98dcd4bbda35614753787aa7983
Fix sched_adjust_global() and clean up surrounding code.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/common/cpupool.c | 85 ++++++++++++++++++++++++++++++--------------
xen/common/schedule.c | 69 +++++++++++++++++------------------
xen/include/public/sysctl.h | 5 +-
xen/include/xen/sched-if.h | 2 -
xen/include/xen/sched.h | 7 ++-
5 files changed, 98 insertions(+), 70 deletions(-)
diff -r 0695a5cdcb42 -r dab8676e97ce xen/common/cpupool.c
--- a/xen/common/cpupool.c Thu Jun 17 07:22:06 2010 +0100
+++ b/xen/common/cpupool.c Thu Jun 17 08:02:27 2010 +0100
@@ -71,6 +71,22 @@ static struct cpupool *cpupool_find_by_i
return exact ? NULL : *q;
}
+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;
+}
+
+void cpupool_put(struct cpupool *pool)
+{
+ spin_unlock(&cpupool_ctl_lock);
+}
+
/*
* create a new cpupool with specified poolid and scheduler
* returns pointer to new cpupool structure if okay, NULL else
@@ -79,18 +95,22 @@ static struct cpupool *cpupool_find_by_i
* - poolid already used
* - unknown scheduler
*/
-struct cpupool *cpupool_create(int poolid, char *sched)
+static struct cpupool *cpupool_create(
+ int poolid, unsigned int sched_id, int *perr)
{
struct cpupool *c;
struct cpupool **q;
int last = 0;
+ *perr = -ENOMEM;
if ( (c = alloc_cpupool_struct()) == NULL )
return NULL;
memset(c, 0, sizeof(*c));
- cpupool_dprintk("cpupool_create(pool=%d,sched=%s)\n", poolid, sched);
- spin_lock(&cpupool_lock);
+ cpupool_dprintk("cpupool_create(pool=%d,sched=%u)\n", poolid, sched_id);
+
+ spin_lock(&cpupool_lock);
+
for_each_cpupool(q)
{
last = (*q)->cpupool_id;
@@ -100,26 +120,39 @@ struct cpupool *cpupool_create(int pooli
if ( *q != NULL )
{
if ( (*q)->cpupool_id == poolid )
+ {
+ spin_unlock(&cpupool_lock);
+ free_cpupool_struct(c);
+ *perr = -EEXIST;
+ return NULL;
+ }
+ c->next = *q;
+ }
+
+ c->cpupool_id = (poolid == CPUPOOLID_NONE) ? (last + 1) : poolid;
+ if ( poolid == 0 )
+ {
+ c->sched = scheduler_get_default();
+ }
+ else
+ {
+ c->sched = scheduler_alloc(sched_id, perr);
+ if ( c->sched == NULL )
{
spin_unlock(&cpupool_lock);
free_cpupool_struct(c);
return NULL;
}
- c->next = *q;
- }
+ }
+
*q = c;
- c->cpupool_id = (poolid == CPUPOOLID_NONE) ? (last + 1) : poolid;
- if ( (c->sched = scheduler_alloc(sched)) == NULL )
- {
- spin_unlock(&cpupool_lock);
- cpupool_destroy(c);
- return NULL;
- }
+
spin_unlock(&cpupool_lock);
cpupool_dprintk("Created cpupool %d with scheduler %s (%s)\n",
c->cpupool_id, c->sched->name, c->sched->opt_name);
+ *perr = 0;
return c;
}
/*
@@ -130,7 +163,7 @@ struct cpupool *cpupool_create(int pooli
* - cpus still assigned to pool
* - pool not in list
*/
-int cpupool_destroy(struct cpupool *c)
+static int cpupool_destroy(struct cpupool *c)
{
struct cpupool **q;
@@ -138,10 +171,15 @@ int cpupool_destroy(struct cpupool *c)
for_each_cpupool(q)
if ( *q == c )
break;
- if ( (*q != c) || (c->n_dom != 0) || cpus_weight(c->cpu_valid) )
+ if ( *q != c )
{
spin_unlock(&cpupool_lock);
- return 1;
+ return -ENOENT;
+ }
+ if ( (c->n_dom != 0) || cpus_weight(c->cpu_valid) )
+ {
+ spin_unlock(&cpupool_lock);
+ return -EBUSY;
}
*q = c->next;
spin_unlock(&cpupool_lock);
@@ -365,19 +403,11 @@ int cpupool_do_sysctl(struct xen_sysctl_
case XEN_SYSCTL_CPUPOOL_OP_CREATE:
{
int poolid;
- const struct scheduler *sched;
poolid = (op->cpupool_id == XEN_SYSCTL_CPUPOOL_PAR_ANY) ?
CPUPOOLID_NONE: op->cpupool_id;
- sched = scheduler_get_by_id(op->sched_id);
- ret = -ENOENT;
- if ( sched == NULL )
- break;
- ret = 0;
- c = cpupool_create(poolid, sched->opt_name);
- if ( c == NULL )
- ret = -EINVAL;
- else
+ c = cpupool_create(poolid, op->sched_id, &ret);
+ if ( c != NULL )
op->cpupool_id = c->cpupool_id;
}
break;
@@ -388,7 +418,7 @@ int cpupool_do_sysctl(struct xen_sysctl_
ret = -ENOENT;
if ( c == NULL )
break;
- ret = (cpupool_destroy(c) != 0) ? -EBUSY : 0;
+ ret = cpupool_destroy(c);
}
break;
@@ -571,8 +601,9 @@ static struct notifier_block cpu_nfb = {
static int __init cpupool_presmp_init(void)
{
+ int err;
void *cpu = (void *)(long)smp_processor_id();
- cpupool0 = cpupool_create(0, NULL);
+ cpupool0 = cpupool_create(0, 0, &err);
BUG_ON(cpupool0 == NULL);
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
register_cpu_notifier(&cpu_nfb);
diff -r 0695a5cdcb42 -r dab8676e97ce xen/common/schedule.c
--- a/xen/common/schedule.c Thu Jun 17 07:22:06 2010 +0100
+++ b/xen/common/schedule.c Thu Jun 17 08:02:27 2010 +0100
@@ -965,17 +965,28 @@ long sched_adjust(struct domain *d, stru
long sched_adjust_global(struct xen_sysctl_scheduler_op *op)
{
- const struct scheduler *sched;
-
- sched = scheduler_get_by_id(op->sched_id);
- if ( sched == NULL )
- return -ESRCH;
+ struct cpupool *pool;
+ int rc;
if ( (op->cmd != XEN_DOMCTL_SCHEDOP_putinfo) &&
(op->cmd != XEN_DOMCTL_SCHEDOP_getinfo) )
return -EINVAL;
- return SCHED_OP(sched, adjust_global, op);
+ pool = cpupool_get_by_id(op->cpupool_id);
+ 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);
+
+ cpupool_put(pool);
+
+ return rc;
}
static void vcpu_periodic_timer_work(struct vcpu *v)
@@ -1152,19 +1163,6 @@ static void poll_timer_fn(void *data)
if ( test_and_clear_bit(v->vcpu_id, v->domain->poll_mask) )
vcpu_unblock(v);
-}
-
-/* Get scheduler by id */
-const struct scheduler *scheduler_get_by_id(unsigned int id)
-{
- int i;
-
- for ( i = 0; schedulers[i] != NULL; i++ )
- {
- if ( schedulers[i]->sched_id == id )
- return schedulers[i];
- }
- return NULL;
}
static int cpu_schedule_up(unsigned int cpu)
@@ -1302,29 +1300,28 @@ void schedule_cpu_switch(unsigned int cp
SCHED_OP(old_ops, free_pdata, ppriv_old, cpu);
}
-struct scheduler *scheduler_alloc(char *name)
+struct scheduler *scheduler_get_default(void)
+{
+ return &ops;
+}
+
+struct scheduler *scheduler_alloc(unsigned int sched_id, int *perr)
{
int i;
- const struct scheduler *data;
struct scheduler *sched;
- if ( name == NULL )
- return &ops;
-
- data = &ops;
- for ( i = 0; (schedulers[i] != NULL) && (name != NULL) ; i++ )
- {
- if ( strcmp(schedulers[i]->opt_name, name) == 0 )
- {
- data = schedulers[i];
- break;
- }
- }
-
+ for ( i = 0; schedulers[i] != NULL; i++ )
+ if ( schedulers[i]->sched_id == sched_id )
+ goto found;
+ *perr = -ENOENT;
+ return NULL;
+
+ found:
+ *perr = -ENOMEM;
if ( (sched = xmalloc(struct scheduler)) == NULL )
return NULL;
- memcpy(sched, data, sizeof(*sched));
- if ( SCHED_OP(sched, init) != 0 )
+ memcpy(sched, schedulers[i], sizeof(*sched));
+ if ( (*perr = SCHED_OP(sched, init)) != 0 )
{
xfree(sched);
sched = NULL;
diff -r 0695a5cdcb42 -r dab8676e97ce xen/include/public/sysctl.h
--- a/xen/include/public/sysctl.h Thu Jun 17 07:22:06 2010 +0100
+++ b/xen/include/public/sysctl.h Thu Jun 17 08:02:27 2010 +0100
@@ -540,8 +540,9 @@ DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpupo
#define XEN_SYSCTL_SCHEDOP_putinfo 0
#define XEN_SYSCTL_SCHEDOP_getinfo 1
struct xen_sysctl_scheduler_op {
- uint32_t sched_id; /* XEN_SCHEDULER_* (domctl.h) */
- uint32_t cmd; /* XEN_SYSCTL_SCHEDOP_* */
+ uint32_t cpupool_id; /* Cpupool whose scheduler is to be targetted. */
+ uint32_t sched_id; /* XEN_SCHEDULER_* (domctl.h) */
+ uint32_t cmd; /* XEN_SYSCTL_SCHEDOP_* */
union {
} u;
};
diff -r 0695a5cdcb42 -r dab8676e97ce xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h Thu Jun 17 07:22:06 2010 +0100
+++ b/xen/include/xen/sched-if.h Thu Jun 17 08:02:27 2010 +0100
@@ -133,6 +133,4 @@ struct cpupool
struct scheduler *sched;
};
-const struct scheduler *scheduler_get_by_id(unsigned int id);
-
#endif /* __XEN_SCHED_IF_H__ */
diff -r 0695a5cdcb42 -r dab8676e97ce xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Thu Jun 17 07:22:06 2010 +0100
+++ b/xen/include/xen/sched.h Thu Jun 17 08:02:27 2010 +0100
@@ -592,7 +592,8 @@ void cpu_init(void);
struct scheduler;
-struct scheduler *scheduler_alloc(char *name);
+struct scheduler *scheduler_get_default(void);
+struct scheduler *scheduler_alloc(unsigned int sched_id, int *perr);
void scheduler_free(struct scheduler *sched);
void schedule_cpu_switch(unsigned int cpu, struct cpupool *c);
void vcpu_force_reschedule(struct vcpu *v);
@@ -634,8 +635,8 @@ extern enum cpufreq_controller {
#define CPUPOOLID_NONE -1
-struct cpupool *cpupool_create(int poolid, char *sched);
-int cpupool_destroy(struct cpupool *c);
+struct cpupool *cpupool_get_by_id(int poolid);
+void cpupool_put(struct cpupool *pool);
int cpupool_add_domain(struct domain *d, int poolid);
void cpupool_rm_domain(struct domain *d);
int cpupool_do_sysctl(struct xen_sysctl_cpupool_op *op);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|