mirror of
https://github.com/mmueller41/mxtasking.git
synced 2026-01-21 12:42:57 +01:00
Adapted MxTasking memory manager to Genode.
This commit is contained in:
@@ -35,7 +35,7 @@ AllocationBlock::~AllocationBlock()
|
|||||||
{
|
{
|
||||||
if (this->_allocated_block != nullptr)
|
if (this->_allocated_block != nullptr)
|
||||||
{
|
{
|
||||||
GlobalHeap::free(this->_allocated_block, this->_size);
|
GlobalHeap::free(this->_allocated_block, this->_size, this->_numa_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <mx/util/core_set.h>
|
#include <mx/util/core_set.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace mx::memory::fixed {
|
namespace mx::memory::fixed {
|
||||||
/**
|
/**
|
||||||
@@ -45,17 +46,18 @@ class Chunk
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Chunk() noexcept = default;
|
Chunk() noexcept = default;
|
||||||
explicit Chunk(void *memory) noexcept : _memory(memory) {}
|
explicit Chunk(void *memory, bool is_allocated) noexcept : _memory(memory), _is_allocated(is_allocated) {}
|
||||||
~Chunk() noexcept = default;
|
~Chunk() noexcept = default;
|
||||||
|
|
||||||
static constexpr auto size() { return 4096 * 4096; /* 16mb */ }
|
static constexpr auto size() { return 4096 * 4096; /* 16mb */ }
|
||||||
|
|
||||||
explicit operator void *() const noexcept { return _memory; }
|
explicit operator void *() const noexcept { return _memory; }
|
||||||
explicit operator std::uintptr_t() const noexcept { return reinterpret_cast<std::uintptr_t>(_memory); }
|
explicit operator std::uintptr_t() const noexcept { return reinterpret_cast<std::uintptr_t>(_memory); }
|
||||||
explicit operator bool() const noexcept { return _memory != nullptr; }
|
explicit operator bool() const noexcept { return _memory != nullptr && _is_allocated; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void *_memory{nullptr};
|
void *_memory{nullptr};
|
||||||
|
bool _is_allocated{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,16 +79,20 @@ public:
|
|||||||
|
|
||||||
~ProcessorHeap() noexcept
|
~ProcessorHeap() noexcept
|
||||||
{
|
{
|
||||||
|
if (_numa_node_id > mx::system::topology::max_node_id())
|
||||||
|
return;
|
||||||
|
|
||||||
for (const auto allocated_chunk : _allocated_chunks)
|
for (const auto allocated_chunk : _allocated_chunks)
|
||||||
{
|
{
|
||||||
GlobalHeap::free(static_cast<void *>(allocated_chunk), Chunk::size());
|
if (static_cast<bool>(allocated_chunk))
|
||||||
|
GlobalHeap::free(static_cast<void *>(allocated_chunk), Chunk::size(), _numa_node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto free_chunk : _free_chunk_buffer)
|
for (const auto free_chunk : _free_chunk_buffer)
|
||||||
{
|
{
|
||||||
if (static_cast<bool>(free_chunk))
|
if (static_cast<bool>(free_chunk))
|
||||||
{
|
{
|
||||||
GlobalHeap::free(static_cast<void *>(free_chunk), Chunk::size());
|
GlobalHeap::free(static_cast<void *>(free_chunk), Chunk::size(), _numa_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +184,7 @@ private:
|
|||||||
auto heap_memory_address = reinterpret_cast<std::uintptr_t>(heap_memory);
|
auto heap_memory_address = reinterpret_cast<std::uintptr_t>(heap_memory);
|
||||||
for (auto i = 0U; i < _free_chunk_buffer.size(); ++i)
|
for (auto i = 0U; i < _free_chunk_buffer.size(); ++i)
|
||||||
{
|
{
|
||||||
_free_chunk_buffer[i] = Chunk(reinterpret_cast<void *>(heap_memory_address + (i * Chunk::size())));
|
_free_chunk_buffer[i] = Chunk(reinterpret_cast<void *>(heap_memory_address + (i * Chunk::size())), i==0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_next_free_chunk.store(0U);
|
_next_free_chunk.store(0U);
|
||||||
@@ -238,7 +244,9 @@ public:
|
|||||||
void fill_buffer()
|
void fill_buffer()
|
||||||
{
|
{
|
||||||
auto chunk = _processor_heap->allocate();
|
auto chunk = _processor_heap->allocate();
|
||||||
|
|
||||||
const auto chunk_address = static_cast<std::uintptr_t>(chunk);
|
const auto chunk_address = static_cast<std::uintptr_t>(chunk);
|
||||||
|
//assert((chunk_address != 0) && "Failed to allocate chunk from processor heap");
|
||||||
|
|
||||||
constexpr auto object_size = S;
|
constexpr auto object_size = S;
|
||||||
constexpr auto count_objects = std::uint64_t{Chunk::size() / object_size};
|
constexpr auto count_objects = std::uint64_t{Chunk::size() / object_size};
|
||||||
@@ -279,7 +287,8 @@ template <std::size_t S> class Allocator final : public TaskAllocatorInterface
|
|||||||
public:
|
public:
|
||||||
explicit Allocator(const util::core_set &core_set)
|
explicit Allocator(const util::core_set &core_set)
|
||||||
{
|
{
|
||||||
for (auto node_id = std::uint8_t(0U); node_id < config::max_numa_nodes(); ++node_id)
|
//assert((system::topology::max_node_id() <= config::max_numa_nodes()) && "More NUMA nodes detected than supported. Increase value for max_numa_nodes() in mx/memory/config.h.");
|
||||||
|
for (auto node_id = std::uint8_t(0U); node_id <= system::topology::max_node_id(); ++node_id)
|
||||||
{
|
{
|
||||||
if (core_set.has_core_of_numa_node(node_id))
|
if (core_set.has_core_of_numa_node(node_id))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,15 +2,76 @@
|
|||||||
#include "alignment_helper.h"
|
#include "alignment_helper.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <numa.h>
|
#include <array>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <base/regional_heap.h>
|
||||||
|
#include <mx/system/topology.h>
|
||||||
|
#include <mx/system/environment.h>
|
||||||
|
#include <mx/memory/config.h>
|
||||||
|
|
||||||
|
#include <base/log.h>
|
||||||
namespace mx::memory {
|
namespace mx::memory {
|
||||||
/**
|
/**
|
||||||
* The global heap represents the heap, provided by the OS.
|
* The global heap represents the heap, provided by the OS.
|
||||||
*/
|
*/
|
||||||
class GlobalHeap
|
class GlobalHeap
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
alignas(64) std::array<Genode::Regional_heap *, config::max_numa_nodes()> heaps{nullptr};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
GlobalHeap()
|
||||||
|
{
|
||||||
|
for (unsigned numa_id = 0; numa_id <= system::topology::max_node_id(); numa_id++) {
|
||||||
|
Topology::Numa_region const &node = system::Environment::node(numa_id);
|
||||||
|
heaps[numa_id] = new Genode::Regional_heap(system::Environment::ram(), system::Environment::rm(), const_cast<Topology::Numa_region&>(node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~GlobalHeap()
|
||||||
|
{
|
||||||
|
for (auto heap : heaps)
|
||||||
|
delete heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *local_allocate(const std::uint8_t numa_node_id, const std::size_t size)
|
||||||
|
{
|
||||||
|
return heaps[numa_node_id]->alloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void local_free(void *ptr, const std::size_t size, std::uint8_t node_id)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
std::uint8_t next_try = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
heaps[node_id]->free(ptr, size);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
catch (Genode::Region_map::Invalid_dataspace)
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
node_id = (node_id == next_try) ? (next_try + 1) % (mx::system::topology::max_node_id()+1) : next_try;
|
||||||
|
next_try = (next_try + 1) % (mx::system::topology::max_node_id()+1);
|
||||||
|
}
|
||||||
|
} while (next_try != 0);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
std::free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GlobalHeap &myself()
|
||||||
|
{
|
||||||
|
static GlobalHeap gheap;
|
||||||
|
return gheap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates the given size on the given NUMA node.
|
* Allocates the given size on the given NUMA node.
|
||||||
*
|
*
|
||||||
@@ -20,7 +81,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
static void *allocate(const std::uint8_t numa_node_id, const std::size_t size)
|
static void *allocate(const std::uint8_t numa_node_id, const std::size_t size)
|
||||||
{
|
{
|
||||||
return numa_alloc_onnode(size, numa_node_id);
|
return myself().local_allocate(numa_node_id, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,15 +93,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
static void *allocate_cache_line_aligned(const std::size_t size)
|
static void *allocate_cache_line_aligned(const std::size_t size)
|
||||||
{
|
{
|
||||||
return std::aligned_alloc(64U, alignment_helper::next_multiple(size, 64UL));
|
void *ptr = nullptr;
|
||||||
|
posix_memalign(&ptr, 64, alignment_helper::next_multiple(size, 64UL));
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the given memory.
|
* Frees the given memory.
|
||||||
*
|
*
|
||||||
* @param memory Pointer to memory.
|
* @param memory Pointer to memory.
|
||||||
* @param size Size of the allocated object.
|
* @param size Size of the allocated object.
|
||||||
*/
|
*/
|
||||||
static void free(void *memory, const std::size_t size) { numa_free(memory, size); }
|
static void free(void *memory, const std::size_t size, std::uint8_t node_id) { myself().local_free(memory, size, node_id); }
|
||||||
};
|
};
|
||||||
} // namespace mx::memory
|
} // namespace mx::memory
|
||||||
@@ -41,7 +41,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @return Allocated memory using systems malloc (but aligned).
|
* @return Allocated memory using systems malloc (but aligned).
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] void *allocate(const std::uint16_t /*core_id*/) override { return std::aligned_alloc(64U, S); }
|
[[nodiscard]] void *allocate(const std::uint16_t /*core_id*/) override { return std::malloc(S); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the given memory using systems free.
|
* Frees the given memory using systems free.
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ private:
|
|||||||
static void release(pointer_type data, const std::size_t capacity) noexcept
|
static void release(pointer_type data, const std::size_t capacity) noexcept
|
||||||
{
|
{
|
||||||
const auto size = sizeof(value_type) * capacity;
|
const auto size = sizeof(value_type) * capacity;
|
||||||
memory::GlobalHeap::free(static_cast<void *>(data), size);
|
memory::GlobalHeap::free(static_cast<void *>(data), size, _numa_node_id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace mx::util
|
} // namespace mx::util
|
||||||
Reference in New Issue
Block a user