diff --git a/repos/ealanos/include/ealanos/memory/superblock.h b/repos/ealanos/include/ealanos/memory/superblock.h new file mode 100644 index 0000000000..b27d533344 --- /dev/null +++ b/repos/ealanos/include/ealanos/memory/superblock.h @@ -0,0 +1,155 @@ +/** + * @file superblock.h + * @author Michael Müller (michael.mueller@uos.de) + * @brief Superblock definition + * @version 0.1 + * @date 2025-03-06 + * + * @copyright Copyright (c) 2025 + * + */ + +#ifndef __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_ +#define __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_ + +#include +#include + +namespace Ealan::Memory { + class Block; + class Hyperblock; + template + class Superblock; +} + +/** + * @brief A memory area that may contain a superblock or user-data + * + * @details A hyperblock represents an arbitrary chunk of memory that is backed by + * physical memory. In Genode terms, it is both a dataspace and a region. + * Hyperblocks may be chained together to build an unbounded memory allocator. + * + */ +class Ealan::Memory::Hyperblock +{ + public: + Hyperblock *_next{nullptr}; +}; + +/** + * @brief A block of memory + * + */ +class Ealan::Memory::Block +{ + public: + void *_superblock{nullptr}; /* Pointer to the superblock, this block was allocated from. */ + void *_block_start; /* Placeholder for marking the start of the usable area of this block. */ + + /** + * @brief Construct a new Block object + * + * @param sb - Pointer to the superblock this block was allocated from + */ + Block(void *sb) : _superblock(sb), _block_start{nullptr} {} + + /** + * @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 A memory area containing consecutive equally sized blocks of memory. + * + * @details A superblock is a waitfree bounded heap of equally sized blocks of memory. Each + * superblock is also a hyperblock and contains at most SIZE/BASE blocks. + * + * @tparam SIZE - size of this superblock in bytes, used to calculate number of blocks + * this superblock can supply + * @tparam BASE - size of the underlying block structure + */ +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 */ + alignas(BASE) Block _block_start[]; /* Marker for the end of the metadata portion */ + + public: + Superblock(Genode::size_t sz) : _size_class(sz), _alloc(SIZE / _size_class) + { + } + + /** + * @brief Allocate a block of SIZE-8 bytes from this superblock + * + * @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); + return &block->_block_start; + } + + /** + * @brief Allocate a block from this superblock aligned to alignment + * + * @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 *ptr = alloc(); + Genode::addr_t base_ptr = reinterpret_cast(ptr) - sizeof(void *); + return reinterpret_cast(base_ptr + alignment); + } + + /** + * @brief Free the block pointed to by ptr. + * + * @details Frees the block pointed to by ptr and, thus, makes it + * available to the superblocks allocator again for reuse. + * The superblock field of the block _must_ not be overwritten + * as it is used to identify the right bit of it in the bitvector + * used by the superblocks allocator. + * + * @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); + } + + /** + * @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(); } + + /** + * @brief Return the address of the first memory block in this superblock + * + * @return Block* - address of the first block + */ + Block *start() { return _block_start; } + + /** + * @brief Placement new used to create a superblock at address pointed to by p. + * + * @param p - Pointer to address to create superblock at. + * @return void* - Pointer to the new superblock. + */ + void *operator new(Genode::size_t, void *p) { return p; } +}; + +#endif /* __INCLUDE__EALANOS__MEMORY__SUPERBLOCK_H_ */ \ No newline at end of file