Index: kernel/generic/src/adt/bitmap.c
===================================================================
--- kernel/generic/src/adt/bitmap.c	(revision 6e75f2dcda90e74dfeaa38430a08f747bf4e05fe)
+++ kernel/generic/src/adt/bitmap.c	(revision 7de184188e72503fed6ae5a5c2ed087b3fe184f4)
@@ -37,4 +37,12 @@
  * setting and clearing ranges of bits and for finding ranges
  * of unset bits.
+ *
+ * The bitmap ADT can optionally implement a two-level hierarchy
+ * for faster range searches. The second level bitmap (of blocks)
+ * is not precise, but conservative. This means that if the block
+ * bit is set, it guarantees that all bits in the block are set.
+ * But if the block bit is unset, nothing can be said about the
+ * bits in the block.
+ *
  */
 
@@ -48,22 +56,4 @@
 #define ALL_ZEROES  0x00
 
-/** Unchecked version of bitmap_get()
- *
- * This version of bitmap_get() does not do any boundary checks.
- *
- * @param bitmap  Bitmap to access.
- * @param element Element to access.
- *
- * @return Bit value of the element in the bitmap.
- *
- */
-static unsigned int bitmap_get_fast(bitmap_t *bitmap, size_t element)
-{
-	size_t byte = element / BITMAP_ELEMENT;
-	uint8_t mask = 1 << (element & BITMAP_REMAINER);
-	
-	return !!((bitmap->bits)[byte] & mask);
-}
-
 /** Get bitmap size
  *
@@ -71,9 +61,11 @@
  *
  * @param elements   Number bits stored in bitmap.
+ * @param block_size Block size of the 2nd level bitmap.
+ *                   If set to zero, no 2nd level is used.
  *
  * @return Size (in bytes) required for the bitmap.
  *
  */
-size_t bitmap_size(size_t elements)
+size_t bitmap_size(size_t elements, size_t block_size)
 {
 	size_t size = elements / BITMAP_ELEMENT;
@@ -82,4 +74,11 @@
 		size++;
 	
+	if (block_size > 0) {
+		size += elements / block_size;
+		
+		if ((elements % block_size) != 0)
+			size++;
+	}
+	
 	return size;
 }
@@ -91,4 +90,6 @@
  * @param bitmap     Bitmap structure.
  * @param elements   Number of bits stored in bitmap.
+ * @param block_size Block size of the 2nd level bitmap.
+ *                   If set to zero, no 2nd level is used.
  * @param data       Address of the memory used to hold the map.
  *                   The optional 2nd level bitmap follows the 1st
@@ -96,9 +97,60 @@
  *
  */
-void bitmap_initialize(bitmap_t *bitmap, size_t elements, void *data)
+void bitmap_initialize(bitmap_t *bitmap, size_t elements, size_t block_size,
+    void *data)
 {
 	bitmap->elements = elements;
 	bitmap->bits = (uint8_t *) data;
-	bitmap->next_fit = 0;
+	
+	if (block_size > 0) {
+		bitmap->block_size = block_size;
+		bitmap->blocks = bitmap->bits +
+		    bitmap_size(elements, 0);
+	} else {
+		bitmap->block_size = 0;
+		bitmap->blocks = NULL;
+	}
+}
+
+static void bitmap_set_range_internal(uint8_t *bits, size_t start, size_t count)
+{
+	if (count == 0)
+		return;
+	
+	size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT);
+	
+	/* Leading unaligned bits */
+	size_t lub = min(aligned_start - start, count);
+	
+	/* Aligned middle bits */
+	size_t amb = (count > lub) ? (count - lub) : 0;
+	
+	/* Trailing aligned bits */
+	size_t tab = amb % BITMAP_ELEMENT;
+	
+	if (start + count < aligned_start) {
+		/* Set bits in the middle of byte. */
+		bits[start / BITMAP_ELEMENT] |=
+		    ((1 << lub) - 1) << (start & BITMAP_REMAINER);
+		return;
+	}
+	
+	if (lub) {
+		/* Make sure to set any leading unaligned bits. */
+		bits[start / BITMAP_ELEMENT] |=
+		    ~((1 << (BITMAP_ELEMENT - lub)) - 1);
+	}
+	
+	size_t i;
+	
+	for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
+		/* The middle bits can be set byte by byte. */
+		bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ONES;
+	}
+	
+	if (tab) {
+		/* Make sure to set any trailing aligned bits. */
+		bits[aligned_start / BITMAP_ELEMENT + i] |= (1 << tab) - 1;
+	}
 }
 
@@ -114,8 +166,28 @@
 	ASSERT(start + count <= bitmap->elements);
 	
+	bitmap_set_range_internal(bitmap->bits, start, count);
+	
+	if (bitmap->block_size > 0) {
+		size_t aligned_start = ALIGN_UP(start, bitmap->block_size);
+		
+		/* Leading unaligned bits */
+		size_t lub = min(aligned_start - start, count);
+		
+		/* Aligned middle bits */
+		size_t amb = (count > lub) ? (count - lub) : 0;
+		
+		size_t aligned_size = amb / bitmap->block_size;
+		
+		bitmap_set_range_internal(bitmap->blocks, aligned_start,
+		    aligned_size);
+	}
+}
+
+static void bitmap_clear_range_internal(uint8_t *bits, size_t start,
+    size_t count)
+{
 	if (count == 0)
 		return;
 	
-	size_t start_byte = start / BITMAP_ELEMENT;
 	size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT);
 	
@@ -130,14 +202,14 @@
 	
 	if (start + count < aligned_start) {
-		/* Set bits in the middle of byte. */
-		bitmap->bits[start_byte] |=
-		    ((1 << lub) - 1) << (start & BITMAP_REMAINER);
+		/* Set bits in the middle of byte */
+		bits[start / BITMAP_ELEMENT] &=
+		    ~(((1 << lub) - 1) << (start & BITMAP_REMAINER));
 		return;
 	}
 	
 	if (lub) {
-		/* Make sure to set any leading unaligned bits. */
-		bitmap->bits[start_byte] |=
-		    ~((1 << (BITMAP_ELEMENT - lub)) - 1);
+		/* Make sure to clear any leading unaligned bits. */
+		bits[start / BITMAP_ELEMENT] &=
+		    (1 << (BITMAP_ELEMENT - lub)) - 1;
 	}
 	
@@ -145,13 +217,11 @@
 	
 	for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
-		/* The middle bits can be set byte by byte. */
-		bitmap->bits[aligned_start / BITMAP_ELEMENT + i] =
-		    ALL_ONES;
+		/* The middle bits can be cleared byte by byte. */
+		bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ZEROES;
 	}
 	
 	if (tab) {
-		/* Make sure to set any trailing aligned bits. */
-		bitmap->bits[aligned_start / BITMAP_ELEMENT + i] |=
-		    (1 << tab) - 1;
+		/* Make sure to clear any trailing aligned bits. */
+		bits[aligned_start / BITMAP_ELEMENT + i] &= ~((1 << tab) - 1);
 	}
 }
@@ -168,47 +238,19 @@
 	ASSERT(start + count <= bitmap->elements);
 	
-	if (count == 0)
-		return;
-	
-	size_t start_byte = start / BITMAP_ELEMENT;
-	size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT);
-	
-	/* Leading unaligned bits */
-	size_t lub = min(aligned_start - start, count);
-	
-	/* Aligned middle bits */
-	size_t amb = (count > lub) ? (count - lub) : 0;
-	
-	/* Trailing aligned bits */
-	size_t tab = amb % BITMAP_ELEMENT;
-	
-	if (start + count < aligned_start) {
-		/* Set bits in the middle of byte */
-		bitmap->bits[start_byte] &=
-		    ~(((1 << lub) - 1) << (start & BITMAP_REMAINER));
-		return;
-	}
-	
-	if (lub) {
-		/* Make sure to clear any leading unaligned bits. */
-		bitmap->bits[start_byte] &=
-		    (1 << (BITMAP_ELEMENT - lub)) - 1;
-	}
-	
-	size_t i;
-	
-	for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
-		/* The middle bits can be cleared byte by byte. */
-		bitmap->bits[aligned_start / BITMAP_ELEMENT + i] =
-		    ALL_ZEROES;
-	}
-	
-	if (tab) {
-		/* Make sure to clear any trailing aligned bits. */
-		bitmap->bits[aligned_start / BITMAP_ELEMENT + i] &=
-		    ~((1 << tab) - 1);
-	}
-	
-	bitmap->next_fit = start_byte;
+	bitmap_clear_range_internal(bitmap->bits, start, count);
+	
+	if (bitmap->block_size > 0) {
+		size_t aligned_start = start / bitmap->block_size;
+		
+		size_t aligned_end = (start + count) / bitmap->block_size;
+		
+		if (((start + count) % bitmap->block_size) != 0)
+			aligned_end++;
+		
+		size_t aligned_size = aligned_end - aligned_start;
+		
+		bitmap_clear_range_internal(bitmap->blocks, aligned_start,
+		    aligned_size);
+	}
 }
 
@@ -238,88 +280,4 @@
 }
 
-static int constraint_satisfy(size_t index, size_t base, size_t constraint)
-{
-	return (((base + index) & constraint) == 0);
-}
-
-/** Find a continuous zero bit range
- *
- * Find a continuous zero bit range in the bitmap. The address
- * computed as the sum of the index of the first zero bit and
- * the base argument needs to be compliant with the constraint
- * (those bits that are set in the constraint cannot be set in
- * the address).
- *
- * If the index argument is non-NULL, the continuous zero range
- * is set and the index of the first bit is stored to index.
- * Otherwise the bitmap stays untouched.
- *
- * @param bitmap     Bitmap structure.
- * @param count      Number of continuous zero bits to find.
- * @param base       Address of the first bit in the bitmap.
- * @param constraint Constraint for the address of the first zero bit.
- * @param index      Place to store the index of the first zero
- *                   bit. Can be NULL (in which case the bitmap
- *                   is not modified).
- *
- * @return Non-zero if a continuous range of zero bits satisfying
- *         the constraint has been found.
- * @return Zero otherwise.
- *
- */
-int bitmap_allocate_range(bitmap_t *bitmap, size_t count, size_t base,
-    size_t constraint, size_t *index)
-{
-	if (count == 0)
-		return false;
-	
-	size_t size = bitmap_size(bitmap->elements);
-	
-	for (size_t pos = 0; pos < size; pos++) {
-		size_t byte = (bitmap->next_fit + pos) % size;
-		
-		/* Skip if the current byte has all bits set */
-		if (bitmap->bits[byte] == ALL_ONES)
-			continue;
-		
-		size_t byte_bit = byte * BITMAP_ELEMENT;
-		
-		for (size_t bit = 0; bit < BITMAP_ELEMENT; bit++) {
-			size_t i = byte_bit + bit;
-			
-			if (i >= bitmap->elements)
-				break;
-			
-			if (!constraint_satisfy(i, base, constraint))
-				continue;
-			
-			if (!bitmap_get_fast(bitmap, i)) {
-				size_t continuous = 1;
-				
-				for (size_t j = 1; j < count; j++) {
-					if ((i + j < bitmap->elements) &&
-					    (!bitmap_get_fast(bitmap, i + j)))
-						continuous++;
-					else
-						break;
-				}
-				
-				if (continuous == count) {
-					if (index != NULL) {
-						bitmap_set_range(bitmap, i, count);
-						bitmap->next_fit = i / BITMAP_ELEMENT;
-						*index = i;
-					}
-					
-					return true;
-				} else
-					i += continuous;
-			}
-		}
-	}
-	
-	return false;
-}
-
 /** @}
  */
