From: Paul Mundt <lethal@linux-sh.org>
To: Andrew Morton <akpm@osdl.org>, Paul Jackson <pj@sgi.com>,
James Bottomley <James.Bottomley@SteelEye.com>,
tony@atomide.com, linux-kernel@vger.kernel.org
Subject: [PATCH 2/3] bitmap: region multiword spanning support
Date: Fri, 27 Jan 2006 16:06:00 +0200 [thread overview]
Message-ID: <20060127140600.GC29632@linux-sh.org> (raw)
In-Reply-To: <20060127140457.GA29632@linux-sh.org>
Add support to the lib/bitmap.c bitmap_*_region() routines
for bitmap regions larger than one word (nbits > BITS_PER_LONG).
This removes a BUG_ON() in lib bitmap.
I have an updated store queue API for SH that is currently using this
with relative success, and at first glance, it seems like this could be
useful for x86 (arch/i386/kernel/pci-dma.c) as well. Particularly for
anything using dma_declare_coherent_memory() on large areas and that
attempts to allocate large buffers from that space.
This applies on top of the previous bitmap region cleanup work done by
Paul Jackson, who also did some cleanup to this patch.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
lib/bitmap.c | 108 ++++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 75 insertions(+), 33 deletions(-)
963100ab9721a76326a5479685e03d76dec25cf0
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 3fab1ce..f49eabe 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -692,26 +692,44 @@ EXPORT_SYMBOL(bitmap_bitremap);
*/
int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
{
- unsigned long mask;
- int nbits = 1 << order;
- int i;
-
- if (nbits > BITS_PER_LONG)
- return -EINVAL;
+ int nbits; /* number of bits in region */
+ int nlongs; /* num longs spanned by region in bitmap */
+ int nbitsinlong; /* num bits of region in each spanned long */
+ unsigned long mask; /* bitmask of bits [0 .. nbitsinlong-1] */
+ int i; /* scans bitmap by longs */
+
+ nbits = 1 << order;
+ nlongs = (nbits + (BITS_PER_LONG - 1)) / BITS_PER_LONG;
+ nbitsinlong = nbits;
+ if (nbitsinlong > BITS_PER_LONG)
+ nbitsinlong = BITS_PER_LONG;
/* make a mask of the order */
- mask = (1UL << (nbits - 1));
+ mask = (1UL << (nbitsinlong - 1));
mask += mask - 1;
- /* run up the bitmap nbits at a time */
- for (i = 0; i < bits; i += nbits) {
+ /* run up the bitmap nbitsinlong at a time */
+ for (i = 0; i < bits; i += nbitsinlong) {
int index = i / BITS_PER_LONG;
int offset = i - (index * BITS_PER_LONG);
- if ((bitmap[index] & (mask << offset)) == 0) {
+ int j, space = 1;
+
+ /* find space in the bitmap */
+ for (j = 0; j < nlongs; j++)
+ if ((bitmap[index + j] & (mask << offset))) {
+ space = 0;
+ break;
+ }
+
+ /* keep looking */
+ if (unlikely(!space))
+ continue;
+
+ for (j = 0; j < nlongs; j++)
/* set region in bitmap */
- bitmap[index] |= (mask << offset);
- return i;
- }
+ bitmap[index + j] |= (mask << offset);
+
+ return i;
}
return -ENOMEM;
}
@@ -728,13 +746,28 @@ EXPORT_SYMBOL(bitmap_find_free_region);
*/
void bitmap_release_region(unsigned long *bitmap, int pos, int order)
{
- int nbits = 1 << order;
- unsigned long mask = (1UL << (nbits - 1));
- int index = pos / BITS_PER_LONG;
- int offset = pos - (index * BITS_PER_LONG);
+ int nbits; /* number of bits in region */
+ int nlongs; /* num longs spanned by region in bitmap */
+ int index; /* index first long of region in bitmap */
+ int offset; /* bit offset region in bitmap[index] */
+ int nbitsinlong; /* num bits of region in each spanned long */
+ unsigned long mask; /* bitmask of bits [0 .. nbitsinlong-1] */
+ int i; /* scans bitmap by longs */
+
+ nbits = 1 << order;
+ nlongs = (nbits + (BITS_PER_LONG - 1)) / BITS_PER_LONG;
+ index = pos / BITS_PER_LONG;
+ offset = pos - (index * BITS_PER_LONG);
+
+ nbitsinlong = nbits;
+ if (nbitsinlong > BITS_PER_LONG)
+ nbitsinlong = BITS_PER_LONG;
+ mask = (1UL << (nbitsinlong - 1));
mask += mask - 1;
- bitmap[index] &= ~(mask << offset);
+
+ for (i = 0; i < nlongs; i++)
+ bitmap[index + i] &= ~(mask << offset);
}
EXPORT_SYMBOL(bitmap_release_region);
@@ -750,22 +783,31 @@ EXPORT_SYMBOL(bitmap_release_region);
*/
int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
{
- int nbits = 1 << order;
- unsigned long mask = (1UL << (nbits - 1));
- int index = pos / BITS_PER_LONG;
- int offset = pos - (index * BITS_PER_LONG);
-
- /*
- * We don't do regions of nbits > BITS_PER_LONG. The
- * algorithm would be a simple look for multiple zeros in the
- * array, but there's no driver today that needs this. If you
- * trip this BUG(), you get to code it...
- */
- BUG_ON(nbits > BITS_PER_LONG);
+ int nbits; /* number of bits in region */
+ int nlongs; /* num longs spanned by region in bitmap */
+ int index; /* index first long of region in bitmap */
+ int offset; /* bit offset region in bitmap[index] */
+ int nbitsinlong; /* num bits of region in each spanned long */
+ unsigned long mask; /* bitmask of bits [0 .. nbitsinlong-1] */
+ int i; /* scans bitmap by longs */
+
+ nbits = 1 << order;
+ nlongs = (nbits + (BITS_PER_LONG - 1)) / BITS_PER_LONG;
+ index = pos / BITS_PER_LONG;
+ offset = pos - (index * BITS_PER_LONG);
+
+ nbitsinlong = nbits;
+ if (nbitsinlong > BITS_PER_LONG)
+ nbitsinlong = BITS_PER_LONG;
+
+ mask = (1UL << (nbitsinlong - 1));
mask += mask - 1;
- if (bitmap[index] & (mask << offset))
- return -EBUSY;
- bitmap[index] |= (mask << offset);
+
+ for (i = 0; i < nlongs; i++)
+ if (bitmap[index + i] & (mask << offset))
+ return -EBUSY;
+ for (i = 0; i < nlongs; i++)
+ bitmap[index + i] |= (mask << offset);
return 0;
}
EXPORT_SYMBOL(bitmap_allocate_region);
next prev parent reply other threads:[~2006-01-27 14:06 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-01-27 14:04 [PATCH 0/3] bitmap: multiword allocations and region restructuring Paul Mundt
2006-01-27 14:05 ` [PATCH 1/3] bitmap: region cleanup Paul Mundt
2006-01-27 14:06 ` Paul Mundt [this message]
2006-01-27 14:06 ` [PATCH 3/3] bitmap: region restructuring Paul Mundt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060127140600.GC29632@linux-sh.org \
--to=lethal@linux-sh.org \
--cc=James.Bottomley@SteelEye.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pj@sgi.com \
--cc=tony@atomide.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox