aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig7
-rw-r--r--lib/cpumask.c54
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
159config HAVE_LMB 159config HAVE_LMB
160 boolean 160 boolean
161 161
162config 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
162endmenu 169endmenu
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
79bool 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 */
93bool 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}
112EXPORT_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 */
124bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
125{
126 return alloc_cpumask_var_node(mask, flags, numa_node_id());
127}
99EXPORT_SYMBOL(alloc_cpumask_var); 128EXPORT_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 */
101void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask) 139void __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 */
106void free_cpumask_var(cpumask_var_t mask) 150void free_cpumask_var(cpumask_var_t mask)
107{ 151{
108 kfree(mask); 152 kfree(mask);
109} 153}
110EXPORT_SYMBOL(free_cpumask_var); 154EXPORT_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 */
112void __init free_bootmem_cpumask_var(cpumask_var_t mask) 160void __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());