From ba0ce13fe3054b2ca46889806c9de5a25601c5fd Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Mon, 10 Oct 2022 20:54:30 -0700 Subject: [PATCH] [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. --- src/kernel/heap_allocator.cpp | 24 ++++++++++++++++++++++++ src/kernel/heap_allocator.h | 16 ++++++++++++++++ src/libraries/util/util.module | 1 + src/libraries/util/util/allocator.h | 28 ++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 src/libraries/util/util/allocator.h diff --git a/src/kernel/heap_allocator.cpp b/src/kernel/heap_allocator.cpp index 9c24c7c..cff726f 100644 --- a/src/kernel/heap_allocator.cpp +++ b/src/kernel/heap_allocator.cpp @@ -102,6 +102,30 @@ heap_allocator::free(void *p) 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::pop_free(unsigned order) { diff --git a/src/kernel/heap_allocator.h b/src/kernel/heap_allocator.h index 8059b30..70daa6f 100644 --- a/src/kernel/heap_allocator.h +++ b/src/kernel/heap_allocator.h @@ -30,6 +30,10 @@ public: /// \arg p A pointer previously retuned by allocate() 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. static const unsigned min_order = 6; // 2^6 == 64 B @@ -102,3 +106,15 @@ protected: 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); + } +}; diff --git a/src/libraries/util/util.module b/src/libraries/util/util.module index 9da9cf7..3162a8d 100644 --- a/src/libraries/util/util.module +++ b/src/libraries/util/util.module @@ -8,6 +8,7 @@ module("util", "spinlock.cpp", ], public_headers = [ + "util/allocator.h", "util/basic_types.h", "util/bip_buffer.h", "util/bitset.h", diff --git a/src/libraries/util/util/allocator.h b/src/libraries/util/util/allocator.h new file mode 100644 index 0000000..0f4ea35 --- /dev/null +++ b/src/libraries/util/util/allocator.h @@ -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(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