aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-04-11 23:05:41 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-04-11 23:05:41 -0700
commit77c8efaeba52f0ebe0aaab689bdbb53bf6f5a723 (patch)
treed744d5128c5ef1ca3ec29ff68f717caa64ee063d /lib
parent387f7c83eb26b4f45e6d843f2ef703aafbe6c80f (diff)
downloadhistory-77c8efaeba52f0ebe0aaab689bdbb53bf6f5a723.tar.gz
[PATCH] Remove bitmap_shift_*() bitmap length limits
From: William Lee Irwin III <wli@holomorphy.com> Chang bitmap_shift_left()/bitmap_shift_right() to have O(1) stackspace requirements. Given zeroed tail preconditions these implementations satisfy zeroed tail postconditions, which makes them compatible with whatever changes from Paul Jackson one may want to merge in the future. No particular effort was required to ensure this. A small (but hopefully forgiveable) cleanup is a spelling correction: s/bitmap_shift_write/bitmap_shift_right/ in one of the kerneldoc comments. The primary effect of the patch is to remove the MAX_BITMAP_BITS limitation, so restoring the NR_CPUS to be limited only by stackspace and slab allocator maximums. They also look vaguely more efficient than the current code, though as this was not done for performance reasons, no performance testing was done.
Diffstat (limited to 'lib')
-rw-r--r--lib/bitmap.c70
1 files changed, 49 insertions, 21 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 68abf679808bf4..602b919ef5510f 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -12,8 +12,6 @@
#include <asm/bitops.h>
#include <asm/uaccess.h>
-#define MAX_BITMAP_BITS 512U /* for ia64 NR_CPUS maximum */
-
int bitmap_empty(const unsigned long *bitmap, int bits)
{
int k, lim = bits/BITS_PER_LONG;
@@ -72,7 +70,7 @@ void bitmap_complement(unsigned long *bitmap, int bits)
EXPORT_SYMBOL(bitmap_complement);
/*
- * bitmap_shift_write - logical right shift of the bits in a bitmap
+ * bitmap_shift_right - logical right shift of the bits in a bitmap
* @dst - destination bitmap
* @src - source bitmap
* @nbits - shift by this many bits
@@ -85,15 +83,32 @@ EXPORT_SYMBOL(bitmap_complement);
void bitmap_shift_right(unsigned long *dst,
const unsigned long *src, int shift, int bits)
{
- int k;
- DECLARE_BITMAP(__shr_tmp, MAX_BITMAP_BITS);
-
- BUG_ON(bits > MAX_BITMAP_BITS);
- bitmap_clear(__shr_tmp, bits);
- for (k = 0; k < bits - shift; ++k)
- if (test_bit(k + shift, src))
- set_bit(k, __shr_tmp);
- bitmap_copy(dst, __shr_tmp, bits);
+ int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
+ int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+ unsigned long mask = (1UL << left) - 1;
+ for (k = 0; off + k < lim; ++k) {
+ unsigned long upper, lower;
+
+ /*
+ * If shift is not word aligned, take lower rem bits of
+ * word above and make them the top rem bits of result.
+ */
+ if (!rem || off + k + 1 >= lim)
+ upper = 0;
+ else {
+ upper = src[off + k + 1];
+ if (off + k + 1 == lim - 1 && left)
+ upper &= mask;
+ }
+ lower = src[off + k];
+ if (left && off + k == lim - 1)
+ lower &= mask;
+ dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
+ if (left && k == lim - 1)
+ dst[k] &= mask;
+ }
+ if (off)
+ memset(&dst[lim - off], 0, off*sizeof(unsigned long));
}
EXPORT_SYMBOL(bitmap_shift_right);
@@ -111,15 +126,28 @@ EXPORT_SYMBOL(bitmap_shift_right);
void bitmap_shift_left(unsigned long *dst,
const unsigned long *src, int shift, int bits)
{
- int k;
- DECLARE_BITMAP(__shl_tmp, MAX_BITMAP_BITS);
-
- BUG_ON(bits > MAX_BITMAP_BITS);
- bitmap_clear(__shl_tmp, bits);
- for (k = bits; k >= shift; --k)
- if (test_bit(k - shift, src))
- set_bit(k, __shl_tmp);
- bitmap_copy(dst, __shl_tmp, bits);
+ int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
+ int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+ for (k = lim - off - 1; k >= 0; --k) {
+ unsigned long upper, lower;
+
+ /*
+ * If shift is not word aligned, take upper rem bits of
+ * word below and make them the bottom rem bits of result.
+ */
+ if (rem && k > 0)
+ lower = src[k - 1];
+ else
+ lower = 0;
+ upper = src[k];
+ if (left && k == lim - 1)
+ upper &= (1UL << left) - 1;
+ dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
+ if (left && k + off == lim - 1)
+ dst[k + off] &= (1UL << left) - 1;
+ }
+ if (off)
+ memset(dst, 0, off*sizeof(unsigned long));
}
EXPORT_SYMBOL(bitmap_shift_left);