Changes in kernel/generic/src/adt/bitmap.c [f72906c:64f3d3b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/adt/bitmap.c
rf72906c r64f3d3b 37 37 * setting and clearing ranges of bits and for finding ranges 38 38 * of unset bits. 39 * 40 * The bitmap ADT can optionally implement a two-level hierarchy 41 * for faster range searches. The second level bitmap (of blocks) 42 * is not precise, but conservative. This means that if the block 43 * bit is set, it guarantees that all bits in the block are set. 44 * But if the block bit is unset, nothing can be said about the 45 * bits in the block. 46 * 39 47 */ 40 48 … … 48 56 #define ALL_ZEROES 0x00 49 57 58 /** Compute the size of a bitmap 59 * 60 * Compute the size of a bitmap that can store given number 61 * of elements. 62 * 63 * @param elements Number of elements to store. 64 * 65 * @return Size of the bitmap (in units of BITMAP_ELEMENT bits). 66 * 67 */ 68 static size_t bitmap_bytes(size_t elements) 69 { 70 size_t bytes = elements / BITMAP_ELEMENT; 71 72 if ((elements % BITMAP_ELEMENT) != 0) 73 bytes++; 74 75 return bytes; 76 } 77 78 /** Compute the number of 2nd level blocks 79 * 80 * Compute the number of 2nd level blocks for a given number 81 * of elements. 82 * 83 * @param elements Number of elements. 84 * @param block_size Number of elements in one block. 85 * 86 * @return Number of 2nd level blocks. 87 * @return Zero if block_size is zero. 88 * 89 */ 90 static size_t bitmap_blocks(size_t elements, size_t block_size) 91 { 92 if (block_size == 0) 93 return 0; 94 95 size_t blocks = elements / block_size; 96 97 if ((elements % block_size) != 0) 98 blocks++; 99 100 return blocks; 101 } 102 50 103 /** Unchecked version of bitmap_get() 51 104 * … … 60 113 static unsigned int bitmap_get_fast(bitmap_t *bitmap, size_t element) 61 114 { 62 size_t byte = element / BITMAP_ELEMENT; 63 uint8_t mask = 1 << (element & BITMAP_REMAINER); 64 65 return !!((bitmap->bits)[byte] & mask); 115 return !!((bitmap->bits)[element / BITMAP_ELEMENT] & 116 (1 << (element & BITMAP_REMAINER))); 66 117 } 67 118 … … 71 122 * 72 123 * @param elements Number bits stored in bitmap. 124 * @param block_size Block size of the 2nd level bitmap. 125 * If set to zero, no 2nd level is used. 73 126 * 74 127 * @return Size (in bytes) required for the bitmap. 75 128 * 76 129 */ 77 size_t bitmap_size(size_t elements) 78 { 79 size_t size = elements / BITMAP_ELEMENT; 80 81 if ((elements % BITMAP_ELEMENT) != 0) 82 size++; 83 84 return size; 130 size_t bitmap_size(size_t elements, size_t block_size) 131 { 132 size_t blocks = bitmap_blocks(elements, block_size); 133 134 return (bitmap_bytes(elements) + bitmap_bytes(blocks)); 85 135 } 86 136 … … 91 141 * @param bitmap Bitmap structure. 92 142 * @param elements Number of bits stored in bitmap. 143 * @param block_size Block size of the 2nd level bitmap. 144 * If set to zero, no 2nd level is used. 93 145 * @param data Address of the memory used to hold the map. 94 146 * The optional 2nd level bitmap follows the 1st … … 96 148 * 97 149 */ 98 void bitmap_initialize(bitmap_t *bitmap, size_t elements, void *data) 150 void bitmap_initialize(bitmap_t *bitmap, size_t elements, size_t block_size, 151 void *data) 99 152 { 100 153 bitmap->elements = elements; 101 154 bitmap->bits = (uint8_t *) data; 102 bitmap->next_fit = 0; 155 156 if (block_size > 0) { 157 bitmap->block_size = block_size; 158 bitmap->blocks = bitmap->bits + 159 bitmap_size(elements, 0); 160 } else { 161 bitmap->block_size = 0; 162 bitmap->blocks = NULL; 163 } 164 } 165 166 static void bitmap_set_range_internal(uint8_t *bits, size_t start, size_t count) 167 { 168 if (count == 0) 169 return; 170 171 size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT); 172 173 /* Leading unaligned bits */ 174 size_t lub = min(aligned_start - start, count); 175 176 /* Aligned middle bits */ 177 size_t amb = (count > lub) ? (count - lub) : 0; 178 179 /* Trailing aligned bits */ 180 size_t tab = amb % BITMAP_ELEMENT; 181 182 if (start + count < aligned_start) { 183 /* Set bits in the middle of byte. */ 184 bits[start / BITMAP_ELEMENT] |= 185 ((1 << lub) - 1) << (start & BITMAP_REMAINER); 186 return; 187 } 188 189 if (lub) { 190 /* Make sure to set any leading unaligned bits. */ 191 bits[start / BITMAP_ELEMENT] |= 192 ~((1 << (BITMAP_ELEMENT - lub)) - 1); 193 } 194 195 size_t i; 196 197 for (i = 0; i < amb / BITMAP_ELEMENT; i++) { 198 /* The middle bits can be set byte by byte. */ 199 bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ONES; 200 } 201 202 if (tab) { 203 /* Make sure to set any trailing aligned bits. */ 204 bits[aligned_start / BITMAP_ELEMENT + i] |= (1 << tab) - 1; 205 } 103 206 } 104 207 … … 114 217 ASSERT(start + count <= bitmap->elements); 115 218 219 bitmap_set_range_internal(bitmap->bits, start, count); 220 221 if (bitmap->block_size > 0) { 222 size_t aligned_start = ALIGN_UP(start, bitmap->block_size); 223 224 /* Leading unaligned bits */ 225 size_t lub = min(aligned_start - start, count); 226 227 /* Aligned middle bits */ 228 size_t amb = (count > lub) ? (count - lub) : 0; 229 230 size_t aligned_size = amb / bitmap->block_size; 231 232 bitmap_set_range_internal(bitmap->blocks, aligned_start, 233 aligned_size); 234 } 235 } 236 237 static void bitmap_clear_range_internal(uint8_t *bits, size_t start, 238 size_t count) 239 { 116 240 if (count == 0) 117 241 return; 118 242 119 size_t start_byte = start / BITMAP_ELEMENT;120 243 size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT); 121 244 … … 130 253 131 254 if (start + count < aligned_start) { 132 /* Set bits in the middle of byte .*/133 bit map->bits[start_byte] |=134 ((1 << lub) - 1) << (start & BITMAP_REMAINER);255 /* Set bits in the middle of byte */ 256 bits[start / BITMAP_ELEMENT] &= 257 ~(((1 << lub) - 1) << (start & BITMAP_REMAINER)); 135 258 return; 136 259 } 137 260 138 261 if (lub) { 139 /* Make sure to setany leading unaligned bits. */140 bit map->bits[start_byte] |=141 ~((1 << (BITMAP_ELEMENT - lub)) - 1);262 /* Make sure to clear any leading unaligned bits. */ 263 bits[start / BITMAP_ELEMENT] &= 264 (1 << (BITMAP_ELEMENT - lub)) - 1; 142 265 } 143 266 … … 145 268 146 269 for (i = 0; i < amb / BITMAP_ELEMENT; i++) { 147 /* The middle bits can be set byte by byte. */ 148 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] = 149 ALL_ONES; 270 /* The middle bits can be cleared byte by byte. */ 271 bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ZEROES; 150 272 } 151 273 152 274 if (tab) { 153 /* Make sure to set any trailing aligned bits. */ 154 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] |= 155 (1 << tab) - 1; 275 /* Make sure to clear any trailing aligned bits. */ 276 bits[aligned_start / BITMAP_ELEMENT + i] &= ~((1 << tab) - 1); 156 277 } 157 278 } … … 168 289 ASSERT(start + count <= bitmap->elements); 169 290 170 if (count == 0) 171 return; 172 173 size_t start_byte = start / BITMAP_ELEMENT; 174 size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT); 175 176 /* Leading unaligned bits */ 177 size_t lub = min(aligned_start - start, count); 178 179 /* Aligned middle bits */ 180 size_t amb = (count > lub) ? (count - lub) : 0; 181 182 /* Trailing aligned bits */ 183 size_t tab = amb % BITMAP_ELEMENT; 184 185 if (start + count < aligned_start) { 186 /* Set bits in the middle of byte */ 187 bitmap->bits[start_byte] &= 188 ~(((1 << lub) - 1) << (start & BITMAP_REMAINER)); 189 return; 190 } 191 192 if (lub) { 193 /* Make sure to clear any leading unaligned bits. */ 194 bitmap->bits[start_byte] &= 195 (1 << (BITMAP_ELEMENT - lub)) - 1; 196 } 197 198 size_t i; 199 200 for (i = 0; i < amb / BITMAP_ELEMENT; i++) { 201 /* The middle bits can be cleared byte by byte. */ 202 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] = 203 ALL_ZEROES; 204 } 205 206 if (tab) { 207 /* Make sure to clear any trailing aligned bits. */ 208 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] &= 209 ~((1 << tab) - 1); 210 } 211 212 bitmap->next_fit = start_byte; 291 bitmap_clear_range_internal(bitmap->bits, start, count); 292 293 if (bitmap->block_size > 0) { 294 size_t aligned_start = start / bitmap->block_size; 295 296 size_t aligned_end = (start + count) / bitmap->block_size; 297 298 if (((start + count) % bitmap->block_size) != 0) 299 aligned_end++; 300 301 size_t aligned_size = aligned_end - aligned_start; 302 303 bitmap_clear_range_internal(bitmap->blocks, aligned_start, 304 aligned_size); 305 } 213 306 } 214 307 … … 258 351 * @param count Number of continuous zero bits to find. 259 352 * @param base Address of the first bit in the bitmap. 260 * @param prefered Prefered address to start searching from.261 353 * @param constraint Constraint for the address of the first zero bit. 262 354 * @param index Place to store the index of the first zero … … 270 362 */ 271 363 int bitmap_allocate_range(bitmap_t *bitmap, size_t count, size_t base, 272 size_t prefered, size_tconstraint, size_t *index)364 size_t constraint, size_t *index) 273 365 { 274 366 if (count == 0) 275 367 return false; 276 368 277 size_t size = bitmap_size(bitmap->elements); 278 size_t next_fit = bitmap->next_fit; 279 280 /* 281 * Adjust the next-fit value according to the address 282 * the caller prefers to start the search at. 283 */ 284 if ((prefered > base) && (prefered < base + bitmap->elements)) { 285 size_t prefered_fit = (prefered - base) / BITMAP_ELEMENT; 286 287 if (prefered_fit > next_fit) 288 next_fit = prefered_fit; 289 } 290 291 for (size_t pos = 0; pos < size; pos++) { 292 size_t byte = (next_fit + pos) % size; 293 369 size_t bytes = bitmap_bytes(bitmap->elements); 370 371 for (size_t byte = 0; byte < bytes; byte++) { 294 372 /* Skip if the current byte has all bits set */ 295 373 if (bitmap->bits[byte] == ALL_ONES) … … 308 386 309 387 if (!bitmap_get_fast(bitmap, i)) { 310 size_t continuous = 1;388 bool continuous = true; 311 389 312 390 for (size_t j = 1; j < count; j++) { 313 if ((i + j < bitmap->elements) && 314 (!bitmap_get_fast(bitmap, i + j))) 315 continuous++; 316 else 391 if ((i + j >= bitmap->elements) || 392 (bitmap_get_fast(bitmap, i + j))) { 393 continuous = false; 317 394 break; 395 } 318 396 } 319 397 320 if (continuous == count) {398 if (continuous) { 321 399 if (index != NULL) { 322 400 bitmap_set_range(bitmap, i, count); 323 bitmap->next_fit = i / BITMAP_ELEMENT;324 401 *index = i; 325 402 } 326 403 327 404 return true; 328 } else 329 i += continuous; 405 } 330 406 } 331 407 }
Note:
See TracChangeset
for help on using the changeset viewer.