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