[PATCH] Dynamic sched domains: cpuset changes

Adds the core update_cpu_domains code and updated cpusets documentation

Signed-off-by: Dinakar Guniguntala <dino@in.ibm.com>
Acked-by: Paul Jackson <pj@sgi.com>
Acked-by: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Dinakar Guniguntala
2005-06-25 14:57:34 -07:00
committed by Linus Torvalds
parent 1a20ff27ef
commit 85d7b94981
2 changed files with 92 additions and 13 deletions

View File

@@ -595,10 +595,62 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
return 0;
}
/*
* For a given cpuset cur, partition the system as follows
* a. All cpus in the parent cpuset's cpus_allowed that are not part of any
* exclusive child cpusets
* b. All cpus in the current cpuset's cpus_allowed that are not part of any
* exclusive child cpusets
* Build these two partitions by calling partition_sched_domains
*
* Call with cpuset_sem held. May nest a call to the
* lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
*/
static void update_cpu_domains(struct cpuset *cur)
{
struct cpuset *c, *par = cur->parent;
cpumask_t pspan, cspan;
if (par == NULL || cpus_empty(cur->cpus_allowed))
return;
/*
* Get all cpus from parent's cpus_allowed not part of exclusive
* children
*/
pspan = par->cpus_allowed;
list_for_each_entry(c, &par->children, sibling) {
if (is_cpu_exclusive(c))
cpus_andnot(pspan, pspan, c->cpus_allowed);
}
if (is_removed(cur) || !is_cpu_exclusive(cur)) {
cpus_or(pspan, pspan, cur->cpus_allowed);
if (cpus_equal(pspan, cur->cpus_allowed))
return;
cspan = CPU_MASK_NONE;
} else {
if (cpus_empty(pspan))
return;
cspan = cur->cpus_allowed;
/*
* Get all cpus from current cpuset's cpus_allowed not part
* of exclusive children
*/
list_for_each_entry(c, &cur->children, sibling) {
if (is_cpu_exclusive(c))
cpus_andnot(cspan, cspan, c->cpus_allowed);
}
}
lock_cpu_hotplug();
partition_sched_domains(&pspan, &cspan);
unlock_cpu_hotplug();
}
static int update_cpumask(struct cpuset *cs, char *buf)
{
struct cpuset trialcs;
int retval;
int retval, cpus_unchanged;
trialcs = *cs;
retval = cpulist_parse(buf, trialcs.cpus_allowed);
@@ -608,9 +660,13 @@ static int update_cpumask(struct cpuset *cs, char *buf)
if (cpus_empty(trialcs.cpus_allowed))
return -ENOSPC;
retval = validate_change(cs, &trialcs);
if (retval == 0)
cs->cpus_allowed = trialcs.cpus_allowed;
return retval;
if (retval < 0)
return retval;
cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed);
cs->cpus_allowed = trialcs.cpus_allowed;
if (is_cpu_exclusive(cs) && !cpus_unchanged)
update_cpu_domains(cs);
return 0;
}
static int update_nodemask(struct cpuset *cs, char *buf)
@@ -646,7 +702,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
{
int turning_on;
struct cpuset trialcs;
int err;
int err, cpu_exclusive_changed;
turning_on = (simple_strtoul(buf, NULL, 10) != 0);
@@ -657,13 +713,18 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
clear_bit(bit, &trialcs.flags);
err = validate_change(cs, &trialcs);
if (err == 0) {
if (turning_on)
set_bit(bit, &cs->flags);
else
clear_bit(bit, &cs->flags);
}
return err;
if (err < 0)
return err;
cpu_exclusive_changed =
(is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
if (turning_on)
set_bit(bit, &cs->flags);
else
clear_bit(bit, &cs->flags);
if (cpu_exclusive_changed)
update_cpu_domains(cs);
return 0;
}
static int attach_task(struct cpuset *cs, char *buf)
@@ -1309,12 +1370,14 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
up(&cpuset_sem);
return -EBUSY;
}
spin_lock(&cs->dentry->d_lock);
parent = cs->parent;
set_bit(CS_REMOVED, &cs->flags);
if (is_cpu_exclusive(cs))
update_cpu_domains(cs);
list_del(&cs->sibling); /* delete my sibling from parent->children */
if (list_empty(&parent->children))
check_for_release(parent);
spin_lock(&cs->dentry->d_lock);
d = dget(cs->dentry);
cs->dentry = NULL;
spin_unlock(&d->d_lock);