mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
Clean up 'Sliced_heap'
This patch cleans up the implementation of the sliced heap, adds a constructor that takes references instead of pointers, and adds the function 'meta_data_size' to determine the meta-data overhead per block. The latter can be used to dimension slab allocators such that slab blocks use whole pages.
This commit is contained in:
parent
4f69772ecc
commit
ba0545de07
@ -174,20 +174,44 @@ class Genode::Sliced_heap : public Allocator
|
||||
{
|
||||
private:
|
||||
|
||||
class Block;
|
||||
/**
|
||||
* Meta-data header placed in front of each allocated block
|
||||
*/
|
||||
struct Block : List<Block>::Element
|
||||
{
|
||||
Ram_dataspace_capability const ds;
|
||||
size_t const size;
|
||||
|
||||
Ram_session *_ram_session; /* RAM session for backing store */
|
||||
Region_map *_region_map; /* region map of the address space */
|
||||
Block(Ram_dataspace_capability ds, size_t size) : ds(ds), size(size)
|
||||
{ }
|
||||
};
|
||||
|
||||
Ram_session &_ram_session; /* RAM session for backing store */
|
||||
Region_map &_region_map; /* region map of the address space */
|
||||
size_t _consumed; /* number of allocated bytes */
|
||||
List<Block> _block_list; /* list of allocated blocks */
|
||||
List<Block> _blocks; /* list of allocated blocks */
|
||||
Lock _lock; /* serialize allocations */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Return size of header prepended to each allocated block in bytes
|
||||
*/
|
||||
static constexpr size_t meta_data_size() { return sizeof(Block); }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \deprecated Use the other constructor that takes reference
|
||||
* arguments
|
||||
*/
|
||||
Sliced_heap(Ram_session *ram_session, Region_map *region_map)
|
||||
: Sliced_heap(*ram_session, *region_map) { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Sliced_heap(Ram_session *ram_session, Region_map *region_map);
|
||||
Sliced_heap(Ram_session &ram_session, Region_map ®ion_map);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
|
@ -5,67 +5,37 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2006-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <util/construct_at.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Sliced_heap::Block : public List<Sliced_heap::Block>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Ram_dataspace_capability _ds_cap;
|
||||
size_t _size;
|
||||
char _data[];
|
||||
|
||||
public:
|
||||
|
||||
inline void *operator new(size_t size, void *at_addr) {
|
||||
return at_addr; }
|
||||
|
||||
inline void operator delete (void*) { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Block(Ram_dataspace_capability ds_cap, size_t size):
|
||||
_ds_cap(ds_cap), _size(size) { }
|
||||
|
||||
/**
|
||||
* Accessors
|
||||
*/
|
||||
Ram_dataspace_capability ds_cap() { return _ds_cap; }
|
||||
size_t size() { return _size; }
|
||||
void *data_start() { return &_data[0]; }
|
||||
|
||||
/**
|
||||
* Lookup Slab_entry by given address
|
||||
*
|
||||
* The specified address is supposed to point to data[0].
|
||||
*/
|
||||
static Block *block(void *addr) {
|
||||
return (Block *)((addr_t)addr - sizeof(Block)); }
|
||||
};
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Sliced_heap::Sliced_heap(Ram_session *ram_session, Region_map *region_map):
|
||||
_ram_session(ram_session), _region_map(region_map),
|
||||
_consumed(0) { }
|
||||
Sliced_heap::Sliced_heap(Ram_session &ram_session, Region_map ®ion_map)
|
||||
:
|
||||
_ram_session(ram_session), _region_map(region_map), _consumed(0)
|
||||
{ }
|
||||
|
||||
|
||||
Sliced_heap::~Sliced_heap()
|
||||
{
|
||||
for (Block *b; (b = _block_list.first()); )
|
||||
free(b->data_start(), b->size()); }
|
||||
for (Block *b; (b = _blocks.first()); ) {
|
||||
/*
|
||||
* Compute pointer to payload, which follows the meta-data header.
|
||||
* Note the pointer arithmetics. By adding 1 to 'b', we end up with
|
||||
* 'payload' pointing to the data portion of the block.
|
||||
*/
|
||||
void * const payload = b + 1;
|
||||
free(payload, b->size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Sliced_heap::alloc(size_t size, void **out_addr)
|
||||
@ -74,14 +44,14 @@ bool Sliced_heap::alloc(size_t size, void **out_addr)
|
||||
size = align_addr(size + sizeof(Block), 12);
|
||||
|
||||
Ram_dataspace_capability ds_cap;
|
||||
void *local_addr;
|
||||
Block *block = nullptr;
|
||||
|
||||
try {
|
||||
ds_cap = _ram_session->alloc(size);
|
||||
local_addr = _region_map->attach(ds_cap);
|
||||
ds_cap = _ram_session.alloc(size);
|
||||
block = _region_map.attach(ds_cap);
|
||||
} catch (Region_map::Attach_failed) {
|
||||
PERR("Could not attach dataspace to local address space");
|
||||
_ram_session->free(ds_cap);
|
||||
_ram_session.free(ds_cap);
|
||||
return false;
|
||||
} catch (Ram_session::Alloc_failed) {
|
||||
PERR("Could not allocate dataspace with size %zu", size);
|
||||
@ -91,10 +61,14 @@ bool Sliced_heap::alloc(size_t size, void **out_addr)
|
||||
/* serialize access to block list */
|
||||
Lock::Guard lock_guard(_lock);
|
||||
|
||||
Block *b = new(local_addr) Block(ds_cap, size);
|
||||
construct_at<Block>(block, ds_cap, size);
|
||||
|
||||
_consumed += size;
|
||||
_block_list.insert(b);
|
||||
*out_addr = b->data_start();
|
||||
_blocks.insert(block);
|
||||
|
||||
/* skip meta data prepended to the payload portion of the block */
|
||||
*out_addr = block + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -102,21 +76,32 @@ bool Sliced_heap::alloc(size_t size, void **out_addr)
|
||||
void Sliced_heap::free(void *addr, size_t size)
|
||||
{
|
||||
Ram_dataspace_capability ds_cap;
|
||||
void * local_addr;
|
||||
void *local_addr = nullptr;
|
||||
{
|
||||
/* serialize access to block list */
|
||||
Lock::Guard lock_guard(_lock);
|
||||
|
||||
Block *b = Block::block(addr);
|
||||
_block_list.remove(b);
|
||||
_consumed -= b->size();
|
||||
ds_cap = b->ds_cap();
|
||||
local_addr = b;
|
||||
delete b;
|
||||
/*
|
||||
* The 'addr' argument points to the payload. We use pointer
|
||||
* arithmetics to determine the pointer to the block's meta data that
|
||||
* is prepended to the payload.
|
||||
*/
|
||||
Block * const block = reinterpret_cast<Block *>(addr) - 1;
|
||||
|
||||
_blocks.remove(block);
|
||||
_consumed -= block->size;
|
||||
ds_cap = block->ds;
|
||||
local_addr = block;
|
||||
|
||||
/*
|
||||
* Call destructor to properly destruct the dataspace capability
|
||||
* member of the 'Block'.
|
||||
*/
|
||||
block->~Block();
|
||||
}
|
||||
|
||||
_region_map->detach(local_addr);
|
||||
_ram_session->free(ds_cap);
|
||||
_region_map.detach(local_addr);
|
||||
_ram_session.free(ds_cap);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user