source: rtems/cpukit/rtems/src/event.c @ a2016b99

4.104.114.84.95
Last change on this file since a2016b99 was 03f2154e, checked in by Joel Sherrill <joel.sherrill@…>, on 04/22/97 at 17:20:27

headers updated to reflect new style copyright notice as part
of switching to the modified GNU GPL.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*
2 *  Event Manager
3 *
4 *  COPYRIGHT (c) 1989-1997.
5 *  On-Line Applications Research Corporation (OAR).
6 *  Copyright assigned to U.S. Government, 1994.
7 *
8 *  The license and distribution terms for this file may in
9 *  the file LICENSE in this distribution or at
10 *  http://www.OARcorp.com/rtems/license.html.
11 *
12 *  $Id$
13 */
14
15#include <rtems/system.h>
16#include <rtems/rtems/status.h>
17#include <rtems/rtems/event.h>
18#include <rtems/score/isr.h>
19#include <rtems/score/object.h>
20#include <rtems/rtems/options.h>
21#include <rtems/score/states.h>
22#include <rtems/score/thread.h>
23#include <rtems/rtems/tasks.h>
24
25/*PAGE
26 *
27 *  _Event_Manager_initialization
28 *
29 *  DESCRIPTION:
30 *
31 *  This routine performs the initialization necessary for this manager.
32 */
33 
34void _Event_Manager_initialization( void )
35{
36  _Event_Sync_state = EVENT_SYNC_SYNCHRONIZED;
37 
38  /*
39   *  Register the MP Process Packet routine.
40   */
41 
42  _MPCI_Register_packet_processor( MP_PACKET_EVENT, _Event_MP_Process_packet );
43}
44
45/*PAGE
46 *
47 *  rtems_event_send
48 *
49 *  This directive allows a thread send an event set to another thread.
50 *
51 *  Input parameters:
52 *    id    - thread id
53 *    event - event set
54 *
55 *  Output parameters:
56 *    RTEMS_SUCCESSFUL - if successful
57 *    error code - if unsuccessful
58 */
59
60rtems_status_code rtems_event_send(
61  Objects_Id         id,
62  rtems_event_set event_in
63)
64{
65  register Thread_Control *the_thread;
66  Objects_Locations        location;
67  RTEMS_API_Control       *api;
68
69  the_thread = _Thread_Get( id, &location );
70  switch ( location ) {
71    case OBJECTS_ERROR:
72      return RTEMS_INVALID_ID;
73    case OBJECTS_REMOTE:
74      return(
75        _Event_MP_Send_request_packet(
76          EVENT_MP_SEND_REQUEST,
77          id,
78          event_in
79        )
80      );
81    case OBJECTS_LOCAL:
82      api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
83      _Event_sets_Post( event_in, &api->pending_events );
84      _Event_Surrender( the_thread );
85      _Thread_Enable_dispatch();
86      return RTEMS_SUCCESSFUL;
87  }
88
89  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
90}
91
92/*PAGE
93 *
94 *  rtems_event_receive
95 *
96 *  This directive allows a thread to receive a set of events.
97 *
98 *  Input parameters:
99 *    event_in   - input event condition
100 *    option_set - options
101 *    ticks      - number of ticks to wait (0 means wait forever)
102 *    event_out  - pointer to output event set
103 *
104 *  Output parameters:
105 *    event out         - event set
106 *    RTEMS_SUCCESSFUL - if successful
107 *    error code        - if unsuccessful
108 */
109
110rtems_status_code rtems_event_receive(
111  rtems_event_set  event_in,
112  rtems_option     option_set,
113  rtems_interval   ticks,
114  rtems_event_set *event_out
115)
116{
117  RTEMS_API_Control       *api;
118
119  api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
120
121  if ( _Event_sets_Is_empty( event_in ) ) {
122    *event_out = api->pending_events;
123    return RTEMS_SUCCESSFUL;
124  }
125
126  _Thread_Disable_dispatch();
127  _Event_Seize( event_in, option_set, ticks, event_out );
128  _Thread_Enable_dispatch();
129  return( _Thread_Executing->Wait.return_code );
130}
131
132
133/*PAGE
134 *
135 *  _Event_Seize
136 *
137 *  This routine attempts to satisfy the requested event condition
138 *  for the running thread.
139 *
140 *  Input parameters:
141 *    event_in   - the event condition to satisfy
142 *    option_set - acquire event options
143 *    ticks      - interval to wait
144 *    event_out  - pointer to event set output area
145 *
146 *  Output parameters: NONE
147 *    *event_out - event set output area filled in
148 *
149 *  INTERRUPT LATENCY:
150 *    available
151 *    wait
152 *    check sync
153 */
154
155void _Event_Seize(
156  rtems_event_set  event_in,
157  rtems_option     option_set,
158  rtems_interval   ticks,
159  rtems_event_set *event_out
160)
161{
162  Thread_Control    *executing;
163  rtems_event_set    seized_events;
164  rtems_event_set    pending_events;
165  ISR_Level          level;
166  RTEMS_API_Control  *api;
167  Event_Sync_states   sync_state;
168
169  executing = _Thread_Executing;
170  executing->Wait.return_code = RTEMS_SUCCESSFUL;
171
172  api = executing->API_Extensions[ THREAD_API_RTEMS ];
173
174  _ISR_Disable( level );
175  pending_events = api->pending_events;
176  seized_events  = _Event_sets_Get( pending_events, event_in );
177
178  if ( !_Event_sets_Is_empty( seized_events ) &&
179       (seized_events == event_in || _Options_Is_any( option_set )) ) {
180    api->pending_events =
181      _Event_sets_Clear( pending_events, seized_events );
182    _ISR_Enable( level );
183    *event_out = seized_events;
184    return;
185  }
186
187  if ( _Options_Is_no_wait( option_set ) ) {
188    _ISR_Enable( level );
189    executing->Wait.return_code = RTEMS_UNSATISFIED;
190    *event_out = seized_events;
191    return;
192  }
193
194  _Event_Sync_state = EVENT_SYNC_NOTHING_HAPPENED;
195
196  executing->Wait.option            = (unsigned32) option_set;
197  executing->Wait.count             = (unsigned32) event_in;
198  executing->Wait.return_argument   = event_out;
199
200  _ISR_Enable( level );
201
202  if ( ticks ) {
203    _Watchdog_Initialize(
204      &executing->Timer,
205      _Event_Timeout,
206      executing->Object.id,
207      NULL
208    );
209    _Watchdog_Insert_ticks( &executing->Timer, ticks );
210  }
211
212  _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT );
213
214  _ISR_Disable( level );
215
216  sync_state = _Event_Sync_state;
217  _Event_Sync_state = EVENT_SYNC_SYNCHRONIZED;
218
219  switch ( sync_state ) {
220    case EVENT_SYNC_SYNCHRONIZED:
221      /*
222       *  This cannot happen.  It indicates that this routine did not
223       *  enter the synchronization states above.
224       */
225      return;
226
227    case EVENT_SYNC_NOTHING_HAPPENED:
228      _ISR_Enable( level );
229      return;
230
231    case EVENT_SYNC_TIMEOUT:
232      executing->Wait.return_code = RTEMS_TIMEOUT;
233      _ISR_Enable( level );
234      _Thread_Unblock( executing );
235      return;
236
237    case EVENT_SYNC_SATISFIED:
238      if ( _Watchdog_Is_active( &executing->Timer ) ) {
239        _Watchdog_Deactivate( &executing->Timer );
240        _ISR_Enable( level );
241        (void) _Watchdog_Remove( &executing->Timer );
242      } else
243        _ISR_Enable( level );
244      _Thread_Unblock( executing );
245      return;
246  }
247}
248
249/*PAGE
250 *
251 *  _Event_Surrender
252 *
253 *  This routines remove a thread from the specified threadq.
254 *
255 *  Input parameters:
256 *    the_thread - pointer to thread to be dequeued
257 *
258 *  Output parameters: NONE
259 *
260 *  INTERRUPT LATENCY:
261 *    before flash
262 *    after flash
263 *    check sync
264 */
265
266void _Event_Surrender(
267  Thread_Control *the_thread
268)
269{
270  ISR_Level           level;
271  rtems_event_set     pending_events;
272  rtems_event_set     event_condition;
273  rtems_event_set     seized_events;
274  rtems_option        option_set;
275  RTEMS_API_Control  *api;
276
277  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
278
279  option_set = (rtems_option) the_thread->Wait.option;
280
281  _ISR_Disable( level );
282  pending_events  = api->pending_events;
283  event_condition = (rtems_event_set) the_thread->Wait.count;
284
285  seized_events = _Event_sets_Get( pending_events, event_condition );
286
287  if ( !_Event_sets_Is_empty( seized_events ) ) {
288    if ( _States_Is_waiting_for_event( the_thread->current_state ) ) {
289      if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
290        api->pending_events =
291           _Event_sets_Clear( pending_events, seized_events );
292        *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
293
294        _ISR_Flash( level );
295
296        if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
297          _ISR_Enable( level );
298          _Thread_Unblock( the_thread );
299        }
300        else {
301          _Watchdog_Deactivate( &the_thread->Timer );
302          _ISR_Enable( level );
303          (void) _Watchdog_Remove( &the_thread->Timer );
304          _Thread_Unblock( the_thread );
305        }
306        return;
307      }
308    }
309
310    switch ( _Event_Sync_state ) {
311      case EVENT_SYNC_SYNCHRONIZED:
312      case EVENT_SYNC_SATISFIED:
313        break;
314 
315      case EVENT_SYNC_NOTHING_HAPPENED:
316      case EVENT_SYNC_TIMEOUT:
317        if ( !_Thread_Is_executing( the_thread ) )
318          break;
319
320        if ( seized_events == event_condition || _Options_Is_any(option_set) ) {
321          api->pending_events =
322               _Event_sets_Clear( pending_events,seized_events );
323          *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
324          _Event_Sync_state = EVENT_SYNC_SATISFIED;
325        }
326        break;
327    }
328  }
329  _ISR_Enable( level );
330}
331
332/*PAGE
333 *
334 *  _Event_Timeout
335 *
336 *  This routine processes a thread which timeouts while waiting to
337 *  receive an event_set. It is called by the watchdog handler.
338 *
339 *  Input parameters:
340 *    id - thread id
341 *
342 *  Output parameters: NONE
343 */
344
345void _Event_Timeout(
346  Objects_Id  id,
347  void       *ignored
348)
349{
350  Thread_Control *the_thread;
351  Objects_Locations      location;
352
353  the_thread = _Thread_Get( id, &location );
354  switch ( location ) {
355    case OBJECTS_ERROR:
356    case OBJECTS_REMOTE:  /* impossible */
357      break;
358    case OBJECTS_LOCAL:
359 
360      /*
361       *  If the event manager is not synchronized, then it is either
362       *  "nothing happened", "timeout", or "satisfied".   If the_thread
363       *  is the executing thread, then it is in the process of blocking
364       *  and it is the thread which is responsible for the synchronization
365       *  process.
366       *
367       *  If it is not satisfied, then it is "nothing happened" and
368       *  this is the "timeout" transition.  After a request is satisfied,
369       *  a timeout is not allowed to occur.
370       */
371
372      if ( _Event_Sync_state != EVENT_SYNC_SYNCHRONIZED &&
373           _Thread_Is_executing( the_thread ) ) {
374        if ( _Event_Sync_state != EVENT_SYNC_SATISFIED )
375          _Event_Sync_state = EVENT_SYNC_TIMEOUT;
376      } else {
377        the_thread->Wait.return_code = RTEMS_TIMEOUT;
378        _Thread_Unblock( the_thread );
379      }
380      _Thread_Unnest_dispatch();
381      break;
382  }
383}
Note: See TracBrowser for help on using the repository browser.