diff --git a/base-hw/src/core/include/signal_root.h b/base-hw/src/core/include/signal_root.h
index 01be1e25af..871f1f5d5f 100644
--- a/base-hw/src/core/include/signal_root.h
+++ b/base-hw/src/core/include/signal_root.h
@@ -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);
}
diff --git a/base-hw/src/core/include/signal_session_component.h b/base-hw/src/core/include/signal_session_component.h
index 1ba9a4271b..4911a6aec7 100644
--- a/base-hw/src/core/include/signal_session_component.h
+++ b/base-hw/src/core/include/signal_session_component.h
@@ -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
#include
+/* core includes */
+#include
+#include
+
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
- {
- public:
+ template
+ 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
+ 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
+ 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_pool;
- typedef Object_pool 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
+class Genode::Signal_session_object
+:
+ public Object_pool >::Entry
{
public:
+ typedef Object_pool > 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) + 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);
}
};
-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
+ 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
+ static constexpr size_t _slab_size() { return _slab_slots() * T::size(); }
+};
+
+class Genode::Signal_session_component
+:
+ public Rpc_object,
+ 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()];
+ char _first_contexts_slab [Traits::_slab_size()];
+
+ /**
+ * 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(),
+ (Slab_block *)&_first_receivers_slab, &_allocator),
+ _contexts_slab(Context::size(), Traits::_slab_size(),
+ (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_ */
diff --git a/base-hw/src/core/signal_session_component.cc b/base-hw/src/core/signal_session_component.cc
index bf9ddd1175..038e4b11ed 100644
--- a/base-hw/src/core/signal_session_component.cc
+++ b/base-hw/src/core/signal_session_component.cc
@@ -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();
}