Subversion Repositories shark

Rev

Rev 422 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
422 giacomo 1
/*
2
 * A simple "approximate counter" for use in ext2 and ext3 superblocks.
3
 *
4
 * WARNING: these things are HUGE.  4 kbytes per counter on 32-way P4.
5
 */
6
 
7
#include <linux/config.h>
8
#include <linux/spinlock.h>
9
#include <linux/smp.h>
10
#include <linux/threads.h>
11
 
12
#ifdef CONFIG_SMP
13
 
14
struct __percpu_counter {
15
        long count;
16
} ____cacheline_aligned;
17
 
18
struct percpu_counter {
19
        spinlock_t lock;
20
        long count;
21
        struct __percpu_counter counters[NR_CPUS];
22
};
23
 
24
#if NR_CPUS >= 16
25
#define FBC_BATCH       (NR_CPUS*2)
26
#else
27
#define FBC_BATCH       (NR_CPUS*4)
28
#endif
29
 
30
static inline void percpu_counter_init(struct percpu_counter *fbc)
31
{
32
        int i;
33
 
34
        spin_lock_init(&fbc->lock);
35
        fbc->count = 0;
36
        for (i = 0; i < NR_CPUS; i++)
37
                fbc->counters[i].count = 0;
38
}
39
 
40
void percpu_counter_mod(struct percpu_counter *fbc, long amount);
41
 
42
static inline long percpu_counter_read(struct percpu_counter *fbc)
43
{
44
        return fbc->count;
45
}
46
 
47
/*
48
 * It is possible for the percpu_counter_read() to return a small negative
49
 * number for some counter which should never be negative.
50
 */
51
static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
52
{
53
        long ret = fbc->count;
54
 
55
        barrier();              /* Prevent reloads of fbc->count */
56
        if (ret > 0)
57
                return ret;
58
        return 1;
59
}
60
 
61
#else
62
 
63
struct percpu_counter {
64
        long count;
65
};
66
 
67
static inline void percpu_counter_init(struct percpu_counter *fbc)
68
{
69
        fbc->count = 0;
70
}
71
 
72
static inline void
73
percpu_counter_mod(struct percpu_counter *fbc, long amount)
74
{
75
        preempt_disable();
76
        fbc->count += amount;
77
        preempt_enable();
78
}
79
 
80
static inline long percpu_counter_read(struct percpu_counter *fbc)
81
{
82
        return fbc->count;
83
}
84
 
85
static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
86
{
87
        return fbc->count;
88
}
89
 
90
#endif  /* CONFIG_SMP */
91
 
92
static inline void percpu_counter_inc(struct percpu_counter *fbc)
93
{
94
        percpu_counter_mod(fbc, 1);
95
}
96
 
97
static inline void percpu_counter_dec(struct percpu_counter *fbc)
98
{
99
        percpu_counter_mod(fbc, -1);
100
}