diff --git a/repos/ealanos/include/ealanos/memory/coreheap.h b/repos/ealanos/include/ealanos/memory/coreheap.h index 94607af1f9..e9dbcd54a1 100644 --- a/repos/ealanos/include/ealanos/memory/coreheap.h +++ b/repos/ealanos/include/ealanos/memory/coreheap.h @@ -52,34 +52,50 @@ class Ealan::Memory::Core_heap { Tukija::uint8_t mem_regions = 0; _tip = const_cast(Tip::tip()); - Tip::Memory_region ®ion = _tip->memory_for_domain(domain_id, &mem_regions); - Range_allocator::Range range = {.start = reinterpret_cast(region.start), .end = reinterpret_cast(region.end)}; + try { + Tip::Memory_region ®ion = _tip->memory_for_domain(domain_id, &mem_regions); + Range_allocator::Range range = {.start = reinterpret_cast(region.start), .end = reinterpret_cast(region.end)}; - Ram_dataspace_capability ds_cap = _pd.try_alloc_from_range(size, Genode::CACHED, range).convert( - [&](Ram_dataspace_capability cap) { return cap; }, - [&](Ram_allocator::Alloc_error) { return Ram_dataspace_capability(); }); + Ram_dataspace_capability ds_cap = _pd.try_alloc_from_range(size, Genode::CACHED, range).convert([&](Ram_dataspace_capability cap) + { return cap; }, + [&](Ram_allocator::Alloc_error err) + { + Genode::error("Failed to allocate phyiscal memory in domain ", domain_id, ":", err); + return Ram_dataspace_capability(); }); - if (!ds_cap.valid()) + if (!ds_cap.valid()) { + Genode::warning("Failed to allocate physical memory for hyperblock"); + return nullptr; + } + + Region_map::Attr attr{}; + attr.writeable = true; + void *hb = _rm.attach(ds_cap, attr).convert( + [&](Region_map::Range r) { return reinterpret_cast(r.start); }, + [&](Region_map::Attach_error) { return nullptr; }); + + if (!hb) { + Genode::warning("Failed to obtain regionmap for hyperblock"); + return nullptr; + } + + Hyperblock *hyperblock = new (hb) Hyperblock(); + hyperblock->cap = ds_cap; + + return hyperblock; + } catch (Tukija::Tip::Domain_has_no_memory_regions) { + Genode::error("Domain ", domain_id, " has no memory regions."); return nullptr; - - Region_map::Attr attr{}; - attr.writeable = true; - void *hb = _rm.attach(ds_cap, attr).convert( - [&](Region_map::Range r) { return reinterpret_cast(r.start); }, - [&](Region_map::Attach_error) { return nullptr; }); - - if (!hb) - return nullptr; - - Hyperblock *hyperblock = new (hb) Hyperblock(); - hyperblock->cap = ds_cap; - - return hyperblock; + } } Sb *_allocate_superblock(unsigned domain_id, Genode::size_t sz_class) { Hyperblock *hb = _allocate_hyperblock(domain_id, MAX * 2); + if (!hb) { + Genode::warning("Failed to allocate superblock for size class ", sz_class, " in domain ", domain_id); + return nullptr; + } return new (static_cast(hb)) Superblock(sz_class); } @@ -87,7 +103,11 @@ class Ealan::Memory::Core_heap Core_heap &operator=(Core_heap &); public: - Core_heap(Pd_session &pd, Region_map &rm) : _pd(pd), _rm(rm) {} + Core_heap(Pd_session &pd, Region_map &rm) : _pd(pd), _rm(rm) { + Genode::log("Size of superblock array is ", sizeof(_superblocks)); + Genode::log("Individual superblock size is: ", sizeof(Sb)); + Genode::log("Size of individual ist of superblocks: ", sizeof(Ealan::util::MPSCQueue)); + } ~Core_heap() { @@ -106,7 +126,10 @@ class Ealan::Memory::Core_heap void *aligned_alloc(Genode::size_t size, unsigned domain_id, Genode::size_t alignment) { - if (size > MAX) { + void *ptr = nullptr; + + if (size > MAX) + { /* directly allocate a hyperblock */ Hyperblock *hb = _allocate_hyperblock(domain_id, size+sizeof(Hyperblock*) + sizeof(Ram_dataspace_capability)); hb->_next = reinterpret_cast(magic_num); @@ -118,18 +141,26 @@ class Ealan::Memory::Core_heap if (!sb) { sb = _allocate_superblock(domain_id, sz_class); + if (!sb) + return nullptr; _superblocks[sz_class / MIN - 1][domain_id].push_back(sb); - } else if (sb->free_blocks() == 0) { - for (; sb && sb->free_blocks() == 0; sb = static_cast(sb->next())) - ; - if (!sb) { - Sb *new_sb = _allocate_superblock(domain_id, sz_class); - _superblocks[sz_class / MIN - 1][domain_id].push_back(new_sb); - sb = new_sb; - } + } + + for (; sb != nullptr ; sb = static_cast(sb->next())) { + ptr = sb->aligned_alloc(alignment); + if (ptr) + return ptr; + } + + if (!sb) { + sb = _allocate_superblock(domain_id, sz_class); + if (!sb) + return nullptr; + _superblocks[sz_class / MIN - 1][domain_id].push_back(sb); + return sb->aligned_alloc(alignment); } - return sb->aligned_alloc(alignment); + return ptr; } void *aligned_alloc(Genode::size_t size, Genode::size_t alignment) @@ -152,6 +183,10 @@ class Ealan::Memory::Core_heap void free(void *ptr, Genode::size_t alignment = 0) { + if (!ptr) { + Genode::warning("Tried to free nullptr"); + return; + } void *p = reinterpret_cast((reinterpret_cast(ptr) - sizeof(Hyperblock *) - sizeof(Ram_dataspace_capability))); Hyperblock *hb = reinterpret_cast(p); @@ -166,8 +201,16 @@ class Ealan::Memory::Core_heap Block *b = Block::metadata(p); + if (!b) { + Genode::warning("Invalid block. Not freeing."); + return; + } Sb *sb = static_cast(b->_superblock); - sb->free(ptr); + if (!sb) { + Genode::warning("Corrupt or invalid memory block."); + return; + } + sb->free(p); } void reserve_superblocks(size_t count, unsigned domain_id, size_t sz_class) diff --git a/repos/ealanos/include/ealanos/memory/hamstraaja.h b/repos/ealanos/include/ealanos/memory/hamstraaja.h index 9d2fb44838..8b8ca5ea43 100644 --- a/repos/ealanos/include/ealanos/memory/hamstraaja.h +++ b/repos/ealanos/include/ealanos/memory/hamstraaja.h @@ -43,6 +43,9 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator 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); + } return *_core_heaps[pos]; } @@ -51,12 +54,16 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator return Thread::myself()->affinity(); } + Hamstraaja &operator=(Hamstraaja ©); + Hamstraaja(Hamstraaja const ©); + public: 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++) { _core_heaps[cpu] = new (_backend) Core_heap(_pd, _rm); + Genode::log("Size of CoreHeap for size ", MAX * 2, " with ", MIN, " blocks is: ", sizeof(Core_heap)); } } @@ -92,7 +99,7 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator void *alloc(size_t size, unsigned domain_id) { _quota_used += overhead(size) + size; - return _location_to_heap(_my_location()).alloc(size, domain_id); + return _location_to_heap(_my_location()).aligned_alloc(size, 0, domain_id); } /** @@ -104,6 +111,7 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator void *alloc(size_t size) { _quota_used += overhead(size) + size; + //Genode::log("Allocating ", size, " bytes."); return _location_to_heap(_my_location()).alloc(size); } @@ -116,6 +124,10 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator */ void free(void *ptr, size_t alignment, size_t size) { + if (!ptr) { + Genode::warning("Tried to free nullptr"); + return; + } _quota_used -= overhead(size) + size; return _location_to_heap(_my_location()).free(ptr, alignment); } @@ -154,7 +166,7 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator } } - void free(void *ptr, size_t size) override { free(ptr, 0, size); } + void free(void *ptr, size_t size=0) override { free(ptr, 0, size); } size_t consumed() const override { return _quota_used; } size_t overhead(size_t size) const override { diff --git a/repos/ealanos/include/ealanos/memory/superblock.h b/repos/ealanos/include/ealanos/memory/superblock.h index 9f1226ada3..702d9145ea 100644 --- a/repos/ealanos/include/ealanos/memory/superblock.h +++ b/repos/ealanos/include/ealanos/memory/superblock.h @@ -14,6 +14,7 @@ #include #include +#include namespace Ealan::Memory { class Block; @@ -44,37 +45,29 @@ class Ealan::Memory::Hyperblock * @brief A block of memory * */ -class Ealan::Memory::Block +struct Ealan::Memory::Block { - public: - void *_superblock{nullptr}; /* Pointer to the superblock, this block was allocated from. */ - Genode::size_t _alignment{0}; - void *_block_start; /* Placeholder for marking the start of the usable area of this block. */ + void *_superblock{nullptr}; /* Pointer to the superblock, this block was allocated from. */ + char _padding[56]; - /** - * @brief Construct a new Block object - * - * @param sb - Pointer to the superblock this block was allocated from - */ - Block(void *sb, Genode::size_t align) : _superblock(sb), _alignment(align), _block_start{nullptr} {} + /** + * @brief Return a pointer to the metadata of this block + * + * @param ptr - application-facing pointer for which to request the metadata + * @return Block* - pointer to the Block datastructure containing the metadata + */ + static Block *metadata(void *ptr) { + return reinterpret_cast(reinterpret_cast(ptr) - sizeof(Block)); + } - /** - * @brief Creates a new block at the address pointed to by p - * - * @param p - the address at which the block shall be created - * @return void* - pointer to the new block - */ - void *operator new(Genode::size_t, void *p) { return p; } - - /** - * @brief Return a pointer to the metadata of this block - * - * @param ptr - application-facing pointer for which to request the metadata - * @return Block* - pointer to the Block datastructure containing the metadata - */ - static Block *metadata(void *ptr) { - return reinterpret_cast(reinterpret_cast(ptr) - sizeof(Genode::size_t) - sizeof(void *)); - } + bool reserve(void *sb) { + void *expect{nullptr}; + return __atomic_compare_exchange_n(&_superblock, &expect, sb, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); + } + + void free() { + __atomic_store_n(&_superblock, nullptr, __ATOMIC_RELEASE); + } }; /** @@ -91,13 +84,22 @@ template class Ealan::Memory::Superblock : public Hyperblock { private: - Genode::size_t _size_class{0}; /* actual size of the blocks in this superblock */ - Bit_alloc<0, SIZE/BASE> _alloc; /* Bit allocator to allocate blocks from this superblock */ - Block _block_start[]; /* Marker for the end of the metadata portion */ + Genode::size_t _size_class; + alignas(64) Genode::addr_t _start{0}; /* Start address of the blocks */ public: - Superblock(Genode::size_t sz) : _size_class(sz), _alloc(SIZE / _size_class) + 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("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("Capacity is ", capacity()); + Genode::log("-------------------");*/ } /** @@ -106,14 +108,19 @@ class Ealan::Memory::Superblock : public Hyperblock * @return void* - pointer to the allocated block */ void *alloc() { - long idx = static_cast(_alloc.alloc()); - - if (!idx) - return nullptr; - - Genode::addr_t block_addr = reinterpret_cast(_block_start) + idx * _size_class; - Block *block = new (reinterpret_cast(block_addr)) Block(this, 0); - return &block->_block_start; + 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); + } + return nullptr; } /** @@ -122,13 +129,17 @@ class Ealan::Memory::Superblock : public Hyperblock * @param alignment - adress alignment to use (must be at least 8) * @return void* - pointer to this block aligned to alignment bytes boundary */ - void *aligned_alloc(Genode::size_t alignment = 64) { + void *aligned_alloc(Genode::size_t alignment = 0) { void *ptr = alloc(); - Genode::addr_t base_ptr = reinterpret_cast(ptr) - sizeof(Genode::size_t) - sizeof(void *); - reinterpret_cast(base_ptr)->_alignment = alignment; + if (!ptr) + return nullptr; return reinterpret_cast(reinterpret_cast(ptr) + alignment); } + Genode::size_t capacity() { + return (reinterpret_cast(this) + SIZE - reinterpret_cast(&_start)) / (sizeof(Block) + _size_class); + } + /** * @brief Free the block pointed to by ptr. * @@ -141,23 +152,23 @@ class Ealan::Memory::Superblock : public Hyperblock * @param ptr - Pointer to memory block to free */ void free(void *ptr) { - Genode::size_t idx = (reinterpret_cast(ptr) - reinterpret_cast(_block_start)) / _size_class; - _alloc.release(idx); - } + if (!ptr) + return; - /** - * @brief Return number of blocks that can be allocated from this superblock - * - * @return Genode::size_t - Number of available blocks - */ - Genode::size_t free_blocks() { return _alloc.left(); } + Block *b = reinterpret_cast(reinterpret_cast(ptr) - 64); + Block *end = reinterpret_cast(reinterpret_cast(this) + SIZE); + if (b > --end) + return; + + b->free(); + } /** * @brief Return the address of the first memory block in this superblock * * @return Block* - address of the first block */ - Block *start() { return _block_start; } + Block *start() { return reinterpret_cast(&_start); } /** * @brief Placement new used to create a superblock at address pointed to by p.