]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - include/linux/percpu_counter.h
lib: percpu_counter variable batch
[linux-2.6.git] / include / linux / percpu_counter.h
1 #ifndef _LINUX_PERCPU_COUNTER_H
2 #define _LINUX_PERCPU_COUNTER_H
3 /*
4  * A simple "approximate counter" for use in ext2 and ext3 superblocks.
5  *
6  * WARNING: these things are HUGE.  4 kbytes per counter on 32-way P4.
7  */
8
9 #include <linux/spinlock.h>
10 #include <linux/smp.h>
11 #include <linux/list.h>
12 #include <linux/threads.h>
13 #include <linux/percpu.h>
14 #include <linux/types.h>
15
16 #ifdef CONFIG_SMP
17
18 struct percpu_counter {
19         spinlock_t lock;
20         s64 count;
21 #ifdef CONFIG_HOTPLUG_CPU
22         struct list_head list;  /* All percpu_counters are on a list */
23 #endif
24         s32 *counters;
25 };
26
27 #if NR_CPUS >= 16
28 #define FBC_BATCH       (NR_CPUS*2)
29 #else
30 #define FBC_BATCH       (NR_CPUS*4)
31 #endif
32
33 void percpu_counter_init(struct percpu_counter *fbc, s64 amount);
34 void percpu_counter_destroy(struct percpu_counter *fbc);
35 void __percpu_counter_add(struct percpu_counter *fbc, s32 amount, s32 batch);
36 s64 percpu_counter_sum(struct percpu_counter *fbc);
37
38 static inline void percpu_counter_add(struct percpu_counter *fbc, s32 amount)
39 {
40         __percpu_counter_add(fbc, amount, FBC_BATCH);
41 }
42
43 static inline s64 percpu_counter_read(struct percpu_counter *fbc)
44 {
45         return fbc->count;
46 }
47
48 /*
49  * It is possible for the percpu_counter_read() to return a small negative
50  * number for some counter which should never be negative.
51  *
52  */
53 static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
54 {
55         s64 ret = fbc->count;
56
57         barrier();              /* Prevent reloads of fbc->count */
58         if (ret >= 0)
59                 return ret;
60         return 1;
61 }
62
63 #else
64
65 struct percpu_counter {
66         s64 count;
67 };
68
69 static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
70 {
71         fbc->count = amount;
72 }
73
74 static inline void percpu_counter_destroy(struct percpu_counter *fbc)
75 {
76 }
77
78 #define __percpu_counter_add(fbc, amount, batch) \
79         percpu_counter_add(fbc, amount)
80
81 static inline void
82 percpu_counter_add(struct percpu_counter *fbc, s32 amount)
83 {
84         preempt_disable();
85         fbc->count += amount;
86         preempt_enable();
87 }
88
89 static inline s64 percpu_counter_read(struct percpu_counter *fbc)
90 {
91         return fbc->count;
92 }
93
94 static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
95 {
96         return fbc->count;
97 }
98
99 static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
100 {
101         return percpu_counter_read_positive(fbc);
102 }
103
104 #endif  /* CONFIG_SMP */
105
106 static inline void percpu_counter_inc(struct percpu_counter *fbc)
107 {
108         percpu_counter_add(fbc, 1);
109 }
110
111 static inline void percpu_counter_dec(struct percpu_counter *fbc)
112 {
113         percpu_counter_add(fbc, -1);
114 }
115
116 static inline void percpu_counter_sub(struct percpu_counter *fbc, s64 amount)
117 {
118         percpu_counter_add(fbc, -amount);
119 }
120
121 #endif /* _LINUX_PERCPU_COUNTER_H */