summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-04-12 12:59:51 -0700
committerJames Bottomley <jejb@raven.il.steeleye.com>2003-04-12 12:59:51 -0700
commitba8e8755393fd032e448b3cfa35cb01743807699 (patch)
tree75a18c8515be1213c8d0eea312aedb8e39713aaa /lib
parentf688c084bc58323c8a7ca19090884ac5da7b6c04 (diff)
[PATCH] percpu_counters: approximate but scalable counters
Several places in ext2 and ext3 are using filesystem-wide counters which use global locking. Mainly for the orlov allocator's heuristics. To solve the contention which this causes we can trade off accuracy against speed. This patch introduces a "percpu_counter" library type in which the counts are per-cpu and are periodically spilled into a global counter. Readers only read the global counter. These objects are *large*. On a 32 CPU P4, they are 4 kbytes. On a 4 way p3, 128 bytes.
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile1
-rw-r--r--lib/percpu_counter.c18
2 files changed, 19 insertions, 0 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 24e6b3adc098..6ab94d3cb906 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -14,6 +14,7 @@ obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+obj-$(CONFIG_SMP) += percpu_counter.o
ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
obj-y += dec_and_lock.o
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
new file mode 100644
index 000000000000..73f99d99f9ac
--- /dev/null
+++ b/lib/percpu_counter.c
@@ -0,0 +1,18 @@
+
+#include <linux/percpu_counter.h>
+
+void percpu_counter_mod(struct percpu_counter *fbc, long amount)
+{
+ int cpu = get_cpu();
+ long count = fbc->counters[cpu].count;
+
+ count += amount;
+ if (count >= FBC_BATCH || count <= -FBC_BATCH) {
+ spin_lock(&fbc->lock);
+ fbc->count += count;
+ spin_unlock(&fbc->lock);
+ count = 0;
+ }
+ fbc->counters[cpu].count = count;
+ put_cpu();
+}