source: rtems/c/src/exec/rtems/src/event.c @ 97e2729d

4.104.114.84.95
Last change on this file since 97e2729d was 97e2729d, checked in by Joel Sherrill <joel.sherrill@…>, on 11/23/98 at 17:38:09

Added --disable-multiprocessing flag and modified a lot of files to make
it work.

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