genode/repos/base/src/core/include/signal_source_component.h

144 lines
3.6 KiB
C++

/*
* \brief Signal-delivery mechanism
* \author Norman Feske
* \date 2009-08-05
*/
/*
* Copyright (C) 2009-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 _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
#define _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
#include <signal_source/rpc_object.h>
#include <base/allocator_guard.h>
#include <base/tslab.h>
#include <base/lock.h>
#include <base/rpc_client.h>
#include <base/rpc_server.h>
#include <util/fifo.h>
#include <base/signal.h>
namespace Genode {
class Signal_context_component;
class Signal_source_component;
typedef Fifo<Signal_context_component> Signal_queue;
}
class Genode::Signal_context_component : public Rpc_object<Signal_context>,
public Signal_queue::Element
{
private:
long _imprint;
int _cnt;
Signal_source_component *_source;
public:
/**
* Constructor
*/
Signal_context_component(long imprint,
Signal_source_component *source)
: _imprint(imprint), _cnt(0), _source(source) { }
/**
* Destructor
*/
inline ~Signal_context_component();
/**
* Increment number of signals to be delivered at once
*/
void increment_signal_cnt(int increment) { _cnt += increment; }
/**
* Reset number of pending signals
*/
void reset_signal_cnt() { _cnt = 0; }
long imprint() { return _imprint; }
int cnt() { return _cnt; }
Signal_source_component *source() { return _source; }
};
class Genode::Signal_source_component : public Signal_source_rpc_object
{
/**
* Helper for clean destruction of signal-receiver component
*
* Normally, reply capabilities are implicitly destroyed when answering
* an RPC call. But when destructing a signal session while a signal-
* receiver client is blocking on a 'wait_for_signal' call, this
* blocking call will never return via the normal control flow
* (signal submission). In this case, the reply capability would
* outlive the signal session. To avoid the leakage of such reply
* capabilities, we let the signal-session destructor perform a
* core-local RPC call to the so-called 'Finalizer' object, which has
* the sole purpose of replying to the last outstanding
* 'wait_for_signal' call and thereby releasing the corresponding
* reply capability.
*/
struct Finalizer
{
GENODE_RPC(Rpc_exit, void, exit);
GENODE_RPC_INTERFACE(Rpc_exit);
};
struct Finalizer_component : Rpc_object<Finalizer, Finalizer_component>
{
Signal_source_component &source;
Finalizer_component(Signal_source_component &source)
: source(source) { }
void exit();
};
private:
Signal_queue _signal_queue;
Rpc_entrypoint *_entrypoint;
Native_capability _reply_cap;
Finalizer_component _finalizer;
Capability<Finalizer> _finalizer_cap;
public:
/**
* Constructor
*/
Signal_source_component(Rpc_entrypoint *rpc_entrypoint);
~Signal_source_component();
void release(Signal_context_component *context);
void submit(Signal_context_component *context,
unsigned long cnt);
/*****************************
** Signal-receiver interface **
*****************************/
Signal wait_for_signal() override;
};
Genode::Signal_context_component::~Signal_context_component()
{
if (is_enqueued() && _source)
_source->release(this);
}
#endif /* _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_ */