[util] Add util allocator.h interface

The allocator is a interface for types that expose allocator functions
for use in container templates like node_map (usage coming soon).

Also added an implementation for the kernel heap allocator.
This commit is contained in:
Justin C. Miller
2022-10-10 20:54:30 -07:00
parent 48e3f9f9d2
commit ba0ce13fe3
4 changed files with 69 additions and 0 deletions

View File

@@ -102,6 +102,30 @@ heap_allocator::free(void *p)
register_free_block(block, block->order); register_free_block(block, block->order);
} }
void *
heap_allocator::reallocate(void *p, size_t old_length, size_t new_length)
{
if (!p) {
kassert(old_length == 0,
"Attempt to reallocate from null with non-zero old_length");
return allocate(new_length);
}
block_info *info = m_map.find(map_key(p));
kassert(info, "Attempt to reallocate unknown block");
if (!info)
return nullptr;
if (new_length <= (1 << info->order))
return p;
void *new_block = allocate(new_length);
memcpy(new_block, p, old_length);
free(p);
return new_block;
}
heap_allocator::free_header * heap_allocator::free_header *
heap_allocator::pop_free(unsigned order) heap_allocator::pop_free(unsigned order)
{ {

View File

@@ -30,6 +30,10 @@ public:
/// \arg p A pointer previously retuned by allocate() /// \arg p A pointer previously retuned by allocate()
void free(void *p); void free(void *p);
/// Grow the given allocation if possible, or return a new
/// allocation with the contents copied over.
void * reallocate(void *p, size_t old_length, size_t new_length);
/// Minimum block size is (2^min_order). Must be at least 6. /// Minimum block size is (2^min_order). Must be at least 6.
static const unsigned min_order = 6; // 2^6 == 64 B static const unsigned min_order = 6; // 2^6 == 64 B
@@ -102,3 +106,15 @@ protected:
heap_allocator(const heap_allocator &) = delete; heap_allocator(const heap_allocator &) = delete;
}; };
extern heap_allocator &g_kernel_heap;
/// A class implementing util's allocator interface using the kernel heap
struct heap_allocated
{
inline static void * allocate(size_t size) { return g_kernel_heap.allocate(size); }
inline static void free(void *p) { g_kernel_heap.free(p); }
inline static void * realloc(void *p, size_t oldsize, size_t newsize) {
return g_kernel_heap.reallocate(p, oldsize, newsize);
}
};

View File

@@ -8,6 +8,7 @@ module("util",
"spinlock.cpp", "spinlock.cpp",
], ],
public_headers = [ public_headers = [
"util/allocator.h",
"util/basic_types.h", "util/basic_types.h",
"util/bip_buffer.h", "util/bip_buffer.h",
"util/bitset.h", "util/bitset.h",

View File

@@ -0,0 +1,28 @@
#pragma once
/// \file allocator.h
/// Definition of the allocator interface.
namespace util {
// Allocators are types with three static methods with these signatures
struct default_allocator
{
inline static void * allocate(size_t size) { return new char[size]; }
inline static void free(void *p) { delete [] reinterpret_cast<char*>(p); }
inline static void * realloc(void *p, size_t oldsize, size_t newsize) {
void *newp = memcpy(allocate(newsize), p, oldsize);
free(p);
return newp;
}
};
struct null_allocator
{
inline static void * allocate(size_t size) { return nullptr; }
inline static void free(void *p) {}
inline static void * realloc(void *p, size_t, size_t) { return p; }
};
} // namespace util