diff options
Diffstat (limited to 'cpukit/rtems')
-rw-r--r-- | cpukit/rtems/Makefile.am | 2 | ||||
-rw-r--r-- | cpukit/rtems/include/rtems/rtems/event.h | 203 | ||||
-rw-r--r-- | cpukit/rtems/include/rtems/rtems/tasks.h | 2 | ||||
-rw-r--r-- | cpukit/rtems/src/event.c | 1 | ||||
-rw-r--r-- | cpukit/rtems/src/systemeventreceive.c | 68 | ||||
-rw-r--r-- | cpukit/rtems/src/systemeventsend.c | 65 | ||||
-rw-r--r-- | cpukit/rtems/src/tasks.c | 2 |
7 files changed, 343 insertions, 0 deletions
diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am index bbf861177e..ff3174ebbc 100644 --- a/cpukit/rtems/Makefile.am +++ b/cpukit/rtems/Makefile.am @@ -209,6 +209,8 @@ librtems_a_SOURCES += src/eventsend.c librtems_a_SOURCES += src/eventsurrender.c librtems_a_SOURCES += src/eventtimeout.c librtems_a_SOURCES += src/eventdata.c +librtems_a_SOURCES += src/systemeventsend.c +librtems_a_SOURCES += src/systemeventreceive.c ## SIGNAL_C_FILES librtems_a_SOURCES += src/signal.c diff --git a/cpukit/rtems/include/rtems/rtems/event.h b/cpukit/rtems/include/rtems/rtems/event.h index 381b328de2..b8d9987848 100644 --- a/cpukit/rtems/include/rtems/rtems/event.h +++ b/cpukit/rtems/include/rtems/rtems/event.h @@ -207,6 +207,207 @@ rtems_status_code rtems_event_receive ( /** @} */ /** + * @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 transient usage. + */ +#define RTEMS_EVENT_SYSTEM_TRANSIENT RTEMS_EVENT_0 + +/** + * @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\ncall rtems_event_transient_receive()"]; + * M=>>IDLE [label="blocking operation"]; + * IDLE=>>S [label="request completion"]; + * S box S [label="call 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="call rtems_event_transient_send()"]; + * S=>>M [label="transient event is now pending"]; + * M box M [label="call rtems_event_transient_receive()\nfinish request"]; + * |||; + * --- [label="sequence with timeout event"]; + * M box M [label="prepare request\nissue request\ncall rtems_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\ncall rtems_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 + ); +} + +/** @} */ + +/** * @defgroup ScoreEvent Event Handler * * @ingroup Score @@ -252,6 +453,8 @@ void _Event_Timeout( RTEMS_EVENT_EXTERN Thread_blocking_operation_States _Event_Sync_state; +RTEMS_EVENT_EXTERN Thread_blocking_operation_States _System_event_Sync_state; + /** @} */ #if defined(RTEMS_MULTIPROCESSING) diff --git a/cpukit/rtems/include/rtems/rtems/tasks.h b/cpukit/rtems/include/rtems/rtems/tasks.h index d11e0bc522..f141c102e6 100644 --- a/cpukit/rtems/include/rtems/rtems/tasks.h +++ b/cpukit/rtems/include/rtems/rtems/tasks.h @@ -212,6 +212,8 @@ typedef struct { typedef struct { /** This field contains the event control for this task. */ Event_Control Event; + /** This field contains the system event control for this task. */ + Event_Control System_event; /** This field contains the Classic API Signal information for this task. */ ASR_Information Signal; /** diff --git a/cpukit/rtems/src/event.c b/cpukit/rtems/src/event.c index ed148e8b37..d5c29f6a3e 100644 --- a/cpukit/rtems/src/event.c +++ b/cpukit/rtems/src/event.c @@ -34,6 +34,7 @@ void _Event_Manager_initialization( void ) { _Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; + _System_event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; /* * Register the MP Process Packet routine. diff --git a/cpukit/rtems/src/systemeventreceive.c b/cpukit/rtems/src/systemeventreceive.c new file mode 100644 index 0000000000..43f2bec048 --- /dev/null +++ b/cpukit/rtems/src/systemeventreceive.c @@ -0,0 +1,68 @@ +/** + * @file + * + * @ingroup ClassicEventSystem + * + * @brief rtems_event_system_receive() implementation. + */ + +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/rtems/event.h> +#include <rtems/rtems/tasks.h> + +rtems_status_code rtems_event_system_receive( + rtems_event_set event_in, + rtems_option option_set, + rtems_interval ticks, + rtems_event_set *event_out +) +{ + rtems_status_code sc; + + if ( event_out != NULL ) { + Thread_Control *executing = _Thread_Executing; + RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ]; + Event_Control *event = &api->System_event; + + if ( !_Event_sets_Is_empty( event_in ) ) { + _Thread_Disable_dispatch(); + _Event_Seize( + event_in, + option_set, + ticks, + event_out, + executing, + event, + &_System_event_Sync_state, + STATES_WAITING_FOR_SYSTEM_EVENT + ); + _Thread_Enable_dispatch(); + + sc = executing->Wait.return_code; + } else { + *event_out = event->pending_events; + sc = RTEMS_SUCCESSFUL; + } + } else { + sc = RTEMS_INVALID_ADDRESS; + } + + return sc; +} diff --git a/cpukit/rtems/src/systemeventsend.c b/cpukit/rtems/src/systemeventsend.c new file mode 100644 index 0000000000..13d31ccf85 --- /dev/null +++ b/cpukit/rtems/src/systemeventsend.c @@ -0,0 +1,65 @@ +/** + * @file + * + * @ingroup ClassicEventSystem + * + * @brief rtems_event_system_send() implementation. + */ + +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/rtems/event.h> +#include <rtems/rtems/tasks.h> + +rtems_status_code rtems_event_system_send( + rtems_id id, + rtems_event_set event_in +) +{ + rtems_status_code sc; + Thread_Control *thread; + Objects_Locations location; + RTEMS_API_Control *api; + + thread = _Thread_Get( id, &location ); + switch ( location ) { + case OBJECTS_LOCAL: + api = thread->API_Extensions[ THREAD_API_RTEMS ]; + _Event_Surrender( + thread, + event_in, + &api->System_event, + &_System_event_Sync_state, + STATES_WAITING_FOR_SYSTEM_EVENT + ); + _Thread_Enable_dispatch(); + sc = RTEMS_SUCCESSFUL; + break; +#ifdef RTEMS_MULTIPROCESSING + case OBJECTS_REMOTE: + sc = RTEMS_ILLEGAL_ON_REMOTE_OBJECT; + break; +#endif + default: + sc = RTEMS_INVALID_ID; + break; + } + + return sc; +} diff --git a/cpukit/rtems/src/tasks.c b/cpukit/rtems/src/tasks.c index 325eba0546..c679f1e6f2 100644 --- a/cpukit/rtems/src/tasks.c +++ b/cpukit/rtems/src/tasks.c @@ -65,6 +65,7 @@ static bool _RTEMS_tasks_Create_extension( created->API_Extensions[ THREAD_API_RTEMS ] = api; _Event_Initialize( &api->Event ); + _Event_Initialize( &api->System_event ); _ASR_Initialize( &api->Signal ); created->task_variables = NULL; @@ -93,6 +94,7 @@ static void _RTEMS_tasks_Start_extension( api = started->API_Extensions[ THREAD_API_RTEMS ]; _Event_Initialize( &api->Event ); + _Event_Initialize( &api->System_event ); } /* |