diff options
author | Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> | 2008-04-15 01:04:23 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-19 13:45:00 -0400 |
commit | 1d3504fcf5606579d60b649d19f44b3871c1ddae (patch) | |
tree | 001a1b57bd7f123fd51361d78d9277b2dcac1bf3 /kernel/sched.c | |
parent | 4d5f35533fb9b2cd553cec6611195bcbfb7ffd84 (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.c | 78 |
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 | ||
6776 | SD_INIT_FUNC(CPU) | 6777 | SD_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 | ||
6823 | static int default_relax_domain_level = -1; | ||
6824 | |||
6825 | static 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 | |||
6832 | static 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 | */ |
6826 | static int build_sched_domains(const cpumask_t *cpu_map) | 6857 | static 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 | ||
7164 | static int build_sched_domains(const cpumask_t *cpu_map) | ||
7165 | { | ||
7166 | return __build_sched_domains(cpu_map, NULL); | ||
7167 | } | ||
7168 | |||
7127 | static cpumask_t *doms_cur; /* current sched domains */ | 7169 | static cpumask_t *doms_cur; /* current sched domains */ |
7128 | static int ndoms_cur; /* number of sched domains in 'doms_cur' */ | 7170 | static int ndoms_cur; /* number of sched domains in 'doms_cur' */ |
7171 | static 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" */ | ||
7231 | static 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 | */ |
7206 | void partition_sched_domains(int ndoms_new, cpumask_t *doms_new) | 7267 | void 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); | ||
7241 | match2: | 7307 | match2: |
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(); |