at v2.6.25 2.0 kB view raw
1#ifndef __LINUX_PCOUNTER_H 2#define __LINUX_PCOUNTER_H 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 */ 14struct pcounter { 15#ifdef CONFIG_SMP 16 void (*add)(struct pcounter *self, int inc); 17 int (*getval)(const struct pcounter *self, int cpu); 18 int *per_cpu_values; 19#else 20 int val; 21#endif 22}; 23 24#ifdef CONFIG_SMP 25#include <linux/percpu.h> 26 27#define DEFINE_PCOUNTER(NAME) \ 28static DEFINE_PER_CPU(int, NAME##_pcounter_values); \ 29static void NAME##_pcounter_add(struct pcounter *self, int val) \ 30{ \ 31 __get_cpu_var(NAME##_pcounter_values) += val; \ 32} \ 33static int NAME##_pcounter_getval(const struct pcounter *self, int cpu) \ 34{ \ 35 return per_cpu(NAME##_pcounter_values, cpu); \ 36} \ 37 38#define PCOUNTER_MEMBER_INITIALIZER(NAME, MEMBER) \ 39 MEMBER = { \ 40 .add = NAME##_pcounter_add, \ 41 .getval = NAME##_pcounter_getval, \ 42 } 43 44 45static inline void pcounter_add(struct pcounter *self, int inc) 46{ 47 self->add(self, inc); 48} 49 50extern int pcounter_getval(const struct pcounter *self); 51extern int pcounter_alloc(struct pcounter *self); 52extern void pcounter_free(struct pcounter *self); 53 54 55#else /* CONFIG_SMP */ 56 57static inline void pcounter_add(struct pcounter *self, int inc) 58{ 59 self->val += inc; 60} 61 62static 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 */