diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 7 | ||||
-rw-r--r-- | lib/cpumask.c | 54 |
2 files changed, 58 insertions, 3 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index fd4118e097f0..2ba43c4a5b07 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -159,4 +159,11 @@ config CHECK_SIGNATURE | |||
159 | config HAVE_LMB | 159 | config HAVE_LMB |
160 | boolean | 160 | boolean |
161 | 161 | ||
162 | config CPUMASK_OFFSTACK | ||
163 | bool "Force CPU masks off stack" if DEBUG_PER_CPU_MAPS | ||
164 | help | ||
165 | Use dynamic allocation for cpumask_var_t, instead of putting | ||
166 | them on the stack. This is a bit more expensive, but avoids | ||
167 | stack overflow. | ||
168 | |||
162 | endmenu | 169 | endmenu |
diff --git a/lib/cpumask.c b/lib/cpumask.c index 8d03f22c6ced..a24edf137f41 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c | |||
@@ -76,15 +76,28 @@ int cpumask_any_but(const struct cpumask *mask, unsigned int cpu) | |||
76 | 76 | ||
77 | /* These are not inline because of header tangles. */ | 77 | /* These are not inline because of header tangles. */ |
78 | #ifdef CONFIG_CPUMASK_OFFSTACK | 78 | #ifdef CONFIG_CPUMASK_OFFSTACK |
79 | bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) | 79 | /** |
80 | * alloc_cpumask_var_node - allocate a struct cpumask on a given node | ||
81 | * @mask: pointer to cpumask_var_t where the cpumask is returned | ||
82 | * @flags: GFP_ flags | ||
83 | * | ||
84 | * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is | ||
85 | * a nop returning a constant 1 (in <linux/cpumask.h>) | ||
86 | * Returns TRUE if memory allocation succeeded, FALSE otherwise. | ||
87 | * | ||
88 | * In addition, mask will be NULL if this fails. Note that gcc is | ||
89 | * usually smart enough to know that mask can never be NULL if | ||
90 | * CONFIG_CPUMASK_OFFSTACK=n, so does code elimination in that case | ||
91 | * too. | ||
92 | */ | ||
93 | bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node) | ||
80 | { | 94 | { |
81 | if (likely(slab_is_available())) | 95 | if (likely(slab_is_available())) |
82 | *mask = kmalloc(cpumask_size(), flags); | 96 | *mask = kmalloc_node(cpumask_size(), flags, node); |
83 | else { | 97 | else { |
84 | #ifdef CONFIG_DEBUG_PER_CPU_MAPS | 98 | #ifdef CONFIG_DEBUG_PER_CPU_MAPS |
85 | printk(KERN_ERR | 99 | printk(KERN_ERR |
86 | "=> alloc_cpumask_var: kmalloc not available!\n"); | 100 | "=> alloc_cpumask_var: kmalloc not available!\n"); |
87 | dump_stack(); | ||
88 | #endif | 101 | #endif |
89 | *mask = NULL; | 102 | *mask = NULL; |
90 | } | 103 | } |
@@ -96,19 +109,54 @@ bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) | |||
96 | #endif | 109 | #endif |
97 | return *mask != NULL; | 110 | return *mask != NULL; |
98 | } | 111 | } |
112 | EXPORT_SYMBOL(alloc_cpumask_var_node); | ||
113 | |||
114 | /** | ||
115 | * alloc_cpumask_var - allocate a struct cpumask | ||
116 | * @mask: pointer to cpumask_var_t where the cpumask is returned | ||
117 | * @flags: GFP_ flags | ||
118 | * | ||
119 | * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is | ||
120 | * a nop returning a constant 1 (in <linux/cpumask.h>). | ||
121 | * | ||
122 | * See alloc_cpumask_var_node. | ||
123 | */ | ||
124 | bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) | ||
125 | { | ||
126 | return alloc_cpumask_var_node(mask, flags, numa_node_id()); | ||
127 | } | ||
99 | EXPORT_SYMBOL(alloc_cpumask_var); | 128 | EXPORT_SYMBOL(alloc_cpumask_var); |
100 | 129 | ||
130 | /** | ||
131 | * alloc_bootmem_cpumask_var - allocate a struct cpumask from the bootmem arena. | ||
132 | * @mask: pointer to cpumask_var_t where the cpumask is returned | ||
133 | * | ||
134 | * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is | ||
135 | * a nop returning a constant 1 (in <linux/cpumask.h>) | ||
136 | * Either returns an allocated (zero-filled) cpumask, or causes the | ||
137 | * system to panic. | ||
138 | */ | ||
101 | void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask) | 139 | void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask) |
102 | { | 140 | { |
103 | *mask = alloc_bootmem(cpumask_size()); | 141 | *mask = alloc_bootmem(cpumask_size()); |
104 | } | 142 | } |
105 | 143 | ||
144 | /** | ||
145 | * free_cpumask_var - frees memory allocated for a struct cpumask. | ||
146 | * @mask: cpumask to free | ||
147 | * | ||
148 | * This is safe on a NULL mask. | ||
149 | */ | ||
106 | void free_cpumask_var(cpumask_var_t mask) | 150 | void free_cpumask_var(cpumask_var_t mask) |
107 | { | 151 | { |
108 | kfree(mask); | 152 | kfree(mask); |
109 | } | 153 | } |
110 | EXPORT_SYMBOL(free_cpumask_var); | 154 | EXPORT_SYMBOL(free_cpumask_var); |
111 | 155 | ||
156 | /** | ||
157 | * free_bootmem_cpumask_var - frees result of alloc_bootmem_cpumask_var | ||
158 | * @mask: cpumask to free | ||
159 | */ | ||
112 | void __init free_bootmem_cpumask_var(cpumask_var_t mask) | 160 | void __init free_bootmem_cpumask_var(cpumask_var_t mask) |
113 | { | 161 | { |
114 | free_bootmem((unsigned long)mask, cpumask_size()); | 162 | free_bootmem((unsigned long)mask, cpumask_size()); |