source: rtems/cpukit/rtems/src/eventsurrender.c @ 9eb056f

4.115
Last change on this file since 9eb056f was 9eb056f, checked in by Sebastian Huber <sebastian.huber@…>, on 05/11/15 at 13:11:00

rtems: Avoid Giant lock for events

  • Property mode set to 100644
File size: 3.2 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Surrender Event
5 *  @ingroup ClassicEvent
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2008.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18  #include "config.h"
19#endif
20
21#include <rtems/rtems/eventimpl.h>
22#include <rtems/rtems/optionsimpl.h>
23#include <rtems/score/threadimpl.h>
24#include <rtems/score/watchdogimpl.h>
25
26static void _Event_Satisfy(
27  Thread_Control  *the_thread,
28  Event_Control   *event,
29  rtems_event_set  pending_events,
30  rtems_event_set  seized_events
31)
32{
33  event->pending_events = _Event_sets_Clear( pending_events, seized_events );
34  *(rtems_event_set *) the_thread->Wait.return_argument = seized_events;
35}
36
37static bool _Event_Is_satisfied(
38  const Thread_Control *the_thread,
39  rtems_event_set       pending_events,
40  rtems_event_set      *seized_events
41)
42{
43  rtems_option    option_set;
44  rtems_event_set event_condition;
45
46  option_set = the_thread->Wait.option;
47  event_condition = the_thread->Wait.count;
48  *seized_events = _Event_sets_Get( pending_events, event_condition );
49
50  return !_Event_sets_Is_empty( *seized_events )
51    && ( *seized_events == event_condition || _Options_Is_any( option_set ) );
52}
53
54void _Event_Surrender(
55  Thread_Control    *the_thread,
56  rtems_event_set    event_in,
57  Event_Control     *event,
58  Thread_Wait_flags  wait_class,
59  ISR_lock_Context  *lock_context
60)
61{
62  rtems_event_set   pending_events;
63  rtems_event_set   seized_events;
64  Thread_Wait_flags wait_flags;
65  bool              unblock;
66
67  _Thread_Lock_acquire_default_critical( the_thread, lock_context );
68
69  _Event_sets_Post( event_in, &event->pending_events );
70  pending_events = event->pending_events;
71
72  wait_flags = _Thread_Wait_flags_get( the_thread );
73
74  if (
75    ( wait_flags & THREAD_WAIT_CLASS_MASK ) == wait_class
76      && _Event_Is_satisfied( the_thread, pending_events, &seized_events )
77  ) {
78    Thread_Wait_flags intend_to_block;
79    Thread_Wait_flags blocked;
80    bool success;
81
82    intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
83    blocked = wait_class | THREAD_WAIT_STATE_BLOCKED;
84
85    success = _Thread_Wait_flags_try_change_critical(
86      the_thread,
87      intend_to_block,
88      wait_class | THREAD_WAIT_STATE_READY_AGAIN
89    );
90    if ( success ) {
91      _Event_Satisfy( the_thread, event, pending_events, seized_events );
92      unblock = false;
93    } else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
94      _Event_Satisfy( the_thread, event, pending_events, seized_events );
95      _Thread_Wait_flags_set(
96        the_thread,
97        wait_class | THREAD_WAIT_STATE_READY_AGAIN
98      );
99      unblock = true;
100    } else {
101      unblock = false;
102    }
103  } else {
104    unblock = false;
105  }
106
107  if ( unblock ) {
108    Per_CPU_Control *cpu_self;
109
110    cpu_self = _Thread_Dispatch_disable_critical( lock_context );
111    _Thread_Lock_release_default( the_thread, lock_context );
112
113    _Watchdog_Remove_ticks( &the_thread->Timer );
114    _Thread_Unblock( the_thread );
115
116    _Thread_Dispatch_enable( cpu_self );
117  } else {
118    _Thread_Lock_release_default( the_thread, lock_context );
119  }
120}
Note: See TracBrowser for help on using the repository browser.