diff options
Diffstat (limited to 'lib/percpu_counter.c')
-rw-r--r-- | lib/percpu_counter.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index cf22c617baa4..9659eabffc31 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c | |||
@@ -14,15 +14,29 @@ static LIST_HEAD(percpu_counters); | |||
14 | static DEFINE_MUTEX(percpu_counters_lock); | 14 | static DEFINE_MUTEX(percpu_counters_lock); |
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | void percpu_counter_mod(struct percpu_counter *fbc, s32 amount) | 17 | void percpu_counter_set(struct percpu_counter *fbc, s64 amount) |
18 | { | 18 | { |
19 | long count; | 19 | int cpu; |
20 | |||
21 | spin_lock(&fbc->lock); | ||
22 | for_each_possible_cpu(cpu) { | ||
23 | s32 *pcount = per_cpu_ptr(fbc->counters, cpu); | ||
24 | *pcount = 0; | ||
25 | } | ||
26 | fbc->count = amount; | ||
27 | spin_unlock(&fbc->lock); | ||
28 | } | ||
29 | EXPORT_SYMBOL(percpu_counter_set); | ||
30 | |||
31 | void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) | ||
32 | { | ||
33 | s64 count; | ||
20 | s32 *pcount; | 34 | s32 *pcount; |
21 | int cpu = get_cpu(); | 35 | int cpu = get_cpu(); |
22 | 36 | ||
23 | pcount = per_cpu_ptr(fbc->counters, cpu); | 37 | pcount = per_cpu_ptr(fbc->counters, cpu); |
24 | count = *pcount + amount; | 38 | count = *pcount + amount; |
25 | if (count >= FBC_BATCH || count <= -FBC_BATCH) { | 39 | if (count >= batch || count <= -batch) { |
26 | spin_lock(&fbc->lock); | 40 | spin_lock(&fbc->lock); |
27 | fbc->count += count; | 41 | fbc->count += count; |
28 | *pcount = 0; | 42 | *pcount = 0; |
@@ -32,13 +46,13 @@ void percpu_counter_mod(struct percpu_counter *fbc, s32 amount) | |||
32 | } | 46 | } |
33 | put_cpu(); | 47 | put_cpu(); |
34 | } | 48 | } |
35 | EXPORT_SYMBOL(percpu_counter_mod); | 49 | EXPORT_SYMBOL(__percpu_counter_add); |
36 | 50 | ||
37 | /* | 51 | /* |
38 | * Add up all the per-cpu counts, return the result. This is a more accurate | 52 | * Add up all the per-cpu counts, return the result. This is a more accurate |
39 | * but much slower version of percpu_counter_read_positive() | 53 | * but much slower version of percpu_counter_read_positive() |
40 | */ | 54 | */ |
41 | s64 percpu_counter_sum(struct percpu_counter *fbc) | 55 | s64 __percpu_counter_sum(struct percpu_counter *fbc) |
42 | { | 56 | { |
43 | s64 ret; | 57 | s64 ret; |
44 | int cpu; | 58 | int cpu; |
@@ -50,25 +64,43 @@ s64 percpu_counter_sum(struct percpu_counter *fbc) | |||
50 | ret += *pcount; | 64 | ret += *pcount; |
51 | } | 65 | } |
52 | spin_unlock(&fbc->lock); | 66 | spin_unlock(&fbc->lock); |
53 | return ret < 0 ? 0 : ret; | 67 | return ret; |
54 | } | 68 | } |
55 | EXPORT_SYMBOL(percpu_counter_sum); | 69 | EXPORT_SYMBOL(__percpu_counter_sum); |
70 | |||
71 | static struct lock_class_key percpu_counter_irqsafe; | ||
56 | 72 | ||
57 | void percpu_counter_init(struct percpu_counter *fbc, s64 amount) | 73 | int percpu_counter_init(struct percpu_counter *fbc, s64 amount) |
58 | { | 74 | { |
59 | spin_lock_init(&fbc->lock); | 75 | spin_lock_init(&fbc->lock); |
60 | fbc->count = amount; | 76 | fbc->count = amount; |
61 | fbc->counters = alloc_percpu(s32); | 77 | fbc->counters = alloc_percpu(s32); |
78 | if (!fbc->counters) | ||
79 | return -ENOMEM; | ||
62 | #ifdef CONFIG_HOTPLUG_CPU | 80 | #ifdef CONFIG_HOTPLUG_CPU |
63 | mutex_lock(&percpu_counters_lock); | 81 | mutex_lock(&percpu_counters_lock); |
64 | list_add(&fbc->list, &percpu_counters); | 82 | list_add(&fbc->list, &percpu_counters); |
65 | mutex_unlock(&percpu_counters_lock); | 83 | mutex_unlock(&percpu_counters_lock); |
66 | #endif | 84 | #endif |
85 | return 0; | ||
67 | } | 86 | } |
68 | EXPORT_SYMBOL(percpu_counter_init); | 87 | EXPORT_SYMBOL(percpu_counter_init); |
69 | 88 | ||
89 | int percpu_counter_init_irq(struct percpu_counter *fbc, s64 amount) | ||
90 | { | ||
91 | int err; | ||
92 | |||
93 | err = percpu_counter_init(fbc, amount); | ||
94 | if (!err) | ||
95 | lockdep_set_class(&fbc->lock, &percpu_counter_irqsafe); | ||
96 | return err; | ||
97 | } | ||
98 | |||
70 | void percpu_counter_destroy(struct percpu_counter *fbc) | 99 | void percpu_counter_destroy(struct percpu_counter *fbc) |
71 | { | 100 | { |
101 | if (!fbc->counters) | ||
102 | return; | ||
103 | |||
72 | free_percpu(fbc->counters); | 104 | free_percpu(fbc->counters); |
73 | #ifdef CONFIG_HOTPLUG_CPU | 105 | #ifdef CONFIG_HOTPLUG_CPU |
74 | mutex_lock(&percpu_counters_lock); | 106 | mutex_lock(&percpu_counters_lock); |