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

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

partial implementation of a two-level bitmap data structure

  • Property mode set to 100644
File size: 7.5 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 * 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 *
47 */
48
49#include <adt/bitmap.h>
50#include <typedefs.h>
51#include <align.h>
52#include <debug.h>
53#include <macros.h>
54
55#define ALL_ONES 0xff
56#define ALL_ZEROES 0x00
57
58/** Get bitmap size
59 *
60 * Return the size (in bytes) required for the bitmap.
61 *
62 * @param elements Number bits stored in bitmap.
63 * @param block_size Block size of the 2nd level bitmap.
64 * If set to zero, no 2nd level is used.
65 *
66 * @return Size (in bytes) required for the bitmap.
67 *
68 */
69size_t bitmap_size(size_t elements, size_t block_size)
70{
71 size_t size = elements / BITMAP_ELEMENT;
72
73 if ((elements % BITMAP_ELEMENT) != 0)
74 size++;
75
76 if (block_size > 0) {
77 size += elements / block_size;
78
79 if ((elements % block_size) != 0)
80 size++;
81 }
82
83 return size;
84}
85
86/** Initialize bitmap.
87 *
88 * No portion of the bitmap is set or cleared by this function.
89 *
90 * @param bitmap Bitmap structure.
91 * @param elements Number of bits stored in bitmap.
92 * @param block_size Block size of the 2nd level bitmap.
93 * If set to zero, no 2nd level is used.
94 * @param data Address of the memory used to hold the map.
95 * The optional 2nd level bitmap follows the 1st
96 * level bitmap.
97 *
98 */
99void bitmap_initialize(bitmap_t *bitmap, size_t elements, size_t block_size,
100 void *data)
101{
102 bitmap->elements = elements;
103 bitmap->bits = (uint8_t *) data;
104
105 if (block_size > 0) {
106 bitmap->block_size = block_size;
107 bitmap->blocks = bitmap->bits +
108 bitmap_size(elements, 0);
109 } else {
110 bitmap->block_size = 0;
111 bitmap->blocks = NULL;
112 }
113}
114
115static void bitmap_set_range_internal(uint8_t *bits, size_t start, size_t count)
116{
117 if (count == 0)
118 return;
119
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) {
132 /* Set bits in the middle of byte. */
133 bits[start / BITMAP_ELEMENT] |=
134 ((1 << lub) - 1) << (start & BITMAP_REMAINER);
135 return;
136 }
137
138 if (lub) {
139 /* Make sure to set any leading unaligned bits. */
140 bits[start / BITMAP_ELEMENT] |=
141 ~((1 << (BITMAP_ELEMENT - lub)) - 1);
142 }
143
144 size_t i;
145
146 for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
147 /* The middle bits can be set byte by byte. */
148 bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ONES;
149 }
150
151 if (tab) {
152 /* Make sure to set any trailing aligned bits. */
153 bits[aligned_start / BITMAP_ELEMENT + i] |= (1 << tab) - 1;
154 }
155}
156
157/** Set range of bits.
158 *
159 * @param bitmap Bitmap structure.
160 * @param start Starting bit.
161 * @param count Number of bits to set.
162 *
163 */
164void bitmap_set_range(bitmap_t *bitmap, size_t start, size_t count)
165{
166 ASSERT(start + count <= bitmap->elements);
167
168 bitmap_set_range_internal(bitmap->bits, start, count);
169
170 if (bitmap->block_size > 0) {
171 size_t aligned_start = ALIGN_UP(start, bitmap->block_size);
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 size_t aligned_size = amb / bitmap->block_size;
180
181 bitmap_set_range_internal(bitmap->blocks, aligned_start,
182 aligned_size);
183 }
184}
185
186static void bitmap_clear_range_internal(uint8_t *bits, size_t start,
187 size_t count)
188{
189 if (count == 0)
190 return;
191
192 size_t aligned_start = ALIGN_UP(start, BITMAP_ELEMENT);
193
194 /* Leading unaligned bits */
195 size_t lub = min(aligned_start - start, count);
196
197 /* Aligned middle bits */
198 size_t amb = (count > lub) ? (count - lub) : 0;
199
200 /* Trailing aligned bits */
201 size_t tab = amb % BITMAP_ELEMENT;
202
203 if (start + count < aligned_start) {
204 /* Set bits in the middle of byte */
205 bits[start / BITMAP_ELEMENT] &=
206 ~(((1 << lub) - 1) << (start & BITMAP_REMAINER));
207 return;
208 }
209
210 if (lub) {
211 /* Make sure to clear any leading unaligned bits. */
212 bits[start / BITMAP_ELEMENT] &=
213 (1 << (BITMAP_ELEMENT - lub)) - 1;
214 }
215
216 size_t i;
217
218 for (i = 0; i < amb / BITMAP_ELEMENT; i++) {
219 /* The middle bits can be cleared byte by byte. */
220 bits[aligned_start / BITMAP_ELEMENT + i] = ALL_ZEROES;
221 }
222
223 if (tab) {
224 /* Make sure to clear any trailing aligned bits. */
225 bits[aligned_start / BITMAP_ELEMENT + i] &= ~((1 << tab) - 1);
226 }
227}
228
229/** Clear range of bits.
230 *
231 * @param bitmap Bitmap structure.
232 * @param start Starting bit.
233 * @param count Number of bits to clear.
234 *
235 */
236void bitmap_clear_range(bitmap_t *bitmap, size_t start, size_t count)
237{
238 ASSERT(start + count <= bitmap->elements);
239
240 bitmap_clear_range_internal(bitmap->bits, start, count);
241
242 if (bitmap->block_size > 0) {
243 size_t aligned_start = start / bitmap->block_size;
244
245 size_t aligned_end = (start + count) / bitmap->block_size;
246
247 if (((start + count) % bitmap->block_size) != 0)
248 aligned_end++;
249
250 size_t aligned_size = aligned_end - aligned_start;
251
252 bitmap_clear_range_internal(bitmap->blocks, aligned_start,
253 aligned_size);
254 }
255}
256
257/** Copy portion of one bitmap into another bitmap.
258 *
259 * @param dst Destination bitmap.
260 * @param src Source bitmap.
261 * @param count Number of bits to copy.
262 *
263 */
264void bitmap_copy(bitmap_t *dst, bitmap_t *src, size_t count)
265{
266 ASSERT(count <= dst->elements);
267 ASSERT(count <= src->elements);
268
269 size_t i;
270
271 for (i = 0; i < count / BITMAP_ELEMENT; i++)
272 dst->bits[i] = src->bits[i];
273
274 if (count % BITMAP_ELEMENT) {
275 bitmap_clear_range(dst, i * BITMAP_ELEMENT,
276 count % BITMAP_ELEMENT);
277 dst->bits[i] |= src->bits[i] &
278 ((1 << (count % BITMAP_ELEMENT)) - 1);
279 }
280}
281
282/** @}
283 */
Note: See TracBrowser for help on using the repository browser.