blob: 682525511c9e90d352f2d46730932e9711ce457e [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);
Andrew Mortone2bab3d2006-03-07 21:55:31 -080042long percpu_counter_sum(struct percpu_counter *fbc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
44static inline long percpu_counter_read(struct percpu_counter *fbc)
45{
46 return fbc->count;
47}
48
49/*
50 * It is possible for the percpu_counter_read() to return a small negative
51 * number for some counter which should never be negative.
52 */
53static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
54{
55 long 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
65struct percpu_counter {
66 long count;
67};
68
69static inline void percpu_counter_init(struct percpu_counter *fbc)
70{
71 fbc->count = 0;
72}
73
74static inline void percpu_counter_destroy(struct percpu_counter *fbc)
75{
76}
77
78static inline void
79percpu_counter_mod(struct percpu_counter *fbc, long amount)
80{
81 preempt_disable();
82 fbc->count += amount;
83 preempt_enable();
84}
85
86static inline long percpu_counter_read(struct percpu_counter *fbc)
87{
88 return fbc->count;
89}
90
91static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
92{
93 return fbc->count;
94}
95
Andrew Mortone2bab3d2006-03-07 21:55:31 -080096static inline long percpu_counter_sum(struct percpu_counter *fbc)
97{
98 return percpu_counter_read_positive(fbc);
99}
100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#endif /* CONFIG_SMP */
102
103static inline void percpu_counter_inc(struct percpu_counter *fbc)
104{
105 percpu_counter_mod(fbc, 1);
106}
107
108static inline void percpu_counter_dec(struct percpu_counter *fbc)
109{
110 percpu_counter_mod(fbc, -1);
111}
112
113#endif /* _LINUX_PERCPU_COUNTER_H */