Change bitmap interface, update references.
authorBen Pfaff <blp@cs.stanford.edu>
Thu, 23 Sep 2004 00:57:01 +0000 (00:57 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Thu, 23 Sep 2004 00:57:01 +0000 (00:57 +0000)
src/filesys/filesys.c
src/filesys/inode.c
src/lib/kernel/bitmap.c
src/lib/kernel/bitmap.h

index 59212ca774f3cf64e3878d82a593216bf294101d..28a2f7f046eb748c5946d1b8579699ee9c52b7e6 100644 (file)
@@ -166,7 +166,8 @@ filesys_create (const char *name, off_t initial_size)
   if (free_map == NULL)
     goto done;
   bitmap_read (free_map, free_map_file);
-  inode_sector = bitmap_find_and_set (free_map);
+  inode_sector = bitmap_scan_and_flip (free_map, 0, disk_size (filesys_disk),
+                                       false);
   if (inode_sector == BITMAP_ERROR)
     goto done;
 
index dbec4b900ef882128ef1aefd1133b70ab8396fd1..c704148911be75b70116795299d93ed7af15d395 100644 (file)
@@ -72,7 +72,7 @@ inode_create (struct bitmap *b, disk_sector_t sector, off_t length)
   idx->data.length = length;
   while (idx->data.sector_cnt < sector_cnt)
     {
-      size_t sector = bitmap_find_and_set (b);
+      size_t sector = bitmap_scan_and_flip (b, 0, bitmap_size (b), false);
       if (sector == BITMAP_ERROR)
         goto error;
 
index f1fa1130bbe107a53e862b807bdec3f7e2fa5fdb..c65d612c43e5232bd7b94cb9c2cfe2ba616980f2 100644 (file)
@@ -69,8 +69,9 @@ last_mask (const struct bitmap *b)
   return last_bits ? ((elem_type) 1 << last_bits) - 1 : (elem_type) -1;
 }
 \f
-/* Initializes B to be a bitmap of BIT_CNT bits.
-   Returns true if successfalse, false if memory allocation
+/* Initializes B to be a bitmap of BIT_CNT bits
+   and sets all of its bits to false.
+   Returns true if success, false if memory allocation
    failed. */
 struct bitmap *
 bitmap_create (size_t bit_cnt) 
@@ -90,7 +91,9 @@ bitmap_create (size_t bit_cnt)
   return NULL;
 }
 
-/* Destroys bitmap B, freeing its storage. */
+/* Destroys bitmap B, freeing its storage.
+   Not for use on bitmaps created by
+   bitmap_create_preallocated(). */
 void
 bitmap_destroy (struct bitmap *b) 
 {
@@ -136,6 +139,21 @@ bitmap_set_all (struct bitmap *b, bool value)
     }
 }
 
+/* Sets the bits numbered START through END, exclusive, in B to
+   VALUE. */
+void
+bitmap_set_multiple (struct bitmap *b, size_t start, size_t end, bool value) 
+{
+  size_t idx;
+  
+  ASSERT (b != NULL);
+  ASSERT (start <= end);
+  ASSERT (end <= b->bit_cnt);
+
+  for (idx = start; idx < end; idx++)
+    bitmap_set (b, idx, value);
+}
+
 /* Sets the bit numbered IDX in B to true. */
 void
 bitmap_mark (struct bitmap *b, size_t idx) 
@@ -170,126 +188,93 @@ bitmap_test (const struct bitmap *b, size_t idx)
   return (b->bits[elem_idx (idx)] & bit_mask (idx)) != 0;
 }
 
-/* Returns the smallest index of a bit set to VALUE in B.
-   If no bits in B are set to VALUE, returns BITMAP_ERROR. */
-size_t
-bitmap_scan (const struct bitmap *b, bool value) 
+/* Returns true if any bit from START to END, exclusive, is set
+   to VALUE. */
+static bool
+contains (const struct bitmap *b, size_t start, size_t end, bool value) 
 {
-  elem_type ignore = value ? 0 : (elem_type) -1;
   size_t idx;
   
   ASSERT (b != NULL);
-  for (idx = 0; idx < elem_cnt (b); idx++)
-    {
-      elem_type e = b->bits[idx];
-      if (e != ignore)
-        {
-          idx *= ELEM_BITS;
+  ASSERT (start <= end);
+  ASSERT (end <= b->bit_cnt);
 
-          while ((e & 1) != value)
-            {
-              e >>= 1;
-              idx++;
-            }
-
-          return idx < b->bit_cnt ? idx : BITMAP_ERROR;
-        }
-    }
-  return BITMAP_ERROR;
+  for (idx = start; idx < end; idx++)
+    if (bitmap_test (b, idx) == value)
+      return true;
+  return false;
 }
 
-/* Finds the smallest index of a bit set to false in B,
-   sets it to true, and returns the index.
-   If no bits in B are set to false, changes no bits and
-   returns BITMAP_ERROR. */
+/* Finds and returns the starting index of the first group of CNT
+   consecutive bits in B at or after START that are all set to
+   VALUE.
+   If there is no such group, returns BITMAP_ERROR. */
 size_t
-bitmap_find_and_set (struct bitmap *b
+bitmap_scan (const struct bitmap *b, size_t start, size_t cnt, bool value
 {
-  size_t idx = bitmap_scan (b, false);
-  if (idx != BITMAP_ERROR) 
-    bitmap_mark (b, idx);
-  return idx;
+  size_t idx, last;
+  
+  ASSERT (b != NULL);
+  ASSERT (start <= b->bit_cnt);
+
+  for (idx = start, last = b->bit_cnt - cnt; idx <= last; idx++)
+    if (!contains (b, idx, idx + cnt, !value))
+      return idx;
+  return BITMAP_ERROR;
 }
 
-/* Finds the smallest index of a bit set to true in B,
-   sets it to false, and returns the index.
-   If no bits in B are set to true, changes no bits and
-   returns BITMAP_ERROR. */
+/* Finds the first group of CNT consecutive bits in B at or after
+   START that are all set to VALUE, flips them all to !VALUE,
+   and returns the index of the first bit in the group.
+   If there is no such group, returns BITMAP_ERROR. */
 size_t
-bitmap_find_and_clear (struct bitmap *b) 
+bitmap_scan_and_flip (struct bitmap *b, size_t start, size_t cnt, bool value)
 {
-  size_t idx = bitmap_scan (b, true);
+  size_t idx = bitmap_scan (b, start, cnt, value);
   if (idx != BITMAP_ERROR) 
-    bitmap_reset (b, idx);
+    bitmap_set_multiple (b, idx, idx + cnt, !value);
   return idx;
 }
 
-/* Returns the number of bits in B set to true. */
+/* Returns the number of bits in B between START and END,
+   exclusive, that are set to VALUE. */
 size_t
-bitmap_set_cnt (const struct bitmap *b
+bitmap_count (const struct bitmap *b, size_t start, size_t end, bool value
 {
-  size_t cnt;
-  size_t i;
+  size_t idx, cnt;
 
   ASSERT (b != NULL);
+  ASSERT (start <= end);
+  ASSERT (end <= b->bit_cnt);
+
   cnt = 0;
-  for (i = 0; i < elem_cnt (b); i++)
-    {
-      elem_type e = b->bits[i];
-      while (e != 0) 
-        {
-          cnt++;
-          e &= e - 1;
-        }
-    }
+  for (idx = start; idx < end; idx++)
+    cnt += bitmap_test (b, idx) == value;
   return cnt;
 }
 
-/* Returns true if any bits in B are set to true,
-   and false otherwise.*/
+/* Returns true if any bits in B between START and END,
+   exclusive, are set to true, and false otherwise.*/
 bool
-bitmap_any (const struct bitmap *b) 
+bitmap_any (const struct bitmap *b, size_t start, size_t end
 {
-  size_t i;
-
-  ASSERT (b != NULL);
-  for (i = 0; i < elem_cnt (b); i++)
-    if (b->bits[i])
-      return true;
-  return false;
+  return contains (b, start, end, true);
 }
 
-/* Returns the number of bits in B set to false. */
+/* Returns true if no bits in B between START and END, exclusive,
+   are set to true, and false otherwise.*/
 bool
-bitmap_clear_cnt (const struct bitmap *b
+bitmap_none (const struct bitmap *b, size_t start, size_t end
 {
-  return b->bit_cnt - bitmap_set_cnt (b);
+  return !contains (b, start, end, true);
 }
 
-/* Returns true if no bits in B are set to true,
-   and false otherwise.*/
+/* Returns true if every bit in B between START and END,
+   exclusive, is set to true, and false otherwise. */
 bool
-bitmap_none (const struct bitmap *b
+bitmap_all (const struct bitmap *b, size_t start, size_t end
 {
-  return !bitmap_any (b); 
-}
-
-/* Returns true if every bit in B is set to true,
-   and false otherwise. */
-bool
-bitmap_all (const struct bitmap *b) 
-{
-  size_t i;
-
-  ASSERT (b != NULL);
-
-  if (b->bit_cnt == 0)
-    return true;
-  
-  for (i = 0; i < elem_cnt (b) - 1; i++)
-    if (b->bits[i] != (elem_type) -1)
-      return false;
-  return b->bits[i] == last_mask (b);
+  return !contains (b, start, end, false);
 }
 
 #ifdef FILESYS
@@ -325,3 +310,30 @@ bitmap_dump (const struct bitmap *b)
 {
   hex_dump (0, b->bits, byte_cnt (b), false);
 }
+
+/* Returns the number of bytes required to accomodate a bitmap
+   with BIT_CNT bits. */
+size_t
+bitmap_needed_bytes (size_t bit_cnt) 
+{
+  struct bitmap b;
+  b.bit_cnt = bit_cnt;
+  return byte_cnt (&b) + sizeof b;
+}
+
+/* Creates and returns a bitmap with BIT_CNT bits in the
+   BLOCK_SIZE bytes of storage preallocated at BLOCK.
+   BLOCK_SIZE must be at least bitmap_needed_bytes(BIT_CNT). */
+struct bitmap *
+bitmap_create_preallocated (size_t bit_cnt, void *block, size_t block_size) 
+{
+  struct bitmap *b = block;
+  
+  ASSERT (block_size >= bitmap_needed_bytes (bit_cnt));
+
+  b->bit_cnt = bit_cnt;
+  b->bits = (elem_type *) (b + 1);
+  bitmap_set_all (b, false);
+  return b;
+}
+
index 8aef186f709a6073c6c445f19b20285f2b114d08..dbb70046c96c9074119689827169dacf249fcde2 100644 (file)
@@ -13,6 +13,7 @@ size_t bitmap_size (const struct bitmap *);
 
 void bitmap_set (struct bitmap *, size_t idx, bool);
 void bitmap_set_all (struct bitmap *, bool);
+void bitmap_set_multiple (struct bitmap *, size_t start, size_t end, bool);
 
 void bitmap_mark (struct bitmap *, size_t idx);
 void bitmap_reset (struct bitmap *, size_t idx);
@@ -21,16 +22,14 @@ void bitmap_flip (struct bitmap *, size_t idx);
 bool bitmap_test (const struct bitmap *, size_t idx);
 
 #define BITMAP_ERROR ((size_t) -1)
-size_t bitmap_scan (const struct bitmap *, bool);
-size_t bitmap_find_and_set (struct bitmap *);
-size_t bitmap_find_and_clear (struct bitmap *);
+size_t bitmap_scan (const struct bitmap *, size_t start, size_t cnt, bool);
+size_t bitmap_scan_and_flip (struct bitmap *, size_t start, size_t cnt,
+                             bool);
 
-size_t bitmap_set_cnt (const struct bitmap *);
-bool bitmap_clear_cnt (const struct bitmap *);
-
-bool bitmap_any (const struct bitmap *);
-bool bitmap_none (const struct bitmap *);
-bool bitmap_all (const struct bitmap *);
+size_t bitmap_count (const struct bitmap *, size_t start, size_t end, bool);
+bool bitmap_any (const struct bitmap *, size_t start, size_t end);
+bool bitmap_none (const struct bitmap *, size_t start, size_t end);
+bool bitmap_all (const struct bitmap *, size_t start, size_t end);
 
 #ifdef FILESYS
 struct file;
@@ -41,4 +40,8 @@ void bitmap_write (const struct bitmap *, struct file *);
 
 void bitmap_dump (const struct bitmap *);
 
+size_t bitmap_needed_bytes (size_t bit_cnt);
+struct bitmap *bitmap_create_preallocated (size_t bit_cnt,
+                                           void *, size_t byte_cnt);
+
 #endif /* lib/kernel/bitmap.h */