sched, cpuset: customize sched domains, core
[rebased for sched-devel/latest] - Add a new cpuset file, having levels: sched_relax_domain_level - Modify partition_sched_domains() and build_sched_domains() to take attributes parameter passed from cpuset. - Fill newidle_idx for node domains which currently unused but might be required if sched_relax_domain_level become higher. - We can change the default level by boot option 'relax_domain_level='. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
4d5f35533f
commit
1d3504fcf5
7 changed files with 161 additions and 11 deletions
|
@ -93,7 +93,7 @@ void build_cpu_to_node_map(void);
|
||||||
.cache_nice_tries = 2, \
|
.cache_nice_tries = 2, \
|
||||||
.busy_idx = 3, \
|
.busy_idx = 3, \
|
||||||
.idle_idx = 2, \
|
.idle_idx = 2, \
|
||||||
.newidle_idx = 0, /* unused */ \
|
.newidle_idx = 2, \
|
||||||
.wake_idx = 1, \
|
.wake_idx = 1, \
|
||||||
.forkexec_idx = 1, \
|
.forkexec_idx = 1, \
|
||||||
.flags = SD_LOAD_BALANCE \
|
.flags = SD_LOAD_BALANCE \
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
.cache_nice_tries = 2, \
|
.cache_nice_tries = 2, \
|
||||||
.busy_idx = 3, \
|
.busy_idx = 3, \
|
||||||
.idle_idx = 2, \
|
.idle_idx = 2, \
|
||||||
.newidle_idx = 0, \
|
.newidle_idx = 2, \
|
||||||
.wake_idx = 1, \
|
.wake_idx = 1, \
|
||||||
.forkexec_idx = 1, \
|
.forkexec_idx = 1, \
|
||||||
.flags = SD_LOAD_BALANCE \
|
.flags = SD_LOAD_BALANCE \
|
||||||
|
|
|
@ -147,7 +147,7 @@ extern unsigned long node_remap_size[];
|
||||||
|
|
||||||
# define SD_CACHE_NICE_TRIES 2
|
# define SD_CACHE_NICE_TRIES 2
|
||||||
# define SD_IDLE_IDX 2
|
# define SD_IDLE_IDX 2
|
||||||
# define SD_NEWIDLE_IDX 0
|
# define SD_NEWIDLE_IDX 2
|
||||||
# define SD_FORKEXEC_IDX 1
|
# define SD_FORKEXEC_IDX 1
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -704,6 +704,7 @@ enum cpu_idle_type {
|
||||||
#define SD_POWERSAVINGS_BALANCE 256 /* Balance for power savings */
|
#define SD_POWERSAVINGS_BALANCE 256 /* Balance for power savings */
|
||||||
#define SD_SHARE_PKG_RESOURCES 512 /* Domain members share cpu pkg resources */
|
#define SD_SHARE_PKG_RESOURCES 512 /* Domain members share cpu pkg resources */
|
||||||
#define SD_SERIALIZE 1024 /* Only a single load balancing instance */
|
#define SD_SERIALIZE 1024 /* Only a single load balancing instance */
|
||||||
|
#define SD_WAKE_IDLE_FAR 2048 /* Gain latency sacrificing cache hit */
|
||||||
|
|
||||||
#define BALANCE_FOR_MC_POWER \
|
#define BALANCE_FOR_MC_POWER \
|
||||||
(sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0)
|
(sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0)
|
||||||
|
@ -733,6 +734,24 @@ struct sched_group {
|
||||||
u32 reciprocal_cpu_power;
|
u32 reciprocal_cpu_power;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sched_domain_level {
|
||||||
|
SD_LV_NONE = 0,
|
||||||
|
SD_LV_SIBLING,
|
||||||
|
SD_LV_MC,
|
||||||
|
SD_LV_CPU,
|
||||||
|
SD_LV_NODE,
|
||||||
|
SD_LV_ALLNODES,
|
||||||
|
SD_LV_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sched_domain_attr {
|
||||||
|
int relax_domain_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SD_ATTR_INIT (struct sched_domain_attr) { \
|
||||||
|
.relax_domain_level = -1, \
|
||||||
|
}
|
||||||
|
|
||||||
struct sched_domain {
|
struct sched_domain {
|
||||||
/* These fields must be setup */
|
/* These fields must be setup */
|
||||||
struct sched_domain *parent; /* top domain must be null terminated */
|
struct sched_domain *parent; /* top domain must be null terminated */
|
||||||
|
@ -750,6 +769,7 @@ struct sched_domain {
|
||||||
unsigned int wake_idx;
|
unsigned int wake_idx;
|
||||||
unsigned int forkexec_idx;
|
unsigned int forkexec_idx;
|
||||||
int flags; /* See SD_* */
|
int flags; /* See SD_* */
|
||||||
|
enum sched_domain_level level;
|
||||||
|
|
||||||
/* Runtime fields. */
|
/* Runtime fields. */
|
||||||
unsigned long last_balance; /* init to jiffies. units in jiffies */
|
unsigned long last_balance; /* init to jiffies. units in jiffies */
|
||||||
|
@ -789,7 +809,8 @@ struct sched_domain {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new);
|
extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
|
||||||
|
struct sched_domain_attr *dattr_new);
|
||||||
extern int arch_reinit_sched_domains(void);
|
extern int arch_reinit_sched_domains(void);
|
||||||
|
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
|
@ -98,6 +98,9 @@ struct cpuset {
|
||||||
/* partition number for rebuild_sched_domains() */
|
/* partition number for rebuild_sched_domains() */
|
||||||
int pn;
|
int pn;
|
||||||
|
|
||||||
|
/* for custom sched domain */
|
||||||
|
int relax_domain_level;
|
||||||
|
|
||||||
/* used for walking a cpuset heirarchy */
|
/* used for walking a cpuset heirarchy */
|
||||||
struct list_head stack_list;
|
struct list_head stack_list;
|
||||||
};
|
};
|
||||||
|
@ -478,6 +481,16 @@ static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
|
||||||
return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
|
return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c)
|
||||||
|
{
|
||||||
|
if (!dattr)
|
||||||
|
return;
|
||||||
|
if (dattr->relax_domain_level < c->relax_domain_level)
|
||||||
|
dattr->relax_domain_level = c->relax_domain_level;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rebuild_sched_domains()
|
* rebuild_sched_domains()
|
||||||
*
|
*
|
||||||
|
@ -553,12 +566,14 @@ static void rebuild_sched_domains(void)
|
||||||
int csn; /* how many cpuset ptrs in csa so far */
|
int csn; /* how many cpuset ptrs in csa so far */
|
||||||
int i, j, k; /* indices for partition finding loops */
|
int i, j, k; /* indices for partition finding loops */
|
||||||
cpumask_t *doms; /* resulting partition; i.e. sched domains */
|
cpumask_t *doms; /* resulting partition; i.e. sched domains */
|
||||||
|
struct sched_domain_attr *dattr; /* attributes for custom domains */
|
||||||
int ndoms; /* number of sched domains in result */
|
int ndoms; /* number of sched domains in result */
|
||||||
int nslot; /* next empty doms[] cpumask_t slot */
|
int nslot; /* next empty doms[] cpumask_t slot */
|
||||||
|
|
||||||
q = NULL;
|
q = NULL;
|
||||||
csa = NULL;
|
csa = NULL;
|
||||||
doms = NULL;
|
doms = NULL;
|
||||||
|
dattr = NULL;
|
||||||
|
|
||||||
/* Special case for the 99% of systems with one, full, sched domain */
|
/* Special case for the 99% of systems with one, full, sched domain */
|
||||||
if (is_sched_load_balance(&top_cpuset)) {
|
if (is_sched_load_balance(&top_cpuset)) {
|
||||||
|
@ -566,6 +581,11 @@ static void rebuild_sched_domains(void)
|
||||||
doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
|
doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
|
||||||
if (!doms)
|
if (!doms)
|
||||||
goto rebuild;
|
goto rebuild;
|
||||||
|
dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL);
|
||||||
|
if (dattr) {
|
||||||
|
*dattr = SD_ATTR_INIT;
|
||||||
|
update_domain_attr(dattr, &top_cpuset);
|
||||||
|
}
|
||||||
*doms = top_cpuset.cpus_allowed;
|
*doms = top_cpuset.cpus_allowed;
|
||||||
goto rebuild;
|
goto rebuild;
|
||||||
}
|
}
|
||||||
|
@ -622,6 +642,7 @@ restart:
|
||||||
doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
|
doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
|
||||||
if (!doms)
|
if (!doms)
|
||||||
goto rebuild;
|
goto rebuild;
|
||||||
|
dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL);
|
||||||
|
|
||||||
for (nslot = 0, i = 0; i < csn; i++) {
|
for (nslot = 0, i = 0; i < csn; i++) {
|
||||||
struct cpuset *a = csa[i];
|
struct cpuset *a = csa[i];
|
||||||
|
@ -644,12 +665,15 @@ restart:
|
||||||
}
|
}
|
||||||
|
|
||||||
cpus_clear(*dp);
|
cpus_clear(*dp);
|
||||||
|
if (dattr)
|
||||||
|
*(dattr + nslot) = SD_ATTR_INIT;
|
||||||
for (j = i; j < csn; j++) {
|
for (j = i; j < csn; j++) {
|
||||||
struct cpuset *b = csa[j];
|
struct cpuset *b = csa[j];
|
||||||
|
|
||||||
if (apn == b->pn) {
|
if (apn == b->pn) {
|
||||||
cpus_or(*dp, *dp, b->cpus_allowed);
|
cpus_or(*dp, *dp, b->cpus_allowed);
|
||||||
b->pn = -1;
|
b->pn = -1;
|
||||||
|
update_domain_attr(dattr, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nslot++;
|
nslot++;
|
||||||
|
@ -660,7 +684,7 @@ restart:
|
||||||
rebuild:
|
rebuild:
|
||||||
/* Have scheduler rebuild sched domains */
|
/* Have scheduler rebuild sched domains */
|
||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
partition_sched_domains(ndoms, doms);
|
partition_sched_domains(ndoms, doms, dattr);
|
||||||
put_online_cpus();
|
put_online_cpus();
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -668,6 +692,7 @@ done:
|
||||||
kfifo_free(q);
|
kfifo_free(q);
|
||||||
kfree(csa);
|
kfree(csa);
|
||||||
/* Don't kfree(doms) -- partition_sched_domains() does that. */
|
/* Don't kfree(doms) -- partition_sched_domains() does that. */
|
||||||
|
/* Don't kfree(dattr) -- partition_sched_domains() does that. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int started_after_time(struct task_struct *t1,
|
static inline int started_after_time(struct task_struct *t1,
|
||||||
|
@ -1011,6 +1036,21 @@ static int update_memory_pressure_enabled(struct cpuset *cs, char *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int update_relax_domain_level(struct cpuset *cs, char *buf)
|
||||||
|
{
|
||||||
|
int val = simple_strtol(buf, NULL, 10);
|
||||||
|
|
||||||
|
if (val < 0)
|
||||||
|
val = -1;
|
||||||
|
|
||||||
|
if (val != cs->relax_domain_level) {
|
||||||
|
cs->relax_domain_level = val;
|
||||||
|
rebuild_sched_domains();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* update_flag - read a 0 or a 1 in a file and update associated flag
|
* update_flag - read a 0 or a 1 in a file and update associated flag
|
||||||
* bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
|
* bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
|
||||||
|
@ -1202,6 +1242,7 @@ typedef enum {
|
||||||
FILE_CPU_EXCLUSIVE,
|
FILE_CPU_EXCLUSIVE,
|
||||||
FILE_MEM_EXCLUSIVE,
|
FILE_MEM_EXCLUSIVE,
|
||||||
FILE_SCHED_LOAD_BALANCE,
|
FILE_SCHED_LOAD_BALANCE,
|
||||||
|
FILE_SCHED_RELAX_DOMAIN_LEVEL,
|
||||||
FILE_MEMORY_PRESSURE_ENABLED,
|
FILE_MEMORY_PRESSURE_ENABLED,
|
||||||
FILE_MEMORY_PRESSURE,
|
FILE_MEMORY_PRESSURE,
|
||||||
FILE_SPREAD_PAGE,
|
FILE_SPREAD_PAGE,
|
||||||
|
@ -1256,6 +1297,9 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont,
|
||||||
case FILE_SCHED_LOAD_BALANCE:
|
case FILE_SCHED_LOAD_BALANCE:
|
||||||
retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, buffer);
|
retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, buffer);
|
||||||
break;
|
break;
|
||||||
|
case FILE_SCHED_RELAX_DOMAIN_LEVEL:
|
||||||
|
retval = update_relax_domain_level(cs, buffer);
|
||||||
|
break;
|
||||||
case FILE_MEMORY_MIGRATE:
|
case FILE_MEMORY_MIGRATE:
|
||||||
retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
|
retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
|
||||||
break;
|
break;
|
||||||
|
@ -1354,6 +1398,9 @@ static ssize_t cpuset_common_file_read(struct cgroup *cont,
|
||||||
case FILE_SCHED_LOAD_BALANCE:
|
case FILE_SCHED_LOAD_BALANCE:
|
||||||
*s++ = is_sched_load_balance(cs) ? '1' : '0';
|
*s++ = is_sched_load_balance(cs) ? '1' : '0';
|
||||||
break;
|
break;
|
||||||
|
case FILE_SCHED_RELAX_DOMAIN_LEVEL:
|
||||||
|
s += sprintf(s, "%d", cs->relax_domain_level);
|
||||||
|
break;
|
||||||
case FILE_MEMORY_MIGRATE:
|
case FILE_MEMORY_MIGRATE:
|
||||||
*s++ = is_memory_migrate(cs) ? '1' : '0';
|
*s++ = is_memory_migrate(cs) ? '1' : '0';
|
||||||
break;
|
break;
|
||||||
|
@ -1424,6 +1471,13 @@ static struct cftype cft_sched_load_balance = {
|
||||||
.private = FILE_SCHED_LOAD_BALANCE,
|
.private = FILE_SCHED_LOAD_BALANCE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct cftype cft_sched_relax_domain_level = {
|
||||||
|
.name = "sched_relax_domain_level",
|
||||||
|
.read = cpuset_common_file_read,
|
||||||
|
.write = cpuset_common_file_write,
|
||||||
|
.private = FILE_SCHED_RELAX_DOMAIN_LEVEL,
|
||||||
|
};
|
||||||
|
|
||||||
static struct cftype cft_memory_migrate = {
|
static struct cftype cft_memory_migrate = {
|
||||||
.name = "memory_migrate",
|
.name = "memory_migrate",
|
||||||
.read = cpuset_common_file_read,
|
.read = cpuset_common_file_read,
|
||||||
|
@ -1475,6 +1529,9 @@ static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
|
||||||
return err;
|
return err;
|
||||||
if ((err = cgroup_add_file(cont, ss, &cft_sched_load_balance)) < 0)
|
if ((err = cgroup_add_file(cont, ss, &cft_sched_load_balance)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
if ((err = cgroup_add_file(cont, ss,
|
||||||
|
&cft_sched_relax_domain_level)) < 0)
|
||||||
|
return err;
|
||||||
if ((err = cgroup_add_file(cont, ss, &cft_memory_pressure)) < 0)
|
if ((err = cgroup_add_file(cont, ss, &cft_memory_pressure)) < 0)
|
||||||
return err;
|
return err;
|
||||||
if ((err = cgroup_add_file(cont, ss, &cft_spread_page)) < 0)
|
if ((err = cgroup_add_file(cont, ss, &cft_spread_page)) < 0)
|
||||||
|
@ -1559,6 +1616,7 @@ static struct cgroup_subsys_state *cpuset_create(
|
||||||
nodes_clear(cs->mems_allowed);
|
nodes_clear(cs->mems_allowed);
|
||||||
cs->mems_generation = cpuset_mems_generation++;
|
cs->mems_generation = cpuset_mems_generation++;
|
||||||
fmeter_init(&cs->fmeter);
|
fmeter_init(&cs->fmeter);
|
||||||
|
cs->relax_domain_level = -1;
|
||||||
|
|
||||||
cs->parent = parent;
|
cs->parent = parent;
|
||||||
number_of_cpusets++;
|
number_of_cpusets++;
|
||||||
|
@ -1631,6 +1689,7 @@ int __init cpuset_init(void)
|
||||||
fmeter_init(&top_cpuset.fmeter);
|
fmeter_init(&top_cpuset.fmeter);
|
||||||
top_cpuset.mems_generation = cpuset_mems_generation++;
|
top_cpuset.mems_generation = cpuset_mems_generation++;
|
||||||
set_bit(CS_SCHED_LOAD_BALANCE, &top_cpuset.flags);
|
set_bit(CS_SCHED_LOAD_BALANCE, &top_cpuset.flags);
|
||||||
|
top_cpuset.relax_domain_level = -1;
|
||||||
|
|
||||||
err = register_filesystem(&cpuset_fs_type);
|
err = register_filesystem(&cpuset_fs_type);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
|
@ -6771,6 +6771,7 @@ static noinline void sd_init_##type(struct sched_domain *sd) \
|
||||||
{ \
|
{ \
|
||||||
memset(sd, 0, sizeof(*sd)); \
|
memset(sd, 0, sizeof(*sd)); \
|
||||||
*sd = SD_##type##_INIT; \
|
*sd = SD_##type##_INIT; \
|
||||||
|
sd->level = SD_LV_##type; \
|
||||||
}
|
}
|
||||||
|
|
||||||
SD_INIT_FUNC(CPU)
|
SD_INIT_FUNC(CPU)
|
||||||
|
@ -6819,11 +6820,42 @@ struct allmasks {
|
||||||
#define SCHED_CPUMASK_VAR(v, a) cpumask_t *v = (cpumask_t *) \
|
#define SCHED_CPUMASK_VAR(v, a) cpumask_t *v = (cpumask_t *) \
|
||||||
((unsigned long)(a) + offsetof(struct allmasks, v))
|
((unsigned long)(a) + offsetof(struct allmasks, v))
|
||||||
|
|
||||||
|
static int default_relax_domain_level = -1;
|
||||||
|
|
||||||
|
static int __init setup_relax_domain_level(char *str)
|
||||||
|
{
|
||||||
|
default_relax_domain_level = simple_strtoul(str, NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("relax_domain_level=", setup_relax_domain_level);
|
||||||
|
|
||||||
|
static void set_domain_attribute(struct sched_domain *sd,
|
||||||
|
struct sched_domain_attr *attr)
|
||||||
|
{
|
||||||
|
int request;
|
||||||
|
|
||||||
|
if (!attr || attr->relax_domain_level < 0) {
|
||||||
|
if (default_relax_domain_level < 0)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
request = default_relax_domain_level;
|
||||||
|
} else
|
||||||
|
request = attr->relax_domain_level;
|
||||||
|
if (request < sd->level) {
|
||||||
|
/* turn off idle balance on this domain */
|
||||||
|
sd->flags &= ~(SD_WAKE_IDLE|SD_BALANCE_NEWIDLE);
|
||||||
|
} else {
|
||||||
|
/* turn on idle balance on this domain */
|
||||||
|
sd->flags |= (SD_WAKE_IDLE_FAR|SD_BALANCE_NEWIDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build sched domains for a given set of cpus and attach the sched domains
|
* Build sched domains for a given set of cpus and attach the sched domains
|
||||||
* to the individual cpus
|
* to the individual cpus
|
||||||
*/
|
*/
|
||||||
static int build_sched_domains(const cpumask_t *cpu_map)
|
static int __build_sched_domains(const cpumask_t *cpu_map,
|
||||||
|
struct sched_domain_attr *attr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct root_domain *rd;
|
struct root_domain *rd;
|
||||||
|
@ -6887,6 +6919,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
|
||||||
SD_NODES_PER_DOMAIN*cpus_weight(*nodemask)) {
|
SD_NODES_PER_DOMAIN*cpus_weight(*nodemask)) {
|
||||||
sd = &per_cpu(allnodes_domains, i);
|
sd = &per_cpu(allnodes_domains, i);
|
||||||
SD_INIT(sd, ALLNODES);
|
SD_INIT(sd, ALLNODES);
|
||||||
|
set_domain_attribute(sd, attr);
|
||||||
sd->span = *cpu_map;
|
sd->span = *cpu_map;
|
||||||
cpu_to_allnodes_group(i, cpu_map, &sd->groups, tmpmask);
|
cpu_to_allnodes_group(i, cpu_map, &sd->groups, tmpmask);
|
||||||
p = sd;
|
p = sd;
|
||||||
|
@ -6896,6 +6929,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
|
||||||
|
|
||||||
sd = &per_cpu(node_domains, i);
|
sd = &per_cpu(node_domains, i);
|
||||||
SD_INIT(sd, NODE);
|
SD_INIT(sd, NODE);
|
||||||
|
set_domain_attribute(sd, attr);
|
||||||
sched_domain_node_span(cpu_to_node(i), &sd->span);
|
sched_domain_node_span(cpu_to_node(i), &sd->span);
|
||||||
sd->parent = p;
|
sd->parent = p;
|
||||||
if (p)
|
if (p)
|
||||||
|
@ -6906,6 +6940,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
|
||||||
p = sd;
|
p = sd;
|
||||||
sd = &per_cpu(phys_domains, i);
|
sd = &per_cpu(phys_domains, i);
|
||||||
SD_INIT(sd, CPU);
|
SD_INIT(sd, CPU);
|
||||||
|
set_domain_attribute(sd, attr);
|
||||||
sd->span = *nodemask;
|
sd->span = *nodemask;
|
||||||
sd->parent = p;
|
sd->parent = p;
|
||||||
if (p)
|
if (p)
|
||||||
|
@ -6916,6 +6951,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
|
||||||
p = sd;
|
p = sd;
|
||||||
sd = &per_cpu(core_domains, i);
|
sd = &per_cpu(core_domains, i);
|
||||||
SD_INIT(sd, MC);
|
SD_INIT(sd, MC);
|
||||||
|
set_domain_attribute(sd, attr);
|
||||||
sd->span = cpu_coregroup_map(i);
|
sd->span = cpu_coregroup_map(i);
|
||||||
cpus_and(sd->span, sd->span, *cpu_map);
|
cpus_and(sd->span, sd->span, *cpu_map);
|
||||||
sd->parent = p;
|
sd->parent = p;
|
||||||
|
@ -6927,6 +6963,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
|
||||||
p = sd;
|
p = sd;
|
||||||
sd = &per_cpu(cpu_domains, i);
|
sd = &per_cpu(cpu_domains, i);
|
||||||
SD_INIT(sd, SIBLING);
|
SD_INIT(sd, SIBLING);
|
||||||
|
set_domain_attribute(sd, attr);
|
||||||
sd->span = per_cpu(cpu_sibling_map, i);
|
sd->span = per_cpu(cpu_sibling_map, i);
|
||||||
cpus_and(sd->span, sd->span, *cpu_map);
|
cpus_and(sd->span, sd->span, *cpu_map);
|
||||||
sd->parent = p;
|
sd->parent = p;
|
||||||
|
@ -7124,8 +7161,15 @@ error:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int build_sched_domains(const cpumask_t *cpu_map)
|
||||||
|
{
|
||||||
|
return __build_sched_domains(cpu_map, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static cpumask_t *doms_cur; /* current sched domains */
|
static cpumask_t *doms_cur; /* current sched domains */
|
||||||
static int ndoms_cur; /* number of sched domains in 'doms_cur' */
|
static int ndoms_cur; /* number of sched domains in 'doms_cur' */
|
||||||
|
static struct sched_domain_attr *dattr_cur; /* attribues of custom domains
|
||||||
|
in 'doms_cur' */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special case: If a kmalloc of a doms_cur partition (array of
|
* Special case: If a kmalloc of a doms_cur partition (array of
|
||||||
|
@ -7153,6 +7197,7 @@ static int arch_init_sched_domains(const cpumask_t *cpu_map)
|
||||||
if (!doms_cur)
|
if (!doms_cur)
|
||||||
doms_cur = &fallback_doms;
|
doms_cur = &fallback_doms;
|
||||||
cpus_andnot(*doms_cur, *cpu_map, cpu_isolated_map);
|
cpus_andnot(*doms_cur, *cpu_map, cpu_isolated_map);
|
||||||
|
dattr_cur = NULL;
|
||||||
err = build_sched_domains(doms_cur);
|
err = build_sched_domains(doms_cur);
|
||||||
register_sched_domain_sysctl();
|
register_sched_domain_sysctl();
|
||||||
|
|
||||||
|
@ -7182,6 +7227,22 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
|
||||||
arch_destroy_sched_domains(cpu_map, &tmpmask);
|
arch_destroy_sched_domains(cpu_map, &tmpmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handle null as "default" */
|
||||||
|
static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
|
||||||
|
struct sched_domain_attr *new, int idx_new)
|
||||||
|
{
|
||||||
|
struct sched_domain_attr tmp;
|
||||||
|
|
||||||
|
/* fast path */
|
||||||
|
if (!new && !cur)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
tmp = SD_ATTR_INIT;
|
||||||
|
return !memcmp(cur ? (cur + idx_cur) : &tmp,
|
||||||
|
new ? (new + idx_new) : &tmp,
|
||||||
|
sizeof(struct sched_domain_attr));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Partition sched domains as specified by the 'ndoms_new'
|
* Partition sched domains as specified by the 'ndoms_new'
|
||||||
* cpumasks in the array doms_new[] of cpumasks. This compares
|
* cpumasks in the array doms_new[] of cpumasks. This compares
|
||||||
|
@ -7203,7 +7264,8 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
|
||||||
*
|
*
|
||||||
* Call with hotplug lock held
|
* Call with hotplug lock held
|
||||||
*/
|
*/
|
||||||
void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
|
void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
|
||||||
|
struct sched_domain_attr *dattr_new)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
@ -7216,12 +7278,14 @@ void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
|
||||||
ndoms_new = 1;
|
ndoms_new = 1;
|
||||||
doms_new = &fallback_doms;
|
doms_new = &fallback_doms;
|
||||||
cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
|
cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
|
||||||
|
dattr_new = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy deleted domains */
|
/* Destroy deleted domains */
|
||||||
for (i = 0; i < ndoms_cur; i++) {
|
for (i = 0; i < ndoms_cur; i++) {
|
||||||
for (j = 0; j < ndoms_new; j++) {
|
for (j = 0; j < ndoms_new; j++) {
|
||||||
if (cpus_equal(doms_cur[i], doms_new[j]))
|
if (cpus_equal(doms_cur[i], doms_new[j])
|
||||||
|
&& dattrs_equal(dattr_cur, i, dattr_new, j))
|
||||||
goto match1;
|
goto match1;
|
||||||
}
|
}
|
||||||
/* no match - a current sched domain not in new doms_new[] */
|
/* no match - a current sched domain not in new doms_new[] */
|
||||||
|
@ -7233,11 +7297,13 @@ match1:
|
||||||
/* Build new domains */
|
/* Build new domains */
|
||||||
for (i = 0; i < ndoms_new; i++) {
|
for (i = 0; i < ndoms_new; i++) {
|
||||||
for (j = 0; j < ndoms_cur; j++) {
|
for (j = 0; j < ndoms_cur; j++) {
|
||||||
if (cpus_equal(doms_new[i], doms_cur[j]))
|
if (cpus_equal(doms_new[i], doms_cur[j])
|
||||||
|
&& dattrs_equal(dattr_new, i, dattr_cur, j))
|
||||||
goto match2;
|
goto match2;
|
||||||
}
|
}
|
||||||
/* no match - add a new doms_new */
|
/* no match - add a new doms_new */
|
||||||
build_sched_domains(doms_new + i);
|
__build_sched_domains(doms_new + i,
|
||||||
|
dattr_new ? dattr_new + i : NULL);
|
||||||
match2:
|
match2:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -7245,7 +7311,9 @@ match2:
|
||||||
/* Remember the new sched domains */
|
/* Remember the new sched domains */
|
||||||
if (doms_cur != &fallback_doms)
|
if (doms_cur != &fallback_doms)
|
||||||
kfree(doms_cur);
|
kfree(doms_cur);
|
||||||
|
kfree(dattr_cur); /* kfree(NULL) is safe */
|
||||||
doms_cur = doms_new;
|
doms_cur = doms_new;
|
||||||
|
dattr_cur = dattr_new;
|
||||||
ndoms_cur = ndoms_new;
|
ndoms_cur = ndoms_new;
|
||||||
|
|
||||||
register_sched_domain_sysctl();
|
register_sched_domain_sysctl();
|
||||||
|
|
|
@ -940,7 +940,9 @@ static int wake_idle(int cpu, struct task_struct *p)
|
||||||
return cpu;
|
return cpu;
|
||||||
|
|
||||||
for_each_domain(cpu, sd) {
|
for_each_domain(cpu, sd) {
|
||||||
if (sd->flags & SD_WAKE_IDLE) {
|
if ((sd->flags & SD_WAKE_IDLE)
|
||||||
|
|| ((sd->flags & SD_WAKE_IDLE_FAR)
|
||||||
|
&& !task_hot(p, task_rq(p)->clock, sd))) {
|
||||||
cpus_and(tmp, sd->span, p->cpus_allowed);
|
cpus_and(tmp, sd->span, p->cpus_allowed);
|
||||||
for_each_cpu_mask(i, tmp) {
|
for_each_cpu_mask(i, tmp) {
|
||||||
if (idle_cpu(i)) {
|
if (idle_cpu(i)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue