Rename the bitmap to axmap
[fio.git] / lib / axmap.c
CommitLineData
7ebd796f
JA
1/*
2 * Bitmap of bitmaps, where each layer is number-of-bits-per-word smaller than
3 * the previous. Hence an 'axmap', since we axe each previous layer into a
4 * much smaller piece. I swear, that is why it's named like that. It has
5 * nothing to do with anything remotely narcissistic.
6 *
7 * A set bit at layer N indicates a full word at layer N-1, and so forth. As
8 * the bitmap becomes progressively more full, checking for existance
9 * becomes cheaper (since fewer layers are walked, making it a lot more
10 * cache friendly) and locating the next free space likewise.
11 *
12 * Axmaps get pretty close to optimal (1 bit per block) space usage, since
13 * layers quickly diminish in size. Doing the size math is straight forward,
14 * since we have log64(blocks) layers of maps. For 20000 blocks, overhead
15 * is roughly 1.9%, or 1.019 bits per block. The number quickly converges
16 * towards 1.0158, or 1.58% of overhead.
17 */
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <assert.h>
22
23#include "../arch/arch.h"
24#include "axmap.h"
25#include "../smalloc.h"
26#include "../minmax.h"
27
28#if BITS_PER_LONG == 64
29#define UNIT_SHIFT 6
30#elif BITS_PER_LONG == 32
31#define UNIT_SHIFT 5
32#else
33#error "Number of arch bits unknown"
34#endif
35
36#define BLOCKS_PER_UNIT (1UL << UNIT_SHIFT)
37#define BLOCKS_PER_UNIT_MASK (BLOCKS_PER_UNIT - 1)
38
39#define firstfree_valid(b) ((b)->first_free != (uint64_t) -1)
40
41struct axmap_level {
42 int level;
43 unsigned long map_size;
44 unsigned long *map;
45};
46
47struct axmap {
48 unsigned int nr_levels;
49 struct axmap_level *levels;
50 uint64_t first_free;
51};
52
53static unsigned long ulog64(unsigned long val, unsigned int log)
54{
55 while (log-- && val)
56 val >>= UNIT_SHIFT;
57
58 return val;
59}
60
61void axmap_reset(struct axmap *axmap)
62{
63 int i;
64
65 for (i = 0; i < axmap->nr_levels; i++) {
66 struct axmap_level *al = &axmap->levels[i];
67
68 memset(al->map, 0, al->map_size * sizeof(unsigned long));
69 }
70}
71
72void axmap_free(struct axmap *axmap)
73{
74 unsigned int i;
75
76 if (!axmap)
77 return;
78
79 for (i = 0; i < axmap->nr_levels; i++)
80 sfree(axmap->levels[i].map);
81
82 sfree(axmap->levels);
83 sfree(axmap);
84}
85
86struct axmap *axmap_new(unsigned long nr_bits)
87{
88 struct axmap *axmap;
89 unsigned int i, levels;
90
91 axmap = smalloc(sizeof(*axmap));
92 if (!axmap)
93 return NULL;
94
95 levels = 1;
96 i = (nr_bits + BLOCKS_PER_UNIT - 1) >> UNIT_SHIFT;
97 while (i > 1) {
98 i = (i + BLOCKS_PER_UNIT - 1) >> UNIT_SHIFT;
99 levels++;
100 }
101
102 axmap->nr_levels = levels;
103 axmap->levels = smalloc(axmap->nr_levels * sizeof(struct axmap_level));
104 axmap->first_free = 0;
105
106 for (i = 0; i < axmap->nr_levels; i++) {
107 struct axmap_level *al = &axmap->levels[i];
108
109 al->level = i;
110 al->map_size = (nr_bits + BLOCKS_PER_UNIT - 1) >> UNIT_SHIFT;
111 al->map = smalloc(al->map_size * sizeof(unsigned long));
112 if (!al->map)
113 goto err;
114
115 nr_bits = (nr_bits + BLOCKS_PER_UNIT - 1) >> UNIT_SHIFT;
116 }
117
118 axmap_reset(axmap);
119 return axmap;
120err:
121 for (i = 0; i < axmap->nr_levels; i++)
122 if (axmap->levels[i].map)
123 sfree(axmap->levels[i].map);
124
125 sfree(axmap->levels);
126 return NULL;
127}
128
129static int axmap_handler(struct axmap *axmap, uint64_t bit_nr,
130 int (*func)(struct axmap_level *, unsigned long, unsigned int,
131 void *), void *data)
132{
133 struct axmap_level *al;
134 int i;
135
136 for (i = 0; i < axmap->nr_levels; i++) {
137 unsigned long index = ulog64(bit_nr, i);
138 unsigned long offset = index >> UNIT_SHIFT;
139 unsigned int bit = index & BLOCKS_PER_UNIT_MASK;
140
141 al = &axmap->levels[i];
142
143 if (func(al, offset, bit, data))
144 return 1;
145 }
146
147 return 0;
148}
149
150static int axmap_handler_topdown(struct axmap *axmap, uint64_t bit_nr,
151 int (*func)(struct axmap_level *, unsigned long, unsigned int, void *),
152 void *data)
153{
154 struct axmap_level *al;
155 int i, level = axmap->nr_levels;
156
157 for (i = axmap->nr_levels - 1; i >= 0; i--) {
158 unsigned long index = ulog64(bit_nr, --level);
159 unsigned long offset = index >> UNIT_SHIFT;
160 unsigned int bit = index & BLOCKS_PER_UNIT_MASK;
161
162 al = &axmap->levels[i];
163
164 if (func(al, offset, bit, data))
165 return 1;
166 }
167
168 return 0;
169}
170
171static int axmap_clear_fn(struct axmap_level *al, unsigned long offset,
172 unsigned int bit, void *unused)
173{
174 if (!(al->map[offset] & (1UL << bit)))
175 return 1;
176
177 al->map[offset] &= ~(1UL << bit);
178 return 0;
179}
180
181void axmap_clear(struct axmap *axmap, uint64_t bit_nr)
182{
183 axmap_handler(axmap, bit_nr, axmap_clear_fn, NULL);
184}
185
186struct axmap_set_data {
187 unsigned int nr_bits;
188 unsigned int set_bits;
189 unsigned int fail_ok;
190};
191
192static unsigned long bit_masks[] = {
193 0x0000000000000000, 0x0000000000000001, 0x0000000000000003, 0x0000000000000007,
194 0x000000000000000f, 0x000000000000001f, 0x000000000000003f, 0x000000000000007f,
195 0x00000000000000ff, 0x00000000000001ff, 0x00000000000003ff, 0x00000000000007ff,
196 0x0000000000000fff, 0x0000000000001fff, 0x0000000000003fff, 0x0000000000007fff,
197 0x000000000000ffff, 0x000000000001ffff, 0x000000000003ffff, 0x000000000007ffff,
198 0x00000000000fffff, 0x00000000001fffff, 0x00000000003fffff, 0x00000000007fffff,
199 0x0000000000ffffff, 0x0000000001ffffff, 0x0000000003ffffff, 0x0000000007ffffff,
200 0x000000000fffffff, 0x000000001fffffff, 0x000000003fffffff, 0x000000007fffffff,
201 0x00000000ffffffff,
202#if BITS_PER_LONG == 64
203 0x00000001ffffffff, 0x00000003ffffffff, 0x00000007ffffffff, 0x0000000fffffffff,
204 0x0000001fffffffff, 0x0000003fffffffff, 0x0000007fffffffff, 0x000000ffffffffff,
205 0x000001ffffffffff, 0x000003ffffffffff, 0x000007ffffffffff, 0x00000fffffffffff,
206 0x00001fffffffffff, 0x00003fffffffffff, 0x00007fffffffffff, 0x0000ffffffffffff,
207 0x0001ffffffffffff, 0x0003ffffffffffff, 0x0007ffffffffffff, 0x000fffffffffffff,
208 0x001fffffffffffff, 0x003fffffffffffff, 0x007fffffffffffff, 0x00ffffffffffffff,
209 0x01ffffffffffffff, 0x03ffffffffffffff, 0x07ffffffffffffff, 0x0fffffffffffffff,
210 0x1fffffffffffffff, 0x3fffffffffffffff, 0x7fffffffffffffff, 0xffffffffffffffff
211#endif
212};
213
214static int axmap_set_fn(struct axmap_level *al, unsigned long offset,
215 unsigned int bit, void *__data)
216{
217 struct axmap_set_data *data = __data;
218 unsigned long mask, overlap;
219 unsigned int nr_bits;
220
221 nr_bits = min(data->nr_bits, BLOCKS_PER_UNIT - bit);
222
223 mask = bit_masks[nr_bits] << bit;
224
225 /*
226 * Mask off any potential overlap, only sets contig regions
227 */
228 overlap = al->map[offset] & mask;
229 if (overlap == mask) {
230 assert(data->fail_ok);
231 return 1;
232 }
233
234 while (overlap) {
235 unsigned long clear_mask = ~(1UL << ffz(~overlap));
236
237 mask &= clear_mask;
238 overlap &= clear_mask;
239 nr_bits--;
240 }
241
242 assert(mask);
243 assert(!(al->map[offset] & mask));
244
245 al->map[offset] |= mask;
246
247 if (!al->level)
248 data->set_bits = nr_bits;
249
250 data->nr_bits = 1;
251 return al->map[offset] != -1UL;
252}
253
254static void __axmap_set(struct axmap *axmap, uint64_t bit_nr,
255 struct axmap_set_data *data)
256{
257 unsigned int set_bits, nr_bits = data->nr_bits;
258
259 if (axmap->first_free >= bit_nr &&
260 axmap->first_free < bit_nr + data->nr_bits)
261 axmap->first_free = -1ULL;
262
263 set_bits = 0;
264 while (nr_bits) {
265 axmap_handler(axmap, bit_nr, axmap_set_fn, data);
266 set_bits += data->set_bits;
267
268 if (data->set_bits != (BLOCKS_PER_UNIT - nr_bits))
269 break;
270
271 nr_bits -= data->set_bits;
272 bit_nr += data->set_bits;
273
274 data->nr_bits = nr_bits;
275 data->fail_ok = 1;
276 }
277
278 data->set_bits = set_bits;
279}
280
281void axmap_set(struct axmap *axmap, uint64_t bit_nr)
282{
283 struct axmap_set_data data = { .nr_bits = 1, };
284
285 __axmap_set(axmap, bit_nr, &data);
286}
287
288unsigned int axmap_set_nr(struct axmap *axmap, uint64_t bit_nr, unsigned int nr_bits)
289{
290 struct axmap_set_data data = { .nr_bits = nr_bits, };
291
292 __axmap_set(axmap, bit_nr, &data);
293 return data.set_bits;
294}
295
296static int axmap_isset_fn(struct axmap_level *al, unsigned long offset,
297 unsigned int bit, void *unused)
298{
299 return (al->map[offset] & (1UL << bit)) != 0;
300}
301
302int axmap_isset(struct axmap *axmap, uint64_t bit_nr)
303{
304 return axmap_handler_topdown(axmap, bit_nr, axmap_isset_fn, NULL);
305}
306
307static uint64_t axmap_find_first_free(struct axmap *axmap, unsigned int level,
308 uint64_t index)
309{
310 unsigned long j;
311 int i;
312
313 /*
314 * Start at the bottom, then converge towards first free bit at the top
315 */
316 for (i = level; i >= 0; i--) {
317 struct axmap_level *al = &axmap->levels[i];
318
319 if (index >= al->map_size) {
320 index = -1ULL;
321 break;
322 }
323
324 for (j = index; j < al->map_size; j++) {
325 if (al->map[j] == -1UL)
326 continue;
327
328 /*
329 * First free bit here is our index into the first
330 * free bit at the next higher level
331 */
332 index = (j << UNIT_SHIFT) + ffz(al->map[j]);
333 break;
334 }
335 }
336
337 return index;
338}
339
340uint64_t axmap_first_free(struct axmap *axmap)
341{
342 if (firstfree_valid(axmap))
343 return axmap->first_free;
344
345 axmap->first_free = axmap_find_first_free(axmap, axmap->nr_levels - 1, 0);
346 return axmap->first_free;
347}
348
349struct axmap_next_free_data {
350 unsigned int level;
351 unsigned long offset;
352 uint64_t bit;
353};
354
355static int axmap_next_free_fn(struct axmap_level *al, unsigned long offset,
356 unsigned int bit, void *__data)
357{
358 struct axmap_next_free_data *data = __data;
359 uint64_t mask = ~((1UL << ((data->bit & BLOCKS_PER_UNIT_MASK) + 1)) - 1);
360
361 if (!(mask & al->map[offset]))
362 return 0;
363
364 if (al->map[offset] != -1UL) {
365 data->level = al->level;
366 data->offset = offset;
367 return 1;
368 }
369
370 data->bit = (data->bit + BLOCKS_PER_UNIT - 1) / BLOCKS_PER_UNIT;
371 return 0;
372}
373
374/*
375 * 'bit_nr' is already set. Find the next free bit after this one.
376 */
377uint64_t axmap_next_free(struct axmap *axmap, uint64_t bit_nr)
378{
379 struct axmap_next_free_data data = { .level = -1U, .bit = bit_nr, };
380
381 if (firstfree_valid(axmap) && bit_nr < axmap->first_free)
382 return axmap->first_free;
383
384 if (!axmap_handler(axmap, bit_nr, axmap_next_free_fn, &data))
385 return axmap_first_free(axmap);
386
387 assert(data.level != -1U);
388
389 return axmap_find_first_free(axmap, data.level, data.offset);
390}