aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorHidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>2008-04-15 01:04:23 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-19 13:45:00 -0400
commit1d3504fcf5606579d60b649d19f44b3871c1ddae (patch)
tree001a1b57bd7f123fd51361d78d9277b2dcac1bf3 /kernel/sched.c
parent4d5f35533fb9b2cd553cec6611195bcbfb7ffd84 (diff)
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>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c78
1 files changed, 73 insertions, 5 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 475e3fcab738..62d7481caca5 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6771,6 +6771,7 @@ static noinline void sd_init_##type(struct sched_domain *sd) \
6771{ \ 6771{ \
6772 memset(sd, 0, sizeof(*sd)); \ 6772 memset(sd, 0, sizeof(*sd)); \
6773 *sd = SD_##type##_INIT; \ 6773 *sd = SD_##type##_INIT; \
6774 sd->level = SD_LV_##type; \
6774} 6775}
6775 6776
6776SD_INIT_FUNC(CPU) 6777SD_INIT_FUNC(CPU)
@@ -6819,11 +6820,42 @@ struct allmasks {
6819#define SCHED_CPUMASK_VAR(v, a) cpumask_t *v = (cpumask_t *) \ 6820#define SCHED_CPUMASK_VAR(v, a) cpumask_t *v = (cpumask_t *) \
6820 ((unsigned long)(a) + offsetof(struct allmasks, v)) 6821 ((unsigned long)(a) + offsetof(struct allmasks, v))
6821 6822
6823static int default_relax_domain_level = -1;
6824
6825static int __init setup_relax_domain_level(char *str)
6826{
6827 default_relax_domain_level = simple_strtoul(str, NULL, 0);
6828 return 1;
6829}
6830__setup("relax_domain_level=", setup_relax_domain_level);
6831
6832static void set_domain_attribute(struct sched_domain *sd,
6833 struct sched_domain_attr *attr)
6834{
6835 int request;
6836
6837 if (!attr || attr->relax_domain_level < 0) {
6838 if (default_relax_domain_level < 0)
6839 return;
6840 else
6841 request = default_relax_domain_level;
6842 } else
6843 request = attr->relax_domain_level;
6844 if (request < sd->level) {
6845 /* turn off idle balance on this domain */
6846 sd->flags &= ~(SD_WAKE_IDLE|SD_BALANCE_NEWIDLE);
6847 } else {
6848 /* turn on idle balance on this domain */
6849 sd->flags |= (SD_WAKE_IDLE_FAR|SD_BALANCE_NEWIDLE);
6850 }
6851}
6852
6822/* 6853/*
6823 * Build sched domains for a given set of cpus and attach the sched domains 6854 * Build sched domains for a given set of cpus and attach the sched domains
6824 * to the individual cpus 6855 * to the individual cpus
6825 */ 6856 */
6826static int build_sched_domains(const cpumask_t *cpu_map) 6857static int __build_sched_domains(const cpumask_t *cpu_map,
6858 struct sched_domain_attr *attr)
6827{ 6859{
6828 int i; 6860 int i;
6829 struct root_domain *rd; 6861 struct root_domain *rd;
@@ -6887,6 +6919,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
6887 SD_NODES_PER_DOMAIN*cpus_weight(*nodemask)) { 6919 SD_NODES_PER_DOMAIN*cpus_weight(*nodemask)) {
6888 sd = &per_cpu(allnodes_domains, i); 6920 sd = &per_cpu(allnodes_domains, i);
6889 SD_INIT(sd, ALLNODES); 6921 SD_INIT(sd, ALLNODES);
6922 set_domain_attribute(sd, attr);
6890 sd->span = *cpu_map; 6923 sd->span = *cpu_map;
6891 cpu_to_allnodes_group(i, cpu_map, &sd->groups, tmpmask); 6924 cpu_to_allnodes_group(i, cpu_map, &sd->groups, tmpmask);
6892 p = sd; 6925 p = sd;
@@ -6896,6 +6929,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
6896 6929
6897 sd = &per_cpu(node_domains, i); 6930 sd = &per_cpu(node_domains, i);
6898 SD_INIT(sd, NODE); 6931 SD_INIT(sd, NODE);
6932 set_domain_attribute(sd, attr);
6899 sched_domain_node_span(cpu_to_node(i), &sd->span); 6933 sched_domain_node_span(cpu_to_node(i), &sd->span);
6900 sd->parent = p; 6934 sd->parent = p;
6901 if (p) 6935 if (p)
@@ -6906,6 +6940,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
6906 p = sd; 6940 p = sd;
6907 sd = &per_cpu(phys_domains, i); 6941 sd = &per_cpu(phys_domains, i);
6908 SD_INIT(sd, CPU); 6942 SD_INIT(sd, CPU);
6943 set_domain_attribute(sd, attr);
6909 sd->span = *nodemask; 6944 sd->span = *nodemask;
6910 sd->parent = p; 6945 sd->parent = p;
6911 if (p) 6946 if (p)
@@ -6916,6 +6951,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
6916 p = sd; 6951 p = sd;
6917 sd = &per_cpu(core_domains, i); 6952 sd = &per_cpu(core_domains, i);
6918 SD_INIT(sd, MC); 6953 SD_INIT(sd, MC);
6954 set_domain_attribute(sd, attr);
6919 sd->span = cpu_coregroup_map(i); 6955 sd->span = cpu_coregroup_map(i);
6920 cpus_and(sd->span, sd->span, *cpu_map); 6956 cpus_and(sd->span, sd->span, *cpu_map);
6921 sd->parent = p; 6957 sd->parent = p;
@@ -6927,6 +6963,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
6927 p = sd; 6963 p = sd;
6928 sd = &per_cpu(cpu_domains, i); 6964 sd = &per_cpu(cpu_domains, i);
6929 SD_INIT(sd, SIBLING); 6965 SD_INIT(sd, SIBLING);
6966 set_domain_attribute(sd, attr);
6930 sd->span = per_cpu(cpu_sibling_map, i); 6967 sd->span = per_cpu(cpu_sibling_map, i);
6931 cpus_and(sd->span, sd->span, *cpu_map); 6968 cpus_and(sd->span, sd->span, *cpu_map);
6932 sd->parent = p; 6969 sd->parent = p;
@@ -7124,8 +7161,15 @@ error:
7124#endif 7161#endif
7125} 7162}
7126 7163
7164static int build_sched_domains(const cpumask_t *cpu_map)
7165{
7166 return __build_sched_domains(cpu_map, NULL);
7167}
7168
7127static cpumask_t *doms_cur; /* current sched domains */ 7169static cpumask_t *doms_cur; /* current sched domains */
7128static int ndoms_cur; /* number of sched domains in 'doms_cur' */ 7170static int ndoms_cur; /* number of sched domains in 'doms_cur' */
7171static struct sched_domain_attr *dattr_cur; /* attribues of custom domains
7172 in 'doms_cur' */
7129 7173
7130/* 7174/*
7131 * Special case: If a kmalloc of a doms_cur partition (array of 7175 * 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)
7153 if (!doms_cur) 7197 if (!doms_cur)
7154 doms_cur = &fallback_doms; 7198 doms_cur = &fallback_doms;
7155 cpus_andnot(*doms_cur, *cpu_map, cpu_isolated_map); 7199 cpus_andnot(*doms_cur, *cpu_map, cpu_isolated_map);
7200 dattr_cur = NULL;
7156 err = build_sched_domains(doms_cur); 7201 err = build_sched_domains(doms_cur);
7157 register_sched_domain_sysctl(); 7202 register_sched_domain_sysctl();
7158 7203
@@ -7182,6 +7227,22 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
7182 arch_destroy_sched_domains(cpu_map, &tmpmask); 7227 arch_destroy_sched_domains(cpu_map, &tmpmask);
7183} 7228}
7184 7229
7230/* handle null as "default" */
7231static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
7232 struct sched_domain_attr *new, int idx_new)
7233{
7234 struct sched_domain_attr tmp;
7235
7236 /* fast path */
7237 if (!new && !cur)
7238 return 1;
7239
7240 tmp = SD_ATTR_INIT;
7241 return !memcmp(cur ? (cur + idx_cur) : &tmp,
7242 new ? (new + idx_new) : &tmp,
7243 sizeof(struct sched_domain_attr));
7244}
7245
7185/* 7246/*
7186 * Partition sched domains as specified by the 'ndoms_new' 7247 * Partition sched domains as specified by the 'ndoms_new'
7187 * cpumasks in the array doms_new[] of cpumasks. This compares 7248 * cpumasks in the array doms_new[] of cpumasks. This compares
@@ -7203,7 +7264,8 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
7203 * 7264 *
7204 * Call with hotplug lock held 7265 * Call with hotplug lock held
7205 */ 7266 */
7206void partition_sched_domains(int ndoms_new, cpumask_t *doms_new) 7267void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
7268 struct sched_domain_attr *dattr_new)
7207{ 7269{
7208 int i, j; 7270 int i, j;
7209 7271
@@ -7216,12 +7278,14 @@ void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
7216 ndoms_new = 1; 7278 ndoms_new = 1;
7217 doms_new = &fallback_doms; 7279 doms_new = &fallback_doms;
7218 cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map); 7280 cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
7281 dattr_new = NULL;
7219 } 7282 }
7220 7283
7221 /* Destroy deleted domains */ 7284 /* Destroy deleted domains */
7222 for (i = 0; i < ndoms_cur; i++) { 7285 for (i = 0; i < ndoms_cur; i++) {
7223 for (j = 0; j < ndoms_new; j++) { 7286 for (j = 0; j < ndoms_new; j++) {
7224 if (cpus_equal(doms_cur[i], doms_new[j])) 7287 if (cpus_equal(doms_cur[i], doms_new[j])
7288 && dattrs_equal(dattr_cur, i, dattr_new, j))
7225 goto match1; 7289 goto match1;
7226 } 7290 }
7227 /* no match - a current sched domain not in new doms_new[] */ 7291 /* no match - a current sched domain not in new doms_new[] */
@@ -7233,11 +7297,13 @@ match1:
7233 /* Build new domains */ 7297 /* Build new domains */
7234 for (i = 0; i < ndoms_new; i++) { 7298 for (i = 0; i < ndoms_new; i++) {
7235 for (j = 0; j < ndoms_cur; j++) { 7299 for (j = 0; j < ndoms_cur; j++) {
7236 if (cpus_equal(doms_new[i], doms_cur[j])) 7300 if (cpus_equal(doms_new[i], doms_cur[j])
7301 && dattrs_equal(dattr_new, i, dattr_cur, j))
7237 goto match2; 7302 goto match2;
7238 } 7303 }
7239 /* no match - add a new doms_new */ 7304 /* no match - add a new doms_new */
7240 build_sched_domains(doms_new + i); 7305 __build_sched_domains(doms_new + i,
7306 dattr_new ? dattr_new + i : NULL);
7241match2: 7307match2:
7242 ; 7308 ;
7243 } 7309 }
@@ -7245,7 +7311,9 @@ match2:
7245 /* Remember the new sched domains */ 7311 /* Remember the new sched domains */
7246 if (doms_cur != &fallback_doms) 7312 if (doms_cur != &fallback_doms)
7247 kfree(doms_cur); 7313 kfree(doms_cur);
7314 kfree(dattr_cur); /* kfree(NULL) is safe */
7248 doms_cur = doms_new; 7315 doms_cur = doms_new;
7316 dattr_cur = dattr_new;
7249 ndoms_cur = ndoms_new; 7317 ndoms_cur = ndoms_new;
7250 7318
7251 register_sched_domain_sysctl(); 7319 register_sched_domain_sysctl();