Fixed arena allocator aligned allocation functions
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, macos-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, macos-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled
Moved arena allocator initialization to an explicit init() function to avoid performing this test on each allocation.
This commit is contained in:
@@ -31,19 +31,26 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace mimir {
|
namespace mimir {
|
||||||
class Arena
|
class Arena
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Arena(size_t minSize = 1ULL << 24, size_t maxSize = 1ULL << 32);
|
Arena();
|
||||||
~Arena();
|
~Arena();
|
||||||
|
bool init(size_t minSize = 1ULL << 24, size_t maxSize = 1ULL << 32);
|
||||||
|
|
||||||
|
// Allocate `size` bytes
|
||||||
std::byte* alloc(size_t size);
|
std::byte* alloc(size_t size);
|
||||||
|
|
||||||
|
// Allocate `size` bytes, aligned to 16 bytes and padded to next 16-byte offset.
|
||||||
std::byte* allocA16(size_t size);
|
std::byte* allocA16(size_t size);
|
||||||
|
|
||||||
|
// Allocate `size` bytes, aligned to 64 bytes and padded to next 64-byte offset.
|
||||||
std::byte* allocA64(size_t size);
|
std::byte* allocA64(size_t size);
|
||||||
|
|
||||||
|
// Reset the arena, potentially also releasing committed pages
|
||||||
void reset();
|
void reset();
|
||||||
private:
|
private:
|
||||||
std::byte* m_data;
|
std::byte* m_data;
|
||||||
|
|||||||
@@ -51,24 +51,13 @@
|
|||||||
|
|
||||||
namespace mimir {
|
namespace mimir {
|
||||||
|
|
||||||
struct ArenaControlBlock
|
Arena::Arena()
|
||||||
{
|
: m_minSize(0)
|
||||||
size_t allocated;
|
, m_maxSize(0)
|
||||||
size_t comitted;
|
|
||||||
size_t next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(ArenaControlBlock) < 4096);
|
|
||||||
|
|
||||||
Arena::Arena(size_t minSize, size_t maxSize)
|
|
||||||
: m_minSize(minSize)
|
|
||||||
, m_maxSize(maxSize)
|
|
||||||
, m_data(nullptr)
|
, m_data(nullptr)
|
||||||
, m_usedSize(0)
|
, m_usedSize(0)
|
||||||
, m_committedSize(0)
|
, m_committedSize(0)
|
||||||
{
|
{
|
||||||
assert(maxSize >= minSize);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < kWatermarkLen; i++) {
|
for (size_t i = 0; i < kWatermarkLen; i++) {
|
||||||
m_watermark[i] = 0;
|
m_watermark[i] = 0;
|
||||||
}
|
}
|
||||||
@@ -89,27 +78,36 @@ Arena::~Arena()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::byte* Arena::alloc(size_t size)
|
bool Arena::init(size_t minSize, size_t maxSize)
|
||||||
{
|
{
|
||||||
size_t neededSize = m_usedSize + size;
|
assert(maxSize >= minSize);
|
||||||
|
assert(m_data == nullptr);
|
||||||
|
assert(m_usedSize == 0);
|
||||||
|
assert(m_committedSize == 0);
|
||||||
|
|
||||||
|
m_minSize = KRAKEN_MEM_ROUND_UP_PAGE(minSize);
|
||||||
|
m_maxSize = KRAKEN_MEM_ROUND_UP_PAGE(maxSize);
|
||||||
|
|
||||||
if (m_data == nullptr) {
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
m_data = (std::byte*)VirtualAlloc(NULL, KRAKEN_MEM_ROUND_UP_PAGE(m_maxSize), MEM_RESERVE, PAGE_NOACCESS);
|
m_data = (std::byte*)VirtualAlloc(NULL, KRAKEN_MEM_ROUND_UP_PAGE(m_maxSize), MEM_RESERVE, PAGE_NOACCESS);
|
||||||
if (m_data == nullptr) {
|
if (m_data == nullptr) {
|
||||||
ReportWindowsLastError("VirtualAlloc");
|
ReportWindowsLastError("VirtualAlloc");
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
#elif defined(__unix__) || defined(__APPLE__) || defined(ANDROID)
|
#elif defined(__unix__) || defined(__APPLE__) || defined(ANDROID)
|
||||||
m_data = (std::byte*)mmap(NULL, KRAKEN_MEM_ROUND_UP_PAGE(m_maxSize), PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
m_data = (std::byte*)mmap(NULL, KRAKEN_MEM_ROUND_UP_PAGE(m_maxSize), PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
if (m_data == MAP_FAILED) {
|
if (m_data == MAP_FAILED) {
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static_assert(false, "Not Implemented");
|
static_assert(false, "Not Implemented");
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::byte* Arena::alloc(size_t size)
|
||||||
|
{
|
||||||
|
size_t neededSize = m_usedSize + size;
|
||||||
if (neededSize > m_committedSize)
|
if (neededSize > m_committedSize)
|
||||||
{
|
{
|
||||||
size_t newSize = std::bit_ceil(neededSize) << 1;
|
size_t newSize = std::bit_ceil(neededSize) << 1;
|
||||||
@@ -142,7 +140,7 @@ std::byte* Arena::allocA16(size_t size)
|
|||||||
{
|
{
|
||||||
uint32_t nextByte = (m_usedSize + 15) & ~15;
|
uint32_t nextByte = (m_usedSize + 15) & ~15;
|
||||||
uint32_t roundedSize = (size + 15) & ~15;
|
uint32_t roundedSize = (size + 15) & ~15;
|
||||||
if (alloc(size) == nullptr) {
|
if (alloc(roundedSize + nextByte - m_usedSize) == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +151,7 @@ std::byte* Arena::allocA64(size_t size)
|
|||||||
{
|
{
|
||||||
uint32_t nextByte = (m_usedSize + 63) & ~63;
|
uint32_t nextByte = (m_usedSize + 63) & ~63;
|
||||||
uint32_t roundedSize = (size + 63) & ~63;
|
uint32_t roundedSize = (size + 63) & ~63;
|
||||||
if (alloc(size) == nullptr) {
|
if (alloc(roundedSize + nextByte - m_usedSize) == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user