base: hide slab implementation details from API

Issue #1908
This commit is contained in:
Norman Feske 2016-03-31 18:17:07 +02:00 committed by Christian Helmuth
parent db5969e6cc
commit fbc35cb796
16 changed files with 406 additions and 386 deletions

View File

@ -56,7 +56,7 @@ class Genode::Rpc_cap_factory
Rpc_cap_factory(Allocator &md_alloc)
:
_slab(&md_alloc, (Slab_block*)&_initial_slab_block)
_slab(&md_alloc, &_initial_slab_block)
{ }
~Rpc_cap_factory()

View File

@ -38,8 +38,7 @@ class Genode::Signal_broker
public:
Slab(Allocator * const allocator)
: Tslab<T, BLOCK_SIZE>(allocator,
(Slab_block*)&_first_block) { }
: Tslab<T, BLOCK_SIZE>(allocator, &_first_block) { }
};
Allocator &_md_alloc;

View File

@ -30,6 +30,12 @@
using namespace Kernel;
static inline void free_obj_id_ref(Pd *pd, void *ptr)
{
pd->platform_pd()->capability_slab().free(ptr, sizeof(Object_identity_reference));
}
void Ipc_node::copy_msg(Ipc_node * const sender)
{
using namespace Genode;
@ -46,7 +52,7 @@ void Ipc_node::copy_msg(Ipc_node * const sender)
/* if there is no capability to send, just free the pre-allocation */
if (i >= sender->_utcb->cap_cnt()) {
pd()->platform_pd()->capability_slab().free(_obj_id_ref_ptr[i]);
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
continue;
}
@ -57,7 +63,7 @@ void Ipc_node::copy_msg(Ipc_node * const sender)
/* if the caller's capability is invalid, free the pre-allocation */
if (!oir) {
_utcb->cap_add(cap_id_invalid());
pd()->platform_pd()->capability_slab().free(_obj_id_ref_ptr[i]);
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
continue;
}
@ -68,9 +74,9 @@ void Ipc_node::copy_msg(Ipc_node * const sender)
if (!dst_oir && (pd() != core_pd())) {
dst_oir = oir->factory(_obj_id_ref_ptr[i], *pd());
if (!dst_oir)
pd()->platform_pd()->capability_slab().free(_obj_id_ref_ptr[i]);
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
} else /* otherwise free the pre-allocation */
pd()->platform_pd()->capability_slab().free(_obj_id_ref_ptr[i]);
free_obj_id_ref(pd(), _obj_id_ref_ptr[i]);
if (dst_oir) dst_oir->add_to_utcb();

View File

@ -108,13 +108,13 @@ Hw::Address_space::~Address_space()
*************************************/
Capability_space::Capability_space()
: _slab(nullptr, (Slab_block*)&_initial_sb) { }
: _slab(nullptr, &_initial_sb) { }
void Capability_space::upgrade_slab(Allocator &alloc)
{
for (;;) {
Slab_block * block;
void *block = nullptr;
/*
* On every upgrade we try allocating as many blocks as possible.
@ -122,7 +122,6 @@ void Capability_space::upgrade_slab(Allocator &alloc)
* this is normal as we use it as indication when to exit the loop.
*/
if (!alloc.alloc(SLAB_SIZE, &block)) return;
block = construct_at<Slab_block>(block, &_slab);
_slab.insert_sb(block);
}
}

View File

@ -17,148 +17,14 @@
#include <base/allocator.h>
#include <base/stdint.h>
namespace Genode {
class Slab;
class Slab_block;
class Slab_entry;
}
namespace Genode { class Slab; }
/**
* A slab block holds an array of slab entries.
* Transitional type definition, for API compatibility only
*
* \deprecated To be removed once all Slab users are updated.
*/
class Genode::Slab_block
{
public:
Slab_block *next; /* next block */
Slab_block *prev; /* previous block */
private:
enum { FREE, USED };
Slab *_slab; /* back reference to slab allocator */
size_t _avail; /* free entries of this block */
/*
* Each slab block consists of three areas, a fixed-size header
* that contains the member variables declared above, a byte array
* called state table that holds the allocation state for each slab
* entry, and an area holding the actual slab entries. The number
* of state-table elements corresponds to the maximum number of slab
* entries per slab block (the '_num_elem' member variable of the
* Slab allocator).
*/
char _data[]; /* dynamic data (state table and slab entries) */
/*
* Caution! no member variables allowed below this line!
*/
/**
* Return the allocation state of a slab entry
*/
inline bool state(int idx) { return _data[idx]; }
/**
* Set the allocation state of a slab entry
*/
inline void state(int idx, bool state) { _data[idx] = state; }
/**
* Request address of slab entry by its index
*/
Slab_entry *slab_entry(int idx);
/**
* Determine block index of specified slab entry
*/
int slab_entry_idx(Slab_entry *e);
public:
/**
* Constructor
*
* Normally, Slab_blocks are constructed by a Slab allocator
* that specifies itself as constructor argument.
*/
explicit Slab_block(Slab *s = 0) { if (s) slab(s); }
/**
* Configure block to be managed by the specified slab allocator
*/
void slab(Slab *slab);
/**
* Request number of available entries in block
*/
unsigned avail() const { return _avail; }
/**
* Allocate slab entry from block
*/
void *alloc();
/**
* Return a used slab block entry
*/
Slab_entry *first_used_entry();
/**
* These functions are called by Slab_entry.
*/
void inc_avail(Slab_entry *e);
void dec_avail();
/**
* Debug and test hooks
*/
void dump();
int check_bounds();
};
class Genode::Slab_entry
{
private:
Slab_block *_sb;
char _data[];
/*
* Caution! no member variables allowed below this line!
*/
public:
void init() { _sb = 0; }
void occupy(Slab_block *sb)
{
_sb = sb;
_sb->dec_avail();
}
void free()
{
_sb->inc_avail(this);
_sb = 0;
}
void *addr() { return _data; }
/**
* Lookup Slab_entry by given address
*
* The specified address is supposed to point to _data[0].
*/
static Slab_entry *slab_entry(void *addr) {
return (Slab_entry *)((addr_t)addr - sizeof(Slab_entry)); }
};
namespace Genode { typedef void Slab_block; }
/**
@ -168,27 +34,55 @@ class Genode::Slab : public Allocator
{
private:
size_t _slab_size; /* size of one slab entry */
size_t _block_size; /* size of slab block */
size_t _num_elem; /* number of slab entries per block */
Slab_block *_first_sb; /* first slab block */
Slab_block *_initial_sb; /* initial (static) slab block */
bool _alloc_state; /* indicator for 'currently in service' */
struct Block;
struct Entry;
Allocator *_backing_store;
size_t const _slab_size; /* size of one slab entry */
size_t const _block_size; /* size of slab block */
size_t const _entries_per_block; /* number of slab entries per block */
Block *_first_sb; /* first slab block */
Block *_initial_sb; /* initial (static) slab block */
bool _alloc_state; /* indicator for 'currently in service' */
Allocator *_backing_store;
/**
* Allocate and initialize new slab block
*/
Slab_block *_new_slab_block();
Block *_new_slab_block();
/*****************************
** Methods used by 'Block' **
*****************************/
/**
* Remove block from slab block list
*
* \noapi
*/
void _remove_sb(Block *sb);
/**
* Insert block into slab block list
*
* \noapi
*/
void _insert_sb(Block *sb, Block *at = 0);
/**
* Free slab entry
*/
void _free(void *addr);
/**
* Return true if number of free slab entries is higher than n
*/
bool _num_free_entries_higher_than(int n);
public:
inline size_t slab_size() const { return _slab_size; }
inline size_t block_size() const { return _block_size; }
inline size_t num_elem() const { return _num_elem; }
inline size_t entry_size() const { return sizeof(Slab_entry) + _slab_size; }
/**
* Constructor
*
@ -197,7 +91,7 @@ class Genode::Slab : public Allocator
* especially for the allocation of the second slab
* block.
*/
Slab(size_t slab_size, size_t block_size, Slab_block *initial_sb,
Slab(size_t slab_size, size_t block_size, void *initial_sb,
Allocator *backing_store = 0);
/**
@ -206,40 +100,17 @@ class Genode::Slab : public Allocator
~Slab();
/**
* Debug function for dumping the current slab block list
* Add new slab block as backing store
*
* \noapi
* The specified 'ptr' has to point to a buffer with the size of one
* slab block.
*/
void dump_sb_list();
void insert_sb(void *ptr);
/**
* Remove block from slab block list
*
* \noapi
* Return a used slab element, or nullptr if empty
*/
void remove_sb(Slab_block *sb);
/**
* Insert block into slab block list
*
* \noapi
*/
void insert_sb(Slab_block *sb, Slab_block *at = 0);
/**
* Free slab entry
*/
static void free(void *addr);
/**
* Return a used slab element
*/
void *first_used_elem();
/**
* Return true if number of free slab entries is higher than n
*/
bool num_free_entries_higher_than(int n);
void *any_used_elem();
/**
* Define/request backing-store allocator
@ -255,6 +126,7 @@ class Genode::Slab : public Allocator
*/
Allocator *backing_store() { return _backing_store; }
/*************************
** Allocator interface **
*************************/
@ -266,9 +138,9 @@ class Genode::Slab : public Allocator
* preconfigured slab-entry size are allocated.
*/
bool alloc(size_t size, void **addr) override;
void free(void *addr, size_t) override { free(addr); }
void free(void *addr, size_t) override { _free(addr); }
size_t consumed() const override;
size_t overhead(size_t) const override { return _block_size/_num_elem; }
size_t overhead(size_t) const override { return _block_size/_entries_per_block; }
bool need_size_for_free() const override { return false; }
};

View File

@ -22,12 +22,11 @@ namespace Genode { template <typename, size_t> struct Tslab; }
template <typename T, Genode::size_t BLOCK_SIZE>
struct Genode::Tslab : Slab
{
Tslab(Allocator *backing_store,
Slab_block *initial_sb = 0)
Tslab(Allocator *backing_store, void *initial_sb = 0)
: Slab(sizeof(T), BLOCK_SIZE, initial_sb, backing_store)
{ }
T *first_object() { return (T *)Slab::first_used_elem(); }
T *first_object() { return (T *)Slab::any_used_elem(); }
};
#endif /* _INCLUDE__BASE__TSLAB_H_ */

View File

@ -5,88 +5,200 @@
*/
/*
* 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 <base/slab.h>
#include <util/construct_at.h>
#include <util/misc_math.h>
using namespace Genode;
/**
* A slab block holds an array of slab entries.
*/
class Genode::Slab::Block
{
public:
Block *next = nullptr; /* next block */
Block *prev = nullptr; /* previous block */
private:
enum { FREE, USED };
Slab &_slab; /* back reference to slab */
size_t _avail = _slab._entries_per_block; /* free entries of this block */
/*
* Each slab block consists of three areas, a fixed-size header
* that contains the member variables declared above, a byte array
* called state table that holds the allocation state for each slab
* entry, and an area holding the actual slab entries. The number
* of state-table elements corresponds to the maximum number of slab
* entries per slab block (the '_entries_per_block' member variable of
* the Slab allocator).
*/
char _data[]; /* dynamic data (state table and slab entries) */
/*
* Caution! no member variables allowed below this line!
*/
/**
* Return the allocation state of a slab entry
*/
inline bool _state(int idx) { return _data[idx]; }
/**
* Set the allocation state of a slab entry
*/
inline void _state(int idx, bool state) { _data[idx] = state; }
/**
* Request address of slab entry by its index
*/
Entry *_slab_entry(int idx);
/**
* Determine block index of specified slab entry
*/
int _slab_entry_idx(Entry *e);
public:
/**
* Constructor
*/
explicit Block(Slab &slab) : _slab(slab)
{
for (unsigned i = 0; i < _avail; i++)
_state(i, FREE);
}
/**
* Request number of available entries in block
*/
unsigned avail() const { return _avail; }
/**
* Allocate slab entry from block
*/
void *alloc();
/**
* Return a used slab block entry
*/
Entry *any_used_entry();
/**
* These functions are called by Slab::Entry.
*/
void inc_avail(Entry &e);
void dec_avail();
/**
* Debug and test hooks
*/
void dump();
int check_bounds();
};
struct Genode::Slab::Entry
{
Block &block;
char data[];
/*
* Caution! no member variables allowed below this line!
*/
explicit Entry(Block &block) : block(block)
{
block.dec_avail();
}
~Entry()
{
block.inc_avail(*this);
}
/**
* Lookup Entry by given address
*
* The specified address is supposed to point to _data[0].
*/
static Entry *slab_entry(void *addr) {
return (Entry *)((addr_t)addr - sizeof(Entry)); }
};
/****************
** Slab block **
****************/
/**
* Placement operator - tool for directly calling a constructor
*/
inline void *operator new(size_t, void *at) { return at; }
void Slab_block::slab(Slab *slab)
{
_slab = slab;
_avail = _slab->num_elem();
next = prev = 0;
for (unsigned i = 0; i < _avail; i++)
state(i, FREE);
}
Slab_entry *Slab_block::slab_entry(int idx)
Slab::Entry *Slab::Block::_slab_entry(int idx)
{
/*
* The slab slots start after the state array that consists
* of 'num_elem' bytes. We align the first slot to a four-aligned
* address.
*/
return (Slab_entry *)&_data[align_addr(_slab->num_elem(), log2(sizeof(addr_t)))
+ _slab->entry_size()*idx];
size_t const entry_size = sizeof(Entry) + _slab._slab_size;
return (Entry *)&_data[align_addr(_slab._entries_per_block, log2(sizeof(addr_t)))
+ entry_size*idx];
}
int Slab_block::slab_entry_idx(Slab_entry *e) {
return ((addr_t)e - (addr_t)slab_entry(0))/_slab->entry_size(); }
void *Slab_block::alloc()
int Slab::Block::_slab_entry_idx(Slab::Entry *e)
{
size_t num_elem = _slab->num_elem();
for (unsigned i = 0; i < num_elem; i++)
if (state(i) == FREE) {
state(i, USED);
Slab_entry *e = slab_entry(i);
e->occupy(this);
return e->addr();
}
return 0;
size_t const entry_size = sizeof(Entry) + _slab._slab_size;
return ((addr_t)e - (addr_t)_slab_entry(0))/entry_size;
}
Slab_entry *Slab_block::first_used_entry()
void *Slab::Block::alloc()
{
size_t num_elem = _slab->num_elem();
for (unsigned i = 0; i < num_elem; i++)
if (state(i) == USED)
return slab_entry(i);
return 0;
for (unsigned i = 0; i < _slab._entries_per_block; i++) {
if (_state(i) != FREE)
continue;
_state(i, USED);
Entry * const e = _slab_entry(i);
construct_at<Entry>(e, *this);
return e->data;
}
return nullptr;
}
void Slab_block::inc_avail(Slab_entry *e)
Slab::Entry *Slab::Block::any_used_entry()
{
for (unsigned i = 0; i < _slab._entries_per_block; i++)
if (_state(i) == USED)
return _slab_entry(i);
return nullptr;
}
void Slab::Block::inc_avail(Entry &e)
{
/* mark slab entry as free */
int idx = slab_entry_idx(e);
state(idx, FREE);
int const idx = _slab_entry_idx(&e);
_state(idx, FREE);
_avail++;
/* search previous block with higher avail value than this' */
Slab_block *at = prev;
Block *at = prev;
while (at && (at->avail() < _avail))
at = at->prev;
@ -95,29 +207,29 @@ void Slab_block::inc_avail(Slab_entry *e)
* If we already are the first block or our avail value is lower than the
* previous block, do not reposition the block in the list.
*/
if (prev == 0 || at == prev)
if (prev == nullptr || at == prev)
return;
/* reposition block in list after block with higher avail value */
_slab->remove_sb(this);
_slab->insert_sb(this, at);
_slab._remove_sb(this);
_slab._insert_sb(this, at);
}
void Slab_block::dec_avail()
void Slab::Block::dec_avail()
{
_avail--;
/* search subsequent block with lower avail value than this' */
Slab_block *at = this;
Block *at = this;
while (at->next && at->next->avail() > _avail)
at = at->next;
if (at == this) return;
_slab->remove_sb(this);
_slab->insert_sb(this, at);
_slab._remove_sb(this);
_slab._insert_sb(this, at);
}
@ -125,31 +237,33 @@ void Slab_block::dec_avail()
** Slab **
**********/
Slab::Slab(size_t slab_size, size_t block_size, Slab_block *initial_sb,
Allocator *backing_store)
: _slab_size(slab_size),
_block_size(block_size),
_first_sb(initial_sb),
_initial_sb(initial_sb),
_alloc_state(false),
_backing_store(backing_store)
{
Slab::Slab(size_t slab_size, size_t block_size, void *initial_sb,
Allocator *backing_store)
:
_slab_size(slab_size),
_block_size(block_size),
/*
* Calculate number of entries per slab block.
*
* The 'sizeof(umword_t)' is for the alignment of the first slab entry.
* The 1 is for one byte state entry.
*/
_num_elem = (_block_size - sizeof(Slab_block) - sizeof(umword_t))
/ (entry_size() + 1);
_entries_per_block((_block_size - sizeof(Block) - sizeof(umword_t))
/ (_slab_size + sizeof(Entry) + 1)),
_first_sb((Block *)initial_sb),
_initial_sb(_first_sb),
_alloc_state(false),
_backing_store(backing_store)
{
/* if no initial slab block was specified, try to get one */
if (!_first_sb && _backing_store)
_first_sb = _new_slab_block();
/* init first slab block */
if (_first_sb)
_first_sb->slab(this);
construct_at<Block>(_first_sb, *this);
}
@ -157,8 +271,8 @@ Slab::~Slab()
{
/* free backing store */
while (_first_sb) {
Slab_block *sb = _first_sb;
remove_sb(_first_sb);
Block * const sb = _first_sb;
_remove_sb(_first_sb);
/*
* Only free slab blocks that we allocated. This is not the case for
@ -170,21 +284,20 @@ Slab::~Slab()
}
Slab_block *Slab::_new_slab_block()
Slab::Block *Slab::_new_slab_block()
{
void *sb = 0;
void *sb = nullptr;
if (!_backing_store || !_backing_store->alloc(_block_size, &sb))
return 0;
return nullptr;
/* call constructor by using the placement new operator */
return new(sb) Slab_block(this);
return construct_at<Block>(sb, *this);
}
void Slab::remove_sb(Slab_block *sb)
void Slab::_remove_sb(Block *sb)
{
Slab_block *prev = sb->prev;
Slab_block *next = sb->next;
Block *prev = sb->prev;
Block *next = sb->next;
if (prev) prev->next = next;
if (next) next->prev = prev;
@ -192,14 +305,14 @@ void Slab::remove_sb(Slab_block *sb)
if (_first_sb == sb)
_first_sb = next;
sb->prev = sb->next = 0;
sb->prev = sb->next = nullptr;
}
void Slab::insert_sb(Slab_block *sb, Slab_block *at)
void Slab::_insert_sb(Block *sb, Block *at)
{
/* determine next-pointer where to assign the current sb */
Slab_block **nextptr_to_sb = at ? &at->next : &_first_sb;
Block **nextptr_to_sb = at ? &at->next : &_first_sb;
/* insert current sb */
sb->next = *nextptr_to_sb;
@ -213,11 +326,11 @@ void Slab::insert_sb(Slab_block *sb, Slab_block *at)
}
bool Slab::num_free_entries_higher_than(int n)
bool Slab::_num_free_entries_higher_than(int n)
{
int cnt = 0;
for (Slab_block *b = _first_sb; b && b->avail() > 0; b = b->next) {
for (Block *b = _first_sb; b && b->avail() > 0; b = b->next) {
cnt += b->avail();
if (cnt > n)
return true;
@ -226,6 +339,12 @@ bool Slab::num_free_entries_higher_than(int n)
}
void Slab::insert_sb(void *ptr)
{
_insert_sb(construct_at<Block>(ptr, *this));
}
bool Slab::alloc(size_t size, void **out_addr)
{
/* sanity check if first slab block is gone */
@ -239,11 +358,11 @@ bool Slab::alloc(size_t size, void **out_addr)
* new slab block early enough - that is if there are only three free slab
* entries left.
*/
if (_backing_store && !num_free_entries_higher_than(3) && !_alloc_state) {
if (_backing_store && !_num_free_entries_higher_than(3) && !_alloc_state) {
/* allocate new block for slab */
_alloc_state = true;
Slab_block *sb = _new_slab_block();
Block *sb = _new_slab_block();
_alloc_state = false;
if (!sb) return false;
@ -253,35 +372,36 @@ bool Slab::alloc(size_t size, void **out_addr)
* so we can insert it at the beginning of the sorted block
* list.
*/
insert_sb(sb);
_insert_sb(sb);
}
*out_addr = _first_sb->alloc();
return *out_addr == 0 ? false : true;
return *out_addr == nullptr ? false : true;
}
void Slab::free(void *addr)
void Slab::_free(void *addr)
{
Slab_entry *e = addr ? Slab_entry::slab_entry(addr) : 0;
Entry *e = addr ? Entry::slab_entry(addr) : nullptr;
if (e) e->free();
if (e)
e->~Entry();
}
void *Slab::first_used_elem()
void *Slab::any_used_elem()
{
for (Slab_block *b = _first_sb; b; b = b->next) {
for (Block *b = _first_sb; b; b = b->next) {
/* skip completely free slab blocks */
if (b->avail() == _num_elem)
if (b->avail() == _entries_per_block)
continue;
/* found a block with used elements - return address of the first one */
Slab_entry *e = b->first_used_entry();
if (e) return e->addr();
Entry *e = b->any_used_entry();
if (e) return e->data;
}
return 0;
return nullptr;
}
@ -289,7 +409,7 @@ size_t Slab::consumed() const
{
/* count number of slab blocks */
unsigned sb_cnt = 0;
for (Slab_block *sb = _first_sb; sb; sb = sb->next)
for (Block *sb = _first_sb; sb; sb = sb->next)
sb_cnt++;
return sb_cnt * _block_size;

View File

@ -127,31 +127,29 @@ class Bsd::Slab_alloc : public Genode::Slab
{
private:
/*
* Each slab block in the slab contains about 8 objects (slab entries)
* as proposed in the paper by Bonwick and block sizes are multiples of
* page size.
*/
static size_t _calculate_block_size(size_t object_size)
Genode::size_t const _object_size;
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Genode::Slab_entry))
+ sizeof(Genode::Slab_block);
Genode::size_t const block_size = 16*object_size;
return Genode::align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Slab_backend_alloc &allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, &allocator) { }
Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator)
:
Slab(object_size, _calculate_block_size(object_size), 0, &allocator),
_object_size(object_size)
{ }
/**
* Convenience slabe-entry allocation
*/
addr_t alloc()
Genode::addr_t alloc()
{
addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
Genode::addr_t result;
return (Slab::alloc(_object_size, (void **)&result) ? result : 0);
}
void free(void *ptr) { Slab::free(ptr, _object_size); }
};
@ -164,7 +162,7 @@ class Bsd::Malloc
enum {
SLAB_START_LOG2 = 5, /* 32 B */
SLAB_STOP_LOG2 = 17, /* 64 KiB */
SLAB_STOP_LOG2 = 16, /* 64 KiB */
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
};

View File

@ -503,33 +503,36 @@ struct Slab_backend_alloc : public Genode::Allocator,
};
struct Slab_alloc : public Genode::Slab
class Slab_alloc : public Genode::Slab
{
/*
* Each slab block in the slab contains about 8 objects (slab entries)
* as proposed in the paper by Bonwick and block sizes are multiples of
* page size.
*/
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
Genode::size_t block_size = 8 * (object_size + sizeof(Genode::Slab_entry))
+ sizeof(Genode::Slab_block);
return Genode::align_addr(block_size, 12);
}
private:
Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, &allocator) { }
Genode::size_t const _object_size;
/**
* Convenience slabe-entry allocation
*/
Genode::addr_t alloc()
{
Genode::addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
}
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
Genode::size_t const block_size = 8*object_size;
return Genode::align_addr(block_size, 12);
}
public:
Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator)
:
Slab(object_size, _calculate_block_size(object_size), 0, &allocator),
_object_size(object_size)
{ }
Genode::addr_t alloc()
{
Genode::addr_t result;
return (Slab::alloc(_object_size, (void **)&result) ? result : 0);
}
void free(void *ptr) { Slab::free(ptr, _object_size); }
};
struct Slab
{
enum {

View File

@ -18,6 +18,7 @@
/* Genode includes */
#include <base/slab.h>
#include <util/misc_math.h>
/* Linux emulation environment includes */
#include <lx_emul/impl/internal/slab_backend_alloc.h>
@ -28,6 +29,8 @@ class Lx::Slab_alloc : public Genode::Slab
{
private:
size_t const _object_size;
/*
* Each slab block in the slab contains about 8 objects (slab entries)
* as proposed in the paper by Bonwick and block sizes are multiples of
@ -35,15 +38,17 @@ class Lx::Slab_alloc : public Genode::Slab
*/
static size_t _calculate_block_size(size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Genode::Slab_entry))
+ sizeof(Genode::Slab_block);
size_t block_size = 16*object_size;
return Genode::align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Slab_backend_alloc &allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, &allocator) { }
:
Slab(object_size, _calculate_block_size(object_size), 0, &allocator),
_object_size(object_size)
{ }
/**
* Convenience slabe-entry allocation
@ -51,7 +56,12 @@ class Lx::Slab_alloc : public Genode::Slab
Genode::addr_t alloc()
{
Genode::addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
return (Slab::alloc(_object_size, (void **)&result) ? result : 0);
}
void free(void *ptr)
{
Slab::free(ptr, _object_size);
}
};

View File

@ -152,23 +152,29 @@ class Genode::Slab_alloc : public Genode::Slab
{
private:
size_t _calculate_block_size(size_t object_size)
Genode::size_t const _object_size;
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Slab_entry)) + sizeof(Slab_block);
Genode::size_t const block_size = 16*object_size;
return align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Backend_alloc *allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, allocator)
{ }
:
Slab(object_size, _calculate_block_size(object_size), 0, allocator),
_object_size(object_size)
{ }
inline addr_t alloc()
{
addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
}
inline addr_t alloc()
{
Genode::addr_t result;
return (Slab::alloc(_object_size, (void **)&result) ? result : 0);
}
void free(void *ptr) { Slab::free(ptr, _object_size); }
};
/**

View File

@ -169,23 +169,29 @@ class Genode::Slab_alloc : public Genode::Slab
{
private:
size_t _calculate_block_size(size_t object_size)
Genode::size_t const _object_size;
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Slab_entry)) + sizeof(Slab_block);
return align_addr(block_size, 12);
Genode::size_t const block_size = 16*object_size;
return Genode::align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Slab_backend_alloc *allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, allocator)
{ }
Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator)
:
Slab(object_size, _calculate_block_size(object_size), 0, &allocator),
_object_size(object_size)
{ }
inline addr_t alloc()
{
addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
}
Genode::addr_t alloc()
{
Genode::addr_t result;
return (Slab::alloc(_object_size, (void **)&result) ? result : 0);
}
void free(void *ptr) { Slab::free(ptr, _object_size); }
};
@ -247,7 +253,7 @@ class Malloc
/* init slab allocators */
for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++)
_allocator[i - SLAB_START_LOG2] = new (Genode::env()->heap())
Slab_alloc(1U << i, alloc);
Slab_alloc(1U << i, *alloc);
}
static unsigned long max_alloc() { return 1U << SLAB_STOP_LOG2; }

View File

@ -191,31 +191,29 @@ class Lx::Slab_alloc : public Genode::Slab
{
private:
/*
* Each slab block in the slab contains about 8 objects (slab entries)
* as proposed in the paper by Bonwick and block sizes are multiples of
* page size.
*/
static size_t _calculate_block_size(size_t object_size)
Genode::size_t const _object_size;
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Genode::Slab_entry))
+ sizeof(Genode::Slab_block);
Genode::size_t const block_size = 16*object_size;
return Genode::align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Slab_backend_alloc &allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, &allocator) { }
Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator)
:
Slab(object_size, _calculate_block_size(object_size), 0, &allocator),
_object_size(object_size)
{ }
/**
* Convenience slabe-entry allocation
*/
addr_t alloc()
Genode::addr_t alloc()
{
addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
Genode::addr_t result;
return (Slab::alloc(_object_size, (void **)&result) ? result : 0);
}
void free(void *ptr) { Slab::free(ptr, _object_size); }
};

View File

@ -65,6 +65,10 @@ class Wifi_session_component : public Nic::Session_component
}
struct sk_buff *skb = ::alloc_skb(packet.size() + HEAD_ROOM, GFP_KERNEL);
if (skb == nullptr) {
PERR("Could not allocate new sk_buff");
return false;
}
skb_reserve(skb, HEAD_ROOM);
unsigned char *data = skb_put(skb, packet.size());

View File

@ -32,23 +32,31 @@ namespace Genode {
class Slab_alloc : public Slab
{
private:
size_t const _object_size;
size_t _calculate_block_size(size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Slab_entry)) + sizeof(Slab_block);
size_t block_size = 16*object_size;
return align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Allocator *backing_store)
: Slab(object_size, _calculate_block_size(object_size), 0, backing_store)
:
Slab(object_size, _calculate_block_size(object_size), 0, backing_store),
_object_size(object_size)
{ }
inline void *alloc()
void *alloc()
{
void *result;
return (Slab::alloc(slab_size(), &result) ? result : 0);
return (Slab::alloc(_object_size, &result) ? result : 0);
}
void free(void *ptr) { Slab::free(ptr, _object_size); }
};
}

View File

@ -67,11 +67,9 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
};
Genode::Tslab<Genode::Io_port_connection, IO_BLOCK_SIZE> _slab_ioport;
Genode::Slab_block _slab_ioport_block;
char _slab_ioport_block_data[IO_BLOCK_SIZE];
Genode::Tslab<Io_mem, IO_MEM_SIZE> _slab_iomem;
Genode::Slab_block _slab_iomem_block;
char _slab_iomem_block_data[IO_MEM_SIZE];
char _mem_irq_component[sizeof(Irq_session_component)];
@ -200,20 +198,14 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
Platform::Device::ACCESS_8BIT)),
_irq_session(nullptr),
_slab_ioport(md_alloc, &_slab_ioport_block),
_slab_iomem(md_alloc, &_slab_iomem_block)
_slab_ioport(md_alloc, &_slab_ioport_block_data),
_slab_iomem(md_alloc, &_slab_iomem_block_data)
{
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
_io_port_conn[i] = nullptr;
}
if (_slab_ioport.num_elem() != Device::NUM_RESOURCES)
PERR("incorrect amount of space for io port resources");
if (_slab_iomem.num_elem() != Device::NUM_RESOURCES)
PERR("incorrect amount of space for io mem resources");
_disable_bus_master_dma();
}
/**
@ -226,8 +218,8 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
_ep(ep), _session(session),
_irq_line(irq),
_irq_session(nullptr),
_slab_ioport(0, &_slab_ioport_block),
_slab_iomem(0, &_slab_iomem_block)
_slab_ioport(0, &_slab_ioport_block_data),
_slab_iomem(0, &_slab_iomem_block_data)
{
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++)
_io_port_conn[i] = nullptr;