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
T &
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
T &
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_ */