hw: cleanup signal-session component

ref #1123
This commit is contained in:
Martin Stein 2014-04-15 12:23:22 +02:00 committed by Christian Helmuth
parent 3d274366ab
commit b53601d01b
3 changed files with 159 additions and 162 deletions

View File

@ -78,22 +78,6 @@ namespace Genode
{
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota").long_value(0);
/*
* FIXME
* We check these assertions because space for initial SLAB
* blocks can be scaled pragmatically only via
* RECEIVERS_SLAB_BLOCK_SIZE and CONTEXTS_SLAB_BLOCK_SIZE
* (array size can't come from a function)
*/
if (Signal_session_component::RECEIVERS_SB_SIZE <
32 * Kernel::signal_receiver_size() ||
Signal_session_component::CONTEXTS_SB_SIZE <
32 * Kernel::signal_context_size())
{
PERR("Undersized SLAB blocks");
throw Root::Exception();
}
return new (md_alloc())
Signal_session_component(md_alloc(), ram_quota);
}

View File

@ -1,5 +1,5 @@
/*
* \brief Signal service on the HW-core
* \brief Server-sided implementation of a signal session
* \author Martin stein
* \date 2012-05-05
*/
@ -21,162 +21,200 @@
#include <base/allocator_guard.h>
#include <base/object_pool.h>
/* core includes */
#include <kernel/signal_receiver.h>
#include <util.h>
namespace Genode
{
/**
* Provides the signal service
* Combines kernel data and core data of an object a signal session manages
*
* \param T type of the kernel data
*/
class Signal_session_component : public Rpc_object<Signal_session>
{
public:
template <typename T>
class Signal_session_object;
enum {
/**
* Lastly Receiver::slab_size() was 112. Additionally we
* have to take in account, that the backing store might add
* its metadata and round up to next page size. So we choose
* 35 * 112 which mostly is save to end up in one page only.
*/
RECEIVERS_SB_SIZE = 3920,
typedef Signal_session_object<Kernel::Signal_receiver>
Signal_session_receiver;
/**
* Lastly Context::slab_size() size was 124. Additionally we
* have to take in account, that the backing store might add
* its metadata and round up to next page size. So we choose
* 32 * 124 which mostly is save to end up in one page only.
*/
CONTEXTS_SB_SIZE = 3968,
};
typedef Signal_session_object<Kernel::Signal_context>
Signal_session_context;
private:
/**
* Traits that are used in signal session components
*
* FIXME: This class is merely necessary because GCC 4.7.2 appears to have
* a problem with using a static-constexpr method for the
* dimensioning of a member array within the same class.
*/
class Signal_session_traits;
/**
* Maps a signal-receiver name to related core and kernel resources
*/
class Receiver;
/**
* Maps a signal-context name to related core and kernel resources
*/
class Context;
typedef Object_pool<Receiver> Receiver_pool;
typedef Object_pool<Context> Context_pool;
Allocator_guard _md_alloc;
Slab _receivers_slab;
Receiver_pool _receivers;
Slab _contexts_slab;
Context_pool _contexts;
char _initial_receivers_sb [RECEIVERS_SB_SIZE];
char _initial_contexts_sb [CONTEXTS_SB_SIZE];
/**
* Destruct receiver 'r'
*/
void _destruct_receiver(Receiver * const r);
/**
* Destruct context 'c'
*/
void _destruct_context(Context * const c);
public:
/**
* Constructor
*
* \param md Metadata allocator
* \param ram_quota Amount of RAM quota donated to this session
*/
Signal_session_component(Allocator * const md,
size_t const ram_quota);
/**
* Destructor
*/
~Signal_session_component();
/**
* Raise the quota of this session by 'q'
*/
void upgrade_ram_quota(size_t const q) { _md_alloc.upgrade(q); }
/******************************
** Signal_session interface **
******************************/
Signal_receiver_capability alloc_receiver();
Signal_context_capability
alloc_context(Signal_receiver_capability, unsigned const);
void free_receiver(Signal_receiver_capability);
void free_context(Signal_context_capability);
};
/**
* Server-sided implementation of a signal session
*/
class Signal_session_component;
}
class Genode::Signal_session_component::Receiver : public Receiver_pool::Entry
template <typename T>
class Genode::Signal_session_object
:
public Object_pool<Signal_session_object<T> >::Entry
{
public:
typedef Object_pool<Signal_session_object<T> > Pool;
/**
* Constructor
*/
Receiver(Untyped_capability cap) : Entry(cap) { }
Signal_session_object(Untyped_capability cap) : Pool::Entry(cap) { }
/**
* Name of signal receiver
* Kernel name of the object
*/
unsigned id() const { return Receiver_pool::Entry::cap().dst(); }
unsigned id() const { return Pool::Entry::cap().dst(); }
/**
* Size of SLAB block occupied by resources and this resource info
* Size of the data starting at the base of this object
*/
static size_t slab_size()
static constexpr size_t size()
{
return sizeof(Receiver) + Kernel::signal_receiver_size();
return sizeof(Signal_session_object<T>) + sizeof(T);
}
/**
* Base of region donated to the kernel
* Base of the kernel donation associated with a specific SLAB address
*
* \param slab_addr SLAB address
*/
static addr_t kernel_donation(void * const slab_addr)
static constexpr addr_t kernel_donation(void * const slab_addr)
{
return ((addr_t)slab_addr + sizeof(Receiver));
return (addr_t)slab_addr + sizeof(Signal_session_object<T>);
}
};
class Genode::Signal_session_component::Context : public Context_pool::Entry
class Genode::Signal_session_traits
{
private:
/**
* Return the raw size of a slab
*/
static constexpr size_t _slab_raw() { return get_page_size(); }
/**
* Return the size of the static buffer for meta data per slab
*/
static constexpr size_t _slab_buffer() { return 128; }
/**
* Return the size available for allocations per slab
*/
static constexpr size_t _slab_avail() { return _slab_raw() - _slab_buffer(); }
/**
* Return the amount of allocatable slots per slab
*
* \param T object type of the slab
*/
template <typename T>
static constexpr size_t _slab_slots() { return _slab_avail() / T::size(); }
protected:
/**
* Return the size of allocatable space per slab
*
* \param T object type of the slab
*/
template <typename T>
static constexpr size_t _slab_size() { return _slab_slots<T>() * T::size(); }
};
class Genode::Signal_session_component
:
public Rpc_object<Signal_session>,
public Signal_session_traits
{
private:
typedef Signal_session_receiver Receiver;
typedef Signal_session_context Context;
typedef Signal_session_traits Traits;
Allocator_guard _allocator;
Slab _receivers_slab;
Receiver::Pool _receivers;
Slab _contexts_slab;
Context::Pool _contexts;
char _first_receivers_slab [Traits::_slab_size<Receiver>()];
char _first_contexts_slab [Traits::_slab_size<Context>()];
/**
* Destruct receiver 'r'
*/
void _destruct_receiver(Receiver * const r);
/**
* Destruct context 'c'
*/
void _destruct_context(Context * const c);
public:
/**
* Constructor
*
* \param allocator RAM allocator for meta data
* \param quota amount of RAM quota donated to this session
*/
Context(Untyped_capability cap) : Entry(cap) { }
Signal_session_component(Allocator * const allocator,
size_t const quota)
:
_allocator(allocator, quota),
_receivers_slab(Receiver::size(), Traits::_slab_size<Receiver>(),
(Slab_block *)&_first_receivers_slab, &_allocator),
_contexts_slab(Context::size(), Traits::_slab_size<Context>(),
(Slab_block *)&_first_contexts_slab, &_allocator)
{ }
/**
* Name of signal context
* Destructor
*/
unsigned id() const { return Context_pool::Entry::cap().dst(); }
/**
* Size of SLAB block occupied by resources and this resource info
*/
static size_t slab_size()
~Signal_session_component()
{
return sizeof(Context) + Kernel::signal_context_size();
while (1) {
Context * const c = _contexts.first_locked();
if (!c) { break; }
_destruct_context(c);
}
while (1) {
Receiver * const r = _receivers.first_locked();
if (!r) { break; }
_destruct_receiver(r);
}
}
/**
* Base of region donated to the kernel
* Raise the quota of this session by 'q'
*/
static addr_t kernel_donation(void * const slab_addr)
{
return ((addr_t)slab_addr + sizeof(Context));
}
void upgrade_ram_quota(size_t const q) { _allocator.upgrade(q); }
/******************************
** Signal_session interface **
******************************/
Signal_receiver_capability alloc_receiver();
Signal_context_capability
alloc_context(Signal_receiver_capability, unsigned const);
void free_receiver(Signal_receiver_capability);
void free_context(Signal_context_capability);
};
#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
#endif /* _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_ */

View File

@ -24,36 +24,11 @@
using namespace Genode;
Signal_session_component::Signal_session_component(Allocator * const md,
size_t const ram_quota) :
_md_alloc(md, ram_quota),
_receivers_slab(Receiver::slab_size(), RECEIVERS_SB_SIZE,
(Slab_block *)&_initial_receivers_sb, &_md_alloc),
_contexts_slab(Context::slab_size(), CONTEXTS_SB_SIZE,
(Slab_block *)&_initial_contexts_sb, &_md_alloc)
{ }
Signal_session_component::~Signal_session_component()
{
while (1) {
Context * const c = _contexts.first_locked();
if (!c) { break; }
_destruct_context(c);
}
while (1) {
Receiver * const r = _receivers.first_locked();
if (!r) { break; }
_destruct_receiver(r);
}
}
Signal_receiver_capability Signal_session_component::alloc_receiver()
{
/* allocate resources for receiver */
void * p;
if (!_receivers_slab.alloc(Receiver::slab_size(), &p)) {
if (!_receivers_slab.alloc(Receiver::size(), &p)) {
PERR("failed to allocate signal-receiver resources");
throw Out_of_metadata();
}
@ -63,7 +38,7 @@ Signal_receiver_capability Signal_session_component::alloc_receiver()
if (!id)
{
/* clean up */
_receivers_slab.free(p, Receiver::slab_size());
_receivers_slab.free(p, Receiver::size());
PERR("failed to create signal receiver");
throw Create_receiver_failed();
}
@ -87,7 +62,7 @@ void Signal_session_component::free_receiver(Signal_receiver_capability cap)
}
/* release resources */
_destruct_receiver(r);
_receivers_slab.free(r, Receiver::slab_size());
_receivers_slab.free(r, Receiver::size());
}
@ -97,7 +72,7 @@ Signal_session_component::alloc_context(Signal_receiver_capability r,
{
/* allocate resources for context */
void * p;
if (!_contexts_slab.alloc(Context::slab_size(), &p)) {
if (!_contexts_slab.alloc(Context::size(), &p)) {
PERR("failed to allocate signal-context resources");
throw Out_of_metadata();
}
@ -107,7 +82,7 @@ Signal_session_component::alloc_context(Signal_receiver_capability r,
if (!id)
{
/* clean up */
_contexts_slab.free(p, Context::slab_size());
_contexts_slab.free(p, Context::size());
PERR("failed to create signal context");
throw Create_context_failed();
}
@ -130,7 +105,7 @@ void Signal_session_component::free_context(Signal_context_capability cap)
}
/* release resources */
_destruct_context(c);
_contexts_slab.free(c, Context::slab_size());
_contexts_slab.free(c, Context::size());
}
@ -146,7 +121,7 @@ void Signal_session_component::_destruct_context(Context * const c)
}
/* release core resources */
_contexts.remove_locked(c);
c->~Context();
c->~Signal_session_context();
}
@ -162,5 +137,5 @@ void Signal_session_component::_destruct_receiver(Receiver * const r)
}
/* release core resources */
_receivers.remove_locked(r);
r->~Receiver();
r->~Signal_session_receiver();
}