77edf2270b35435538fbbb5adeec52096403f50b
[pintos-anon] / src / lib / kernel / bitmap.c
1 #include "bitmap.h"
2 #include <debug.h>
3 #include <limits.h>
4 #include <random.h>
5 #include <round.h>
6 #include <stdio.h>
7 #include "threads/malloc.h"
8 #ifdef FILESYS
9 #include "filesys/file.h"
10 #endif
11 \f
12 /* Element type.
13
14    This must be an unsigned integer type at least as wide as int.
15
16    Each bit represents one bit in the bitmap.
17    If bit 0 in an element represents bit K in the bitmap,
18    then bit 1 in the element represents bit K+1 in the bitmap,
19    and so on. */
20 typedef unsigned long elem_type;
21
22 /* Number of bits in an element. */
23 #define ELEM_BITS (sizeof (elem_type) * CHAR_BIT)
24
25 /* From the outside, a bitmap is an array of bits.  From the
26    inside, it's an array of elem_type (defined above) that
27    simulates an array of bits. */
28 struct bitmap
29   {
30     size_t bit_cnt;     /* Number of bits. */
31     elem_type *bits;    /* Elements that represent bits. */
32   };
33
34 /* Returns the index of the element that contains the bit
35    numbered BIT_IDX. */
36 static inline size_t
37 elem_idx (size_t bit_idx) 
38 {
39   return bit_idx / ELEM_BITS;
40 }
41
42 /* Returns an elem_type where only the bit corresponding to
43    BIT_IDX is turned on. */
44 static inline elem_type
45 bit_mask (size_t bit_idx) 
46 {
47   return (elem_type) 1 << (bit_idx % ELEM_BITS);
48 }
49
50 /* Returns the number of elements required for BIT_CNT bits. */
51 static inline size_t
52 elem_cnt (size_t bit_cnt)
53 {
54   return DIV_ROUND_UP (bit_cnt, ELEM_BITS);
55 }
56
57 /* Returns the number of bytes required for BIT_CNT bits. */
58 static inline size_t
59 byte_cnt (size_t bit_cnt)
60 {
61   return sizeof (elem_type) * elem_cnt (bit_cnt);
62 }
63
64 /* Returns a bit mask in which the bits actually used in the last
65    element of B's bits are set to 1 and the rest are set to 0. */
66 static inline elem_type
67 last_mask (const struct bitmap *b) 
68 {
69   int last_bits = b->bit_cnt % ELEM_BITS;
70   return last_bits ? ((elem_type) 1 << last_bits) - 1 : (elem_type) -1;
71 }
72 \f
73 /* Creation and destruction. */
74
75 /* Initializes B to be a bitmap of BIT_CNT bits
76    and sets all of its bits to false.
77    Returns true if success, false if memory allocation
78    failed. */
79 struct bitmap *
80 bitmap_create (size_t bit_cnt) 
81 {
82   struct bitmap *b = malloc (sizeof *b);
83   if (b != NULL)
84     {
85       b->bit_cnt = bit_cnt;
86       b->bits = malloc (byte_cnt (bit_cnt));
87       if (b->bits != NULL || bit_cnt == 0)
88         {
89           bitmap_set_all (b, false);
90           return b;
91         }
92       free (b);
93     }
94   return NULL;
95 }
96
97 /* Creates and returns a bitmap with BIT_CNT bits in the
98    BLOCK_SIZE bytes of storage preallocated at BLOCK.
99    BLOCK_SIZE must be at least bitmap_needed_bytes(BIT_CNT). */
100 struct bitmap *
101 bitmap_create_in_buf (size_t bit_cnt, void *block, size_t block_size UNUSED)
102 {
103   struct bitmap *b = block;
104   
105   ASSERT (block_size >= bitmap_buf_size (bit_cnt));
106
107   b->bit_cnt = bit_cnt;
108   b->bits = (elem_type *) (b + 1);
109   bitmap_set_all (b, false);
110   return b;
111 }
112
113 /* Returns the number of bytes required to accomodate a bitmap
114    with BIT_CNT bits (for use with bitmap_create_in_buf()). */
115 size_t
116 bitmap_buf_size (size_t bit_cnt) 
117 {
118   return sizeof (struct bitmap) + byte_cnt (bit_cnt);
119 }
120
121 /* Destroys bitmap B, freeing its storage.
122    Not for use on bitmaps created by
123    bitmap_create_preallocated(). */
124 void
125 bitmap_destroy (struct bitmap *b) 
126 {
127   if (b != NULL) 
128     {
129       free (b->bits);
130       free (b);
131     }
132 }
133 \f
134 /* Bitmap size. */
135
136 /* Returns the number of bits in B. */
137 size_t
138 bitmap_size (const struct bitmap *b)
139 {
140   return b->bit_cnt;
141 }
142 \f
143 /* Setting and testing single bits. */
144
145 /* Atomically sets the bit numbered IDX in B to VALUE. */
146 void
147 bitmap_set (struct bitmap *b, size_t idx, bool value) 
148 {
149   ASSERT (b != NULL);
150   ASSERT (idx < b->bit_cnt);
151   if (value)
152     bitmap_mark (b, idx);
153   else
154     bitmap_reset (b, idx);
155 }
156
157 /* Atomically sets the bit numbered BIT_IDX in B to true. */
158 void
159 bitmap_mark (struct bitmap *b, size_t bit_idx) 
160 {
161   size_t idx = elem_idx (bit_idx);
162   elem_type mask = bit_mask (bit_idx);
163
164   /* This is equivalent to `b->bits[idx] |= mask' except that it
165      is guaranteed to be atomic on a uniprocessor machine.  See
166      the description of the OR instruction in [IA32-v2b]. */
167   asm ("orl %1, %0" : "=m" (b->bits[idx]) : "r" (mask) : "cc");
168 }
169
170 /* Atomically sets the bit numbered BIT_IDX in B to false. */
171 void
172 bitmap_reset (struct bitmap *b, size_t bit_idx) 
173 {
174   size_t idx = elem_idx (bit_idx);
175   elem_type mask = bit_mask (bit_idx);
176
177   /* This is equivalent to `b->bits[idx] &= ~mask' except that it
178      is guaranteed to be atomic on a uniprocessor machine.  See
179      the description of the AND instruction in [IA32-v2a]. */
180   asm ("andl %1, %0" : "=m" (b->bits[idx]) : "r" (~mask) : "cc");
181 }
182
183 /* Atomically toggles the bit numbered IDX in B;
184    that is, if it is true, makes it false,
185    and if it is false, makes it true. */
186 void
187 bitmap_flip (struct bitmap *b, size_t bit_idx) 
188 {
189   size_t idx = elem_idx (bit_idx);
190   elem_type mask = bit_mask (bit_idx);
191
192   /* This is equivalent to `b->bits[idx] ^= mask' except that it
193      is guaranteed to be atomic on a uniprocessor machine.  See
194      the description of the XOR instruction in [IA32-v2b]. */
195   asm ("xorl %1, %0" : "=m" (b->bits[idx]) : "r" (mask) : "cc");
196 }
197
198 /* Returns the value of the bit numbered IDX in B. */
199 bool
200 bitmap_test (const struct bitmap *b, size_t idx) 
201 {
202   ASSERT (b != NULL);
203   ASSERT (idx < b->bit_cnt);
204   return (b->bits[elem_idx (idx)] & bit_mask (idx)) != 0;
205 }
206 \f
207 /* Setting and testing multiple bits. */
208
209 /* Sets all bits in B to VALUE. */
210 void
211 bitmap_set_all (struct bitmap *b, bool value) 
212 {
213   ASSERT (b != NULL);
214
215   bitmap_set_multiple (b, 0, bitmap_size (b), value);
216 }
217
218 /* Sets the CNT bits starting at START in B to VALUE. */
219 void
220 bitmap_set_multiple (struct bitmap *b, size_t start, size_t cnt, bool value) 
221 {
222   size_t i;
223   
224   ASSERT (b != NULL);
225   ASSERT (start <= b->bit_cnt);
226   ASSERT (start + cnt <= b->bit_cnt);
227
228   for (i = 0; i < cnt; i++)
229     bitmap_set (b, start + i, value);
230 }
231
232 /* Returns the number of bits in B between START and START + CNT,
233    exclusive, that are set to VALUE. */
234 size_t
235 bitmap_count (const struct bitmap *b, size_t start, size_t cnt, bool value) 
236 {
237   size_t i, value_cnt;
238
239   ASSERT (b != NULL);
240   ASSERT (start <= b->bit_cnt);
241   ASSERT (start + cnt <= b->bit_cnt);
242
243   value_cnt = 0;
244   for (i = 0; i < cnt; i++)
245     if (bitmap_test (b, start + i) == value)
246       value_cnt++;
247   return value_cnt;
248 }
249
250 /* Returns true if any bits in B between START and START + CNT,
251    exclusive, are set to VALUE, and false otherwise. */
252 bool
253 bitmap_contains (const struct bitmap *b, size_t start, size_t cnt, bool value) 
254 {
255   size_t i;
256   
257   ASSERT (b != NULL);
258   ASSERT (start <= b->bit_cnt);
259   ASSERT (start + cnt <= b->bit_cnt);
260
261   for (i = 0; i < cnt; i++)
262     if (bitmap_test (b, start + i) == value)
263       return true;
264   return false;
265 }
266
267 /* Returns true if any bits in B between START and START + CNT,
268    exclusive, are set to true, and false otherwise.*/
269 bool
270 bitmap_any (const struct bitmap *b, size_t start, size_t cnt) 
271 {
272   return bitmap_contains (b, start, cnt, true);
273 }
274
275 /* Returns true if no bits in B between START and START + CNT,
276    exclusive, are set to true, and false otherwise.*/
277 bool
278 bitmap_none (const struct bitmap *b, size_t start, size_t cnt) 
279 {
280   return !bitmap_contains (b, start, cnt, true);
281 }
282
283 /* Returns true if every bit in B between START and START + CNT,
284    exclusive, is set to true, and false otherwise. */
285 bool
286 bitmap_all (const struct bitmap *b, size_t start, size_t cnt) 
287 {
288   return !bitmap_contains (b, start, cnt, false);
289 }
290 \f
291 /* Finding set or unset bits. */
292
293 /* Finds and returns the starting index of a group of CNT
294    consecutive bits in B at or after START that are all set to
295    VALUE.
296    If there is no such group, returns BITMAP_ERROR. */
297 size_t
298 bitmap_scan (const struct bitmap *b, size_t start, size_t cnt, bool value) 
299 {
300   ASSERT (b != NULL);
301   ASSERT (start <= b->bit_cnt);
302
303   if (cnt <= b->bit_cnt) 
304     {
305       size_t last = b->bit_cnt - cnt;
306       size_t middle = start + random_ulong () % (last - start + 1); 
307       size_t i = middle;
308       do
309         {
310           if (!bitmap_contains (b, i, cnt, !value))
311             return i; 
312           i = i != last ? i + 1 : start;
313         }
314       while (i != middle);
315     }
316   return BITMAP_ERROR;
317 }
318
319 /* Finds a group of CNT consecutive bits in B at or after
320    START that are all set to VALUE, flips them all to !VALUE,
321    and returns the index of the first bit in the group.
322    If there is no such group, returns BITMAP_ERROR.
323    If CNT is zero, returns 0.
324    Bits are set atomically, but testing bits is not atomic with
325    setting them. */
326 size_t
327 bitmap_scan_and_flip (struct bitmap *b, size_t start, size_t cnt, bool value)
328 {
329   size_t idx = bitmap_scan (b, start, cnt, value);
330   if (idx != BITMAP_ERROR) 
331     bitmap_set_multiple (b, idx, cnt, !value);
332   return idx;
333 }
334 \f
335 /* File input and output. */
336
337 #ifdef FILESYS
338 /* Returns the number of bytes needed to store B in a file. */
339 size_t
340 bitmap_file_size (const struct bitmap *b) 
341 {
342   return byte_cnt (b->bit_cnt);
343 }
344
345 /* Reads B from FILE.  Returns true if successful, false
346    otherwise. */
347 bool
348 bitmap_read (struct bitmap *b, struct file *file) 
349 {
350   bool success = true;
351   if (b->bit_cnt > 0) 
352     {
353       off_t size = byte_cnt (b->bit_cnt);
354       success = file_read_at (file, b->bits, size, 0) == size;
355       b->bits[elem_cnt (b->bit_cnt) - 1] &= last_mask (b);
356     }
357   return success;
358 }
359
360 /* Writes B to FILE.  Return true if successful, false
361    otherwise. */
362 bool
363 bitmap_write (const struct bitmap *b, struct file *file)
364 {
365   off_t size = byte_cnt (b->bit_cnt);
366   return file_write_at (file, b->bits, size, 0) == size;
367 }
368 #endif /* FILESYS */
369 \f
370 /* Debugging. */
371
372 /* Dumps the contents of B to the console as hexadecimal. */
373 void
374 bitmap_dump (const struct bitmap *b) 
375 {
376   hex_dump (0, b->bits, byte_cnt (b->bit_cnt), false);
377 }
378