From 72211e3d7b29cec887257d59578669f198c2d3da Mon Sep 17 00:00:00 2001 From: Brett Date: Mon, 19 Aug 2024 12:13:13 -0400 Subject: [PATCH] atomic allocator --- CMakeLists.txt | 2 +- include/blt/std/atomic_allocator.h | 86 +++++++++++++++++++++++++++++- include/blt/std/mmap.h | 31 +++++++++++ libraries/parallel-hashmap | 2 +- src/blt/std/mmap.cpp | 26 +++++++++ 5 files changed, 143 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a18ddf3..2512b18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 0.18.37) +set(BLT_VERSION 0.18.38) set(BLT_TEST_VERSION 0.0.1) set(BLT_TARGET BLT) diff --git a/include/blt/std/atomic_allocator.h b/include/blt/std/atomic_allocator.h index 5406074..81dad83 100644 --- a/include/blt/std/atomic_allocator.h +++ b/include/blt/std/atomic_allocator.h @@ -31,12 +31,94 @@ #include #include "logging.h" #include - +#include namespace blt { - + template + class atomic_bump_allocator + { + private: + struct block + { + struct block_metadata_t + { + const blt::size_t size = 0; + std::atomic allocated_objects = 0; + std::atomic next = nullptr; + std::atomic prev = nullptr; + std::atomic offset = nullptr; + } metadata; + blt::u8 buffer[8]{}; + + explicit block(blt::size_t size) + { + metadata.size = size; + metadata.offset = buffer; + } + + [[nodiscard]] blt::ptrdiff_t storage_size() const noexcept + { + return static_cast(metadata.size - sizeof(typename block::block_metadata_t)); + } + + [[nodiscard]] blt::ptrdiff_t used_bytes_in_block() const noexcept + { + return static_cast(metadata.offset - buffer); + } + + [[nodiscard]] blt::ptrdiff_t remaining_bytes_in_block() const noexcept + { + return storage_size() - used_bytes_in_block(); + } + }; + + public: + void* allocate(blt::size_t bytes) + { + auto head_ptr = head.load(std::memory_order_relaxed); + auto new_head = head_ptr; + do + { + if (head_ptr->remaining_bytes_in_block() < bytes) + { + + } + } while (!head.compare_exchange_weak(head_ptr, new_head, std::memory_order_release, std::memory_order_acquire)); + } + + void deallocate(void* ptr) + { + auto blk = to_block(ptr); + --blk.metadata.allocated_objects; + if (blk.metadata.allocated_objects == 0) + { + if (blk->metadata.prev != nullptr) + blk->metadata.prev->metadata.next = blk->metadata.next; + if (blk->metadata.next != nullptr) + blk->metadata.next->metadata.prev = blk->metadata.prev; + alloc.deallocate(blk, blk.metadata.size); + } + } + + private: + static inline block* to_block(void* p) + { + return reinterpret_cast(reinterpret_cast(p) & static_cast(~(BLT_2MB_SIZE - 1))); + } + + inline block* allocate_block(blt::size_t bytes) + { + auto size = align_size_to(bytes, BLT_2MB_SIZE); + auto ptr = static_cast(alloc.allocate(size)); + new(ptr) block{size}; + return ptr; + } + + std::atomic head = nullptr; + Alloc alloc; + }; } diff --git a/include/blt/std/mmap.h b/include/blt/std/mmap.h index 22b70c3..05c60f5 100644 --- a/include/blt/std/mmap.h +++ b/include/blt/std/mmap.h @@ -21,6 +21,7 @@ #include #include +#include #ifdef __unix__ @@ -47,6 +48,36 @@ namespace blt void* allocate_2mb_huge_pages(blt::size_t bytes); + void mmap_free(void* ptr, blt::size_t bytes); + + class mmap_huge_allocator + { + public: + void* allocate(blt::size_t bytes) // NOLINT + { + return allocate_2mb_huge_pages(bytes); + } + + void deallocate(void* ptr, blt::size_t bytes) // NOLINT + { + mmap_free(ptr, bytes); + } + }; + + class aligned_huge_allocator + { + public: + void* allocate(blt::size_t bytes) // NOLINT + { + return std::aligned_alloc(BLT_2MB_SIZE, bytes); + } + + void deallocate(void* ptr, blt::size_t) // NOLINT + { + std::free(ptr); + } + }; + } #endif //BLT_MMAP_H diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index d88c5e1..8a889d3 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit d88c5e15079047777b418132ece5879e7c9aaa2b +Subproject commit 8a889d3699b3c09ade435641fb034427f3fd12b6 diff --git a/src/blt/std/mmap.cpp b/src/blt/std/mmap.cpp index 7f045fc..60dc77d 100644 --- a/src/blt/std/mmap.cpp +++ b/src/blt/std/mmap.cpp @@ -78,4 +78,30 @@ namespace blt } } } + + void* allocate_2mb_huge_pages(blt::size_t bytes) + { +#ifdef __unix__ + auto buffer = mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1, 0); + if (buffer == MAP_FAILED) + { + BLT_WARN_STREAM << "Failed to allocate huge pages, reason:\n"; + handle_mmap_error(BLT_WARN_STREAM); + throw std::bad_alloc(); + } + return buffer; +#else + BLT_ABORT("Platform not supported for huge page allocation!"); +#endif + } + + void mmap_free(void* ptr, blt::size_t bytes) + { + if (munmap(ptr, bytes)) + { + BLT_ERROR_STREAM << "Failed to deallocate\n"; + handle_mmap_error(BLT_ERROR_STREAM); + throw std::bad_alloc(); + } + } } \ No newline at end of file