diff options
Diffstat (limited to 'include/linux/percpu.h')
| -rw-r--r-- | include/linux/percpu.h | 67 |
1 files changed, 32 insertions, 35 deletions
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index cf5efbcf716c..d3a38d687104 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
| @@ -2,10 +2,10 @@ | |||
| 2 | #define __LINUX_PERCPU_H | 2 | #define __LINUX_PERCPU_H |
| 3 | 3 | ||
| 4 | #include <linux/preempt.h> | 4 | #include <linux/preempt.h> |
| 5 | #include <linux/slab.h> /* For kmalloc() */ | ||
| 6 | #include <linux/smp.h> | 5 | #include <linux/smp.h> |
| 7 | #include <linux/cpumask.h> | 6 | #include <linux/cpumask.h> |
| 8 | #include <linux/pfn.h> | 7 | #include <linux/pfn.h> |
| 8 | #include <linux/init.h> | ||
| 9 | 9 | ||
| 10 | #include <asm/percpu.h> | 10 | #include <asm/percpu.h> |
| 11 | 11 | ||
| @@ -27,10 +27,17 @@ | |||
| 27 | * we force a syntax error here if it isn't. | 27 | * we force a syntax error here if it isn't. |
| 28 | */ | 28 | */ |
| 29 | #define get_cpu_var(var) (*({ \ | 29 | #define get_cpu_var(var) (*({ \ |
| 30 | extern int simple_identifier_##var(void); \ | ||
| 31 | preempt_disable(); \ | 30 | preempt_disable(); \ |
| 32 | &__get_cpu_var(var); })) | 31 | &__get_cpu_var(var); })) |
| 33 | #define put_cpu_var(var) preempt_enable() | 32 | |
| 33 | /* | ||
| 34 | * The weird & is necessary because sparse considers (void)(var) to be | ||
| 35 | * a direct dereference of percpu variable (var). | ||
| 36 | */ | ||
| 37 | #define put_cpu_var(var) do { \ | ||
| 38 | (void)&(var); \ | ||
| 39 | preempt_enable(); \ | ||
| 40 | } while (0) | ||
| 34 | 41 | ||
| 35 | #ifdef CONFIG_SMP | 42 | #ifdef CONFIG_SMP |
| 36 | 43 | ||
| @@ -127,10 +134,8 @@ extern int __init pcpu_page_first_chunk(size_t reserved_size, | |||
| 127 | */ | 134 | */ |
| 128 | #define per_cpu_ptr(ptr, cpu) SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))) | 135 | #define per_cpu_ptr(ptr, cpu) SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))) |
| 129 | 136 | ||
| 130 | extern void *__alloc_reserved_percpu(size_t size, size_t align); | 137 | extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align); |
| 131 | extern void *__alloc_percpu(size_t size, size_t align); | 138 | extern bool is_kernel_percpu_address(unsigned long addr); |
| 132 | extern void free_percpu(void *__pdata); | ||
| 133 | extern phys_addr_t per_cpu_ptr_to_phys(void *addr); | ||
| 134 | 139 | ||
| 135 | #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA | 140 | #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA |
| 136 | extern void __init setup_per_cpu_areas(void); | 141 | extern void __init setup_per_cpu_areas(void); |
| @@ -140,25 +145,10 @@ extern void __init setup_per_cpu_areas(void); | |||
| 140 | 145 | ||
| 141 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) | 146 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) |
| 142 | 147 | ||
| 143 | static inline void *__alloc_percpu(size_t size, size_t align) | 148 | /* can't distinguish from other static vars, always false */ |
| 144 | { | 149 | static inline bool is_kernel_percpu_address(unsigned long addr) |
| 145 | /* | ||
| 146 | * Can't easily make larger alignment work with kmalloc. WARN | ||
| 147 | * on it. Larger alignment should only be used for module | ||
| 148 | * percpu sections on SMP for which this path isn't used. | ||
| 149 | */ | ||
| 150 | WARN_ON_ONCE(align > SMP_CACHE_BYTES); | ||
| 151 | return kzalloc(size, GFP_KERNEL); | ||
| 152 | } | ||
| 153 | |||
| 154 | static inline void free_percpu(void *p) | ||
| 155 | { | ||
| 156 | kfree(p); | ||
| 157 | } | ||
| 158 | |||
| 159 | static inline phys_addr_t per_cpu_ptr_to_phys(void *addr) | ||
| 160 | { | 150 | { |
| 161 | return __pa(addr); | 151 | return false; |
| 162 | } | 152 | } |
| 163 | 153 | ||
| 164 | static inline void __init setup_per_cpu_areas(void) { } | 154 | static inline void __init setup_per_cpu_areas(void) { } |
| @@ -170,8 +160,12 @@ static inline void *pcpu_lpage_remapped(void *kaddr) | |||
| 170 | 160 | ||
| 171 | #endif /* CONFIG_SMP */ | 161 | #endif /* CONFIG_SMP */ |
| 172 | 162 | ||
| 163 | extern void __percpu *__alloc_percpu(size_t size, size_t align); | ||
| 164 | extern void free_percpu(void __percpu *__pdata); | ||
| 165 | extern phys_addr_t per_cpu_ptr_to_phys(void *addr); | ||
| 166 | |||
| 173 | #define alloc_percpu(type) \ | 167 | #define alloc_percpu(type) \ |
| 174 | (typeof(type) *)__alloc_percpu(sizeof(type), __alignof__(type)) | 168 | (typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type)) |
| 175 | 169 | ||
| 176 | /* | 170 | /* |
| 177 | * Optional methods for optimized non-lvalue per-cpu variable access. | 171 | * Optional methods for optimized non-lvalue per-cpu variable access. |
| @@ -188,17 +182,19 @@ static inline void *pcpu_lpage_remapped(void *kaddr) | |||
| 188 | #ifndef percpu_read | 182 | #ifndef percpu_read |
| 189 | # define percpu_read(var) \ | 183 | # define percpu_read(var) \ |
| 190 | ({ \ | 184 | ({ \ |
| 191 | typeof(per_cpu_var(var)) __tmp_var__; \ | 185 | typeof(var) *pr_ptr__ = &(var); \ |
| 192 | __tmp_var__ = get_cpu_var(var); \ | 186 | typeof(var) pr_ret__; \ |
| 193 | put_cpu_var(var); \ | 187 | pr_ret__ = get_cpu_var(*pr_ptr__); \ |
| 194 | __tmp_var__; \ | 188 | put_cpu_var(*pr_ptr__); \ |
| 189 | pr_ret__; \ | ||
| 195 | }) | 190 | }) |
| 196 | #endif | 191 | #endif |
| 197 | 192 | ||
| 198 | #define __percpu_generic_to_op(var, val, op) \ | 193 | #define __percpu_generic_to_op(var, val, op) \ |
| 199 | do { \ | 194 | do { \ |
| 200 | get_cpu_var(var) op val; \ | 195 | typeof(var) *pgto_ptr__ = &(var); \ |
| 201 | put_cpu_var(var); \ | 196 | get_cpu_var(*pgto_ptr__) op val; \ |
| 197 | put_cpu_var(*pgto_ptr__); \ | ||
| 202 | } while (0) | 198 | } while (0) |
| 203 | 199 | ||
| 204 | #ifndef percpu_write | 200 | #ifndef percpu_write |
| @@ -234,6 +230,7 @@ extern void __bad_size_call_parameter(void); | |||
| 234 | 230 | ||
| 235 | #define __pcpu_size_call_return(stem, variable) \ | 231 | #define __pcpu_size_call_return(stem, variable) \ |
| 236 | ({ typeof(variable) pscr_ret__; \ | 232 | ({ typeof(variable) pscr_ret__; \ |
| 233 | __verify_pcpu_ptr(&(variable)); \ | ||
| 237 | switch(sizeof(variable)) { \ | 234 | switch(sizeof(variable)) { \ |
| 238 | case 1: pscr_ret__ = stem##1(variable);break; \ | 235 | case 1: pscr_ret__ = stem##1(variable);break; \ |
| 239 | case 2: pscr_ret__ = stem##2(variable);break; \ | 236 | case 2: pscr_ret__ = stem##2(variable);break; \ |
| @@ -247,6 +244,7 @@ extern void __bad_size_call_parameter(void); | |||
| 247 | 244 | ||
| 248 | #define __pcpu_size_call(stem, variable, ...) \ | 245 | #define __pcpu_size_call(stem, variable, ...) \ |
| 249 | do { \ | 246 | do { \ |
| 247 | __verify_pcpu_ptr(&(variable)); \ | ||
| 250 | switch(sizeof(variable)) { \ | 248 | switch(sizeof(variable)) { \ |
| 251 | case 1: stem##1(variable, __VA_ARGS__);break; \ | 249 | case 1: stem##1(variable, __VA_ARGS__);break; \ |
| 252 | case 2: stem##2(variable, __VA_ARGS__);break; \ | 250 | case 2: stem##2(variable, __VA_ARGS__);break; \ |
| @@ -259,8 +257,7 @@ do { \ | |||
| 259 | 257 | ||
| 260 | /* | 258 | /* |
| 261 | * Optimized manipulation for memory allocated through the per cpu | 259 | * Optimized manipulation for memory allocated through the per cpu |
| 262 | * allocator or for addresses of per cpu variables (can be determined | 260 | * allocator or for addresses of per cpu variables. |
| 263 | * using per_cpu_var(xx). | ||
| 264 | * | 261 | * |
| 265 | * These operation guarantee exclusivity of access for other operations | 262 | * These operation guarantee exclusivity of access for other operations |
| 266 | * on the *same* processor. The assumption is that per cpu data is only | 263 | * on the *same* processor. The assumption is that per cpu data is only |
| @@ -311,7 +308,7 @@ do { \ | |||
| 311 | #define _this_cpu_generic_to_op(pcp, val, op) \ | 308 | #define _this_cpu_generic_to_op(pcp, val, op) \ |
| 312 | do { \ | 309 | do { \ |
| 313 | preempt_disable(); \ | 310 | preempt_disable(); \ |
| 314 | *__this_cpu_ptr(&pcp) op val; \ | 311 | *__this_cpu_ptr(&(pcp)) op val; \ |
| 315 | preempt_enable(); \ | 312 | preempt_enable(); \ |
| 316 | } while (0) | 313 | } while (0) |
| 317 | 314 | ||
