blob: 0f72f5ab3caf04bafe5733f2bd6340bd4d6828c0 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
/**
* @file
*
* @brief Surrender Event
* @ingroup ClassicEvent
*/
/*
* COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
* 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/score/watchdogimpl.h>
void _Event_Surrender(
Thread_Control *the_thread,
rtems_event_set event_in,
Event_Control *event,
Thread_blocking_operation_States *sync_state,
States_Control wait_state
)
{
ISR_Level level;
rtems_event_set pending_events;
rtems_event_set event_condition;
rtems_event_set seized_events;
rtems_option option_set;
option_set = the_thread->Wait.option;
_ISR_Disable( level );
_Event_sets_Post( event_in, &event->pending_events );
pending_events = event->pending_events;
/*
* At this point the event condition is a speculative quantity. Later state
* checks will show if the thread actually waits for an event.
*/
event_condition = the_thread->Wait.count;
seized_events = _Event_sets_Get( pending_events, event_condition );
if (
!_Event_sets_Is_empty( seized_events )
&& ( seized_events == event_condition || _Options_Is_any( option_set ) )
) {
/*
* If we are sending to the executing thread, then we have a critical
* section issue to deal with. The entity sending to the executing thread
* can be either the executing thread or an ISR. In case it is the
* executing thread, then the blocking operation state is not equal to
* THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED.
*/
if ( _Thread_Is_executing( the_thread ) &&
*sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
event->pending_events = _Event_sets_Clear(
pending_events,
seized_events
);
the_thread->Wait.count = 0;
*(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
*sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
} else if ( _States_Are_set( the_thread->current_state, wait_state ) ) {
event->pending_events = _Event_sets_Clear(
pending_events,
seized_events
);
the_thread->Wait.count = 0;
*(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
_ISR_Flash( level );
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
_ISR_Enable( level );
_Thread_Unblock( the_thread );
} else {
_Watchdog_Deactivate( &the_thread->Timer );
_ISR_Enable( level );
(void) _Watchdog_Remove( &the_thread->Timer );
_Thread_Unblock( the_thread );
}
return;
}
}
_ISR_Enable( level );
}
|