Fix a bug where allocator was unable to allocate up to last (n%64) blocks, add tests for it
parent
dd76eda5e5
commit
f49fd53d55
|
@ -13,19 +13,19 @@ allocator::allocator(uint64_t blocks)
|
|||
{
|
||||
throw std::invalid_argument("blocks");
|
||||
}
|
||||
uint64_t p2 = 1, total = 1;
|
||||
uint64_t p2 = 1;
|
||||
total = 0;
|
||||
while (p2 * 64 < blocks)
|
||||
{
|
||||
p2 = p2 * 64;
|
||||
total += p2;
|
||||
p2 = p2 * 64;
|
||||
}
|
||||
total -= p2;
|
||||
total += (blocks+63) / 64;
|
||||
mask = new uint64_t[2 + total];
|
||||
mask = new uint64_t[total];
|
||||
size = free = blocks;
|
||||
last_one_mask = (blocks % 64) == 0
|
||||
? UINT64_MAX
|
||||
: ~(UINT64_MAX << (64 - blocks % 64));
|
||||
: ((1l << (blocks % 64)) - 1);
|
||||
for (uint64_t i = 0; i < total; i++)
|
||||
{
|
||||
mask[i] = 0;
|
||||
|
@ -99,6 +99,10 @@ uint64_t allocator::find_free()
|
|||
uint64_t p2 = 1, offset = 0, addr = 0, f, i;
|
||||
while (p2 < size)
|
||||
{
|
||||
if (offset+addr >= total)
|
||||
{
|
||||
return UINT64_MAX;
|
||||
}
|
||||
uint64_t m = mask[offset + addr];
|
||||
for (i = 0, f = 1; i < 64; i++, f <<= 1)
|
||||
{
|
||||
|
@ -113,11 +117,6 @@ uint64_t allocator::find_free()
|
|||
return UINT64_MAX;
|
||||
}
|
||||
addr = (addr * 64) | i;
|
||||
if (addr >= size)
|
||||
{
|
||||
// No space
|
||||
return UINT64_MAX;
|
||||
}
|
||||
offset += p2;
|
||||
p2 = p2 * 64;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// Hierarchical bitmap allocator
|
||||
class allocator
|
||||
{
|
||||
uint64_t total;
|
||||
uint64_t size;
|
||||
uint64_t free;
|
||||
uint64_t last_one_mask;
|
||||
|
|
|
@ -2,20 +2,39 @@
|
|||
// License: VNPL-1.1 (see README.md for details)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "allocator.h"
|
||||
|
||||
void alloc_all(int size)
|
||||
{
|
||||
allocator *a = new allocator(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
uint64_t x = a->find_free();
|
||||
if (x == UINT64_MAX)
|
||||
{
|
||||
printf("ran out of space %d allocated=%d\n", size, i);
|
||||
exit(1);
|
||||
}
|
||||
if (x != i)
|
||||
{
|
||||
printf("incorrect block allocated: expected %d, got %lu\n", i, x);
|
||||
}
|
||||
a->set(x, true);
|
||||
}
|
||||
uint64_t x = a->find_free();
|
||||
if (x != UINT64_MAX)
|
||||
{
|
||||
printf("extra free space found: %lx (%d)\n", x, size);
|
||||
exit(1);
|
||||
}
|
||||
delete a;
|
||||
}
|
||||
|
||||
int main(int narg, char *args[])
|
||||
{
|
||||
allocator a(8192);
|
||||
for (int i = 0; i < 8192; i++)
|
||||
{
|
||||
uint64_t x = a.find_free();
|
||||
if (x == UINT64_MAX)
|
||||
{
|
||||
printf("ran out of space %d\n", i);
|
||||
return 1;
|
||||
}
|
||||
a.set(x, true);
|
||||
}
|
||||
alloc_all(8192);
|
||||
alloc_all(8062);
|
||||
alloc_all(4096);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue