Changeset 99c2c69e in mainline for kernel/generic/src/adt/bitmap.c
- Timestamp:
- 2013-09-13T00:36:30Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 67fbd5e
- Parents:
- 7f84430 (diff), 11d41be5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/adt/bitmap.c
r7f84430 r99c2c69e 35 35 * 36 36 * This file implements bitmap ADT and provides functions for 37 * setting and clearing ranges of bits. 37 * setting and clearing ranges of bits and for finding ranges 38 * of unset bits. 38 39 */ 39 40 … … 44 45 #include <macros.h> 45 46 46 #define ALL_ONES 0xff 47 #define ALL_ZEROES 0x00 47 #define ALL_ONES 0xff 48 #define ALL_ZEROES 0x00 49 50 /** Unchecked version of bitmap_get() 51 * 52 * This version of bitmap_get() does not do any boundary checks. 53 * 54 * @param bitmap Bitmap to access. 55 * @param element Element to access. 56 * 57 * @return Bit value of the element in the bitmap. 58 * 59 */ 60 static unsigned int bitmap_get_fast(bitmap_t *bitmap, size_t element) 61 { 62 size_t byte = element / BITMAP_ELEMENT; 63 uint8_t mask = 1 << (element & BITMAP_REMAINER); 64 65 return !!((bitmap->bits)[byte] & mask); 66 } 67 68 /** Get bitmap size 69 * 70 * Return the size (in bytes) required for the bitmap. 71 * 72 * @param elements Number bits stored in bitmap. 73 * 74 * @return Size (in bytes) required for the bitmap. 75 * 76 */ 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; 85 } 48 86 49 87 /** Initialize bitmap. … … 51 89 * No portion of the bitmap is set or cleared by this function. 52 90 * 53 * @param bitmap Bitmap structure. 54 * @param map Address of the memory used to hold the map. 55 * @param bits Number of bits stored in bitmap. 56 */ 57 void bitmap_initialize(bitmap_t *bitmap, uint8_t *map, size_t bits) 58 { 59 bitmap->map = map; 60 bitmap->bits = bits; 91 * @param bitmap Bitmap structure. 92 * @param elements Number of bits stored in bitmap. 93 * @param data Address of the memory used to hold the map. 94 * The optional 2nd level bitmap follows the 1st 95 * level bitmap. 96 * 97 */ 98 void bitmap_initialize(bitmap_t *bitmap, size_t elements, void *data) 99 { 100 bitmap->elements = elements; 101 bitmap->bits = (uint8_t *) data; 102 bitmap->next_fit = 0; 61 103 } 62 104 63 105 /** Set range of bits. 64 106 * 65 * @param bitmap Bitmap structure. 66 * @param start Starting bit. 67 * @param bits Number of bits to set. 68 */ 69 void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t bits) 70 { 71 size_t i = 0; 72 size_t aligned_start; 73 size_t lub; /* leading unaligned bits */ 74 size_t amb; /* aligned middle bits */ 75 size_t tab; /* trailing aligned bits */ 76 77 ASSERT(start + bits <= bitmap->bits); 78 79 aligned_start = ALIGN_UP(start, 8); 80 lub = min(aligned_start - start, bits); 81 amb = bits > lub ? bits - lub : 0; 82 tab = amb % 8; 83 84 if (!bits) 107 * @param bitmap Bitmap structure. 108 * @param start Starting bit. 109 * @param count Number of bits to set. 110 * 111 */ 112 void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t count) 113 { 114 ASSERT(start + count <= bitmap->elements); 115 116 if (count == 0) 85 117 return; 86 87 if (start + bits < aligned_start) { 118 119 size_t start_byte = start / BITMAP_ELEMENT; 120 size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT); 121 122 /* Leading unaligned bits */ 123 size_t lub = min(aligned_start - start, count); 124 125 /* Aligned middle bits */ 126 size_t amb = (count > lub) ? (count - lub) : 0; 127 128 /* Trailing aligned bits */ 129 size_t tab = amb % BITMAP_ELEMENT; 130 131 if (start + count < aligned_start) { 88 132 /* Set bits in the middle of byte. */ 89 bitmap->map[start / 8] |= ((1 << lub) - 1) << (start & 7); 133 bitmap->bits[start_byte] |= 134 ((1 << lub) - 1) << (start & BITMAP_REMAINER); 90 135 return; 91 136 } … … 93 138 if (lub) { 94 139 /* Make sure to set any leading unaligned bits. */ 95 bitmap->map[start / 8] |= ~((1 << (8 - lub)) - 1); 96 } 97 for (i = 0; i < amb / 8; i++) { 140 bitmap->bits[start_byte] |= 141 ~((1 << (BITMAP_ELEMENT - lub)) - 1); 142 } 143 144 size_t i; 145 146 for (i = 0; i < amb / BITMAP_ELEMENT; i++) { 98 147 /* The middle bits can be set byte by byte. */ 99 bitmap->map[aligned_start / 8 + i] = ALL_ONES; 100 } 148 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] = 149 ALL_ONES; 150 } 151 101 152 if (tab) { 102 153 /* Make sure to set any trailing aligned bits. */ 103 bitmap-> map[aligned_start / 8 + i] |= (1 << tab) - 1;104 }105 154 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] |= 155 (1 << tab) - 1; 156 } 106 157 } 107 158 108 159 /** Clear range of bits. 109 160 * 110 * @param bitmap Bitmap structure. 111 * @param start Starting bit. 112 * @param bits Number of bits to clear. 113 */ 114 void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t bits) 115 { 116 size_t i = 0; 117 size_t aligned_start; 118 size_t lub; /* leading unaligned bits */ 119 size_t amb; /* aligned middle bits */ 120 size_t tab; /* trailing aligned bits */ 121 122 ASSERT(start + bits <= bitmap->bits); 123 124 aligned_start = ALIGN_UP(start, 8); 125 lub = min(aligned_start - start, bits); 126 amb = bits > lub ? bits - lub : 0; 127 tab = amb % 8; 128 129 if (!bits) 161 * @param bitmap Bitmap structure. 162 * @param start Starting bit. 163 * @param count Number of bits to clear. 164 * 165 */ 166 void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t count) 167 { 168 ASSERT(start + count <= bitmap->elements); 169 170 if (count == 0) 130 171 return; 131 132 if (start + bits < aligned_start) { 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) { 133 186 /* Set bits in the middle of byte */ 134 bitmap->map[start / 8] &= ~(((1 << lub) - 1) << (start & 7)); 187 bitmap->bits[start_byte] &= 188 ~(((1 << lub) - 1) << (start & BITMAP_REMAINER)); 135 189 return; 136 190 } 137 191 138 192 if (lub) { 139 193 /* Make sure to clear any leading unaligned bits. */ 140 bitmap->map[start / 8] &= (1 << (8 - lub)) - 1; 141 } 142 for (i = 0; i < amb / 8; i++) { 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++) { 143 201 /* The middle bits can be cleared byte by byte. */ 144 bitmap->map[aligned_start / 8 + i] = ALL_ZEROES; 145 } 202 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] = 203 ALL_ZEROES; 204 } 205 146 206 if (tab) { 147 207 /* Make sure to clear any trailing aligned bits. */ 148 bitmap->map[aligned_start / 8 + i] &= ~((1 << tab) - 1); 149 } 150 208 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] &= 209 ~((1 << tab) - 1); 210 } 211 212 bitmap->next_fit = start_byte; 151 213 } 152 214 153 215 /** Copy portion of one bitmap into another bitmap. 154 216 * 155 * @param dst Destination bitmap. 156 * @param src Source bitmap. 157 * @param bits Number of bits to copy. 158 */ 159 void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t bits) 160 { 217 * @param dst Destination bitmap. 218 * @param src Source bitmap. 219 * @param count Number of bits to copy. 220 * 221 */ 222 void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t count) 223 { 224 ASSERT(count <= dst->elements); 225 ASSERT(count <= src->elements); 226 161 227 size_t i; 162 228 163 ASSERT(bits <= dst->bits); 164 ASSERT(bits <= src->bits); 165 166 for (i = 0; i < bits / 8; i++) 167 dst->map[i] = src->map[i]; 168 169 if (bits % 8) { 170 bitmap_clear_range(dst, i * 8, bits % 8); 171 dst->map[i] |= src->map[i] & ((1 << (bits % 8)) - 1); 172 } 229 for (i = 0; i < count / BITMAP_ELEMENT; i++) 230 dst->bits[i] = src->bits[i]; 231 232 if (count % BITMAP_ELEMENT) { 233 bitmap_clear_range(dst, i * BITMAP_ELEMENT, 234 count % BITMAP_ELEMENT); 235 dst->bits[i] |= src->bits[i] & 236 ((1 << (count % BITMAP_ELEMENT)) - 1); 237 } 238 } 239 240 static int constraint_satisfy(size_t index, size_t base, size_t constraint) 241 { 242 return (((base + index) & constraint) == 0); 243 } 244 245 /** Find a continuous zero bit range 246 * 247 * Find a continuous zero bit range in the bitmap. The address 248 * computed as the sum of the index of the first zero bit and 249 * the base argument needs to be compliant with the constraint 250 * (those bits that are set in the constraint cannot be set in 251 * the address). 252 * 253 * If the index argument is non-NULL, the continuous zero range 254 * is set and the index of the first bit is stored to index. 255 * Otherwise the bitmap stays untouched. 256 * 257 * @param bitmap Bitmap structure. 258 * @param count Number of continuous zero bits to find. 259 * @param base Address of the first bit in the bitmap. 260 * @param prefered Prefered address to start searching from. 261 * @param constraint Constraint for the address of the first zero bit. 262 * @param index Place to store the index of the first zero 263 * bit. Can be NULL (in which case the bitmap 264 * is not modified). 265 * 266 * @return Non-zero if a continuous range of zero bits satisfying 267 * the constraint has been found. 268 * @return Zero otherwise. 269 * 270 */ 271 int bitmap_allocate_range(bitmap_t *bitmap, size_t count, size_t base, 272 size_t prefered, size_t constraint, size_t *index) 273 { 274 if (count == 0) 275 return false; 276 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 294 /* Skip if the current byte has all bits set */ 295 if (bitmap->bits[byte] == ALL_ONES) 296 continue; 297 298 size_t byte_bit = byte * BITMAP_ELEMENT; 299 300 for (size_t bit = 0; bit < BITMAP_ELEMENT; bit++) { 301 size_t i = byte_bit + bit; 302 303 if (i >= bitmap->elements) 304 break; 305 306 if (!constraint_satisfy(i, base, constraint)) 307 continue; 308 309 if (!bitmap_get_fast(bitmap, i)) { 310 size_t continuous = 1; 311 312 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 317 break; 318 } 319 320 if (continuous == count) { 321 if (index != NULL) { 322 bitmap_set_range(bitmap, i, count); 323 bitmap->next_fit = i / BITMAP_ELEMENT; 324 *index = i; 325 } 326 327 return true; 328 } else 329 i += continuous; 330 } 331 } 332 } 333 334 return false; 173 335 } 174 336
Note:
See TracChangeset
for help on using the changeset viewer.