Fix a bug where allocator was unable to allocate up to last (n%64) blocks, add tests for it

pull/5/head
Vitaliy Filippov 2021-03-13 02:00:22 +03:00
parent dd76eda5e5
commit f49fd53d55
3 changed files with 40 additions and 21 deletions

View File

@ -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;
}

View File

@ -8,6 +8,7 @@
// Hierarchical bitmap allocator
class allocator
{
uint64_t total;
uint64_t size;
uint64_t free;
uint64_t last_one_mask;

View File

@ -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;
}