mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-21 20:08:12 +00:00
5ed5fddb7c
This commit removes APIs that were previously marked as deprecated. This change has the following implications: - The use of the global 'env()' accessor is not possible anymore. - Boolean accessor methods are no longer prefixed with 'is_'. E.g., instead of 'is_valid()', use 'valid()'. - The last traces of 'Ram_session' are gone now. The 'Env::ram()' accessor returns the 'Ram_allocator' interface, which is a subset of the 'Pd_session' interface. - All connection constructors need the 'Env' as argument. - The 'Reporter' constructor needs an 'Env' argument now because the reporter creates a report connection. - The old overload 'Child_policy::resolve_session_request' that returned a 'Service' does not exist anymore. - The base/printf.h header has been removed, use base/log.h instead. - The old notion of 'Signal_dispatcher' is gone. Use 'Signal_handler'. - Transitional headers like os/server.h, cap_session/, volatile_object.h, os/attached*_dataspace.h, signal_rpc_dispatcher.h have been removed. - The distinction between 'Thread_state' and 'Thread_state_base' does not exist anymore. - The header cpu_thread/capability.h along with the type definition of 'Cpu_thread_capability' has been removed. Use the type 'Thread_capability' define in cpu_session/cpu_session.h instead. - Several XML utilities (i.e., at os/include/decorator) could be removed because their functionality is nowadays covered by util/xml_node.h. - The 'os/ram_session_guard.h' has been removed. Use 'Constrained_ram_allocator' provided by base/ram_allocator.h instead. Issue #1987
504 lines
12 KiB
C++
504 lines
12 KiB
C++
/*
|
|
* \brief Delivery and reception of asynchronous notifications
|
|
* \author Norman Feske
|
|
* \date 2008-09-05
|
|
*
|
|
* Each transmitter sends signals to one fixed destination.
|
|
* A receiver can receive signals from multiple sources.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2008-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _INCLUDE__BASE__SIGNAL_H_
|
|
#define _INCLUDE__BASE__SIGNAL_H_
|
|
|
|
#include <util/noncopyable.h>
|
|
#include <util/list.h>
|
|
#include <base/semaphore.h>
|
|
#include <base/capability.h>
|
|
|
|
/* only needed for base-hw */
|
|
namespace Kernel { struct Signal_receiver; }
|
|
|
|
namespace Genode {
|
|
|
|
class Entrypoint;
|
|
class Rpc_entrypoint;
|
|
class Signal_source;
|
|
|
|
class Signal_receiver;
|
|
class Signal_context;
|
|
class Signal_context_registry;
|
|
class Signal_transmitter;
|
|
class Signal;
|
|
class Signal_dispatcher_base;
|
|
|
|
template <typename, typename> class Signal_handler;
|
|
template <typename, typename> class Io_signal_handler;
|
|
|
|
typedef Capability<Signal_context> Signal_context_capability;
|
|
}
|
|
|
|
|
|
/**
|
|
* Signal
|
|
*
|
|
* A signal represents a number of asynchronous notifications produced by
|
|
* one transmitter. If notifications are generated at a higher rate than as
|
|
* they can be processed at the receiver, the transmitter counts the
|
|
* notifications and delivers the total amount with the next signal
|
|
* transmission. This way, the total number of notifications gets properly
|
|
* communicated to the receiver even if the receiver is not highly
|
|
* responsive.
|
|
*
|
|
* Asynchronous notifications do not carry any payload because this payload
|
|
* would need to be queued at the transmitter. However, each transmitter
|
|
* imprints a signal-context reference into each signal. This context
|
|
* can be used by the receiver to distinguish signals coming from different
|
|
* transmitters.
|
|
*/
|
|
class Genode::Signal
|
|
{
|
|
private:
|
|
|
|
struct Data
|
|
{
|
|
Signal_context *context;
|
|
unsigned num;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* \param context signal context specific for the
|
|
* signal-receiver capability used for signal
|
|
* transmission
|
|
* \param num number of signals received from the same
|
|
* transmitter
|
|
*/
|
|
Data(Signal_context *context, unsigned num)
|
|
: context(context), num(num) { }
|
|
|
|
/**
|
|
* Default constructor, representing an invalid signal
|
|
*/
|
|
Data() : context(0), num(0) { }
|
|
|
|
} _data;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* Signal objects are constructed by signal receivers only.
|
|
*/
|
|
Signal(Data data);
|
|
|
|
friend class Kernel::Signal_receiver;
|
|
friend class Signal_receiver;
|
|
friend class Signal_context;
|
|
|
|
void _dec_ref_and_unlock();
|
|
void _inc_ref();
|
|
|
|
public:
|
|
|
|
Signal(Signal const &other);
|
|
|
|
/**
|
|
* \noapi
|
|
*/
|
|
Signal &operator = (Signal const &other);
|
|
|
|
~Signal();
|
|
|
|
Signal_context *context() { return _data.context; }
|
|
unsigned num() const { return _data.num; }
|
|
};
|
|
|
|
|
|
/**
|
|
* Signal transmitter
|
|
*
|
|
* Each signal-transmitter instance acts on behalf the context specified
|
|
* as constructor argument. Therefore, the resources needed for the
|
|
* transmitter such as the consumed memory 'sizeof(Signal_transmitter)'
|
|
* should be accounted to the owner of the context.
|
|
*/
|
|
class Genode::Signal_transmitter
|
|
{
|
|
private:
|
|
|
|
Signal_context_capability _context { }; /* destination */
|
|
|
|
public:
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* \param context capability to signal context that is going to
|
|
* receive signals produced by the transmitter
|
|
*/
|
|
Signal_transmitter(Signal_context_capability context = Signal_context_capability());
|
|
|
|
/**
|
|
* Set signal context
|
|
*/
|
|
void context(Signal_context_capability context);
|
|
|
|
/**
|
|
* Return signal context
|
|
*/
|
|
Signal_context_capability context();
|
|
|
|
/**
|
|
* Trigger signal submission to context
|
|
*
|
|
* \param cnt number of signals to submit at once
|
|
*/
|
|
void submit(unsigned cnt = 1);
|
|
};
|
|
|
|
|
|
/**
|
|
* Signal context
|
|
*
|
|
* A signal context is a destination for signals. One receiver can listen
|
|
* to multple contexts. If a signal arrives, the context is provided with the
|
|
* signal. This enables the receiver to distinguish different signal sources
|
|
* and dispatch incoming signals context-specific.
|
|
*
|
|
* Signal contexts are classified to represent one of two levels: application
|
|
* and I/O. The signal level determines how a signal is handled by
|
|
* 'wait_and_dispatch_one_io_signal', which defers signals corresponding to
|
|
* application-level contexts and dispatches only I/O-level signals.
|
|
*/
|
|
class Genode::Signal_context : Interface, Noncopyable
|
|
{
|
|
public:
|
|
|
|
enum class Level { App, Io };
|
|
|
|
private:
|
|
|
|
/**
|
|
* List element in 'Signal_receiver'
|
|
*/
|
|
Signal_context mutable *_next { nullptr };
|
|
Signal_context mutable *_prev { nullptr };
|
|
|
|
/**
|
|
* List element in process-global registry
|
|
*/
|
|
List_element<Signal_context> _registry_le { this };
|
|
|
|
/**
|
|
* List element in deferred application signal list
|
|
*/
|
|
List_element<Signal_context> _deferred_le { this };
|
|
|
|
/**
|
|
* Receiver to which the context is associated with
|
|
*
|
|
* This member is initialized by the receiver when associating
|
|
* the context with the receiver via the 'cap' method.
|
|
*/
|
|
Signal_receiver *_receiver { nullptr };
|
|
|
|
Lock _lock { }; /* protect '_curr_signal' */
|
|
Signal::Data _curr_signal { }; /* most-currently received signal */
|
|
bool _pending { false }; /* current signal is valid */
|
|
unsigned int _ref_cnt { 0 }; /* number of references to context */
|
|
Lock _destroy_lock { }; /* prevent destruction while the
|
|
context is in use */
|
|
|
|
/**
|
|
* Capability assigned to this context after being assocated with
|
|
* a 'Signal_receiver' via the 'manage' method. We store this
|
|
* capability in the 'Signal_context' for the mere reason to
|
|
* properly destruct the context (see '_unsynchronized_dissolve').
|
|
*/
|
|
Signal_context_capability _cap { };
|
|
|
|
friend class Signal;
|
|
friend class Signal_receiver;
|
|
friend class Signal_context_registry;
|
|
|
|
/*
|
|
* Noncopyable
|
|
*/
|
|
Signal_context &operator = (Signal_context const &);
|
|
Signal_context(Signal_context const &);
|
|
|
|
protected:
|
|
|
|
Level _level = Level::App;
|
|
|
|
public:
|
|
|
|
Signal_context() { }
|
|
|
|
/**
|
|
* Destructor
|
|
*
|
|
* The virtual destructor is just there to generate a vtable for
|
|
* signal-context objects such that signal contexts can be dynamically
|
|
* casted.
|
|
*/
|
|
virtual ~Signal_context();
|
|
|
|
Level level() const { return _level; }
|
|
|
|
List_element<Signal_context> *deferred_le() { return &_deferred_le; }
|
|
|
|
/*
|
|
* Signal contexts are never invoked but only used as arguments for
|
|
* 'Signal_session' methods. Hence, there exists a capability
|
|
* type for it but no real RPC interface.
|
|
*/
|
|
GENODE_RPC_INTERFACE();
|
|
};
|
|
|
|
|
|
/**
|
|
* Signal receiver
|
|
*/
|
|
class Genode::Signal_receiver : Noncopyable
|
|
{
|
|
private:
|
|
|
|
/**
|
|
* A list where the head can be moved
|
|
*/
|
|
class Context_ring
|
|
{
|
|
private:
|
|
|
|
Signal_context *_head { nullptr };
|
|
|
|
public:
|
|
|
|
struct Break_for_each : Exception { };
|
|
|
|
Signal_context *head() const { return _head; }
|
|
|
|
void head(Signal_context *re) { _head = re; }
|
|
|
|
void insert_as_tail(Signal_context *re);
|
|
|
|
void remove(Signal_context const *re);
|
|
|
|
template <typename FUNC>
|
|
void for_each_locked(FUNC && functor) const
|
|
{
|
|
Signal_context *context = _head;
|
|
if (!context) return;
|
|
|
|
do {
|
|
Lock::Guard lock_guard(context->_lock);
|
|
try {
|
|
functor(*context);
|
|
} catch (Break_for_each) { return; }
|
|
context = context->_next;
|
|
} while (context != _head);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Semaphore used to indicate that signal(s) are ready to be picked
|
|
* up. This is needed for platforms other than 'base-hw' only.
|
|
*/
|
|
Semaphore _signal_available { };
|
|
|
|
/**
|
|
* Provides the kernel-object name via the 'dst' method. This is
|
|
* needed for 'base-hw' only.
|
|
*/
|
|
Capability<Signal_source> _cap { };
|
|
|
|
/**
|
|
* List of associated contexts
|
|
*/
|
|
Lock _contexts_lock { };
|
|
Context_ring _contexts { };
|
|
|
|
/**
|
|
* Helper to dissolve given context
|
|
*
|
|
* This method prevents duplicated code in '~Signal_receiver'
|
|
* and 'dissolve'. Note that '_contexts_lock' must be held when
|
|
* calling this method.
|
|
*/
|
|
void _unsynchronized_dissolve(Signal_context *context);
|
|
|
|
/**
|
|
* Hook to platform specific destructor parts
|
|
*/
|
|
void _platform_destructor();
|
|
|
|
/**
|
|
* Hooks to platform specific dissolve parts
|
|
*/
|
|
void _platform_begin_dissolve(Signal_context * const c);
|
|
void _platform_finish_dissolve(Signal_context * const c);
|
|
|
|
public:
|
|
|
|
/**
|
|
* Exception class
|
|
*/
|
|
class Context_already_in_use { };
|
|
class Context_not_associated { };
|
|
class Signal_not_pending { };
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
Signal_receiver();
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
~Signal_receiver();
|
|
|
|
/**
|
|
* Manage signal context and return new signal-context capability
|
|
*
|
|
* \param context context associated with signals delivered to the
|
|
* receiver
|
|
* \throw 'Context_already_in_use'
|
|
* \return new signal-context capability that can be
|
|
* passed to a signal transmitter
|
|
*/
|
|
Signal_context_capability manage(Signal_context *context);
|
|
|
|
/**
|
|
* Dissolve signal context from receiver
|
|
*
|
|
* \param context context to remove from receiver
|
|
* \throw 'Context_not_associated'
|
|
*/
|
|
void dissolve(Signal_context *context);
|
|
|
|
/**
|
|
* Block until a signal is received and return the signal
|
|
*
|
|
* \return received signal
|
|
*/
|
|
Signal wait_for_signal();
|
|
|
|
/**
|
|
* Block until a signal is received
|
|
*/
|
|
void block_for_signal();
|
|
|
|
/**
|
|
* Unblock signal waiter
|
|
*/
|
|
void unblock_signal_waiter(Rpc_entrypoint &rpc_ep);
|
|
|
|
/**
|
|
* Retrieve pending signal
|
|
*
|
|
* \throw 'Signal_not_pending' no pending signal found
|
|
* \return received signal
|
|
*/
|
|
Signal pending_signal();
|
|
|
|
/**
|
|
* Locally submit signal to the receiver
|
|
*
|
|
* \noapi
|
|
*/
|
|
void local_submit(Signal::Data signal);
|
|
|
|
/**
|
|
* Framework-internal signal-dispatcher
|
|
*
|
|
* \noapi
|
|
*
|
|
* This method is called from the thread that monitors the signal
|
|
* source associated with the process. It must not be used for other
|
|
* purposes.
|
|
*/
|
|
static void dispatch_signals(Signal_source *);
|
|
};
|
|
|
|
|
|
/**
|
|
* Abstract interface to be implemented by signal dispatchers
|
|
*/
|
|
struct Genode::Signal_dispatcher_base : Signal_context
|
|
{
|
|
virtual void dispatch(unsigned num) = 0;
|
|
};
|
|
|
|
|
|
/**
|
|
* Signal dispatcher for handling signals by an object method
|
|
*
|
|
* This utility associates an object method 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 method as argument.
|
|
*
|
|
* \param T type of signal-handling class
|
|
* \param EP type of entrypoint handling signal RPC
|
|
*/
|
|
template <typename T, typename EP = Genode::Entrypoint>
|
|
class Genode::Signal_handler : public Signal_dispatcher_base
|
|
{
|
|
private:
|
|
|
|
Signal_context_capability _cap;
|
|
EP &_ep;
|
|
T &_obj;
|
|
void (T::*_member) ();
|
|
|
|
/*
|
|
* Noncopyable
|
|
*/
|
|
Signal_handler(Signal_handler const &);
|
|
Signal_handler &operator = (Signal_handler const &);
|
|
|
|
public:
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* \param ep entrypoint managing this signal RPC
|
|
* \param obj,member object and method to call when
|
|
* the signal occurs
|
|
*/
|
|
Signal_handler(EP &ep, T &obj, void (T::*member)())
|
|
:
|
|
_cap(ep.manage(*this)), _ep(ep), _obj(obj), _member(member)
|
|
{ }
|
|
|
|
~Signal_handler() { _ep.dissolve(*this); }
|
|
|
|
/**
|
|
* Interface of Signal_dispatcher_base
|
|
*/
|
|
void dispatch(unsigned) override { (_obj.*_member)(); }
|
|
|
|
operator Capability<Signal_context>() const { return _cap; }
|
|
};
|
|
|
|
|
|
/**
|
|
* Signal handler for I/O-level signals
|
|
*/
|
|
template <typename T, typename EP = Genode::Entrypoint>
|
|
struct Genode::Io_signal_handler : Signal_handler<T, EP>
|
|
{
|
|
Io_signal_handler(EP &ep, T &obj, void (T::*member)())
|
|
: Signal_handler<T, EP>(ep, obj, member)
|
|
{ Signal_context::_level = Signal_context::Level::Io; }
|
|
};
|
|
|
|
#endif /* _INCLUDE__BASE__SIGNAL_H_ */
|