mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
3d274366ab
commit
b53601d01b
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user