X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=include%2Flinux%2Fpercpu_counter.h;h=a7684a513994725335ac078d457c6a7a02d78455;hb=c4a62ca362258d98f42efb282cfbf9b61caffdbe;hp=682525511c9e90d352f2d46730932e9711ce457e;hpb=e2bab3d92486fb781f4d06f56339264ed1492392;p=safe%2Fjmp%2Flinux-2.6 diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h index 6825255..a7684a5 100644 --- a/include/linux/percpu_counter.h +++ b/include/linux/percpu_counter.h @@ -6,42 +6,58 @@ * WARNING: these things are HUGE. 4 kbytes per counter on 32-way P4. */ -#include #include #include +#include #include #include +#include #ifdef CONFIG_SMP struct percpu_counter { spinlock_t lock; - long count; - long *counters; + s64 count; +#ifdef CONFIG_HOTPLUG_CPU + struct list_head list; /* All percpu_counters are on a list */ +#endif + s32 *counters; }; -#if NR_CPUS >= 16 -#define FBC_BATCH (NR_CPUS*2) -#else -#define FBC_BATCH (NR_CPUS*4) -#endif +extern int percpu_counter_batch; + +int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, + struct lock_class_key *key); + +#define percpu_counter_init(fbc, value) \ + ({ \ + static struct lock_class_key __key; \ + \ + __percpu_counter_init(fbc, value, &__key); \ + }) -static inline void percpu_counter_init(struct percpu_counter *fbc) +void percpu_counter_destroy(struct percpu_counter *fbc); +void percpu_counter_set(struct percpu_counter *fbc, s64 amount); +void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch); +s64 __percpu_counter_sum(struct percpu_counter *fbc); + +static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount) { - spin_lock_init(&fbc->lock); - fbc->count = 0; - fbc->counters = alloc_percpu(long); + __percpu_counter_add(fbc, amount, percpu_counter_batch); } -static inline void percpu_counter_destroy(struct percpu_counter *fbc) +static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc) { - free_percpu(fbc->counters); + s64 ret = __percpu_counter_sum(fbc); + return ret < 0 ? 0 : ret; } -void percpu_counter_mod(struct percpu_counter *fbc, long amount); -long percpu_counter_sum(struct percpu_counter *fbc); +static inline s64 percpu_counter_sum(struct percpu_counter *fbc) +{ + return __percpu_counter_sum(fbc); +} -static inline long percpu_counter_read(struct percpu_counter *fbc) +static inline s64 percpu_counter_read(struct percpu_counter *fbc) { return fbc->count; } @@ -49,13 +65,14 @@ static inline long percpu_counter_read(struct percpu_counter *fbc) /* * It is possible for the percpu_counter_read() to return a small negative * number for some counter which should never be negative. + * */ -static inline long percpu_counter_read_positive(struct percpu_counter *fbc) +static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc) { - long ret = fbc->count; + s64 ret = fbc->count; barrier(); /* Prevent reloads of fbc->count */ - if (ret > 0) + if (ret >= 0) return ret; return 1; } @@ -63,51 +80,70 @@ static inline long percpu_counter_read_positive(struct percpu_counter *fbc) #else struct percpu_counter { - long count; + s64 count; }; -static inline void percpu_counter_init(struct percpu_counter *fbc) +static inline int percpu_counter_init(struct percpu_counter *fbc, s64 amount) { - fbc->count = 0; + fbc->count = amount; + return 0; } static inline void percpu_counter_destroy(struct percpu_counter *fbc) { } +static inline void percpu_counter_set(struct percpu_counter *fbc, s64 amount) +{ + fbc->count = amount; +} + +#define __percpu_counter_add(fbc, amount, batch) \ + percpu_counter_add(fbc, amount) + static inline void -percpu_counter_mod(struct percpu_counter *fbc, long amount) +percpu_counter_add(struct percpu_counter *fbc, s64 amount) { preempt_disable(); fbc->count += amount; preempt_enable(); } -static inline long percpu_counter_read(struct percpu_counter *fbc) +static inline s64 percpu_counter_read(struct percpu_counter *fbc) { return fbc->count; } -static inline long percpu_counter_read_positive(struct percpu_counter *fbc) +static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc) { return fbc->count; } -static inline long percpu_counter_sum(struct percpu_counter *fbc) +static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc) { return percpu_counter_read_positive(fbc); } +static inline s64 percpu_counter_sum(struct percpu_counter *fbc) +{ + return percpu_counter_read(fbc); +} + #endif /* CONFIG_SMP */ static inline void percpu_counter_inc(struct percpu_counter *fbc) { - percpu_counter_mod(fbc, 1); + percpu_counter_add(fbc, 1); } static inline void percpu_counter_dec(struct percpu_counter *fbc) { - percpu_counter_mod(fbc, -1); + percpu_counter_add(fbc, -1); +} + +static inline void percpu_counter_sub(struct percpu_counter *fbc, s64 amount) +{ + percpu_counter_add(fbc, -amount); } #endif /* _LINUX_PERCPU_COUNTER_H */