os: New Signal_rpc_dispatcher utility

The so-called Signal_rpc_dispatcher delegates the handling of signals to
the context of an RPC entrypoint.
This commit is contained in:
Norman Feske 2013-09-07 23:46:21 +02:00
parent 8243329ad4
commit 94bcd3f1bf
1 changed files with 194 additions and 0 deletions

View File

@ -0,0 +1,194 @@
/*
* \brief Utility for dispatching signals via an RPC entrypoint **
* \author Norman Feske
* \date 2013-09-07
*/
/*
* Copyright (C) 2013 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 _INCLUDE__OS__SIGNAL_RPC_DISPATCHER_H_
#define _INCLUDE__OS__SIGNAL_RPC_DISPATCHER_H_
#include <base/rpc_server.h>
#include <base/signal.h>
namespace Genode {
class Signal_rpc_dispatcher_base;
template <typename> class Signal_rpc_functor;
template <typename> class Signal_rpc_member;
template <typename FUNCTOR>
Signal_rpc_functor<FUNCTOR> signal_rpc_functor(FUNCTOR &);
}
struct Genode::Signal_rpc_dispatcher_base : Genode::Signal_dispatcher_base
{
private:
struct Proxy
{
GENODE_RPC(Rpc_handle_signal, void, handle_signal, unsigned);
GENODE_RPC_INTERFACE(Rpc_handle_signal);
};
struct Proxy_component : Genode::Rpc_object<Proxy, Proxy_component>
{
Genode::Signal_rpc_dispatcher_base &_dispatcher;
Proxy_component(Signal_rpc_dispatcher_base &dispatcher)
: _dispatcher(dispatcher) { }
void handle_signal(unsigned num)
{
_dispatcher.dispatch_at_entrypoint(num);
}
};
Proxy_component _proxy;
Capability<Proxy> _proxy_cap;
unsigned _nesting_level;
private:
/**
* To be implemented by the derived class
*/
virtual void dispatch_at_entrypoint(unsigned num) = 0;
protected:
Signal_rpc_dispatcher_base() : _proxy(*this), _nesting_level(0) { }
Capability<Proxy> proxy_cap() { return _proxy_cap; }
public:
/**
* Associate signal dispatcher with entrypoint
*/
Signal_context_capability manage(Signal_receiver &sig_rec, Rpc_entrypoint &ep)
{
_proxy_cap = ep.manage(&_proxy);
return sig_rec.manage(this);
}
/**
* Disassociate signal dispatcher from entrypoint
*/
void dissolve(Signal_receiver &sig_rec, Rpc_entrypoint &ep)
{
ep.dissolve(&_proxy);
_proxy_cap = Capability<Proxy>();
sig_rec.dissolve(this);
}
public:
/**
* Interface of Signal_dispatcher_base
*/
void dispatch(unsigned num)
{
/*
* Keep track of nesting levels to deal with nested signal
* dispatching. When called from within the RPC entrypoint, any
* attempt to perform a RPC call would lead to a deadlock. In
* this case, we call the 'dispatch' function directly.
*/
_nesting_level++;
/* called from the signal-receiving thread */
if (_nesting_level == 1)
proxy_cap().call<Proxy::Rpc_handle_signal>(num);
/* called from the context of the RPC entrypoint */
if (_nesting_level > 1)
dispatch_at_entrypoint(num);
_nesting_level--;
}
};
/**
* Signal dispatcher that executes the signal handling code in the context
* of an RPC entrypoint
*
* The 'Signal_rpc_dispatcher' provides an easy way for a server to serialize
* the handling of signals with incoming RPC requests. Incoming signals are
* delegated to the RPC entrypoint via a local RPC call. The signal handling
* code is then executed in the context of the RPC entrypoint.
*/
template <typename FUNCTOR>
struct Genode::Signal_rpc_functor : Genode::Signal_rpc_dispatcher_base
{
FUNCTOR &functor;
/**
* Constructor
*
* \param func functor taking containing the signal-handling code
*
* The functor 'func' has the signature 'void func(unsigned num)'
* whereas 'num' is the number of signals received at once.
*/
Signal_rpc_functor(FUNCTOR &functor) : functor(functor) { }
/**
* Interface of Signal_rpc_dispatcher_base
*/
void dispatch_at_entrypoint(unsigned num) { functor(num); }
};
/**
* Signal dispatcher for directing signals via RPC to member function
*
* This utility associates member functions with signals. It is intended to
* be used as a member variable of the class that handles incoming signals
* of a certain type. The constructor takes a pointer-to-member to the
* signal handling function as argument. If a signal is received at the
* common signal reception code, this function will be invoked by calling
* 'Signal_dispatcher_base::dispatch'.
*
* \param T type of signal-handling class
*/
template <typename T>
struct Genode::Signal_rpc_member : Genode::Signal_rpc_dispatcher_base
{
T &obj;
void (T::*member) (unsigned);
/**
* Constructor
*
* \param obj,member object and member function to call when
* the signal occurs
*/
Signal_rpc_member(T &obj, void (T::*member)(unsigned))
: obj(obj), member(member) { }
/**
* Interface of Signal_rpc_dispatcher_base
*/
void dispatch_at_entrypoint(unsigned num) { (obj.*member)(num); }
};
/**
* Convenience utility for creating 'Signal_rpc_dispatcher' objects
*/
template <typename FUNCTOR>
Genode::Signal_rpc_functor<FUNCTOR> Genode::signal_rpc_functor(FUNCTOR &func)
{
return Signal_rpc_functor<FUNCTOR>(func);
}
#endif /* _INCLUDE__OS__SIGNAL_RPC_DISPATCHER_H_ */