diff --git a/src/allocator.cpp b/src/allocator.cpp index 83a7229e..39b8a7b9 100644 --- a/src/allocator.cpp +++ b/src/allocator.cpp @@ -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; } diff --git a/src/allocator.h b/src/allocator.h index 76304340..58b6808d 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -8,6 +8,7 @@ // Hierarchical bitmap allocator class allocator { + uint64_t total; uint64_t size; uint64_t free; uint64_t last_one_mask; diff --git a/src/test_allocator.cpp b/src/test_allocator.cpp index 736d3070..71d9fca5 100644 --- a/src/test_allocator.cpp +++ b/src/test_allocator.cpp @@ -2,20 +2,39 @@ // License: VNPL-1.1 (see README.md for details) #include +#include #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; }