blob: bd6708e2c02703e70be886a4229eb4071be33137 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#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/config.h>
10#include <linux/spinlock.h>
11#include <linux/smp.h>
12#include <linux/threads.h>
13#include <linux/percpu.h>
14
15#ifdef CONFIG_SMP
16
17struct percpu_counter {
18 spinlock_t lock;
19 long count;
20 long *counters;
21};
22
23#if NR_CPUS >= 16
24#define FBC_BATCH (NR_CPUS*2)
25#else
26#define FBC_BATCH (NR_CPUS*4)
27#endif
28
29static inline void percpu_counter_init(struct percpu_counter *fbc)
30{
31 spin_lock_init(&fbc->lock);
32 fbc->count = 0;
33 fbc->counters = alloc_percpu(long);
34}
35
36static inline void percpu_counter_destroy(struct percpu_counter *fbc)
37{
38 free_percpu(fbc->counters);
39}
40
41void percpu_counter_mod(struct percpu_counter *fbc, long amount);
42
43static inline long 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 */
52static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
53{
54 long ret = fbc->count;
55
56 barrier(); /* Prevent reloads of fbc->count */
57 if (ret > 0)
58 return ret;
59 return 1;
60}
61
62#else
63
64struct percpu_counter {
65 long count;
66};
67
68static inline void percpu_counter_init(struct percpu_counter *fbc)
69{
70 fbc->count = 0;
71}
72
73static inline void percpu_counter_destroy(struct percpu_counter *fbc)
74{
75}
76
77static inline void
78percpu_counter_mod(struct percpu_counter *fbc, long amount)
79{
80 preempt_disable();
81 fbc->count += amount;
82 preempt_enable();
83}
84
85static inline long percpu_counter_read(struct percpu_counter *fbc)
86{
87 return fbc->count;
88}
89
90static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
91{
92 return fbc->count;
93}
94
95#endif /* CONFIG_SMP */
96
97static inline void percpu_counter_inc(struct percpu_counter *fbc)
98{
99 percpu_counter_mod(fbc, 1);
100}
101
102static inline void percpu_counter_dec(struct percpu_counter *fbc)
103{
104 percpu_counter_mod(fbc, -1);
105}
106
107#endif /* _LINUX_PERCPU_COUNTER_H */