source: rtems/cpukit/rtems/src/eventsurrender.c @ 7d6e94b

4.115
Last change on this file since 7d6e94b was 7d6e94b, checked in by Sebastian Huber <sebastian.huber@…>, on 03/04/15 at 07:02:19

score: Implement fine-grained locking for events

Use the ISR lock of the thread object to protect the event state and
use the Giant lock only for the blocking operations.

Update #2273.

  • 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  _Event_sets_Post( event_in, &event->pending_events );
68  pending_events = event->pending_events;
69
70  wait_flags = _Thread_Wait_flags_get( the_thread );
71
72  if (
73    ( wait_flags & THREAD_WAIT_CLASS_MASK ) == wait_class
74      && _Event_Is_satisfied( the_thread, pending_events, &seized_events )
75  ) {
76    Thread_Wait_flags intend_to_block;
77    Thread_Wait_flags blocked;
78    bool success;
79
80    intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
81    blocked = wait_class | THREAD_WAIT_STATE_BLOCKED;
82
83    success = _Thread_Wait_flags_try_change_critical(
84      the_thread,
85      intend_to_block,
86      wait_class | THREAD_WAIT_STATE_INTERRUPT_SATISFIED
87    );
88    if ( success ) {
89      _Event_Satisfy( the_thread, event, pending_events, seized_events );
90      unblock = false;
91    } else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
92      _Event_Satisfy( the_thread, event, pending_events, seized_events );
93      _Thread_Wait_flags_set(
94        the_thread,
95        wait_class | THREAD_WAIT_STATE_SATISFIED
96      );
97      unblock = true;
98    } else {
99      unblock = false;
100    }
101  } else {
102    unblock = false;
103  }
104
105  if ( unblock ) {
106    Per_CPU_Control *cpu_self;
107
108    cpu_self = _Objects_Release_and_thread_dispatch_disable(
109      &the_thread->Object,
110      lock_context
111    );
112    _Giant_Acquire( cpu_self );
113
114    _Watchdog_Remove( &the_thread->Timer );
115    _Thread_Unblock( the_thread );
116
117    _Giant_Release( cpu_self );
118    _Thread_Dispatch_enable( cpu_self );
119  } else {
120    _Objects_Release_and_ISR_enable( &the_thread->Object, lock_context );
121  }
122}
Note: See TracBrowser for help on using the repository browser.