]>
Commit | Line | Data |
---|---|---|
de4d1db3 ACM |
1 | #ifndef __LINUX_PCOUNTER_H |
2 | #define __LINUX_PCOUNTER_H | |
571e7682 ED |
3 | /* |
4 | * Using a dynamic percpu 'int' variable has a cost : | |
5 | * 1) Extra dereference | |
6 | * Current per_cpu_ptr() implementation uses an array per 'percpu variable'. | |
7 | * 2) memory cost of NR_CPUS*(32+sizeof(void *)) instead of num_possible_cpus()*4 | |
8 | * | |
9 | * This pcounter implementation is an abstraction to be able to use | |
10 | * either a static or a dynamic per cpu variable. | |
11 | * One dynamic per cpu variable gets a fast & cheap implementation, we can | |
12 | * change pcounter implementation too. | |
13 | */ | |
de4d1db3 ACM |
14 | struct pcounter { |
15 | #ifdef CONFIG_SMP | |
16 | void (*add)(struct pcounter *self, int inc); | |
571e7682 | 17 | int (*getval)(const struct pcounter *self, int cpu); |
de4d1db3 ACM |
18 | int *per_cpu_values; |
19 | #else | |
20 | int val; | |
21 | #endif | |
22 | }; | |
23 | ||
de4d1db3 | 24 | #ifdef CONFIG_SMP |
de4d1db3 ACM |
25 | #include <linux/percpu.h> |
26 | ||
571e7682 ED |
27 | #define DEFINE_PCOUNTER(NAME) \ |
28 | static DEFINE_PER_CPU(int, NAME##_pcounter_values); \ | |
29 | static void NAME##_pcounter_add(struct pcounter *self, int val) \ | |
30 | { \ | |
31 | __get_cpu_var(NAME##_pcounter_values) += val; \ | |
32 | } \ | |
33 | static int NAME##_pcounter_getval(const struct pcounter *self, int cpu) \ | |
34 | { \ | |
35 | return per_cpu(NAME##_pcounter_values, cpu); \ | |
36 | } \ | |
de4d1db3 ACM |
37 | |
38 | #define PCOUNTER_MEMBER_INITIALIZER(NAME, MEMBER) \ | |
39 | MEMBER = { \ | |
40 | .add = NAME##_pcounter_add, \ | |
41 | .getval = NAME##_pcounter_getval, \ | |
42 | } | |
43 | ||
de4d1db3 ACM |
44 | |
45 | static inline void pcounter_add(struct pcounter *self, int inc) | |
46 | { | |
47 | self->add(self, inc); | |
48 | } | |
49 | ||
571e7682 ED |
50 | extern int pcounter_getval(const struct pcounter *self); |
51 | extern int pcounter_alloc(struct pcounter *self); | |
52 | extern void pcounter_free(struct pcounter *self); | |
53 | ||
de4d1db3 ACM |
54 | |
55 | #else /* CONFIG_SMP */ | |
56 | ||
57 | static inline void pcounter_add(struct pcounter *self, int inc) | |
58 | { | |
e7d0362d | 59 | self->val += inc; |
de4d1db3 ACM |
60 | } |
61 | ||
62 | static inline int pcounter_getval(const struct pcounter *self) | |
63 | { | |
64 | return self->val; | |
65 | } | |
66 | ||
67 | #define DEFINE_PCOUNTER(NAME) | |
68 | #define PCOUNTER_MEMBER_INITIALIZER(NAME, MEMBER) | |
69 | #define pcounter_alloc(self) 0 | |
70 | #define pcounter_free(self) | |
71 | ||
72 | #endif /* CONFIG_SMP */ | |
73 | ||
74 | #endif /* __LINUX_PCOUNTER_H */ |