summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems/include/rtems/rtems/event.h
blob: ca48ef27da3fc0f10fa1b739cb2de2935dd2f17b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
/**
 * @file rtems/rtems/event.h
 *
 * @defgroup ClassicEvent Events
 *
 * @ingroup ClassicRTEMS
 * @brief Information Related to Event Manager
 *
 * This include file contains the information pertaining to the Event
 * Manager. This manager provides a high performance method of communication
 * and synchronization.
 *
 * Directives provided are:
 *
 * - send an event set to a task
 * - receive event condition
 *
 */

/* COPYRIGHT (c) 1989-2008.
 * On-Line Applications Research Corporation (OAR).
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */

#ifndef _RTEMS_RTEMS_EVENT_H
#define _RTEMS_RTEMS_EVENT_H

#include <rtems/rtems/status.h>
#include <rtems/rtems/types.h>
#include <rtems/rtems/options.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 *  @defgroup ClassicEventSet Event Set
 *
 *  @ingroup ClassicEvent
 *
 *  @{
 */

/**
 *  @brief Integer type to hold an event set of up to 32 events represented as
 *  a bit field.
 */
typedef uint32_t   rtems_event_set;

/**
 *  @brief Constant used to send or receive all events.
 */
#define RTEMS_ALL_EVENTS  0xFFFFFFFF

/** @brief Defines the bit in the event set associated with event 0. */
#define RTEMS_EVENT_0     0x00000001
/** @brief Defines the bit in the event set associated with event 1. */
#define RTEMS_EVENT_1     0x00000002
/** @brief Defines the bit in the event set associated with event 2. */
#define RTEMS_EVENT_2     0x00000004
/** @brief Defines the bit in the event set associated with event 3. */
#define RTEMS_EVENT_3     0x00000008
/** @brief Defines the bit in the event set associated with event 4. */
#define RTEMS_EVENT_4     0x00000010
/** @brief Defines the bit in the event set associated with event 5. */
#define RTEMS_EVENT_5     0x00000020
/** @brief Defines the bit in the event set associated with event 6. */
#define RTEMS_EVENT_6     0x00000040
/** @brief Defines the bit in the event set associated with event 7. */
#define RTEMS_EVENT_7     0x00000080
/** @brief Defines the bit in the event set associated with event 8. */
#define RTEMS_EVENT_8     0x00000100
/** @brief Defines the bit in the event set associated with event 9. */
#define RTEMS_EVENT_9     0x00000200
/** @brief Defines the bit in the event set associated with event 10. */
#define RTEMS_EVENT_10    0x00000400
/** @brief Defines the bit in the event set associated with event 11. */
#define RTEMS_EVENT_11    0x00000800
/** @brief Defines the bit in the event set associated with event 12. */
#define RTEMS_EVENT_12    0x00001000
/** @brief Defines the bit in the event set associated with event 13. */
#define RTEMS_EVENT_13    0x00002000
/** @brief Defines the bit in the event set associated with event 14. */
#define RTEMS_EVENT_14    0x00004000
/** @brief Defines the bit in the event set associated with event 15. */
#define RTEMS_EVENT_15    0x00008000
/** @brief Defines the bit in the event set associated with event 16. */
#define RTEMS_EVENT_16    0x00010000
/** @brief Defines the bit in the event set associated with event 17. */
#define RTEMS_EVENT_17    0x00020000
/** @brief Defines the bit in the event set associated with event 18. */
#define RTEMS_EVENT_18    0x00040000
/** @brief Defines the bit in the event set associated with event 19. */
#define RTEMS_EVENT_19    0x00080000
/** @brief Defines the bit in the event set associated with event 20. */
#define RTEMS_EVENT_20    0x00100000
/** @brief Defines the bit in the event set associated with event 21. */
#define RTEMS_EVENT_21    0x00200000
/** @brief Defines the bit in the event set associated with event 22. */
#define RTEMS_EVENT_22    0x00400000
/** @brief Defines the bit in the event set associated with event 23. */
#define RTEMS_EVENT_23    0x00800000
/** @brief Defines the bit in the event set associated with event 24. */
#define RTEMS_EVENT_24    0x01000000
/** @brief Defines the bit in the event set associated with event 25. */
#define RTEMS_EVENT_25    0x02000000
/** @brief Defines the bit in the event set associated with event 26. */
#define RTEMS_EVENT_26    0x04000000
/** @brief Defines the bit in the event set associated with event 27. */
#define RTEMS_EVENT_27    0x08000000
/** @brief Defines the bit in the event set associated with event 29. */
#define RTEMS_EVENT_28    0x10000000
/** @brief Defines the bit in the event set associated with event 29. */
#define RTEMS_EVENT_29    0x20000000
/** @brief Defines the bit in the event set associated with event 30. */
#define RTEMS_EVENT_30    0x40000000
/** @brief Defines the bit in the event set associated with event 31. */
#define RTEMS_EVENT_31    0x80000000

/** @} */

/**
 *  @defgroup ClassicEvent Events
 *
 *  @ingroup ClassicRTEMS
 *
 *  @brief The event manager provides a high performance method of intertask
 *  communication and synchronization.
 *
 *  An event flag is used by a task (or ISR) to inform another task of the
 *  occurrence of a significant situation. Thirty-two event flags are
 *  associated with each task. A collection of one or more event flags is
 *  referred to as an event set. The data type rtems_event_set is used to
 *  manage event sets.
 *
 *  The application developer should remember the following key characteristics
 *  of event operations when utilizing the event manager:
 *
 *  - Events provide a simple synchronization facility.
 *  - Events are aimed at tasks.
 *  - Tasks can wait on more than one event simultaneously.
 *  - Events are independent of one another.
 *  - Events do not hold or transport data.
 *  - Events are not queued. In other words, if an event is sent more than once
 *    to a task before being received, the second and subsequent send
 *    operations to that same task have no effect.
 *
 *  An event set is posted when it is directed (or sent) to a task. A pending
 *  event is an event that has been posted but not received. An event condition
 *  is used to specify the event set which the task desires to receive and the
 *  algorithm which will be used to determine when the request is satisfied. An
 *  event condition is satisfied based upon one of two algorithms which are
 *  selected by the user. The @ref RTEMS_EVENT_ANY algorithm states that an
 *  event condition is satisfied when at least a single requested event is
 *  posted.  The @ref RTEMS_EVENT_ALL algorithm states that an event condition
 *  is satisfied when every requested event is posted.
 *
 *  An event set or condition is built by a bitwise or of the desired events.
 *  The set of valid events is @ref RTEMS_EVENT_0 through @ref RTEMS_EVENT_31.
 *  If an event is not explicitly specified in the set or condition, then it is
 *  not present. Events are specifically designed to be mutually exclusive,
 *  therefore bitwise or and addition operations are equivalent as long as each
 *  event appears exactly once in the event set list.
 *
 *  For example, when sending the event set consisting of @ref RTEMS_EVENT_6,
 *  @ref RTEMS_EVENT_15, and @ref RTEMS_EVENT_31, the event parameter to the
 *  rtems_event_send() directive should be @ref RTEMS_EVENT_6 |
 *  @ref RTEMS_EVENT_15 | @ref RTEMS_EVENT_31.
 *
 *  @{
 */

/**
 *  @brief Constant used to receive the set of currently pending events in
 *  rtems_event_receive().
 */
#define RTEMS_PENDING_EVENTS      0

/**
 * @brief Sends an Event Set to the Target Task
 *
 * This directive sends an event set @a event_in to the task specified by
 * @a id.
 *
 * Based upon the state of the target task, one of the following situations
 * applies. The target task is
 * - blocked waiting for events.
 * If the waiting task's input event condition is
 * - satisfied, then the task is made ready for execution.
 * - not satisfied, then the event set is posted but left pending and the
 * task remains blocked.
 * - not waiting for events.
 * - The event set is posted and left pending.
 *
 * Identical events sent to a task are not queued. In other words, the second,
 * and subsequent, posting of an event to a task before it can perform an
 * rtems_event_receive() has no effect.
 *
 * The calling task will be preempted if it has preemption enabled and a
 * higher priority task is unblocked as the result of this directive.
 *
 * Sending an event set to a global task which does not reside on the local
 * node will generate a request telling the remote node to send the event set
 * to the appropriate task.
 *
 * @param[in] id Identifier of the target task. Specifying @ref RTEMS_SELF
 * results in the event set being sent to the calling task.
 * @param[in] event_in Event set sent to the target task.
 *
 * @retval RTEMS_SUCCESSFUL Successful operation.
 * @retval RTEMS_INVALID_ID Invalid task identifier.
 */
rtems_status_code rtems_event_send (
  rtems_id        id,
  rtems_event_set event_in
);

/**
 * @brief Receives pending events.
 *
 * This directive attempts to receive the event condition specified in
 * @a event_in. If @a event_in is set to @ref RTEMS_PENDING_EVENTS, then the
 * current pending events are returned in @a event_out and left pending. The
 * @aref RTEMS_WAIT and @aref RTEMS_NO_WAIT options in the @a option_set
 * parameter are used to specify whether or not the task is willing to wait
 * for the event condition to be satisfied. The @ref RTEMS_EVENT_ANY and @ref
 * RTEMS_EVENT_ALL are used in the @a option_set parameter to specify whether
 * at least a single event or the complete event set is necessary to satisfy
 * the event condition. The @a event_out parameter is returned to the calling
 * task with the value that corresponds to the events in @a event_in that were
 * satisfied.
 *
 * A task can determine the pending event set by using a value of
 * @ref RTEMS_PENDING_EVENTS for the input event set @a event_in. The pending
 * events are returned to the calling task but the event set is left
 * unaltered.
 *
 * A task can receive all of the currently pending events by using the a value
 * of @ref RTEMS_ALL_EVENTS for the input event set @a event_in and
 * @ref RTEMS_NO_WAIT | @ref RTEMS_EVENT_ANY for the option set @a option_set.
 * The pending events are returned to the calling task and the event set is
 * cleared. If no events are pending then the @ref RTEMS_UNSATISFIED status
 * code will be returned.
 *
 * If pending events satisfy the event condition, then @a event_out is set to
 * the satisfied events and the pending events in the event condition are
 * cleared.  If the event condition is not satisfied and @ref RTEMS_NO_WAIT is
 * specified, then @a event_out is set to the currently satisfied events.  If
 * the calling task chooses to wait, then it will block waiting for the event
 * condition.
 *
 * If the calling task must wait for the event condition to be satisfied, then
 * the timeout parameter is used to specify the maximum interval to wait. If
 * it is set to @ref RTEMS_NO_TIMEOUT, then the calling task will wait forever.
 *
 * This directive only affects the events specified in @a event_in. Any
 * pending events that do not correspond to any of the events specified in
 * @a event_in will be left pending.
 *
 * A clock tick is required to support the wait with time out functionality of
 * this directive.
 *
 * @param[in] event_in Set of requested events (input events).
 * @param[in] option_set Use a bitwise or of the following options
 * - @ref RTEMS_WAIT - task will wait for event (default),
 * - @ref RTEMS_NO_WAIT - task should not wait,
 * - @ref RTEMS_EVENT_ALL - return after all events (default), and
 * - @ref RTEMS_EVENT_ANY - return after any events.
 * @param[in] ticks Time out in ticks. Use @ref RTEMS_NO_TIMEOUT to wait
 * without a time out (potentially forever).
 * @param[out] event_out Set of received events (output events).
 *
 * @retval RTEMS_SUCCESSFUL Successful operation.
 * @retval RTEMS_UNSATISFIED Input events not satisfied (only with the
 * @ref RTEMS_NO_WAIT option).
 * @retval RTEMS_INVALID_ADDRESS The @a event_out pointer is @c NULL.
 * @retval RTEMS_TIMEOUT Timed out waiting for events.
 */
rtems_status_code rtems_event_receive (
  rtems_event_set  event_in,
  rtems_option     option_set,
  rtems_interval   ticks,
  rtems_event_set *event_out
);

/** @} */

/**
 * @defgroup ClassicEventSystem System Events
 *
 * @ingroup ClassicEvent
 *
 * System events are similar to normal events.  They offer a second set of
 * events.  These events are intended for internal RTEMS use and should not be
 * used by applications (with the exception of the transient system event).
 *
 * The event @ref RTEMS_EVENT_SYSTEM_TRANSIENT is used for transient usage.
 * See also @ref ClassicEventTransient.  This event may be used by every entity
 * that fulfils its usage pattern.
 */
/**@{**/

/**
 * @brief Reserved system event for network SBWAIT usage.
 */
#define RTEMS_EVENT_SYSTEM_NETWORK_SBWAIT RTEMS_EVENT_24

/**
 * @brief Reserved system event for network SOSLEEP usage.
 */
#define RTEMS_EVENT_SYSTEM_NETWORK_SOSLEEP RTEMS_EVENT_25

/**
 * @brief Reserved system event for transient usage.
 */
#define RTEMS_EVENT_SYSTEM_TRANSIENT RTEMS_EVENT_31

/**
 * @brief See rtems_event_send().
 */
rtems_status_code rtems_event_system_send(
  rtems_id id,
  rtems_event_set event_in
);

/**
 * @brief See rtems_event_receive().
 */
rtems_status_code rtems_event_system_receive(
  rtems_event_set event_in,
  rtems_option option_set,
  rtems_interval ticks,
  rtems_event_set *event_out
);

/** @} */

/**
 * @defgroup ClassicEventTransient Transient Event
 *
 * @ingroup ClassicEvent
 *
 * The transient event can be used by a client task to issue a request to
 * another task or interrupt service (server).  The server can send the
 * transient event to the client task to notify about a request completion, see
 * rtems_event_transient_send().  The client task can wait for the transient
 * event reception with rtems_event_transient_receive().
 *
 * The user of the transient event must ensure that this event is not pending
 * once the request is finished or cancelled.  A successful reception of the
 * transient event with rtems_event_transient_receive() will clear the
 * transient event.  If a reception with timeout is used the transient event
 * state is undefined after a timeout return status.  The transient event can
 * be cleared unconditionally with the non-blocking
 * rtems_event_transient_clear().
 *
 * @msc
 *   hscale="1.6";
 *   M [label="Main Task"], IDLE [label="Idle Task"], S [label="Server"], TIME [label="System Tick Handler"];
 *   |||;
 *   --- [label="sequence with request completion"];
 *   M box M [label="prepare request\nissue request\nrtems_event_transient_receive()"];
 *   M=>>IDLE [label="blocking operation"];
 *   IDLE=>>S [label="request completion"];
 *   S box S [label="rtems_event_transient_send()"];
 *   S=>>M [label="task is ready again"];
 *   M box M [label="finish request"];
 *   |||;
 *   --- [label="sequence with early request completion"];
 *   M box M [label="prepare request\nissue request"];
 *   M=>>S [label="request completion"];
 *   S box S [label="rtems_event_transient_send()"];
 *   S=>>M [label="transient event is now pending"];
 *   M box M [label="rtems_event_transient_receive()\nfinish request"];
 *   |||;
 *   --- [label="sequence with timeout event"];
 *   M box M [label="prepare request\nissue request\nrtems_event_transient_receive()"];
 *   M=>>IDLE [label="blocking operation"];
 *   IDLE=>>TIME [label="timeout expired"];
 *   TIME box TIME [label="cancel blocking operation"];
 *   TIME=>>M [label="task is ready again"];
 *   M box M [label="cancel request\nrtems_event_transient_clear()"];
 * @endmsc
 *
 * Suppose you have a task that wants to issue a certain request and then waits
 * for request completion.  It can create a request structure and store its
 * task identifier there.  Now it can place the request on a work queue of
 * another task (or interrupt handler).  Afterwards the task waits for the
 * reception of the transient event.  Once the server task is finished with the
 * request it can send the transient event to the waiting task and wake it up.
 *
 * @code
 * #include <assert.h>
 * #include <rtems.h>
 *
 * typedef struct {
 *   rtems_id task_id;
 *   bool work_done;
 * } request;
 *
 * void server(rtems_task_argument arg)
 * {
 *   rtems_status_code sc;
 *   request *req = (request *) arg;
 *
 *   req->work_done = true;
 *
 *   sc = rtems_event_transient_send(req->task_id);
 *   assert(sc == RTEMS_SUCCESSFUL);
 *
 *   sc = rtems_task_delete(RTEMS_SELF);
 *   assert(sc == RTEMS_SUCCESSFUL);
 * }
 *
 * void issue_request_and_wait_for_completion(void)
 * {
 *   rtems_status_code sc;
 *   rtems_id id;
 *   request req;
 *
 *   req.task_id = rtems_task_self();
 *   req.work_done = false;
 *
 *   sc = rtems_task_create(
 *     rtems_build_name('S', 'E', 'R', 'V'),
 *     1,
 *     RTEMS_MINIMUM_STACK_SIZE,
 *     RTEMS_DEFAULT_MODES,
 *     RTEMS_DEFAULT_ATTRIBUTES,
 *     &id
 *   );
 *   assert(sc == RTEMS_SUCCESSFUL);
 *
 *   sc = rtems_task_start(id, server, (rtems_task_argument) &req);
 *   assert(sc == RTEMS_SUCCESSFUL);
 *
 *   sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
 *   assert(sc == RTEMS_SUCCESSFUL);
 *
 *   assert(req.work_done);
 * }
 * @endcode
 */
/**@{**/

/**
 * @brief See rtems_event_system_send().
 *
 * The system event @ref RTEMS_EVENT_SYSTEM_TRANSIENT will be sent.
 */
RTEMS_INLINE_ROUTINE rtems_status_code rtems_event_transient_send(
  rtems_id id
)
{
  return rtems_event_system_send( id, RTEMS_EVENT_SYSTEM_TRANSIENT );
}

/**
 * @brief See rtems_event_system_receive().
 *
 * The system event @ref RTEMS_EVENT_SYSTEM_TRANSIENT will be received.
 */
RTEMS_INLINE_ROUTINE rtems_status_code rtems_event_transient_receive(
  rtems_option option_set,
  rtems_interval ticks
)
{
  rtems_event_set event_out;

  return rtems_event_system_receive(
    RTEMS_EVENT_SYSTEM_TRANSIENT,
    RTEMS_EVENT_ALL | option_set,
    ticks,
    &event_out
  );
}

/**
 * @brief See rtems_event_system_receive().
 *
 * The system event @ref RTEMS_EVENT_SYSTEM_TRANSIENT will be cleared.
 */
RTEMS_INLINE_ROUTINE void rtems_event_transient_clear( void )
{
  rtems_event_set event_out;

  rtems_event_system_receive(
    RTEMS_EVENT_SYSTEM_TRANSIENT,
    RTEMS_EVENT_ALL | RTEMS_NO_WAIT,
    0,
    &event_out
  );
}

/** @} */

typedef struct {
  rtems_event_set pending_events;
} Event_Control;

#ifdef __cplusplus
}
#endif

#endif
/* end of include file */