genode/repos/base-hw/src/core/include/signal_broker.h
Norman Feske b1910cdd54 Integrate SIGNAL session into PD session
This patch removes the SIGNAL service from core and moves its
functionality to the PD session. Furthermore, it unifies the PD service
implementation and terminology across the various base platforms.

Issue #1841
2016-03-07 12:34:44 +01:00

153 lines
3.6 KiB
C++

/*
* \brief Base-hw-specific signal-delivery mechanism
* \author Norman Feske
* \date 2016-01-04
*/
/*
* Copyright (C) 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.
*/
#ifndef _CORE__INCLUDE__SIGNAL_BROKER_H_
#define _CORE__INCLUDE__SIGNAL_BROKER_H_
/* Genode includes */
#include <base/tslab.h>
/* core-local includes */
#include <assertion.h>
#include <signal_source_component.h>
namespace Genode { class Signal_broker; }
class Genode::Signal_broker
{
private:
template <typename T, size_t BLOCK_SIZE = get_page_size()>
class Slab : public Tslab<T, BLOCK_SIZE>
{
private:
uint8_t _first_block[BLOCK_SIZE];
public:
Slab(Allocator * const allocator)
: Tslab<T, BLOCK_SIZE>(allocator,
(Slab_block*)&_first_block) { }
};
Allocator &_md_alloc;
Slab<Signal_source_component> _sources_slab { &_md_alloc };
Signal_source_pool _sources;
Slab<Signal_context_component> _contexts_slab { &_md_alloc };
Signal_context_pool _contexts;
public:
class Invalid_signal_source : public Exception { };
Signal_broker(Allocator &md_alloc, Rpc_entrypoint &, Rpc_entrypoint &)
:
_md_alloc(md_alloc)
{ }
~Signal_broker()
{
_contexts.remove_all([this] (Signal_context_component *c) {
destroy(&_contexts_slab, c);});
_sources.remove_all([this] (Signal_source_component *s) {
destroy(&_sources_slab, s);});
}
/*
* \throw Allocator::Out_of_memory
*/
Capability<Signal_source> alloc_signal_source()
{
/* the _sources_slab may throw Allocator::Out_of_memory */
Signal_source_component *s = new (_sources_slab) Signal_source_component();
_sources.insert(s);
return reinterpret_cap_cast<Signal_source>(s->cap());
}
void free_signal_source(Capability<Signal_source> cap)
{
Signal_source_component *source = nullptr;
auto lambda = [&] (Signal_source_component *s) {
if (!s) {
PERR("unknown signal source");
return;
}
source = s;
_sources.remove(source);
};
_sources.apply(cap, lambda);
/* destruct signal source outside the lambda to prevent deadlock */
if (source)
destroy(&_sources_slab, source);
}
/*
* \throw Allocator::Out_of_memory
* \throw Invalid_signal_source
*/
Signal_context_capability
alloc_context(Capability<Signal_source> source, unsigned long imprint)
{
auto lambda = [&] (Signal_source_component *s) {
if (!s) {
PERR("unknown signal source");
throw Invalid_signal_source();
}
/* the _contexts_slab may throw Allocator::Out_of_memory */
Signal_context_component *c = new (_contexts_slab)
Signal_context_component(*s, imprint);
_contexts.insert(c);
return reinterpret_cap_cast<Signal_context>(c->cap());
};
return _sources.apply(source, lambda);
}
void free_context(Signal_context_capability context_cap)
{
Signal_context_component *context = nullptr;
auto lambda = [&] (Signal_context_component *c) {
if (!c) {
PERR("unknown signal context");
return;
}
context = c;
_contexts.remove(context);
};
_contexts.apply(context_cap, lambda);
/* destruct context outside the lambda to prevent deadlock */
if (context)
destroy(&_contexts_slab, context);
}
void submit(Signal_context_capability cap, unsigned cnt)
{
/*
* This function is never called as base-hw delivers signals
* directly via the kernel.
*/
}
};
#endif /* _CORE__INCLUDE__SIGNAL_BROKER_H_ */