/** * @file * * @ingroup ClassicEvent * * @brief Classic Event Manager API */ /* 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 #include #include #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 RTEMSAPIClassic * * @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 * @ref RTEMS_WAIT and @ref 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 network socket close. */ #define RTEMS_EVENT_SYSTEM_NETWORK_CLOSE RTEMS_EVENT_26 /** * @brief Reserved system event to resume server threads, e.g timer or * interrupt server. */ #define RTEMS_EVENT_SYSTEM_SERVER_RESUME RTEMS_EVENT_29 /** * @brief Reserved system event for the server threads, e.g timer or interrupt * server. */ #define RTEMS_EVENT_SYSTEM_SERVER RTEMS_EVENT_30 /** * @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 * #include * * 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); * * rtems_task_exit(); * } * * 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 ); } /** @} */ #ifdef __cplusplus } #endif #endif /* end of include file */