6 #include "threads/malloc.h"
8 #include "filesys/file.h"
13 This must be an unsigned integer type at least as wide as int.
15 Each bit represents one bit in the bitmap.
16 If bit 0 in an element represents bit K in the bitmap,
17 then bit 1 in the element represents bit K+1 in the bitmap,
19 typedef unsigned long elem_type;
21 /* Number of bits in an element. */
22 #define ELEM_BITS (sizeof (elem_type) * CHAR_BIT)
24 /* From the outside, a bitmap is an array of bits. From the
25 inside, it's an array of elem_type (defined above) that
26 simulates an array of bits. */
29 size_t bit_cnt; /* Number of bits. */
30 elem_type *bits; /* Elements that represent bits. */
33 /* Returns the index of the element that contains the bit
36 elem_idx (size_t bit_idx)
38 return bit_idx / ELEM_BITS;
41 /* Returns an elem_type where only the bit corresponding to
42 BIT_IDX is turned on. */
43 static inline elem_type
44 bit_mask (size_t bit_idx)
46 return (elem_type) 1 << (bit_idx % ELEM_BITS);
49 /* Returns the number of elements required for BIT_CNT bits. */
51 elem_cnt (size_t bit_cnt)
53 return DIV_ROUND_UP (bit_cnt, ELEM_BITS);
56 /* Returns the number of bytes required for BIT_CNT bits. */
58 byte_cnt (size_t bit_cnt)
60 return sizeof (elem_type) * elem_cnt (bit_cnt);
63 /* Returns a bit mask in which the bits actually used in the last
64 element of B's bits are set to 1 and the rest are set to 0. */
65 static inline elem_type
66 last_mask (const struct bitmap *b)
68 int last_bits = b->bit_cnt % ELEM_BITS;
69 return last_bits ? ((elem_type) 1 << last_bits) - 1 : (elem_type) -1;
72 /* Initializes B to be a bitmap of BIT_CNT bits
73 and sets all of its bits to false.
74 Returns true if success, false if memory allocation
77 bitmap_create (size_t bit_cnt)
79 struct bitmap *b = malloc (sizeof *b);
83 b->bits = malloc (byte_cnt (bit_cnt));
84 if (b->bits != NULL || bit_cnt == 0)
86 bitmap_set_all (b, false);
94 /* Destroys bitmap B, freeing its storage.
95 Not for use on bitmaps created by
96 bitmap_create_preallocated(). */
98 bitmap_destroy (struct bitmap *b)
107 /* Returns the number of bits in B. */
109 bitmap_size (const struct bitmap *b)
114 /* Atomically sets the bit numbered IDX in B to VALUE. */
116 bitmap_set (struct bitmap *b, size_t idx, bool value)
119 ASSERT (idx < b->bit_cnt);
121 bitmap_mark (b, idx);
123 bitmap_reset (b, idx);
126 /* Sets all bits in B to VALUE. */
128 bitmap_set_all (struct bitmap *b, bool value)
132 bitmap_set_multiple (b, 0, bitmap_size (b), value);
135 /* Sets the CNT bits starting at START in B to VALUE. */
137 bitmap_set_multiple (struct bitmap *b, size_t start, size_t cnt, bool value)
142 ASSERT (start <= b->bit_cnt);
143 ASSERT (start + cnt <= b->bit_cnt);
145 for (i = 0; i < cnt; i++)
146 bitmap_set (b, start + i, value);
149 /* Atomically sets the bit numbered BIT_IDX in B to true. */
151 bitmap_mark (struct bitmap *b, size_t bit_idx)
153 size_t idx = elem_idx (bit_idx);
154 elem_type mask = bit_mask (bit_idx);
156 /* This is equivalent to `b->bits[idx] |= mask' except that it
157 is guaranteed to be atomic on a uniprocessor machine. See
158 the description of the OR instruction in [IA32-v2b]. */
159 asm ("or %0, %1" : "=m" (b->bits[idx]) : "r" (mask) : "cc");
162 /* Atomically sets the bit numbered BIT_IDX in B to false. */
164 bitmap_reset (struct bitmap *b, size_t bit_idx)
166 size_t idx = elem_idx (bit_idx);
167 elem_type mask = bit_mask (bit_idx);
169 /* This is equivalent to `b->bits[idx] &= ~mask' except that it
170 is guaranteed to be atomic on a uniprocessor machine. See
171 the description of the AND instruction in [IA32-v2a]. */
172 asm ("and %0, %1" : "=m" (b->bits[idx]) : "r" (~mask) : "cc");
175 /* Atomically toggles the bit numbered IDX in B;
176 that is, if it is true, makes it false,
177 and if it is false, makes it true. */
179 bitmap_flip (struct bitmap *b, size_t bit_idx)
181 size_t idx = elem_idx (bit_idx);
182 elem_type mask = bit_mask (bit_idx);
184 /* This is equivalent to `b->bits[idx] ^= mask' except that it
185 is guaranteed to be atomic on a uniprocessor machine. See
186 the description of the XOR instruction in [IA32-v2b]. */
187 asm ("xor %0, %1" : "=m" (b->bits[idx]) : "r" (mask) : "cc");
190 /* Returns the value of the bit numbered IDX in B. */
192 bitmap_test (const struct bitmap *b, size_t idx)
195 ASSERT (idx < b->bit_cnt);
196 return (b->bits[elem_idx (idx)] & bit_mask (idx)) != 0;
199 /* Returns true if any of the CNT bits starting at START is set
202 contains (const struct bitmap *b, size_t start, size_t cnt, bool value)
207 ASSERT (start <= b->bit_cnt);
208 ASSERT (start + cnt <= b->bit_cnt);
210 for (i = 0; i < cnt; i++)
211 if (bitmap_test (b, start + i) == value)
216 /* Finds and returns the starting index of the first group of CNT
217 consecutive bits in B at or after START that are all set to
219 If there is no such group, returns BITMAP_ERROR. */
221 bitmap_scan (const struct bitmap *b, size_t start, size_t cnt, bool value)
224 ASSERT (start <= b->bit_cnt);
226 if (cnt <= b->bit_cnt)
228 size_t last = b->bit_cnt - cnt;
230 for (i = start; i <= last; i++)
231 if (!contains (b, i, cnt, !value))
237 /* Finds the first group of CNT consecutive bits in B at or after
238 START that are all set to VALUE, flips them all to !VALUE,
239 and returns the index of the first bit in the group.
240 If there is no such group, returns BITMAP_ERROR.
241 If CNT is zero, returns 0.
242 Bits are set atomically, but testing bits is not atomic with
245 bitmap_scan_and_flip (struct bitmap *b, size_t start, size_t cnt, bool value)
247 size_t idx = bitmap_scan (b, start, cnt, value);
248 if (idx != BITMAP_ERROR)
249 bitmap_set_multiple (b, idx, cnt, !value);
253 /* Returns the number of bits in B between START and START + CNT,
254 exclusive, that are set to VALUE. */
256 bitmap_count (const struct bitmap *b, size_t start, size_t cnt, bool value)
261 ASSERT (start <= b->bit_cnt);
262 ASSERT (start + cnt <= b->bit_cnt);
265 for (i = 0; i < cnt; i++)
266 if (bitmap_test (b, start + i) == value)
271 /* Returns true if any bits in B between START and START + CNT,
272 exclusive, are set to true, and false otherwise.*/
274 bitmap_any (const struct bitmap *b, size_t start, size_t cnt)
276 return contains (b, start, cnt, true);
279 /* Returns true if no bits in B between START and START + CNT,
280 exclusive, are set to true, and false otherwise.*/
282 bitmap_none (const struct bitmap *b, size_t start, size_t cnt)
284 return !contains (b, start, cnt, true);
287 /* Returns true if every bit in B between START and START + CNT,
288 exclusive, is set to true, and false otherwise. */
290 bitmap_all (const struct bitmap *b, size_t start, size_t cnt)
292 return !contains (b, start, cnt, false);
296 /* Returns the number of bytes needed to store B in a file. */
298 bitmap_file_size (const struct bitmap *b)
300 return byte_cnt (b->bit_cnt);
303 /* Reads FILE into B, ignoring errors. */
305 bitmap_read (struct bitmap *b, struct file *file)
309 file_read_at (file, b->bits, byte_cnt (b->bit_cnt), 0);
310 b->bits[elem_cnt (b->bit_cnt) - 1] &= last_mask (b);
314 /* Writes FILE to B, ignoring errors. */
316 bitmap_write (const struct bitmap *b, struct file *file)
318 file_write_at (file, b->bits, byte_cnt (b->bit_cnt), 0);
322 /* Dumps the contents of B to the console as hexadecimal. */
324 bitmap_dump (const struct bitmap *b)
326 hex_dump (0, b->bits, byte_cnt (b->bit_cnt), false);
329 /* Returns the number of bytes required to accomodate a bitmap
330 with BIT_CNT bits. */
332 bitmap_needed_bytes (size_t bit_cnt)
334 return sizeof (struct bitmap) + byte_cnt (bit_cnt);
337 /* Creates and returns a bitmap with BIT_CNT bits in the
338 BLOCK_SIZE bytes of storage preallocated at BLOCK.
339 BLOCK_SIZE must be at least bitmap_needed_bytes(BIT_CNT). */
341 bitmap_create_preallocated (size_t bit_cnt, void *block, size_t block_size)
343 struct bitmap *b = block;
345 ASSERT (block_size >= bitmap_needed_bytes (bit_cnt));
347 b->bit_cnt = bit_cnt;
348 b->bits = (elem_type *) (b + 1);
349 bitmap_set_all (b, false);