From 2c2c7a2120c0eda8330fd72e4f3eab26a407719c Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Jun 2025 15:24:28 +0200 Subject: [PATCH] ealanos: Made hamstraaja more efficient. --- .../ealanos/include/ealanos/memory/coreheap.h | 22 +++--- .../include/ealanos/memory/hamstraaja.h | 41 +++++++--- .../include/ealanos/memory/superblock.h | 79 ++++++++++++------- .../ealanos/include/ealanos/util/lifo_queue.h | 39 +++++++++ 4 files changed, 131 insertions(+), 50 deletions(-) create mode 100644 repos/ealanos/include/ealanos/util/lifo_queue.h diff --git a/repos/ealanos/include/ealanos/memory/coreheap.h b/repos/ealanos/include/ealanos/memory/coreheap.h index 1cb17bfb06..fdf3c42243 100644 --- a/repos/ealanos/include/ealanos/memory/coreheap.h +++ b/repos/ealanos/include/ealanos/memory/coreheap.h @@ -12,7 +12,7 @@ #define __INCLUDE__EALANOS__MEMORY__COREHEAP_H_ #include -#include +#include #include #include #include @@ -37,7 +37,7 @@ class Ealan::Memory::Core_heap static constexpr const Genode::size_t num_size_classes = MAX / MIN; static constexpr const unsigned num_numa_domains = 64; static constexpr const unsigned long magic_num = 0xdeadbeefUL; - Ealan::util::MPSCQueue _superblocks[num_size_classes][num_numa_domains]; + alignas(64) Ealan::util::Lifo_queue _superblocks[num_size_classes][num_numa_domains]; Pd_session &_pd; Region_map &_rm; Tip *_tip{const_cast(Tip::tip())}; @@ -91,7 +91,8 @@ class Ealan::Memory::Core_heap Sb *_allocate_superblock(unsigned domain_id, Genode::size_t sz_class) { - Hyperblock *hb = _allocate_hyperblock(domain_id, MAX * 2); + Hyperblock *hb = _allocate_hyperblock(domain_id, MAX * 2); + Genode::log("Need new superblock for sizeclass ", sz_class, " in domain ", domain_id); if (!hb) { Genode::warning("Failed to allocate superblock for size class ", sz_class, " in domain ", domain_id); return nullptr; @@ -111,7 +112,7 @@ class Ealan::Memory::Core_heap for (size_t sz_class = 0; sz_class < num_size_classes; sz_class++) { for (unsigned domain_id = 0; domain_id < num_numa_domains; domain_id++) { Sb *sb; - while ((sb = _superblocks[sz_class][domain_id].pop_front()) != nullptr) + while ((sb = _superblocks[sz_class][domain_id].dequeue()) != nullptr) { Ram_dataspace_capability cap = sb->cap; _rm.detach(reinterpret_cast(sb)); @@ -141,11 +142,14 @@ class Ealan::Memory::Core_heap Genode::size_t sz_class = _calculate_size_class(size+alignment); Sb *sb = _superblocks[sz_class / MIN - 1][domain_id].head(); - if (!sb) { + //if (size == 128) + // Genode::log("Allocating task object from superblock ", sb, " sz_class=", sz_class, " node_id = ", domain_id); + + if (!sb) { sb = _allocate_superblock(domain_id, sz_class); if (!sb) return nullptr; - _superblocks[sz_class / MIN - 1][domain_id].push_back(sb); + _superblocks[sz_class / MIN - 1][domain_id].enqueue(sb); } for (; sb != nullptr ; sb = static_cast(sb->next())) { @@ -158,7 +162,7 @@ class Ealan::Memory::Core_heap sb = _allocate_superblock(domain_id, sz_class); if (!sb) return nullptr; - _superblocks[sz_class / MIN - 1][domain_id].push_back(sb); + _superblocks[sz_class / MIN - 1][domain_id].enqueue(sb); return sb->aligned_alloc(alignment); } @@ -209,7 +213,7 @@ class Ealan::Memory::Core_heap } Sb *sb = static_cast(b->_superblock); if (!sb) { - Genode::warning("Corrupt or invalid memory block."); + Genode::warning("Corrupt or invalid memory block: ", p); return; } sb->free(p); @@ -219,7 +223,7 @@ class Ealan::Memory::Core_heap { for (size_t i = 0; i < count; i++) { Sb *sb = _allocate_superblock(domain_id, sz_class); - _superblocks[sz_class / MIN - 1][domain_id].push_back(sb); + _superblocks[sz_class / MIN - 1][domain_id].enqueue(sb); } } }; diff --git a/repos/ealanos/include/ealanos/memory/hamstraaja.h b/repos/ealanos/include/ealanos/memory/hamstraaja.h index 2f48601be4..d854c8b445 100644 --- a/repos/ealanos/include/ealanos/memory/hamstraaja.h +++ b/repos/ealanos/include/ealanos/memory/hamstraaja.h @@ -11,6 +11,7 @@ #ifndef __INCLUDE__EALANOS__MEMORY__HAMSTRAAJA_H_ #define __INCLUDE__EALANOS__MEMORY__HAMSTRAAJA_H_ +#include "base/log.h" #include #include #include @@ -41,7 +42,7 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator size_t _quota_used{0}; Heap &_location_to_heap(Affinity::Location loc) const - { + { size_t pos = loc.xpos() * loc.height() + loc.ypos(); if (!_core_heaps[pos]) { Genode::error("No heap for location ", loc); @@ -61,10 +62,11 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator Hamstraaja(Genode::Pd_session &pd, Genode::Region_map &rm) : _pd(pd), _rm(rm) { size_t num_cpus = Cip::cip()->habitat_affinity.total(); - for (size_t cpu = 0; cpu < num_cpus; cpu++) { + for (size_t cpu = 0; cpu < num_cpus; cpu++) { _core_heaps[cpu] = new (_backend) Core_heap(_pd, _rm); } Genode::log("Hamstraaja initialized"); + Genode::log("Size of CoreHeap is ", sizeof(Heap)); } ~Hamstraaja() @@ -87,9 +89,14 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator { _quota_used += overhead(size) + size; return _location_to_heap(_my_location()).aligned_alloc(size, domain_id, alignment); - } + } - /** + void *aligned_alloc(size_t size, size_t alignment) + { + return _location_to_heap(_my_location()).aligned_alloc(size, alignment); + } + + /** * @brief Allocate a chunk of memory from a NUMA domain without alignment * * @param size - amount of memory to allocate @@ -99,6 +106,8 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator void *alloc(size_t size, unsigned domain_id) { _quota_used += overhead(size) + size; + //if (size == 128) + // Genode::log("Allocate task on core ", _my_location(), " for Node ", domain_id); return _location_to_heap(_my_location()).aligned_alloc(size, domain_id, 0); } @@ -111,8 +120,13 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator void *alloc(size_t size) { _quota_used += overhead(size) + size; - return _location_to_heap(_my_location()).alloc(size); - } + void *ptr = _location_to_heap(_my_location()).aligned_alloc(size, 0); + if (ptr >= reinterpret_cast(0x7FFF80000000UL)) { + Genode::error("Hamstraaja returned non-canonical address"); + return nullptr; + } + return ptr; + } /** * @brief Free a chunk of memory @@ -147,6 +161,12 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator { _location_to_heap(loc).reserve_superblocks(count, domain_id, sz_class); } + + Genode::size_t size_class(Genode::size_t size) const + { + return (size / MIN + 1) * MIN; + } + /************************* ** Allocator interface ** @@ -154,13 +174,10 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator Alloc_result try_alloc(size_t size) override { - void *ptr = nullptr; - if ((ptr = alloc(size)) != nullptr) - { + void *ptr = nullptr; + if ((ptr = alloc(size)) != nullptr) { return Alloc_result(ptr); - } - else - { + } else { return Alloc_result(Alloc_error::OUT_OF_RAM); } } diff --git a/repos/ealanos/include/ealanos/memory/superblock.h b/repos/ealanos/include/ealanos/memory/superblock.h index 3e7c229b55..559fdb00c1 100644 --- a/repos/ealanos/include/ealanos/memory/superblock.h +++ b/repos/ealanos/include/ealanos/memory/superblock.h @@ -12,7 +12,7 @@ #ifndef __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_ #define __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_ -#include +#include #include #include @@ -45,10 +45,11 @@ class Ealan::Memory::Hyperblock * @brief A block of memory * */ -struct Ealan::Memory::Block -{ - void *_superblock{nullptr}; /* Pointer to the superblock, this block was allocated from. */ - char _padding[56]; +struct Ealan::Memory::Block { + Block *_next{nullptr}; + void *_superblock{nullptr};/* Pointer to the superblock, this block was allocated from. */ + char _padding[48]; + /** * @brief Return a pointer to the metadata of this block @@ -65,9 +66,10 @@ struct Ealan::Memory::Block return __atomic_compare_exchange_n(&_superblock, &expect, sb, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); } - void free() { - __atomic_store_n(&_superblock, nullptr, __ATOMIC_RELEASE); - } + void free() { __atomic_store_n(&_superblock, nullptr, __ATOMIC_RELEASE); } + + void next(Block *ptr) { _next = ptr; } + Block* next() { return _next; } }; /** @@ -84,42 +86,62 @@ template class Ealan::Memory::Superblock : public Hyperblock { private: - Genode::size_t _size_class; - alignas(64) Genode::addr_t _start{0}; /* Start address of the blocks */ + + Genode::size_t _size_class; + alignas(64) Ealan::util::Lifo_queue _blocks{}; + alignas(64) Genode::addr_t _start{0}; /* Start address of the blocks */ public: Superblock(Genode::size_t sz) : _size_class(sz) { if (_size_class > SIZE) { Genode::error("Size class ", _size_class, " is bigger than superblock size ", SIZE); - } - Genode::log("Superblock SIZE=", SIZE, " BASE=", BASE, " this at ", this); + } + /*Genode::log("Superblock SIZE=", SIZE, " BASE=", BASE, " this at ", this); Genode::log("Block metadata size is ", sizeof(Block)); Genode::log("Size class of superblock is ", _size_class); - Block *end = reinterpret_cast(reinterpret_cast(this) + SIZE); - Genode::log("Superblock ends at ", end); + Genode::log("Superblock ends at ", reinterpret_cast(_end)); Genode::log("Capacity is ", capacity()); - Genode::log("-------------------"); - } + Genode::log("-------------------");*/ + + Genode::addr_t end = reinterpret_cast(this) + SIZE - sizeof(Block) - _size_class; + for (Genode::addr_t block = reinterpret_cast(&_start); block < end; block += sizeof(Block) + _size_class) { + Block *b = reinterpret_cast(block); + b->_superblock = this; + _blocks.enqueue(b); + } + } /** * @brief Allocate a block of SIZE-8 bytes from this superblock * * @return void* - pointer to the allocated block */ - void *alloc() { - Block *block = reinterpret_cast(&_start); + void *alloc() + { + Block *block = _blocks.dequeue(); + if (block) + return reinterpret_cast(reinterpret_cast(block)+64); + /*if (block != nullptr) { + if (block->reserve(this)) { + __atomic_compare_exchange_n(&last_freed_block, &block, nullptr, false, + __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); + return reinterpret_cast(reinterpret_cast(block)+64); + } + } + + Block *block = reinterpret_cast(&_start); Block *end = reinterpret_cast(reinterpret_cast(this) + SIZE - 64); while (block < end) { - if (block->_superblock == nullptr) { - if (block->reserve(this)) - { - return reinterpret_cast(reinterpret_cast(block)+64); - } - } Genode::addr_t next = reinterpret_cast(block) + sizeof(Block) + _size_class; - block = reinterpret_cast(next); - } + if (block->_superblock == nullptr) { + if (block->reserve(this)) { + return reinterpret_cast(reinterpret_cast(block) + + 64); + } + } + block = reinterpret_cast(next); + }*/ return nullptr; } @@ -159,9 +181,8 @@ class Ealan::Memory::Superblock : public Hyperblock Block *end = reinterpret_cast(reinterpret_cast(this) + SIZE); if (b > --end) return; - - b->free(); - } + _blocks.enqueue(b); + } /** * @brief Return the address of the first memory block in this superblock diff --git a/repos/ealanos/include/ealanos/util/lifo_queue.h b/repos/ealanos/include/ealanos/util/lifo_queue.h new file mode 100644 index 0000000000..b757f8919a --- /dev/null +++ b/repos/ealanos/include/ealanos/util/lifo_queue.h @@ -0,0 +1,39 @@ +#ifndef __INCLUDE__EALANOS__UTIL_LIFO_QUEUE_H_ +#define __INCLUDE__EALANOS__UTIL_LIFO_QUEUE_H_ + +namespace Ealan::util +{ + template + class Lifo_queue; +} + +template +class Ealan::util::Lifo_queue +{ + private: + + alignas(64) T *_head{nullptr}; + + public: + + void enqueue(T *elem) + { + T *next = __atomic_exchange_n(&_head, elem, __ATOMIC_RELAXED); + elem->next(next); + } + + T *dequeue() + { + if (_head) { + T *elem = __atomic_exchange_n(&_head, _head->next(), __ATOMIC_RELAXED); + return elem; + } + return nullptr; + } + + T *head() + { + return _head; + } +}; +#endif \ No newline at end of file