at v2.6.17 2.3 kB view raw
1#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); 42long percpu_counter_sum(struct percpu_counter *fbc); 43 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 96static inline long percpu_counter_sum(struct percpu_counter *fbc) 97{ 98 return percpu_counter_read_positive(fbc); 99} 100 101#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 */