1  /*
   2   * \brief  Delivery and reception of asynchronous notifications
   3   * \author Norman Feske
   4   * \date   2008-09-05
   5   *
   6   * Each transmitter sends signals to one fixed destination.
   7   * A receiver can receive signals from multiple sources.
   8   */

   9  
  10  /*
  11   * Copyright (C) 2008-2013 Genode Labs GmbH
  12   *
  13   * This file is part of the Genode OS framework, which is distributed
  14   * under the terms of the GNU General Public License version 2.
  15   */

  16  
  17  #ifndef _INCLUDE__BASE__SIGNAL_H_
  18  #define _INCLUDE__BASE__SIGNAL_H_
  19  
  20  #include <util/noncopyable.h>
  21  #include <util/list.h>
  22  #include <base/semaphore.h>
  23  #include <base/capability.h>
  24  
  25  /* only needed for base-hw */
  26  namespace Kernel { struct Signal_receiver; }
  27  
  28  namespace Genode {
  29  
  30     class Signal_source;
  31  
  32     class Signal_receiver;
  33     class Signal_context;
  34     class Signal_context_registry;
  35     class Signal_transmitter;
  36     class Signal;
  37     class Signal_dispatcher_base;
  38  
  39     template <typename>           class Signal_dispatcher;
  40     template <typename, typename> class Signal_handler;
  41  
  42     typedef Capability<Signal_context> Signal_context_capability;
  43  }

  44  
  45  
  46  /**
  47   * Signal
  48   *
  49   * A signal represents a number of asynchronous notifications produced by
  50   * one transmitter. If notifications are generated at a higher rate than as
  51   * they can be processed at the receiver, the transmitter counts the
  52   * notifications and delivers the total amount with the next signal
  53   * transmission. This way, the total number of notifications gets properly
  54   * communicated to the receiver even if the receiver is not highly
  55   * responsive.
  56   *
  57   * Asynchronous notifications do not carry any payload because this payload
  58   * would need to be queued at the transmitter. However, each transmitter
  59   * imprints a signal-context reference into each signal. This context
  60   * can be used by the receiver to distinguish signals coming from different
  61   * transmitters.
  62   */

  63  class Genode::Signal
  64  {
  65     private:
  66  
  67        struct Data
  68        {
  69           Signal_context *context;
  70           unsigned        num;
  71  
  72           /**
  73            * Constructor
  74            *
  75            * \param context  signal context specific for the
  76            *                 signal-receiver capability used for signal
  77            *                 transmission
  78            * \param num      number of signals received from the same
  79            *                 transmitter
  80            */

  81           Data(Signal_context *context, unsigned num)
  82           : context(context), num(num) { }

  83  
  84           /**
  85            * Default constructor, representing an invalid signal
  86            */

  87           Data() : context(0), num(0) { }

  88  
  89        }
 _data;

  90  
  91        /**
  92         * Constructor
  93         *
  94         * Signal objects are constructed by signal receivers only.
  95         */

  96        Signal(Data data);

  97  
  98        friend class Kernel::Signal_receiver;
  99        friend class Signal_receiver;
 100        friend class Signal_context;
 101  
 102        void _dec_ref_and_unlock();
 103        void _inc_ref();

 104  
 105     public:
 106  
 107        Signal(Signal const &other);
 108  
 109        /**
 110         * \noapi
 111         */

 112        Signal &operator = (Signal const &other);

 113  
 114        ~Signal();
 115  
 116        Signal_context *context()       { return _data.context; }
 117        unsigned        num()     const { return _data.num; }

 118  }
;

 119  
 120  
 121  /**
 122   * Signal transmitter
 123   *
 124   * Each signal-transmitter instance acts on behalf the context specified
 125   * as constructor argument. Therefore, the resources needed for the
 126   * transmitter such as the consumed memory `sizeof(Signal_transmitter)`
 127   * should be accounted to the owner of the context.
 128   */

 129  class Genode::Signal_transmitter
 130  {
 131     private:
 132  
 133        Signal_context_capability _context;  /* destination */

 134  
 135     public:
 136  
 137        /**
 138         * Constructor
 139         *
 140         * \param context  capability to signal context that is going to
 141         *                 receive signals produced by the transmitter
 142         */

 143        Signal_transmitter(Signal_context_capability context = Signal_context_capability());

 144  
 145        /**
 146         * Set signal context
 147         */

 148        void context(Signal_context_capability context);

 149  
 150  
 151        /**
 152         * Return signal context
 153         */

 154        Signal_context_capability context();

 155  
 156  
 157        /**
 158         * Trigger signal submission to context
 159         *
 160         * \param cnt  number of signals to submit at once
 161         */

 162        void submit(unsigned cnt = 1);

 163  }
;

 164  
 165  
 166  /**
 167   * Signal receiver
 168   */

 169  class Genode::Signal_receiver : Noncopyable
 170  {
 171     private:
 172  
 173        /**
 174         * Semaphore used to indicate that signal(s) are ready to be picked
 175         * up. This is needed for platforms other than `base-hw` only.
 176         */

 177        Semaphore _signal_available;
 178  
 179        /**
 180         * Provides the kernel-object name via the `dst` method. This is
 181         * needed for `base-hw` only.
 182         */

 183        Capability<Signal_source> _cap;
 184  
 185        /**
 186         * List of associated contexts
 187         */

 188        Lock                                _contexts_lock;
 189        List<List_element<Signal_context> > _contexts;
 190  
 191        /**
 192         * Helper to dissolve given context
 193         *
 194         * This method prevents duplicated code in `~Signal_receiver`
 195         * and `dissolve`. Note that `_contexts_lock` must be held when
 196         * calling this method.
 197         */

 198        void _unsynchronized_dissolve(Signal_context *context);

 199  
 200        /**
 201         * Hook to platform specific destructor parts
 202         */

 203        void _platform_destructor();

 204  
 205        /**
 206         * Hooks to platform specific dissolve parts
 207         */

 208        void _platform_begin_dissolve(Signal_context * const c);

 209        void _platform_finish_dissolve(Signal_context * const c);

 210  
 211     public:
 212  
 213        /**
 214         * Exception class
 215         */

 216        class Context_already_in_use { };

 217        class Context_not_associated { };
 218        class Signal_not_pending     { };
 219  
 220        /**
 221         * Constructor
 222         */

 223        Signal_receiver();

 224  
 225        /**
 226         * Destructor
 227         */

 228        ~Signal_receiver();

 229  
 230        /**
 231         * Manage signal context and return new signal-context capability
 232         *
 233         * \param context  context associated with signals delivered to the
 234         *                 receiver
 235         * \throw          `Context_already_in_use`
 236         * \return         new signal-context capability that can be
 237         *                 passed to a signal transmitter
 238         */

 239        Signal_context_capability manage(Signal_context *context);

 240  
 241        /**
 242         * Dissolve signal context from receiver
 243         *
 244         * \param context  context to remove from receiver
 245         * \throw          `Context_not_associated`
 246         */

 247        void dissolve(Signal_context *context);

 248  
 249        /**
 250         * Return true if signal was received
 251         */

 252        bool pending();

 253  
 254        /**
 255         * Block until a signal is received and return the signal
 256         *
 257         * \return received signal
 258         */

 259        Signal wait_for_signal();

 260  
 261        /**
 262         * Block until a signal is received
 263         */

 264        void block_for_signal();

 265  
 266        /**
 267         * Retrieve  pending signal
 268         *
 269         * \throw   `Signal_not_pending` no pending signal found
 270         * \return  received signal
 271         */

 272        Signal pending_signal();

 273  
 274        /**
 275         * Locally submit signal to the receiver
 276         *
 277         * \noapi
 278         */

 279        void local_submit(Signal::Data signal);

 280  
 281        /**
 282         * Framework-internal signal-dispatcher
 283         *
 284         * \noapi
 285         *
 286         * This method is called from the thread that monitors the signal
 287         * source associated with the process. It must not be used for other
 288         * purposes.
 289         */

 290        static void dispatch_signals(Signal_source *);

 291  }
;

 292  
 293  
 294  /**
 295   * Signal context
 296   *
 297   * A signal context is a destination for signals. One receiver can listen
 298   * to multple contexts. If a signal arrives, the context is provided with the
 299   * signal. This enables the receiver to distinguish different signal sources
 300   * and dispatch incoming signals context-specific.
 301   */

 302  class Genode::Signal_context
 303  {
 304     private:
 305  
 306        /**
 307         * List element in `Signal_receiver`
 308         */

 309        List_element<Signal_context> _receiver_le;
 310  
 311        /**
 312         * List element in process-global registry
 313         */

 314        List_element<Signal_context> _registry_le;
 315  
 316        /**
 317         * Receiver to which the context is associated with
 318         *
 319         * This member is initialized by the receiver when associating
 320         * the context with the receiver via the `cap` method.
 321         */

 322        Signal_receiver *_receiver;
 323  
 324        Lock         _lock;          /* protect `_curr_signal`         */
 325        Signal::Data _curr_signal;   /* most-currently received signal */
 326        bool         _pending;       /* current signal is valid        */
 327        unsigned int _ref_cnt;       /* number of references to this context */
 328        Lock         _destroy_lock;  /* prevent destruction while the
 329                                        context is in use */

 330  
 331        /**
 332         * Capability assigned to this context after being assocated with
 333         * a `Signal_receiver` via the `manage` method. We store this
 334         * capability in the `Signal_context` for the mere reason to
 335         * properly destruct the context (see `_unsynchronized_dissolve`).
 336         */

 337        Signal_context_capability _cap;
 338  
 339        friend class Signal;
 340        friend class Signal_receiver;
 341        friend class Signal_context_registry;

 342  
 343     public:
 344  
 345        /**
 346         * Constructor
 347         */

 348        Signal_context()
 349        : _receiver_le(this), _registry_le(this),
 350          _receiver(0), _pending(0), _ref_cnt(0)
 { }

 351  
 352        /**
 353         * Destructor
 354         *
 355         * The virtual destructor is just there to generate a vtable for
 356         * signal-context objects such that signal contexts can be dynamically
 357         * casted.
 358         */

 359        virtual ~Signal_context();

 360  
 361        /**
 362         * Local signal submission (DEPRECATED)
 363         *
 364         * \noapi
 365         *
 366         * Trigger local signal submission (within the same address space), the
 367         * context has to be bound to a sginal receiver beforehand.
 368         *
 369         * \param num  number of pending signals
 370         */

 371        void submit(unsigned num);

 372  
 373        /*
 374         * Signal contexts are never invoked but only used as arguments for
 375         * `Signal_session` methods. Hence, there exists a capability
 376         * type for it but no real RPC interface.
 377         */

 378        GENODE_RPC_INTERFACE();
 379  }
;

 380  
 381  
 382  /**
 383   * Abstract interface to be implemented by signal dispatchers
 384   */

 385  struct Genode::Signal_dispatcher_base : Signal_context
 386  {
 387     virtual void dispatch(unsigned num) = 0;
 388  }
;

 389  
 390  
 391  /**
 392   * Adapter for directing signals to object methods
 393   *
 394   * This utility associates object methods with signals. It is intended to
 395   * be used as a member variable of the class that handles incoming signals
 396   * of a certain type. The constructor takes a pointer-to-member to the
 397   * signal handling method as argument. If a signal is received at the
 398   * common signal reception code, this method will be invoked by calling
 399   * `Signal_dispatcher_base::dispatch`.
 400   *
 401   * \param T  type of signal-handling class
 402   */

 403  template <typename T>
 404  class Genode::Signal_dispatcher : public Signal_dispatcher_base,
 405                                    public  Signal_context_capability

 406  {
 407     private:
 408  
 409        &obj;
 410        void (T::*member) (unsigned);
 411        Signal_receiver &sig_rec;

 412  
 413     public:
 414  
 415        /**
 416         * Constructor
 417         *
 418         * \param sig_rec     signal receiver to associate the signal
 419         *                    handler with
 420         * \param obj,member  object and method to call when
 421         *                    the signal occurs
 422         */

 423        Signal_dispatcher(Signal_receiver &sig_rec,
 424                          &obj, void (T::*member)(unsigned))

 425        :
 426           Signal_context_capability(sig_rec.manage(this)),
 427           obj(obj), member(member),
 428           sig_rec(sig_rec)

 429        { }

 430  
 431        ~Signal_dispatcher() { sig_rec.dissolve(this); }
 432  
 433        void dispatch(unsigned num) { (obj.*member)(num); }

 434  }
;

 435  
 436  #endif /* _INCLUDE__BASE__SIGNAL_H_ */