forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -211,7 +211,6 @@ librtems_a_SOURCES += src/eventseize.c
|
||||
librtems_a_SOURCES += src/eventsend.c
|
||||
librtems_a_SOURCES += src/eventsurrender.c
|
||||
librtems_a_SOURCES += src/eventtimeout.c
|
||||
librtems_a_SOURCES += src/eventdata.c
|
||||
librtems_a_SOURCES += src/systemeventsend.c
|
||||
librtems_a_SOURCES += src/systemeventreceive.c
|
||||
|
||||
|
||||
@@ -32,16 +32,6 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This constant is defined to extern most of the time when using
|
||||
* this header file. However by defining it to nothing, the data
|
||||
* declared in this header file can be instantiated. This is done
|
||||
* in a single per manager file.
|
||||
*/
|
||||
#ifndef RTEMS_EVENT_EXTERN
|
||||
#define RTEMS_EVENT_EXTERN extern
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This constant is passed as the event_in to the
|
||||
* rtems_event_receive directive to determine which events are pending.
|
||||
@@ -54,10 +44,6 @@ extern "C" {
|
||||
*/
|
||||
#define EVENT_SETS_NONE_PENDING 0
|
||||
|
||||
RTEMS_EVENT_EXTERN Thread_blocking_operation_States _Event_Sync_state;
|
||||
|
||||
RTEMS_EVENT_EXTERN Thread_blocking_operation_States _System_event_Sync_state;
|
||||
|
||||
/**
|
||||
* @brief Event Manager Initialization
|
||||
*
|
||||
@@ -77,24 +63,17 @@ void _Event_Seize(
|
||||
rtems_event_set *event_out,
|
||||
Thread_Control *executing,
|
||||
Event_Control *event,
|
||||
Thread_blocking_operation_States *sync_state,
|
||||
States_Control wait_state
|
||||
Thread_Wait_flags wait_class,
|
||||
States_Control block_state,
|
||||
ISR_lock_Context *lock_context
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Surrender Event
|
||||
*
|
||||
* - INTERRUPT LATENCY:
|
||||
* + before flash
|
||||
* + after flash
|
||||
* + check sync
|
||||
*/
|
||||
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
|
||||
Thread_Wait_flags wait_class,
|
||||
ISR_lock_Context *lock_context
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
|
||||
void _Event_Manager_initialization( void )
|
||||
{
|
||||
_Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
|
||||
_System_event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
|
||||
|
||||
/*
|
||||
* Register the MP Process Packet routine.
|
||||
*/
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Instantiate RTEMS Event Data
|
||||
* @ingroup ClassicEvent
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 1989-2007.
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define RTEMS_EVENT_EXTERN
|
||||
|
||||
#include <rtems/rtems/eventimpl.h>
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <rtems/rtems/eventimpl.h>
|
||||
#include <rtems/rtems/tasks.h>
|
||||
#include <rtems/score/statesimpl.h>
|
||||
#include <rtems/score/threaddispatch.h>
|
||||
#include <rtems/score/threadimpl.h>
|
||||
|
||||
rtems_status_code rtems_event_receive(
|
||||
rtems_event_set event_in,
|
||||
@@ -33,12 +33,12 @@ rtems_status_code rtems_event_receive(
|
||||
rtems_status_code sc;
|
||||
|
||||
if ( event_out != NULL ) {
|
||||
Thread_Control *executing = _Thread_Get_executing();
|
||||
ISR_lock_Context lock_context;
|
||||
Thread_Control *executing = _Thread_Acquire_executing( &lock_context );
|
||||
RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
|
||||
Event_Control *event = &api->Event;
|
||||
|
||||
if ( !_Event_sets_Is_empty( event_in ) ) {
|
||||
_Thread_Disable_dispatch();
|
||||
_Event_Seize(
|
||||
event_in,
|
||||
option_set,
|
||||
@@ -46,14 +46,15 @@ rtems_status_code rtems_event_receive(
|
||||
event_out,
|
||||
executing,
|
||||
event,
|
||||
&_Event_Sync_state,
|
||||
STATES_WAITING_FOR_EVENT
|
||||
THREAD_WAIT_CLASS_EVENT,
|
||||
STATES_WAITING_FOR_EVENT,
|
||||
&lock_context
|
||||
);
|
||||
_Thread_Enable_dispatch();
|
||||
|
||||
sc = executing->Wait.return_code;
|
||||
} else {
|
||||
*event_out = event->pending_events;
|
||||
_Objects_Release_and_ISR_enable( &executing->Object, &lock_context );
|
||||
sc = RTEMS_SUCCESSFUL;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -37,18 +37,19 @@ void _Event_Seize(
|
||||
rtems_event_set *event_out,
|
||||
Thread_Control *executing,
|
||||
Event_Control *event,
|
||||
Thread_blocking_operation_States *sync_state,
|
||||
States_Control wait_state
|
||||
Thread_Wait_flags wait_class,
|
||||
States_Control block_state,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
rtems_event_set seized_events;
|
||||
rtems_event_set pending_events;
|
||||
ISR_Level level;
|
||||
Thread_blocking_operation_States current_sync_state;
|
||||
bool success;
|
||||
Thread_Wait_flags intend_to_block;
|
||||
Per_CPU_Control *cpu_self;
|
||||
|
||||
executing->Wait.return_code = RTEMS_SUCCESSFUL;
|
||||
|
||||
_ISR_Disable( level );
|
||||
pending_events = event->pending_events;
|
||||
seized_events = _Event_sets_Get( pending_events, event_in );
|
||||
|
||||
@@ -56,18 +57,20 @@ void _Event_Seize(
|
||||
(seized_events == event_in || _Options_Is_any( option_set )) ) {
|
||||
event->pending_events =
|
||||
_Event_sets_Clear( pending_events, seized_events );
|
||||
_ISR_Enable( level );
|
||||
_Objects_Release_and_ISR_enable( &executing->Object, lock_context );
|
||||
*event_out = seized_events;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( _Options_Is_no_wait( option_set ) ) {
|
||||
_ISR_Enable( level );
|
||||
_Objects_Release_and_ISR_enable( &executing->Object, lock_context );
|
||||
executing->Wait.return_code = RTEMS_UNSATISFIED;
|
||||
*event_out = seized_events;
|
||||
return;
|
||||
}
|
||||
|
||||
intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
|
||||
|
||||
/*
|
||||
* Note what we are waiting for BEFORE we enter the critical section.
|
||||
* The interrupt critical section management code needs this to be
|
||||
@@ -79,38 +82,36 @@ void _Event_Seize(
|
||||
executing->Wait.option = option_set;
|
||||
executing->Wait.count = event_in;
|
||||
executing->Wait.return_argument = event_out;
|
||||
_Thread_Wait_flags_set( executing, intend_to_block );
|
||||
|
||||
*sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
|
||||
|
||||
_ISR_Enable( level );
|
||||
cpu_self = _Objects_Release_and_thread_dispatch_disable(
|
||||
&executing->Object,
|
||||
lock_context
|
||||
);
|
||||
_Giant_Acquire( cpu_self );
|
||||
|
||||
if ( ticks ) {
|
||||
_Watchdog_Initialize(
|
||||
&executing->Timer,
|
||||
_Event_Timeout,
|
||||
executing->Object.id,
|
||||
sync_state
|
||||
NULL
|
||||
);
|
||||
_Watchdog_Insert_ticks( &executing->Timer, ticks );
|
||||
}
|
||||
|
||||
_Thread_Set_state( executing, wait_state );
|
||||
_Thread_Set_state( executing, block_state );
|
||||
|
||||
_ISR_Disable( level );
|
||||
|
||||
current_sync_state = *sync_state;
|
||||
*sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
|
||||
if ( current_sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
success = _Thread_Wait_flags_try_change(
|
||||
executing,
|
||||
intend_to_block,
|
||||
wait_class | THREAD_WAIT_STATE_BLOCKED
|
||||
);
|
||||
if ( !success ) {
|
||||
_Watchdog_Remove( &executing->Timer );
|
||||
_Thread_Unblock( executing );
|
||||
}
|
||||
|
||||
/*
|
||||
* An interrupt completed the thread's blocking request.
|
||||
* The blocking thread was satisfied by an ISR or timed out.
|
||||
*
|
||||
* WARNING! Entering with interrupts disabled and returning with interrupts
|
||||
* enabled!
|
||||
*/
|
||||
_Thread_blocking_operation_Cancel( current_sync_state, executing, level );
|
||||
_Giant_Release( cpu_self );
|
||||
_Thread_Dispatch_enable( cpu_self );
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ rtems_status_code rtems_event_send(
|
||||
Thread_Control *thread;
|
||||
Objects_Locations location;
|
||||
RTEMS_API_Control *api;
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
thread = _Thread_Get( id, &location );
|
||||
thread = _Thread_Acquire( id, &location, &lock_context );
|
||||
switch ( location ) {
|
||||
case OBJECTS_LOCAL:
|
||||
api = thread->API_Extensions[ THREAD_API_RTEMS ];
|
||||
@@ -40,10 +41,9 @@ rtems_status_code rtems_event_send(
|
||||
thread,
|
||||
event_in,
|
||||
&api->Event,
|
||||
&_Event_Sync_state,
|
||||
STATES_WAITING_FOR_EVENT
|
||||
THREAD_WAIT_CLASS_EVENT,
|
||||
&lock_context
|
||||
);
|
||||
_Objects_Put( &thread->Object );
|
||||
sc = RTEMS_SUCCESSFUL;
|
||||
break;
|
||||
#ifdef RTEMS_MULTIPROCESSING
|
||||
|
||||
@@ -23,75 +23,100 @@
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/score/watchdogimpl.h>
|
||||
|
||||
static void _Event_Satisfy(
|
||||
Thread_Control *the_thread,
|
||||
Event_Control *event,
|
||||
rtems_event_set pending_events,
|
||||
rtems_event_set seized_events
|
||||
)
|
||||
{
|
||||
event->pending_events = _Event_sets_Clear( pending_events, seized_events );
|
||||
*(rtems_event_set *) the_thread->Wait.return_argument = seized_events;
|
||||
}
|
||||
|
||||
static bool _Event_Is_satisfied(
|
||||
const Thread_Control *the_thread,
|
||||
rtems_event_set pending_events,
|
||||
rtems_event_set *seized_events
|
||||
)
|
||||
{
|
||||
rtems_option option_set;
|
||||
rtems_event_set event_condition;
|
||||
|
||||
option_set = the_thread->Wait.option;
|
||||
event_condition = the_thread->Wait.count;
|
||||
*seized_events = _Event_sets_Get( pending_events, event_condition );
|
||||
|
||||
return !_Event_sets_Is_empty( *seized_events )
|
||||
&& ( *seized_events == event_condition || _Options_Is_any( option_set ) );
|
||||
}
|
||||
|
||||
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
|
||||
Thread_Wait_flags wait_class,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
rtems_event_set pending_events;
|
||||
rtems_event_set event_condition;
|
||||
rtems_event_set seized_events;
|
||||
rtems_option option_set;
|
||||
Thread_Wait_flags wait_flags;
|
||||
bool unblock;
|
||||
|
||||
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 );
|
||||
wait_flags = _Thread_Wait_flags_get( the_thread );
|
||||
|
||||
if (
|
||||
!_Event_sets_Is_empty( seized_events )
|
||||
&& ( seized_events == event_condition || _Options_Is_any( option_set ) )
|
||||
( wait_flags & THREAD_WAIT_CLASS_MASK ) == wait_class
|
||||
&& _Event_Is_satisfied( the_thread, pending_events, &seized_events )
|
||||
) {
|
||||
/*
|
||||
* 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;
|
||||
Thread_Wait_flags intend_to_block;
|
||||
Thread_Wait_flags blocked;
|
||||
bool success;
|
||||
|
||||
_ISR_Flash( level );
|
||||
intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
|
||||
blocked = wait_class | THREAD_WAIT_STATE_BLOCKED;
|
||||
|
||||
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
|
||||
_ISR_Enable( level );
|
||||
_Thread_Unblock( the_thread );
|
||||
success = _Thread_Wait_flags_try_change_critical(
|
||||
the_thread,
|
||||
intend_to_block,
|
||||
wait_class | THREAD_WAIT_STATE_INTERRUPT_SATISFIED
|
||||
);
|
||||
if ( success ) {
|
||||
_Event_Satisfy( the_thread, event, pending_events, seized_events );
|
||||
unblock = false;
|
||||
} else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
|
||||
_Event_Satisfy( the_thread, event, pending_events, seized_events );
|
||||
_Thread_Wait_flags_set(
|
||||
the_thread,
|
||||
wait_class | THREAD_WAIT_STATE_SATISFIED
|
||||
);
|
||||
unblock = true;
|
||||
} else {
|
||||
_Watchdog_Deactivate( &the_thread->Timer );
|
||||
_ISR_Enable( level );
|
||||
(void) _Watchdog_Remove( &the_thread->Timer );
|
||||
unblock = false;
|
||||
}
|
||||
} else {
|
||||
unblock = false;
|
||||
}
|
||||
|
||||
if ( unblock ) {
|
||||
Per_CPU_Control *cpu_self;
|
||||
|
||||
cpu_self = _Objects_Release_and_thread_dispatch_disable(
|
||||
&the_thread->Object,
|
||||
lock_context
|
||||
);
|
||||
_Giant_Acquire( cpu_self );
|
||||
|
||||
_Watchdog_Remove( &the_thread->Timer );
|
||||
_Thread_Unblock( the_thread );
|
||||
}
|
||||
return;
|
||||
|
||||
_Giant_Release( cpu_self );
|
||||
_Thread_Dispatch_enable( cpu_self );
|
||||
} else {
|
||||
_Objects_Release_and_ISR_enable( &the_thread->Object, lock_context );
|
||||
}
|
||||
}
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
|
||||
@@ -28,53 +28,59 @@ void _Event_Timeout(
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
Objects_Locations location;
|
||||
ISR_Level level;
|
||||
Thread_blocking_operation_States *sync_state;
|
||||
ISR_lock_Context lock_context;
|
||||
Thread_Wait_flags wait_flags;
|
||||
Thread_Wait_flags wait_class;
|
||||
Thread_Wait_flags intend_to_block;
|
||||
Thread_Wait_flags blocked;
|
||||
bool success;
|
||||
bool unblock;
|
||||
|
||||
sync_state = arg;
|
||||
|
||||
the_thread = _Thread_Get( id, &location );
|
||||
the_thread = _Thread_Acquire( id, &location, &lock_context );
|
||||
switch ( location ) {
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
wait_flags = _Thread_Wait_flags_get( the_thread );
|
||||
wait_class = wait_flags & THREAD_WAIT_CLASS_MASK;
|
||||
intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
|
||||
blocked = wait_class | THREAD_WAIT_STATE_BLOCKED;
|
||||
success = _Thread_Wait_flags_try_change_critical(
|
||||
the_thread,
|
||||
intend_to_block,
|
||||
wait_class | THREAD_WAIT_STATE_INTERRUPT_TIMEOUT
|
||||
);
|
||||
|
||||
/*
|
||||
* If the event manager is not synchronized, then it is either
|
||||
* "nothing happened", "timeout", or "satisfied". If the_thread
|
||||
* is the executing thread, then it is in the process of blocking
|
||||
* and it is the thread which is responsible for the synchronization
|
||||
* process.
|
||||
*
|
||||
* If it is not satisfied, then it is "nothing happened" and
|
||||
* this is the "timeout" transition. After a request is satisfied,
|
||||
* a timeout is not allowed to occur.
|
||||
*/
|
||||
_ISR_Disable( level );
|
||||
/*
|
||||
* Verify that the thread is still waiting for the event condition.
|
||||
* This test is necessary to avoid state corruption if the timeout
|
||||
* happens after the event condition is satisfied in
|
||||
* _Event_Surrender(). A satisfied event condition is indicated with
|
||||
* count set to zero.
|
||||
*/
|
||||
if ( !the_thread->Wait.count ) {
|
||||
_ISR_Enable( level );
|
||||
_Objects_Put_without_thread_dispatch( &the_thread->Object );
|
||||
return;
|
||||
}
|
||||
|
||||
the_thread->Wait.count = 0;
|
||||
if ( _Thread_Is_executing( the_thread ) ) {
|
||||
if ( *sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
|
||||
*sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
|
||||
}
|
||||
|
||||
if ( success ) {
|
||||
the_thread->Wait.return_code = RTEMS_TIMEOUT;
|
||||
_ISR_Enable( level );
|
||||
_Thread_Unblock( the_thread );
|
||||
_Objects_Put_without_thread_dispatch( &the_thread->Object );
|
||||
break;
|
||||
unblock = false;
|
||||
} else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
|
||||
the_thread->Wait.return_code = RTEMS_TIMEOUT;
|
||||
_Thread_Wait_flags_set(
|
||||
the_thread,
|
||||
wait_class | THREAD_WAIT_STATE_TIMEOUT
|
||||
);
|
||||
unblock = true;
|
||||
} else {
|
||||
unblock = false;
|
||||
}
|
||||
|
||||
if ( unblock ) {
|
||||
Per_CPU_Control *cpu_self;
|
||||
|
||||
cpu_self = _Objects_Release_and_thread_dispatch_disable(
|
||||
&the_thread->Object,
|
||||
&lock_context
|
||||
);
|
||||
_Giant_Acquire( cpu_self );
|
||||
|
||||
_Thread_Unblock( the_thread );
|
||||
|
||||
_Giant_Release( cpu_self );
|
||||
_Thread_Dispatch_enable( cpu_self );
|
||||
} else {
|
||||
_Objects_Release_and_ISR_enable( &the_thread->Object, &lock_context );
|
||||
}
|
||||
|
||||
break;
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
case OBJECTS_REMOTE: /* impossible */
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <rtems/rtems/eventimpl.h>
|
||||
#include <rtems/rtems/tasks.h>
|
||||
#include <rtems/score/statesimpl.h>
|
||||
#include <rtems/score/threaddispatch.h>
|
||||
#include <rtems/score/threadimpl.h>
|
||||
|
||||
rtems_status_code rtems_event_system_receive(
|
||||
rtems_event_set event_in,
|
||||
@@ -39,12 +39,12 @@ rtems_status_code rtems_event_system_receive(
|
||||
rtems_status_code sc;
|
||||
|
||||
if ( event_out != NULL ) {
|
||||
Thread_Control *executing = _Thread_Get_executing();
|
||||
ISR_lock_Context lock_context;
|
||||
Thread_Control *executing = _Thread_Acquire_executing( &lock_context );
|
||||
RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
|
||||
Event_Control *event = &api->System_event;
|
||||
|
||||
if ( !_Event_sets_Is_empty( event_in ) ) {
|
||||
_Thread_Disable_dispatch();
|
||||
_Event_Seize(
|
||||
event_in,
|
||||
option_set,
|
||||
@@ -52,14 +52,15 @@ rtems_status_code rtems_event_system_receive(
|
||||
event_out,
|
||||
executing,
|
||||
event,
|
||||
&_System_event_Sync_state,
|
||||
STATES_WAITING_FOR_SYSTEM_EVENT
|
||||
THREAD_WAIT_CLASS_SYSTEM_EVENT,
|
||||
STATES_WAITING_FOR_SYSTEM_EVENT,
|
||||
&lock_context
|
||||
);
|
||||
_Thread_Enable_dispatch();
|
||||
|
||||
sc = executing->Wait.return_code;
|
||||
} else {
|
||||
*event_out = event->pending_events;
|
||||
_Objects_Release_and_ISR_enable( &executing->Object, &lock_context );
|
||||
sc = RTEMS_SUCCESSFUL;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -37,8 +37,9 @@ rtems_status_code rtems_event_system_send(
|
||||
Thread_Control *thread;
|
||||
Objects_Locations location;
|
||||
RTEMS_API_Control *api;
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
thread = _Thread_Get( id, &location );
|
||||
thread = _Thread_Acquire( id, &location, &lock_context );
|
||||
switch ( location ) {
|
||||
case OBJECTS_LOCAL:
|
||||
api = thread->API_Extensions[ THREAD_API_RTEMS ];
|
||||
@@ -46,10 +47,9 @@ rtems_status_code rtems_event_system_send(
|
||||
thread,
|
||||
event_in,
|
||||
&api->System_event,
|
||||
&_System_event_Sync_state,
|
||||
STATES_WAITING_FOR_SYSTEM_EVENT
|
||||
THREAD_WAIT_CLASS_SYSTEM_EVENT,
|
||||
&lock_context
|
||||
);
|
||||
_Objects_Put( &thread->Object );
|
||||
sc = RTEMS_SUCCESSFUL;
|
||||
break;
|
||||
#ifdef RTEMS_MULTIPROCESSING
|
||||
|
||||
@@ -54,8 +54,6 @@ static bool _RTEMS_tasks_Create_extension(
|
||||
|
||||
api = created->API_Extensions[ THREAD_API_RTEMS ];
|
||||
|
||||
_Event_Initialize( &api->Event );
|
||||
_Event_Initialize( &api->System_event );
|
||||
_ASR_Create( &api->Signal );
|
||||
_Thread_Action_initialize( &api->Signal_action, _Signal_Action_handler );
|
||||
#if !defined(RTEMS_SMP)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <tmacros.h>
|
||||
#include <intrcritical.h>
|
||||
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/rtems/eventimpl.h>
|
||||
|
||||
const char rtems_test_name[] = "SPINTRCRITICAL 10";
|
||||
@@ -34,16 +35,28 @@ typedef struct {
|
||||
bool hit;
|
||||
} test_context;
|
||||
|
||||
static bool blocks_for_event(Thread_Wait_flags flags)
|
||||
{
|
||||
return flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK)
|
||||
|| flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_BLOCKED);
|
||||
}
|
||||
|
||||
static bool interrupts_blocking_op(Thread_Wait_flags flags)
|
||||
{
|
||||
return
|
||||
flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK);
|
||||
}
|
||||
|
||||
static void any_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
test_context *ctx = arg;
|
||||
const Thread_Control *thread = ctx->thread;
|
||||
Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
|
||||
|
||||
if (thread->Wait.count != 0) {
|
||||
ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
|
||||
if (blocks_for_event(flags)) {
|
||||
ctx->hit = interrupts_blocking_op(flags);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == EVENTS);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
|
||||
);
|
||||
@@ -52,7 +65,6 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
sc = rtems_event_send(thread->Object.id, GREEN);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == 0);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == GREEN
|
||||
);
|
||||
@@ -61,15 +73,13 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
sc = rtems_event_send(thread->Object.id, RED);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == 0);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == GREEN
|
||||
);
|
||||
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
|
||||
|
||||
_Event_Timeout(thread->Object.id, &_Event_Sync_state);
|
||||
_Event_Timeout(thread->Object.id, NULL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == 0);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == GREEN
|
||||
);
|
||||
@@ -77,9 +87,12 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
|
||||
if (ctx->hit) {
|
||||
rtems_test_assert(
|
||||
_Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
|
||||
_Thread_Wait_flags_get(thread)
|
||||
== (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTERRUPT_SATISFIED)
|
||||
);
|
||||
}
|
||||
|
||||
rtems_test_assert(thread->Wait.count == EVENTS);
|
||||
}
|
||||
|
||||
sc = rtems_timer_reset(timer);
|
||||
@@ -115,7 +128,6 @@ static void test_any_satisfy_before_timeout(test_context *ctx)
|
||||
);
|
||||
|
||||
ctx->hit = false;
|
||||
ctx->thread->Wait.count = 0;
|
||||
|
||||
sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
@@ -137,11 +149,11 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
rtems_status_code sc;
|
||||
test_context *ctx = arg;
|
||||
const Thread_Control *thread = ctx->thread;
|
||||
Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
|
||||
|
||||
if (thread->Wait.count != 0) {
|
||||
ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
|
||||
if (blocks_for_event(flags)) {
|
||||
ctx->hit = interrupts_blocking_op(flags);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == EVENTS);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
|
||||
);
|
||||
@@ -150,7 +162,6 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
sc = rtems_event_send(thread->Object.id, GREEN);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == EVENTS);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
|
||||
);
|
||||
@@ -159,15 +170,13 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
sc = rtems_event_send(thread->Object.id, RED);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == 0);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == EVENTS
|
||||
);
|
||||
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
|
||||
|
||||
_Event_Timeout(thread->Object.id, &_Event_Sync_state);
|
||||
_Event_Timeout(thread->Object.id, NULL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == 0);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == EVENTS
|
||||
);
|
||||
@@ -175,9 +184,12 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
|
||||
|
||||
if (ctx->hit) {
|
||||
rtems_test_assert(
|
||||
_Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
|
||||
_Thread_Wait_flags_get(thread)
|
||||
== (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTERRUPT_SATISFIED)
|
||||
);
|
||||
}
|
||||
|
||||
rtems_test_assert(thread->Wait.count == EVENTS);
|
||||
}
|
||||
|
||||
sc = rtems_timer_reset(timer);
|
||||
@@ -208,7 +220,6 @@ static void test_all_satisfy_before_timeout(test_context *ctx)
|
||||
);
|
||||
|
||||
ctx->hit = false;
|
||||
ctx->thread->Wait.count = 0;
|
||||
|
||||
sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
@@ -230,20 +241,18 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
|
||||
rtems_status_code sc;
|
||||
test_context *ctx = arg;
|
||||
const Thread_Control *thread = ctx->thread;
|
||||
Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
|
||||
|
||||
if (thread->Wait.count != 0) {
|
||||
ctx->hit =
|
||||
_Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
|
||||
if (blocks_for_event(flags)) {
|
||||
ctx->hit = interrupts_blocking_op(flags);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == EVENTS);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
|
||||
);
|
||||
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
|
||||
|
||||
_Event_Timeout(thread->Object.id, &_Event_Sync_state);
|
||||
_Event_Timeout(thread->Object.id, NULL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == 0);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
|
||||
);
|
||||
@@ -252,7 +261,6 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
|
||||
sc = rtems_event_send(thread->Object.id, EVENTS);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
rtems_test_assert(thread->Wait.count == 0);
|
||||
rtems_test_assert(
|
||||
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
|
||||
);
|
||||
@@ -260,9 +268,12 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
|
||||
|
||||
if (ctx->hit) {
|
||||
rtems_test_assert(
|
||||
_Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT
|
||||
_Thread_Wait_flags_get(thread)
|
||||
== (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTERRUPT_TIMEOUT)
|
||||
);
|
||||
}
|
||||
|
||||
rtems_test_assert(thread->Wait.count == EVENTS);
|
||||
}
|
||||
|
||||
sc = rtems_timer_reset(timer);
|
||||
@@ -298,7 +309,6 @@ static void test_timeout_before_all_satisfy(test_context *ctx)
|
||||
);
|
||||
|
||||
ctx->hit = false;
|
||||
ctx->thread->Wait.count = 0;
|
||||
|
||||
sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <intrcritical.h>
|
||||
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/rtems/eventimpl.h>
|
||||
|
||||
const char rtems_test_name[] = "SPINTRCRITICAL 21";
|
||||
@@ -34,8 +35,16 @@ static volatile bool case_hit;
|
||||
|
||||
static rtems_id main_task;
|
||||
|
||||
static Thread_Control *main_thread;
|
||||
|
||||
static rtems_id other_task;
|
||||
|
||||
static bool is_case_hit( void )
|
||||
{
|
||||
return _Thread_Wait_flags_get( main_thread)
|
||||
== ( THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK );
|
||||
}
|
||||
|
||||
static rtems_timer_service_routine test_event_from_isr(
|
||||
rtems_id timer,
|
||||
void *arg
|
||||
@@ -43,7 +52,7 @@ static rtems_timer_service_routine test_event_from_isr(
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
if ( _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
|
||||
if ( is_case_hit() ) {
|
||||
/*
|
||||
* This event send hits the critical section but sends to
|
||||
* another task so doesn't impact this critical section.
|
||||
@@ -84,7 +93,7 @@ static rtems_timer_service_routine test_event_with_timeout_from_isr(
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
if ( _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
|
||||
if ( is_case_hit() ) {
|
||||
/*
|
||||
* We want to catch the task while it is blocking. Otherwise
|
||||
* just send and make it happy.
|
||||
@@ -117,6 +126,7 @@ rtems_task Init(
|
||||
TEST_BEGIN();
|
||||
|
||||
main_task = rtems_task_self();
|
||||
main_thread = _Thread_Get_executing();
|
||||
|
||||
status = rtems_task_create(
|
||||
0xa5a5a5a5,
|
||||
|
||||
@@ -268,8 +268,6 @@ uninitialized =
|
||||
|
||||
/*dpmemimpl.h*/ (sizeof _Dual_ported_memory_Information) +
|
||||
|
||||
/*eventimpl.h*/ (sizeof _Event_Sync_state) +
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
/*eventmp.h*/ 0 +
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user