diff options
Diffstat (limited to 'include/asm-generic/percpu.h')
-rw-r--r-- | include/asm-generic/percpu.h | 97 |
1 files changed, 61 insertions, 36 deletions
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index d85172e9ed45..4b8d31cda1a0 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h | |||
@@ -3,54 +3,79 @@ | |||
3 | #include <linux/compiler.h> | 3 | #include <linux/compiler.h> |
4 | #include <linux/threads.h> | 4 | #include <linux/threads.h> |
5 | 5 | ||
6 | #define __GENERIC_PER_CPU | 6 | /* |
7 | * Determine the real variable name from the name visible in the | ||
8 | * kernel sources. | ||
9 | */ | ||
10 | #define per_cpu_var(var) per_cpu__##var | ||
11 | |||
7 | #ifdef CONFIG_SMP | 12 | #ifdef CONFIG_SMP |
8 | 13 | ||
14 | /* | ||
15 | * per_cpu_offset() is the offset that has to be added to a | ||
16 | * percpu variable to get to the instance for a certain processor. | ||
17 | * | ||
18 | * Most arches use the __per_cpu_offset array for those offsets but | ||
19 | * some arches have their own ways of determining the offset (x86_64, s390). | ||
20 | */ | ||
21 | #ifndef __per_cpu_offset | ||
9 | extern unsigned long __per_cpu_offset[NR_CPUS]; | 22 | extern unsigned long __per_cpu_offset[NR_CPUS]; |
10 | 23 | ||
11 | #define per_cpu_offset(x) (__per_cpu_offset[x]) | 24 | #define per_cpu_offset(x) (__per_cpu_offset[x]) |
25 | #endif | ||
12 | 26 | ||
13 | /* Separate out the type, so (int[3], foo) works. */ | 27 | /* |
14 | #define DEFINE_PER_CPU(type, name) \ | 28 | * Determine the offset for the currently active processor. |
15 | __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name | 29 | * An arch may define __my_cpu_offset to provide a more effective |
16 | 30 | * means of obtaining the offset to the per cpu variables of the | |
17 | #define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ | 31 | * current processor. |
18 | __attribute__((__section__(".data.percpu.shared_aligned"))) \ | 32 | */ |
19 | __typeof__(type) per_cpu__##name \ | 33 | #ifndef __my_cpu_offset |
20 | ____cacheline_aligned_in_smp | 34 | #define __my_cpu_offset per_cpu_offset(raw_smp_processor_id()) |
21 | 35 | #define my_cpu_offset per_cpu_offset(smp_processor_id()) | |
22 | /* var is in discarded region: offset to particular copy we want */ | 36 | #else |
23 | #define per_cpu(var, cpu) (*({ \ | 37 | #define my_cpu_offset __my_cpu_offset |
24 | extern int simple_identifier_##var(void); \ | 38 | #endif |
25 | RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]); })) | 39 | |
26 | #define __get_cpu_var(var) per_cpu(var, smp_processor_id()) | 40 | /* |
27 | #define __raw_get_cpu_var(var) per_cpu(var, raw_smp_processor_id()) | 41 | * Add a offset to a pointer but keep the pointer as is. |
28 | 42 | * | |
29 | /* A macro to avoid #include hell... */ | 43 | * Only S390 provides its own means of moving the pointer. |
30 | #define percpu_modcopy(pcpudst, src, size) \ | 44 | */ |
31 | do { \ | 45 | #ifndef SHIFT_PERCPU_PTR |
32 | unsigned int __i; \ | 46 | #define SHIFT_PERCPU_PTR(__p, __offset) RELOC_HIDE((__p), (__offset)) |
33 | for_each_possible_cpu(__i) \ | 47 | #endif |
34 | memcpy((pcpudst)+__per_cpu_offset[__i], \ | ||
35 | (src), (size)); \ | ||
36 | } while (0) | ||
37 | #else /* ! SMP */ | ||
38 | 48 | ||
39 | #define DEFINE_PER_CPU(type, name) \ | 49 | /* |
40 | __typeof__(type) per_cpu__##name | 50 | * A percpu variable may point to a discarded regions. The following are |
51 | * established ways to produce a usable pointer from the percpu variable | ||
52 | * offset. | ||
53 | */ | ||
54 | #define per_cpu(var, cpu) \ | ||
55 | (*SHIFT_PERCPU_PTR(&per_cpu_var(var), per_cpu_offset(cpu))) | ||
56 | #define __get_cpu_var(var) \ | ||
57 | (*SHIFT_PERCPU_PTR(&per_cpu_var(var), my_cpu_offset)) | ||
58 | #define __raw_get_cpu_var(var) \ | ||
59 | (*SHIFT_PERCPU_PTR(&per_cpu_var(var), __my_cpu_offset)) | ||
41 | 60 | ||
42 | #define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ | ||
43 | DEFINE_PER_CPU(type, name) | ||
44 | 61 | ||
45 | #define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var)) | 62 | #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA |
46 | #define __get_cpu_var(var) per_cpu__##var | 63 | extern void setup_per_cpu_areas(void); |
47 | #define __raw_get_cpu_var(var) per_cpu__##var | 64 | #endif |
65 | |||
66 | #else /* ! SMP */ | ||
67 | |||
68 | #define per_cpu(var, cpu) (*((void)(cpu), &per_cpu_var(var))) | ||
69 | #define __get_cpu_var(var) per_cpu_var(var) | ||
70 | #define __raw_get_cpu_var(var) per_cpu_var(var) | ||
48 | 71 | ||
49 | #endif /* SMP */ | 72 | #endif /* SMP */ |
50 | 73 | ||
51 | #define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name | 74 | #ifndef PER_CPU_ATTRIBUTES |
75 | #define PER_CPU_ATTRIBUTES | ||
76 | #endif | ||
52 | 77 | ||
53 | #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) | 78 | #define DECLARE_PER_CPU(type, name) extern PER_CPU_ATTRIBUTES \ |
54 | #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) | 79 | __typeof__(type) per_cpu_var(name) |
55 | 80 | ||
56 | #endif /* _ASM_GENERIC_PERCPU_H_ */ | 81 | #endif /* _ASM_GENERIC_PERCPU_H_ */ |