diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2009-11-02 23:23:40 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-11-04 07:16:40 -0500 |
| commit | acc3f5d7cabbfd6cec71f0c1f9900621fa2d6ae7 (patch) | |
| tree | 672ed45f6df2f52e8f3cced2ee11ad29a1533890 | |
| parent | e2c880630438f80b474378d5487b511b07665051 (diff) | |
cpumask: Partition_sched_domains takes array of cpumask_var_t
Currently partition_sched_domains() takes a 'struct cpumask
*doms_new' which is a kmalloc'ed array of cpumask_t. You can't
have such an array if 'struct cpumask' is undefined, as we plan
for CONFIG_CPUMASK_OFFSTACK=y.
So, we make this an array of cpumask_var_t instead: this is the
same for the CONFIG_CPUMASK_OFFSTACK=n case, but requires
multiple allocations for the CONFIG_CPUMASK_OFFSTACK=y case.
Hence we add alloc_sched_domains() and free_sched_domains()
functions.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Peter Zijlstra <peterz@infradead.org>
LKML-Reference: <200911031453.40668.rusty@rustcorp.com.au>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | include/linux/sched.h | 8 | ||||
| -rw-r--r-- | kernel/cpuset.c | 19 | ||||
| -rw-r--r-- | kernel/sched.c | 68 |
3 files changed, 61 insertions, 34 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index dfc21fb76bf1..78ba664474f3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1009,9 +1009,13 @@ static inline struct cpumask *sched_domain_span(struct sched_domain *sd) | |||
| 1009 | return to_cpumask(sd->span); | 1009 | return to_cpumask(sd->span); |
| 1010 | } | 1010 | } |
| 1011 | 1011 | ||
| 1012 | extern void partition_sched_domains(int ndoms_new, struct cpumask *doms_new, | 1012 | extern void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], |
| 1013 | struct sched_domain_attr *dattr_new); | 1013 | struct sched_domain_attr *dattr_new); |
| 1014 | 1014 | ||
| 1015 | /* Allocate an array of sched domains, for partition_sched_domains(). */ | ||
| 1016 | cpumask_var_t *alloc_sched_domains(unsigned int ndoms); | ||
| 1017 | void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms); | ||
| 1018 | |||
| 1015 | /* Test a flag in parent sched domain */ | 1019 | /* Test a flag in parent sched domain */ |
| 1016 | static inline int test_sd_parent(struct sched_domain *sd, int flag) | 1020 | static inline int test_sd_parent(struct sched_domain *sd, int flag) |
| 1017 | { | 1021 | { |
| @@ -1029,7 +1033,7 @@ unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu); | |||
| 1029 | struct sched_domain_attr; | 1033 | struct sched_domain_attr; |
| 1030 | 1034 | ||
| 1031 | static inline void | 1035 | static inline void |
| 1032 | partition_sched_domains(int ndoms_new, struct cpumask *doms_new, | 1036 | partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], |
| 1033 | struct sched_domain_attr *dattr_new) | 1037 | struct sched_domain_attr *dattr_new) |
| 1034 | { | 1038 | { |
| 1035 | } | 1039 | } |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d247381e7371..3cf2183b472d 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -537,8 +537,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) | |||
| 537 | * element of the partition (one sched domain) to be passed to | 537 | * element of the partition (one sched domain) to be passed to |
| 538 | * partition_sched_domains(). | 538 | * partition_sched_domains(). |
| 539 | */ | 539 | */ |
| 540 | /* FIXME: see the FIXME in partition_sched_domains() */ | 540 | static int generate_sched_domains(cpumask_var_t **domains, |
| 541 | static int generate_sched_domains(struct cpumask **domains, | ||
| 542 | struct sched_domain_attr **attributes) | 541 | struct sched_domain_attr **attributes) |
| 543 | { | 542 | { |
| 544 | LIST_HEAD(q); /* queue of cpusets to be scanned */ | 543 | LIST_HEAD(q); /* queue of cpusets to be scanned */ |
| @@ -546,7 +545,7 @@ static int generate_sched_domains(struct cpumask **domains, | |||
| 546 | struct cpuset **csa; /* array of all cpuset ptrs */ | 545 | struct cpuset **csa; /* array of all cpuset ptrs */ |
| 547 | int csn; /* how many cpuset ptrs in csa so far */ | 546 | int csn; /* how many cpuset ptrs in csa so far */ |
| 548 | int i, j, k; /* indices for partition finding loops */ | 547 | int i, j, k; /* indices for partition finding loops */ |
| 549 | struct cpumask *doms; /* resulting partition; i.e. sched domains */ | 548 | cpumask_var_t *doms; /* resulting partition; i.e. sched domains */ |
| 550 | struct sched_domain_attr *dattr; /* attributes for custom domains */ | 549 | struct sched_domain_attr *dattr; /* attributes for custom domains */ |
| 551 | int ndoms = 0; /* number of sched domains in result */ | 550 | int ndoms = 0; /* number of sched domains in result */ |
| 552 | int nslot; /* next empty doms[] struct cpumask slot */ | 551 | int nslot; /* next empty doms[] struct cpumask slot */ |
| @@ -557,7 +556,8 @@ static int generate_sched_domains(struct cpumask **domains, | |||
| 557 | 556 | ||
| 558 | /* Special case for the 99% of systems with one, full, sched domain */ | 557 | /* Special case for the 99% of systems with one, full, sched domain */ |
| 559 | if (is_sched_load_balance(&top_cpuset)) { | 558 | if (is_sched_load_balance(&top_cpuset)) { |
| 560 | doms = kmalloc(cpumask_size(), GFP_KERNEL); | 559 | ndoms = 1; |
| 560 | doms = alloc_sched_domains(ndoms); | ||
| 561 | if (!doms) | 561 | if (!doms) |
| 562 | goto done; | 562 | goto done; |
| 563 | 563 | ||
| @@ -566,9 +566,8 @@ static int generate_sched_domains(struct cpumask **domains, | |||
| 566 | *dattr = SD_ATTR_INIT; | 566 | *dattr = SD_ATTR_INIT; |
| 567 | update_domain_attr_tree(dattr, &top_cpuset); | 567 | update_domain_attr_tree(dattr, &top_cpuset); |
| 568 | } | 568 | } |
| 569 | cpumask_copy(doms, top_cpuset.cpus_allowed); | 569 | cpumask_copy(doms[0], top_cpuset.cpus_allowed); |
| 570 | 570 | ||
| 571 | ndoms = 1; | ||
| 572 | goto done; | 571 | goto done; |
| 573 | } | 572 | } |
| 574 | 573 | ||
| @@ -636,7 +635,7 @@ restart: | |||
| 636 | * Now we know how many domains to create. | 635 | * Now we know how many domains to create. |
| 637 | * Convert <csn, csa> to <ndoms, doms> and populate cpu masks. | 636 | * Convert <csn, csa> to <ndoms, doms> and populate cpu masks. |
| 638 | */ | 637 | */ |
| 639 | doms = kmalloc(ndoms * cpumask_size(), GFP_KERNEL); | 638 | doms = alloc_sched_domains(ndoms); |
| 640 | if (!doms) | 639 | if (!doms) |
| 641 | goto done; | 640 | goto done; |
| 642 | 641 | ||
| @@ -656,7 +655,7 @@ restart: | |||
| 656 | continue; | 655 | continue; |
| 657 | } | 656 | } |
| 658 | 657 | ||
| 659 | dp = doms + nslot; | 658 | dp = doms[nslot]; |
| 660 | 659 | ||
| 661 | if (nslot == ndoms) { | 660 | if (nslot == ndoms) { |
| 662 | static int warnings = 10; | 661 | static int warnings = 10; |
| @@ -718,7 +717,7 @@ done: | |||
| 718 | static void do_rebuild_sched_domains(struct work_struct *unused) | 717 | static void do_rebuild_sched_domains(struct work_struct *unused) |
| 719 | { | 718 | { |
| 720 | struct sched_domain_attr *attr; | 719 | struct sched_domain_attr *attr; |
| 721 | struct cpumask *doms; | 720 | cpumask_var_t *doms; |
| 722 | int ndoms; | 721 | int ndoms; |
| 723 | 722 | ||
| 724 | get_online_cpus(); | 723 | get_online_cpus(); |
| @@ -2052,7 +2051,7 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, | |||
| 2052 | unsigned long phase, void *unused_cpu) | 2051 | unsigned long phase, void *unused_cpu) |
| 2053 | { | 2052 | { |
| 2054 | struct sched_domain_attr *attr; | 2053 | struct sched_domain_attr *attr; |
| 2055 | struct cpumask *doms; | 2054 | cpumask_var_t *doms; |
| 2056 | int ndoms; | 2055 | int ndoms; |
| 2057 | 2056 | ||
| 2058 | switch (phase) { | 2057 | switch (phase) { |
diff --git a/kernel/sched.c b/kernel/sched.c index 30fd0ba5f603..ae026aad145b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -8846,7 +8846,7 @@ static int build_sched_domains(const struct cpumask *cpu_map) | |||
| 8846 | return __build_sched_domains(cpu_map, NULL); | 8846 | return __build_sched_domains(cpu_map, NULL); |
| 8847 | } | 8847 | } |
| 8848 | 8848 | ||
| 8849 | static struct cpumask *doms_cur; /* current sched domains */ | 8849 | static cpumask_var_t *doms_cur; /* current sched domains */ |
| 8850 | static int ndoms_cur; /* number of sched domains in 'doms_cur' */ | 8850 | static int ndoms_cur; /* number of sched domains in 'doms_cur' */ |
| 8851 | static struct sched_domain_attr *dattr_cur; | 8851 | static struct sched_domain_attr *dattr_cur; |
| 8852 | /* attribues of custom domains in 'doms_cur' */ | 8852 | /* attribues of custom domains in 'doms_cur' */ |
| @@ -8868,6 +8868,31 @@ int __attribute__((weak)) arch_update_cpu_topology(void) | |||
| 8868 | return 0; | 8868 | return 0; |
| 8869 | } | 8869 | } |
| 8870 | 8870 | ||
| 8871 | cpumask_var_t *alloc_sched_domains(unsigned int ndoms) | ||
| 8872 | { | ||
| 8873 | int i; | ||
| 8874 | cpumask_var_t *doms; | ||
| 8875 | |||
| 8876 | doms = kmalloc(sizeof(*doms) * ndoms, GFP_KERNEL); | ||
| 8877 | if (!doms) | ||
| 8878 | return NULL; | ||
| 8879 | for (i = 0; i < ndoms; i++) { | ||
| 8880 | if (!alloc_cpumask_var(&doms[i], GFP_KERNEL)) { | ||
| 8881 | free_sched_domains(doms, i); | ||
| 8882 | return NULL; | ||
| 8883 | } | ||
| 8884 | } | ||
| 8885 | return doms; | ||
| 8886 | } | ||
| 8887 | |||
| 8888 | void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms) | ||
| 8889 | { | ||
| 8890 | unsigned int i; | ||
| 8891 | for (i = 0; i < ndoms; i++) | ||
| 8892 | free_cpumask_var(doms[i]); | ||
| 8893 | kfree(doms); | ||
| 8894 | } | ||
| 8895 | |||
| 8871 | /* | 8896 | /* |
| 8872 | * Set up scheduler domains and groups. Callers must hold the hotplug lock. | 8897 | * Set up scheduler domains and groups. Callers must hold the hotplug lock. |
| 8873 | * For now this just excludes isolated cpus, but could be used to | 8898 | * For now this just excludes isolated cpus, but could be used to |
| @@ -8879,12 +8904,12 @@ static int arch_init_sched_domains(const struct cpumask *cpu_map) | |||
| 8879 | 8904 | ||
| 8880 | arch_update_cpu_topology(); | 8905 | arch_update_cpu_topology(); |
| 8881 | ndoms_cur = 1; | 8906 | ndoms_cur = 1; |
| 8882 | doms_cur = kmalloc(cpumask_size(), GFP_KERNEL); | 8907 | doms_cur = alloc_sched_domains(ndoms_cur); |
| 8883 | if (!doms_cur) | 8908 | if (!doms_cur) |
| 8884 | doms_cur = fallback_doms; | 8909 | doms_cur = &fallback_doms; |
| 8885 | cpumask_andnot(doms_cur, cpu_map, cpu_isolated_map); | 8910 | cpumask_andnot(doms_cur[0], cpu_map, cpu_isolated_map); |
| 8886 | dattr_cur = NULL; | 8911 | dattr_cur = NULL; |
| 8887 | err = build_sched_domains(doms_cur); | 8912 | err = build_sched_domains(doms_cur[0]); |
| 8888 | register_sched_domain_sysctl(); | 8913 | register_sched_domain_sysctl(); |
| 8889 | 8914 | ||
| 8890 | return err; | 8915 | return err; |
| @@ -8934,19 +8959,19 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur, | |||
| 8934 | * doms_new[] to the current sched domain partitioning, doms_cur[]. | 8959 | * doms_new[] to the current sched domain partitioning, doms_cur[]. |
| 8935 | * It destroys each deleted domain and builds each new domain. | 8960 | * It destroys each deleted domain and builds each new domain. |
| 8936 | * | 8961 | * |
| 8937 | * 'doms_new' is an array of cpumask's of length 'ndoms_new'. | 8962 | * 'doms_new' is an array of cpumask_var_t's of length 'ndoms_new'. |
| 8938 | * The masks don't intersect (don't overlap.) We should setup one | 8963 | * The masks don't intersect (don't overlap.) We should setup one |
| 8939 | * sched domain for each mask. CPUs not in any of the cpumasks will | 8964 | * sched domain for each mask. CPUs not in any of the cpumasks will |
| 8940 | * not be load balanced. If the same cpumask appears both in the | 8965 | * not be load balanced. If the same cpumask appears both in the |
| 8941 | * current 'doms_cur' domains and in the new 'doms_new', we can leave | 8966 | * current 'doms_cur' domains and in the new 'doms_new', we can leave |
| 8942 | * it as it is. | 8967 | * it as it is. |
| 8943 | * | 8968 | * |
| 8944 | * The passed in 'doms_new' should be kmalloc'd. This routine takes | 8969 | * The passed in 'doms_new' should be allocated using |
| 8945 | * ownership of it and will kfree it when done with it. If the caller | 8970 | * alloc_sched_domains. This routine takes ownership of it and will |
| 8946 | * failed the kmalloc call, then it can pass in doms_new == NULL && | 8971 | * free_sched_domains it when done with it. If the caller failed the |
| 8947 | * ndoms_new == 1, and partition_sched_domains() will fallback to | 8972 | * alloc call, then it can pass in doms_new == NULL && ndoms_new == 1, |
| 8948 | * the single partition 'fallback_doms', it also forces the domains | 8973 | * and partition_sched_domains() will fallback to the single partition |
| 8949 | * to be rebuilt. | 8974 | * 'fallback_doms', it also forces the domains to be rebuilt. |
| 8950 | * | 8975 | * |
| 8951 | * If doms_new == NULL it will be replaced with cpu_online_mask. | 8976 | * If doms_new == NULL it will be replaced with cpu_online_mask. |
| 8952 | * ndoms_new == 0 is a special case for destroying existing domains, | 8977 | * ndoms_new == 0 is a special case for destroying existing domains, |
| @@ -8954,8 +8979,7 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur, | |||
| 8954 | * | 8979 | * |
| 8955 | * Call with hotplug lock held | 8980 | * Call with hotplug lock held |
| 8956 | */ | 8981 | */ |
| 8957 | /* FIXME: Change to struct cpumask *doms_new[] */ | 8982 | void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], |
| 8958 | void partition_sched_domains(int ndoms_new, struct cpumask *doms_new, | ||
| 8959 | struct sched_domain_attr *dattr_new) | 8983 | struct sched_domain_attr *dattr_new) |
| 8960 | { | 8984 | { |
| 8961 | int i, j, n; | 8985 | int i, j, n; |
| @@ -8974,40 +8998,40 @@ void partition_sched_domains(int ndoms_new, struct cpumask *doms_new, | |||
| 8974 | /* Destroy deleted domains */ | 8998 | /* Destroy deleted domains */ |
| 8975 | for (i = 0; i < ndoms_cur; i++) { | 8999 | for (i = 0; i < ndoms_cur; i++) { |
| 8976 | for (j = 0; j < n && !new_topology; j++) { | 9000 | for (j = 0; j < n && !new_topology; j++) { |
| 8977 | if (cpumask_equal(&doms_cur[i], &doms_new[j]) | 9001 | if (cpumask_equal(doms_cur[i], doms_new[j]) |
| 8978 | && dattrs_equal(dattr_cur, i, dattr_new, j)) | 9002 | && dattrs_equal(dattr_cur, i, dattr_new, j)) |
| 8979 | goto match1; | 9003 | goto match1; |
| 8980 | } | 9004 | } |
| 8981 | /* no match - a current sched domain not in new doms_new[] */ | 9005 | /* no match - a current sched domain not in new doms_new[] */ |
| 8982 | detach_destroy_domains(doms_cur + i); | 9006 | detach_destroy_domains(doms_cur[i]); |
| 8983 | match1: | 9007 | match1: |
| 8984 | ; | 9008 | ; |
| 8985 | } | 9009 | } |
| 8986 | 9010 | ||
| 8987 | if (doms_new == NULL) { | 9011 | if (doms_new == NULL) { |
| 8988 | ndoms_cur = 0; | 9012 | ndoms_cur = 0; |
| 8989 | doms_new = fallback_doms; | 9013 | doms_new = &fallback_doms; |
| 8990 | cpumask_andnot(&doms_new[0], cpu_online_mask, cpu_isolated_map); | 9014 | cpumask_andnot(doms_new[0], cpu_online_mask, cpu_isolated_map); |
| 8991 | WARN_ON_ONCE(dattr_new); | 9015 | WARN_ON_ONCE(dattr_new); |
| 8992 | } | 9016 | } |
| 8993 | 9017 | ||
| 8994 | /* Build new domains */ | 9018 | /* Build new domains */ |
| 8995 | for (i = 0; i < ndoms_new; i++) { | 9019 | for (i = 0; i < ndoms_new; i++) { |
| 8996 | for (j = 0; j < ndoms_cur && !new_topology; j++) { | 9020 | for (j = 0; j < ndoms_cur && !new_topology; j++) { |
| 8997 | if (cpumask_equal(&doms_new[i], &doms_cur[j]) | 9021 | if (cpumask_equal(doms_new[i], doms_cur[j]) |
| 8998 | && dattrs_equal(dattr_new, i, dattr_cur, j)) | 9022 | && dattrs_equal(dattr_new, i, dattr_cur, j)) |
| 8999 | goto match2; | 9023 | goto match2; |
| 9000 | } | 9024 | } |
| 9001 | /* no match - add a new doms_new */ | 9025 | /* no match - add a new doms_new */ |
| 9002 | __build_sched_domains(doms_new + i, | 9026 | __build_sched_domains(doms_new[i], |
| 9003 | dattr_new ? dattr_new + i : NULL); | 9027 | dattr_new ? dattr_new + i : NULL); |
| 9004 | match2: | 9028 | match2: |
| 9005 | ; | 9029 | ; |
| 9006 | } | 9030 | } |
| 9007 | 9031 | ||
| 9008 | /* Remember the new sched domains */ | 9032 | /* Remember the new sched domains */ |
| 9009 | if (doms_cur != fallback_doms) | 9033 | if (doms_cur != &fallback_doms) |
| 9010 | kfree(doms_cur); | 9034 | free_sched_domains(doms_cur, ndoms_cur); |
| 9011 | kfree(dattr_cur); /* kfree(NULL) is safe */ | 9035 | kfree(dattr_cur); /* kfree(NULL) is safe */ |
| 9012 | doms_cur = doms_new; | 9036 | doms_cur = doms_new; |
| 9013 | dattr_cur = dattr_new; | 9037 | dattr_cur = dattr_new; |
