mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
ealanos: Made hamstraaja more efficient.
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
#define __INCLUDE__EALANOS__MEMORY__COREHEAP_H_
|
#define __INCLUDE__EALANOS__MEMORY__COREHEAP_H_
|
||||||
|
|
||||||
#include <ealanos/memory/superblock.h>
|
#include <ealanos/memory/superblock.h>
|
||||||
#include <ealanos/util/mpsc_queue.h>
|
#include <ealanos/util/lifo_queue.h>
|
||||||
#include <tukija/syscall-generic.h>
|
#include <tukija/syscall-generic.h>
|
||||||
#include <base/attached_ram_dataspace.h>
|
#include <base/attached_ram_dataspace.h>
|
||||||
#include <pd_session/pd_session.h>
|
#include <pd_session/pd_session.h>
|
||||||
@@ -37,7 +37,7 @@ class Ealan::Memory::Core_heap
|
|||||||
static constexpr const Genode::size_t num_size_classes = MAX / MIN;
|
static constexpr const Genode::size_t num_size_classes = MAX / MIN;
|
||||||
static constexpr const unsigned num_numa_domains = 64;
|
static constexpr const unsigned num_numa_domains = 64;
|
||||||
static constexpr const unsigned long magic_num = 0xdeadbeefUL;
|
static constexpr const unsigned long magic_num = 0xdeadbeefUL;
|
||||||
Ealan::util::MPSCQueue<Sb> _superblocks[num_size_classes][num_numa_domains];
|
alignas(64) Ealan::util::Lifo_queue<Sb> _superblocks[num_size_classes][num_numa_domains];
|
||||||
Pd_session &_pd;
|
Pd_session &_pd;
|
||||||
Region_map &_rm;
|
Region_map &_rm;
|
||||||
Tip *_tip{const_cast<Tip *>(Tip::tip())};
|
Tip *_tip{const_cast<Tip *>(Tip::tip())};
|
||||||
@@ -91,7 +91,8 @@ class Ealan::Memory::Core_heap
|
|||||||
|
|
||||||
Sb *_allocate_superblock(unsigned domain_id, Genode::size_t sz_class)
|
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) {
|
if (!hb) {
|
||||||
Genode::warning("Failed to allocate superblock for size class ", sz_class, " in domain ", domain_id);
|
Genode::warning("Failed to allocate superblock for size class ", sz_class, " in domain ", domain_id);
|
||||||
return nullptr;
|
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 (size_t sz_class = 0; sz_class < num_size_classes; sz_class++) {
|
||||||
for (unsigned domain_id = 0; domain_id < num_numa_domains; domain_id++) {
|
for (unsigned domain_id = 0; domain_id < num_numa_domains; domain_id++) {
|
||||||
Sb *sb;
|
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;
|
Ram_dataspace_capability cap = sb->cap;
|
||||||
_rm.detach(reinterpret_cast<addr_t>(sb));
|
_rm.detach(reinterpret_cast<addr_t>(sb));
|
||||||
@@ -141,11 +142,14 @@ class Ealan::Memory::Core_heap
|
|||||||
Genode::size_t sz_class = _calculate_size_class(size+alignment);
|
Genode::size_t sz_class = _calculate_size_class(size+alignment);
|
||||||
Sb *sb = _superblocks[sz_class / MIN - 1][domain_id].head();
|
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);
|
sb = _allocate_superblock(domain_id, sz_class);
|
||||||
if (!sb)
|
if (!sb)
|
||||||
return nullptr;
|
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*>(sb->next())) {
|
for (; sb != nullptr ; sb = static_cast<Sb*>(sb->next())) {
|
||||||
@@ -158,7 +162,7 @@ class Ealan::Memory::Core_heap
|
|||||||
sb = _allocate_superblock(domain_id, sz_class);
|
sb = _allocate_superblock(domain_id, sz_class);
|
||||||
if (!sb)
|
if (!sb)
|
||||||
return nullptr;
|
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);
|
return sb->aligned_alloc(alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +213,7 @@ class Ealan::Memory::Core_heap
|
|||||||
}
|
}
|
||||||
Sb *sb = static_cast<Sb*>(b->_superblock);
|
Sb *sb = static_cast<Sb*>(b->_superblock);
|
||||||
if (!sb) {
|
if (!sb) {
|
||||||
Genode::warning("Corrupt or invalid memory block.");
|
Genode::warning("Corrupt or invalid memory block: ", p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sb->free(p);
|
sb->free(p);
|
||||||
@@ -219,7 +223,7 @@ class Ealan::Memory::Core_heap
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
Sb *sb = _allocate_superblock(domain_id, sz_class);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#ifndef __INCLUDE__EALANOS__MEMORY__HAMSTRAAJA_H_
|
#ifndef __INCLUDE__EALANOS__MEMORY__HAMSTRAAJA_H_
|
||||||
#define __INCLUDE__EALANOS__MEMORY__HAMSTRAAJA_H_
|
#define __INCLUDE__EALANOS__MEMORY__HAMSTRAAJA_H_
|
||||||
|
|
||||||
|
#include "base/log.h"
|
||||||
#include <ealanos/memory/coreheap.h>
|
#include <ealanos/memory/coreheap.h>
|
||||||
#include <tukija/syscall-generic.h>
|
#include <tukija/syscall-generic.h>
|
||||||
#include <base/affinity.h>
|
#include <base/affinity.h>
|
||||||
@@ -41,7 +42,7 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator
|
|||||||
size_t _quota_used{0};
|
size_t _quota_used{0};
|
||||||
|
|
||||||
Heap &_location_to_heap(Affinity::Location loc) const
|
Heap &_location_to_heap(Affinity::Location loc) const
|
||||||
{
|
{
|
||||||
size_t pos = loc.xpos() * loc.height() + loc.ypos();
|
size_t pos = loc.xpos() * loc.height() + loc.ypos();
|
||||||
if (!_core_heaps[pos]) {
|
if (!_core_heaps[pos]) {
|
||||||
Genode::error("No heap for location ", loc);
|
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)
|
Hamstraaja(Genode::Pd_session &pd, Genode::Region_map &rm) : _pd(pd), _rm(rm)
|
||||||
{
|
{
|
||||||
size_t num_cpus = Cip::cip()->habitat_affinity.total();
|
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<MIN, MAX>(_pd, _rm);
|
_core_heaps[cpu] = new (_backend) Core_heap<MIN, MAX>(_pd, _rm);
|
||||||
}
|
}
|
||||||
Genode::log("Hamstraaja initialized");
|
Genode::log("Hamstraaja initialized");
|
||||||
|
Genode::log("Size of CoreHeap is ", sizeof(Heap));
|
||||||
}
|
}
|
||||||
|
|
||||||
~Hamstraaja()
|
~Hamstraaja()
|
||||||
@@ -87,9 +89,14 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator
|
|||||||
{
|
{
|
||||||
_quota_used += overhead(size) + size;
|
_quota_used += overhead(size) + size;
|
||||||
return _location_to_heap(_my_location()).aligned_alloc(size, domain_id, alignment);
|
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
|
* @brief Allocate a chunk of memory from a NUMA domain without alignment
|
||||||
*
|
*
|
||||||
* @param size - amount of memory to allocate
|
* @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)
|
void *alloc(size_t size, unsigned domain_id)
|
||||||
{
|
{
|
||||||
_quota_used += overhead(size) + size;
|
_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);
|
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)
|
void *alloc(size_t size)
|
||||||
{
|
{
|
||||||
_quota_used += overhead(size) + 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<void *>(0x7FFF80000000UL)) {
|
||||||
|
Genode::error("Hamstraaja returned non-canonical address");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free a chunk of memory
|
* @brief Free a chunk of memory
|
||||||
@@ -148,19 +162,22 @@ class Ealan::Memory::Hamstraaja : public Genode::Allocator
|
|||||||
_location_to_heap(loc).reserve_superblocks(count, domain_id, sz_class);
|
_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 **
|
** Allocator interface **
|
||||||
*************************/
|
*************************/
|
||||||
|
|
||||||
Alloc_result try_alloc(size_t size) override
|
Alloc_result try_alloc(size_t size) override
|
||||||
{
|
{
|
||||||
void *ptr = nullptr;
|
void *ptr = nullptr;
|
||||||
if ((ptr = alloc(size)) != nullptr)
|
if ((ptr = alloc(size)) != nullptr) {
|
||||||
{
|
|
||||||
return Alloc_result(ptr);
|
return Alloc_result(ptr);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return Alloc_result(Alloc_error::OUT_OF_RAM);
|
return Alloc_result(Alloc_error::OUT_OF_RAM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#ifndef __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_
|
#ifndef __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_
|
||||||
#define __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_
|
#define __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_
|
||||||
|
|
||||||
#include <ealanos/util/bit_alloc.h>
|
#include <ealanos/util/lifo_queue.h>
|
||||||
#include <base/stdint.h>
|
#include <base/stdint.h>
|
||||||
#include <base/ram_allocator.h>
|
#include <base/ram_allocator.h>
|
||||||
|
|
||||||
@@ -45,10 +45,11 @@ class Ealan::Memory::Hyperblock
|
|||||||
* @brief A block of memory
|
* @brief A block of memory
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Ealan::Memory::Block
|
struct Ealan::Memory::Block {
|
||||||
{
|
Block *_next{nullptr};
|
||||||
void *_superblock{nullptr}; /* Pointer to the superblock, this block was allocated from. */
|
void *_superblock{nullptr};/* Pointer to the superblock, this block was allocated from. */
|
||||||
char _padding[56];
|
char _padding[48];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return a pointer to the metadata of this block
|
* @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);
|
return __atomic_compare_exchange_n(&_superblock, &expect, sb, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void free() {
|
void free() { __atomic_store_n(&_superblock, nullptr, __ATOMIC_RELEASE); }
|
||||||
__atomic_store_n(&_superblock, nullptr, __ATOMIC_RELEASE);
|
|
||||||
}
|
void next(Block *ptr) { _next = ptr; }
|
||||||
|
Block* next() { return _next; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,42 +86,62 @@ template <int SIZE, unsigned BASE>
|
|||||||
class Ealan::Memory::Superblock : public Hyperblock
|
class Ealan::Memory::Superblock : public Hyperblock
|
||||||
{
|
{
|
||||||
private:
|
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<Block> _blocks{};
|
||||||
|
alignas(64) Genode::addr_t _start{0}; /* Start address of the blocks */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Superblock(Genode::size_t sz) : _size_class(sz)
|
Superblock(Genode::size_t sz) : _size_class(sz)
|
||||||
{
|
{
|
||||||
if (_size_class > SIZE) {
|
if (_size_class > SIZE) {
|
||||||
Genode::error("Size class ", _size_class, " is bigger than superblock size ", 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("Block metadata size is ", sizeof(Block));
|
||||||
Genode::log("Size class of superblock is ", _size_class);
|
Genode::log("Size class of superblock is ", _size_class);
|
||||||
Block *end = reinterpret_cast<Block *>(reinterpret_cast<Genode::addr_t>(this) + SIZE);
|
Genode::log("Superblock ends at ", reinterpret_cast<void*>(_end));
|
||||||
Genode::log("Superblock ends at ", end);
|
|
||||||
Genode::log("Capacity is ", capacity());
|
Genode::log("Capacity is ", capacity());
|
||||||
Genode::log("-------------------");
|
Genode::log("-------------------");*/
|
||||||
}
|
|
||||||
|
Genode::addr_t end = reinterpret_cast<Genode::addr_t>(this) + SIZE - sizeof(Block) - _size_class;
|
||||||
|
for (Genode::addr_t block = reinterpret_cast<Genode::addr_t>(&_start); block < end; block += sizeof(Block) + _size_class) {
|
||||||
|
Block *b = reinterpret_cast<Block *>(block);
|
||||||
|
b->_superblock = this;
|
||||||
|
_blocks.enqueue(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocate a block of SIZE-8 bytes from this superblock
|
* @brief Allocate a block of SIZE-8 bytes from this superblock
|
||||||
*
|
*
|
||||||
* @return void* - pointer to the allocated block
|
* @return void* - pointer to the allocated block
|
||||||
*/
|
*/
|
||||||
void *alloc() {
|
void *alloc()
|
||||||
Block *block = reinterpret_cast<Block *>(&_start);
|
{
|
||||||
|
Block *block = _blocks.dequeue();
|
||||||
|
if (block)
|
||||||
|
return reinterpret_cast<Block*>(reinterpret_cast<Genode::addr_t>(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<void*>(reinterpret_cast<Genode::addr_t>(block)+64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Block *block = reinterpret_cast<Block *>(&_start);
|
||||||
Block *end = reinterpret_cast<Block *>(reinterpret_cast<Genode::addr_t>(this) + SIZE - 64);
|
Block *end = reinterpret_cast<Block *>(reinterpret_cast<Genode::addr_t>(this) + SIZE - 64);
|
||||||
while (block < end) {
|
while (block < end) {
|
||||||
if (block->_superblock == nullptr) {
|
|
||||||
if (block->reserve(this))
|
|
||||||
{
|
|
||||||
return reinterpret_cast<void*>(reinterpret_cast<Genode::addr_t>(block)+64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Genode::addr_t next = reinterpret_cast<Genode::addr_t>(block) + sizeof(Block) + _size_class;
|
Genode::addr_t next = reinterpret_cast<Genode::addr_t>(block) + sizeof(Block) + _size_class;
|
||||||
block = reinterpret_cast<Block *>(next);
|
if (block->_superblock == nullptr) {
|
||||||
}
|
if (block->reserve(this)) {
|
||||||
|
return reinterpret_cast<void *>(reinterpret_cast<Genode::addr_t>(block) +
|
||||||
|
64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block = reinterpret_cast<Block *>(next);
|
||||||
|
}*/
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,9 +181,8 @@ class Ealan::Memory::Superblock : public Hyperblock
|
|||||||
Block *end = reinterpret_cast<Block *>(reinterpret_cast<Genode::addr_t>(this) + SIZE);
|
Block *end = reinterpret_cast<Block *>(reinterpret_cast<Genode::addr_t>(this) + SIZE);
|
||||||
if (b > --end)
|
if (b > --end)
|
||||||
return;
|
return;
|
||||||
|
_blocks.enqueue(b);
|
||||||
b->free();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the address of the first memory block in this superblock
|
* @brief Return the address of the first memory block in this superblock
|
||||||
|
|||||||
39
repos/ealanos/include/ealanos/util/lifo_queue.h
Normal file
39
repos/ealanos/include/ealanos/util/lifo_queue.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __INCLUDE__EALANOS__UTIL_LIFO_QUEUE_H_
|
||||||
|
#define __INCLUDE__EALANOS__UTIL_LIFO_QUEUE_H_
|
||||||
|
|
||||||
|
namespace Ealan::util
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
class Lifo_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user