144 lines
3.6 KiB
C
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_ */
|