source: mainline/kernel/generic/src/adt/bitmap.c@ c5396c1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c5396c1 was c5396c1, checked in by Martin Decky <martin@…>, 12 years ago

abandon the 2nd level bitmap
according to observations it is very rare to have allocation requests for more than 8 frames, therefore the conservative update of the 2nd level bitmap can hardly provide any benefits
the natural blocking of the bitmap (by bytes) should provide a reasonable performance

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup genericadt
30 * @{
31 */
32/**
33 * @file
34 * @brief Implementation of bitmap ADT.
35 *
36 * This file implements bitmap ADT and provides functions for
37 * setting and clearing ranges of bits and for finding ranges
38 * of unset bits.
39 */
40
41#include <adt/bitmap.h>
42#include <typedefs.h>
43#include <align.h>
44#include <debug.h>
45#include <macros.h>
46
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 */
60static 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 */
77size_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}
86
87/** Initialize bitmap.
88 *
89 * No portion of the bitmap is set or cleared by this function.
90 *
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 */
98void bitmap_initialize(bitmap_t *bitmap, size_t elements, void *data)
99{
100 bitmap->elements = elements;
101 bitmap->bits = (uint8_t *) data;
102}
103
104/** Set range of bits.
105 *
106 * @param bitmap Bitmap structure.
107 * @param start Starting bit.
108 * @param count Number of bits to set.
109 *
110 */
111void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t count)
112{
113 ASSERT(start + count <= bitmap->elements);
114
115 if (count == 0)
116 return;
117
118 size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT);
119
120 /* Leading unaligned bits */
121 size_t lub = min(aligned_start - start, count);
122
123 /* Aligned middle bits */
124 size_t amb = (count > lub) ? (count - lub) : 0;
125
126 /* Trailing aligned bits */
127 size_t tab = amb % BITMAP_ELEMENT;
128
129 if (start + count < aligned_start) {
130 /* Set bits in the middle of byte. */
131 bitmap->bits[start / BITMAP_ELEMENT] |=
132 ((1 << lub) - 1) << (start & BITMAP_REMAINER);
133 return;
134 }
135
136 if (lub) {
137 /* Make sure to set any leading unaligned bits. */
138 bitmap->bits[start / BITMAP_ELEMENT] |=
139 ~((1 << (BITMAP_ELEMENT - lub)) - 1);
140 }
141
142 size_t i;
143
144 for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
145 /* The middle bits can be set byte by byte. */
146 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] =
147 ALL_ONES;
148 }
149
150 if (tab) {
151 /* Make sure to set any trailing aligned bits. */
152 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] |=
153 (1 << tab) - 1;
154 }
155}
156
157/** Clear range of bits.
158 *
159 * @param bitmap Bitmap structure.
160 * @param start Starting bit.
161 * @param count Number of bits to clear.
162 *
163 */
164void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t count)
165{
166 ASSERT(start + count <= bitmap->elements);
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 bitmap->bits[start / BITMAP_ELEMENT] &=
185 ~(((1 << lub) - 1) << (start & BITMAP_REMAINER));
186 return;
187 }
188
189 if (lub) {
190 /* Make sure to clear any leading unaligned bits. */
191 bitmap->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 cleared byte by byte. */
199 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] =
200 ALL_ZEROES;
201 }
202
203 if (tab) {
204 /* Make sure to clear any trailing aligned bits. */
205 bitmap->bits[aligned_start / BITMAP_ELEMENT + i] &=
206 ~((1 << tab) - 1);
207 }
208}
209
210/** Copy portion of one bitmap into another bitmap.
211 *
212 * @param dst Destination bitmap.
213 * @param src Source bitmap.
214 * @param count Number of bits to copy.
215 *
216 */
217void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t count)
218{
219 ASSERT(count <= dst->elements);
220 ASSERT(count <= src->elements);
221
222 size_t i;
223
224 for (i = 0; i < count / BITMAP_ELEMENT; i++)
225 dst->bits[i] = src->bits[i];
226
227 if (count % BITMAP_ELEMENT) {
228 bitmap_clear_range(dst, i * BITMAP_ELEMENT,
229 count % BITMAP_ELEMENT);
230 dst->bits[i] |= src->bits[i] &
231 ((1 << (count % BITMAP_ELEMENT)) - 1);
232 }
233}
234
235static int constraint_satisfy(size_t index, size_t base, size_t constraint)
236{
237 return (((base + index) & constraint) == 0);
238}
239
240/** Find a continuous zero bit range
241 *
242 * Find a continuous zero bit range in the bitmap. The address
243 * computed as the sum of the index of the first zero bit and
244 * the base argument needs to be compliant with the constraint
245 * (those bits that are set in the constraint cannot be set in
246 * the address).
247 *
248 * If the index argument is non-NULL, the continuous zero range
249 * is set and the index of the first bit is stored to index.
250 * Otherwise the bitmap stays untouched.
251 *
252 * @param bitmap Bitmap structure.
253 * @param count Number of continuous zero bits to find.
254 * @param base Address of the first bit in the bitmap.
255 * @param constraint Constraint for the address of the first zero bit.
256 * @param index Place to store the index of the first zero
257 * bit. Can be NULL (in which case the bitmap
258 * is not modified).
259 *
260 * @return Non-zero if a continuous range of zero bits satisfying
261 * the constraint has been found.
262 * @return Zero otherwise.
263 *
264 */
265int bitmap_allocate_range(bitmap_t *bitmap, size_t count, size_t base,
266 size_t constraint, size_t *index)
267{
268 if (count == 0)
269 return false;
270
271 size_t bytes = bitmap_size(bitmap->elements);
272
273 for (size_t byte = 0; byte < bytes; byte++) {
274 /* Skip if the current byte has all bits set */
275 if (bitmap->bits[byte] == ALL_ONES)
276 continue;
277
278 size_t byte_bit = byte * BITMAP_ELEMENT;
279
280 for (size_t bit = 0; bit < BITMAP_ELEMENT; bit++) {
281 size_t i = byte_bit + bit;
282
283 if (i >= bitmap->elements)
284 break;
285
286 if (!constraint_satisfy(i, base, constraint))
287 continue;
288
289 if (!bitmap_get_fast(bitmap, i)) {
290 bool continuous = true;
291
292 for (size_t j = 1; j < count; j++) {
293 if ((i + j >= bitmap->elements) ||
294 (bitmap_get_fast(bitmap, i + j))) {
295 continuous = false;
296 break;
297 }
298 }
299
300 if (continuous) {
301 if (index != NULL) {
302 bitmap_set_range(bitmap, i, count);
303 *index = i;
304 }
305
306 return true;
307 }
308 }
309 }
310 }
311
312 return false;
313}
314
315/** @}
316 */
Note: See TracBrowser for help on using the repository browser.