aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/percpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/percpu.h')
-rw-r--r--include/linux/percpu.h67
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
130extern void *__alloc_reserved_percpu(size_t size, size_t align); 137extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align);
131extern void *__alloc_percpu(size_t size, size_t align); 138extern bool is_kernel_percpu_address(unsigned long addr);
132extern void free_percpu(void *__pdata);
133extern 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
136extern void __init setup_per_cpu_areas(void); 141extern 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
143static inline void *__alloc_percpu(size_t size, size_t align) 148/* can't distinguish from other static vars, always false */
144{ 149static 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
154static inline void free_percpu(void *p)
155{
156 kfree(p);
157}
158
159static inline phys_addr_t per_cpu_ptr_to_phys(void *addr)
160{ 150{
161 return __pa(addr); 151 return false;
162} 152}
163 153
164static inline void __init setup_per_cpu_areas(void) { } 154static 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
163extern void __percpu *__alloc_percpu(size_t size, size_t align);
164extern void free_percpu(void __percpu *__pdata);
165extern 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) \
199do { \ 194do { \
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, ...) \
249do { \ 246do { \
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) \
312do { \ 309do { \
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