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:
Sebastian Huber
2015-03-04 08:02:19 +01:00
parent 4c8a0acc3d
commit 7d6e94b12a
15 changed files with 255 additions and 253 deletions

View File

@@ -211,7 +211,6 @@ librtems_a_SOURCES += src/eventseize.c
librtems_a_SOURCES += src/eventsend.c librtems_a_SOURCES += src/eventsend.c
librtems_a_SOURCES += src/eventsurrender.c librtems_a_SOURCES += src/eventsurrender.c
librtems_a_SOURCES += src/eventtimeout.c librtems_a_SOURCES += src/eventtimeout.c
librtems_a_SOURCES += src/eventdata.c
librtems_a_SOURCES += src/systemeventsend.c librtems_a_SOURCES += src/systemeventsend.c
librtems_a_SOURCES += src/systemeventreceive.c librtems_a_SOURCES += src/systemeventreceive.c

View File

@@ -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 * This constant is passed as the event_in to the
* rtems_event_receive directive to determine which events are pending. * rtems_event_receive directive to determine which events are pending.
@@ -54,10 +44,6 @@ extern "C" {
*/ */
#define EVENT_SETS_NONE_PENDING 0 #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 * @brief Event Manager Initialization
* *
@@ -71,30 +57,23 @@ RTEMS_EVENT_EXTERN Thread_blocking_operation_States _System_event_Sync_state;
void _Event_Manager_initialization( void ); void _Event_Manager_initialization( void );
void _Event_Seize( void _Event_Seize(
rtems_event_set event_in, rtems_event_set event_in,
rtems_option option_set, rtems_option option_set,
rtems_interval ticks, rtems_interval ticks,
rtems_event_set *event_out, rtems_event_set *event_out,
Thread_Control *executing, Thread_Control *executing,
Event_Control *event, Event_Control *event,
Thread_blocking_operation_States *sync_state, Thread_Wait_flags wait_class,
States_Control wait_state States_Control block_state,
ISR_lock_Context *lock_context
); );
/**
* @brief Surrender Event
*
* - INTERRUPT LATENCY:
* + before flash
* + after flash
* + check sync
*/
void _Event_Surrender( void _Event_Surrender(
Thread_Control *the_thread, Thread_Control *the_thread,
rtems_event_set event_in, rtems_event_set event_in,
Event_Control *event, Event_Control *event,
Thread_blocking_operation_States *sync_state, Thread_Wait_flags wait_class,
States_Control wait_state ISR_lock_Context *lock_context
); );
/** /**

View File

@@ -22,9 +22,6 @@
void _Event_Manager_initialization( void ) 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. * Register the MP Process Packet routine.
*/ */

View File

@@ -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>

View File

@@ -21,7 +21,7 @@
#include <rtems/rtems/eventimpl.h> #include <rtems/rtems/eventimpl.h>
#include <rtems/rtems/tasks.h> #include <rtems/rtems/tasks.h>
#include <rtems/score/statesimpl.h> #include <rtems/score/statesimpl.h>
#include <rtems/score/threaddispatch.h> #include <rtems/score/threadimpl.h>
rtems_status_code rtems_event_receive( rtems_status_code rtems_event_receive(
rtems_event_set event_in, rtems_event_set event_in,
@@ -33,12 +33,12 @@ rtems_status_code rtems_event_receive(
rtems_status_code sc; rtems_status_code sc;
if ( event_out != NULL ) { 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 ]; RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
Event_Control *event = &api->Event; Event_Control *event = &api->Event;
if ( !_Event_sets_Is_empty( event_in ) ) { if ( !_Event_sets_Is_empty( event_in ) ) {
_Thread_Disable_dispatch();
_Event_Seize( _Event_Seize(
event_in, event_in,
option_set, option_set,
@@ -46,14 +46,15 @@ rtems_status_code rtems_event_receive(
event_out, event_out,
executing, executing,
event, event,
&_Event_Sync_state, THREAD_WAIT_CLASS_EVENT,
STATES_WAITING_FOR_EVENT STATES_WAITING_FOR_EVENT,
&lock_context
); );
_Thread_Enable_dispatch();
sc = executing->Wait.return_code; sc = executing->Wait.return_code;
} else { } else {
*event_out = event->pending_events; *event_out = event->pending_events;
_Objects_Release_and_ISR_enable( &executing->Object, &lock_context );
sc = RTEMS_SUCCESSFUL; sc = RTEMS_SUCCESSFUL;
} }
} else { } else {

View File

@@ -31,24 +31,25 @@
*/ */
void _Event_Seize( void _Event_Seize(
rtems_event_set event_in, rtems_event_set event_in,
rtems_option option_set, rtems_option option_set,
rtems_interval ticks, rtems_interval ticks,
rtems_event_set *event_out, rtems_event_set *event_out,
Thread_Control *executing, Thread_Control *executing,
Event_Control *event, Event_Control *event,
Thread_blocking_operation_States *sync_state, Thread_Wait_flags wait_class,
States_Control wait_state States_Control block_state,
ISR_lock_Context *lock_context
) )
{ {
rtems_event_set seized_events; rtems_event_set seized_events;
rtems_event_set pending_events; rtems_event_set pending_events;
ISR_Level level; bool success;
Thread_blocking_operation_States current_sync_state; Thread_Wait_flags intend_to_block;
Per_CPU_Control *cpu_self;
executing->Wait.return_code = RTEMS_SUCCESSFUL; executing->Wait.return_code = RTEMS_SUCCESSFUL;
_ISR_Disable( level );
pending_events = event->pending_events; pending_events = event->pending_events;
seized_events = _Event_sets_Get( pending_events, event_in ); 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 )) ) { (seized_events == event_in || _Options_Is_any( option_set )) ) {
event->pending_events = event->pending_events =
_Event_sets_Clear( pending_events, seized_events ); _Event_sets_Clear( pending_events, seized_events );
_ISR_Enable( level ); _Objects_Release_and_ISR_enable( &executing->Object, lock_context );
*event_out = seized_events; *event_out = seized_events;
return; return;
} }
if ( _Options_Is_no_wait( option_set ) ) { 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; executing->Wait.return_code = RTEMS_UNSATISFIED;
*event_out = seized_events; *event_out = seized_events;
return; return;
} }
intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
/* /*
* Note what we are waiting for BEFORE we enter the critical section. * Note what we are waiting for BEFORE we enter the critical section.
* The interrupt critical section management code needs this to be * The interrupt critical section management code needs this to be
@@ -76,41 +79,39 @@ void _Event_Seize(
* NOTE: Since interrupts are disabled, this isn't that much of an * NOTE: Since interrupts are disabled, this isn't that much of an
* issue but better safe than sorry. * issue but better safe than sorry.
*/ */
executing->Wait.option = option_set; executing->Wait.option = option_set;
executing->Wait.count = event_in; executing->Wait.count = event_in;
executing->Wait.return_argument = event_out; executing->Wait.return_argument = event_out;
_Thread_Wait_flags_set( executing, intend_to_block );
*sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; cpu_self = _Objects_Release_and_thread_dispatch_disable(
&executing->Object,
_ISR_Enable( level ); lock_context
);
_Giant_Acquire( cpu_self );
if ( ticks ) { if ( ticks ) {
_Watchdog_Initialize( _Watchdog_Initialize(
&executing->Timer, &executing->Timer,
_Event_Timeout, _Event_Timeout,
executing->Object.id, executing->Object.id,
sync_state NULL
); );
_Watchdog_Insert_ticks( &executing->Timer, ticks ); _Watchdog_Insert_ticks( &executing->Timer, ticks );
} }
_Thread_Set_state( executing, wait_state ); _Thread_Set_state( executing, block_state );
_ISR_Disable( level ); success = _Thread_Wait_flags_try_change(
executing,
current_sync_state = *sync_state; intend_to_block,
*sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; wait_class | THREAD_WAIT_STATE_BLOCKED
if ( current_sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) { );
_ISR_Enable( level ); if ( !success ) {
return; _Watchdog_Remove( &executing->Timer );
_Thread_Unblock( executing );
} }
/* _Giant_Release( cpu_self );
* An interrupt completed the thread's blocking request. _Thread_Dispatch_enable( cpu_self );
* 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 );
} }

View File

@@ -31,8 +31,9 @@ rtems_status_code rtems_event_send(
Thread_Control *thread; Thread_Control *thread;
Objects_Locations location; Objects_Locations location;
RTEMS_API_Control *api; RTEMS_API_Control *api;
ISR_lock_Context lock_context;
thread = _Thread_Get( id, &location ); thread = _Thread_Acquire( id, &location, &lock_context );
switch ( location ) { switch ( location ) {
case OBJECTS_LOCAL: case OBJECTS_LOCAL:
api = thread->API_Extensions[ THREAD_API_RTEMS ]; api = thread->API_Extensions[ THREAD_API_RTEMS ];
@@ -40,10 +41,9 @@ rtems_status_code rtems_event_send(
thread, thread,
event_in, event_in,
&api->Event, &api->Event,
&_Event_Sync_state, THREAD_WAIT_CLASS_EVENT,
STATES_WAITING_FOR_EVENT &lock_context
); );
_Objects_Put( &thread->Object );
sc = RTEMS_SUCCESSFUL; sc = RTEMS_SUCCESSFUL;
break; break;
#ifdef RTEMS_MULTIPROCESSING #ifdef RTEMS_MULTIPROCESSING

View File

@@ -23,75 +23,100 @@
#include <rtems/score/threadimpl.h> #include <rtems/score/threadimpl.h>
#include <rtems/score/watchdogimpl.h> #include <rtems/score/watchdogimpl.h>
void _Event_Surrender( static void _Event_Satisfy(
Thread_Control *the_thread, Thread_Control *the_thread,
rtems_event_set event_in, Event_Control *event,
Event_Control *event, rtems_event_set pending_events,
Thread_blocking_operation_States *sync_state, rtems_event_set seized_events
States_Control wait_state )
{
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
) )
{ {
ISR_Level level;
rtems_event_set pending_events;
rtems_event_set event_condition;
rtems_event_set seized_events;
rtems_option option_set; rtems_option option_set;
rtems_event_set event_condition;
option_set = the_thread->Wait.option; 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; event_condition = the_thread->Wait.count;
*seized_events = _Event_sets_Get( pending_events, event_condition );
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_Wait_flags wait_class,
ISR_lock_Context *lock_context
)
{
rtems_event_set pending_events;
rtems_event_set seized_events;
Thread_Wait_flags wait_flags;
bool unblock;
_Event_sets_Post( event_in, &event->pending_events );
pending_events = event->pending_events;
wait_flags = _Thread_Wait_flags_get( the_thread );
if ( if (
!_Event_sets_Is_empty( seized_events ) ( wait_flags & THREAD_WAIT_CLASS_MASK ) == wait_class
&& ( seized_events == event_condition || _Options_Is_any( option_set ) ) && _Event_Is_satisfied( the_thread, pending_events, &seized_events )
) { ) {
/* Thread_Wait_flags intend_to_block;
* If we are sending to the executing thread, then we have a critical Thread_Wait_flags blocked;
* section issue to deal with. The entity sending to the executing thread bool success;
* 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 ); 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 ) ) { success = _Thread_Wait_flags_try_change_critical(
_ISR_Enable( level ); the_thread,
_Thread_Unblock( the_thread ); intend_to_block,
} else { wait_class | THREAD_WAIT_STATE_INTERRUPT_SATISFIED
_Watchdog_Deactivate( &the_thread->Timer ); );
_ISR_Enable( level ); if ( success ) {
(void) _Watchdog_Remove( &the_thread->Timer ); _Event_Satisfy( the_thread, event, pending_events, seized_events );
_Thread_Unblock( the_thread ); unblock = false;
} } else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
return; _Event_Satisfy( the_thread, event, pending_events, seized_events );
_Thread_Wait_flags_set(
the_thread,
wait_class | THREAD_WAIT_STATE_SATISFIED
);
unblock = true;
} else {
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 );
_Giant_Release( cpu_self );
_Thread_Dispatch_enable( cpu_self );
} else {
_Objects_Release_and_ISR_enable( &the_thread->Object, lock_context );
} }
_ISR_Enable( level );
} }

View File

@@ -26,55 +26,61 @@ void _Event_Timeout(
void *arg void *arg
) )
{ {
Thread_Control *the_thread; Thread_Control *the_thread;
Objects_Locations location; Objects_Locations location;
ISR_Level level; ISR_lock_Context lock_context;
Thread_blocking_operation_States *sync_state; 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_Acquire( id, &location, &lock_context );
the_thread = _Thread_Get( id, &location );
switch ( location ) { switch ( location ) {
case OBJECTS_LOCAL: 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 ( success ) {
* 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;
}
the_thread->Wait.return_code = RTEMS_TIMEOUT; the_thread->Wait.return_code = RTEMS_TIMEOUT;
_ISR_Enable( level ); unblock = false;
_Thread_Unblock( the_thread ); } else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
_Objects_Put_without_thread_dispatch( &the_thread->Object ); the_thread->Wait.return_code = RTEMS_TIMEOUT;
break; _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) #if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE: /* impossible */ case OBJECTS_REMOTE: /* impossible */
#endif #endif

View File

@@ -27,7 +27,7 @@
#include <rtems/rtems/eventimpl.h> #include <rtems/rtems/eventimpl.h>
#include <rtems/rtems/tasks.h> #include <rtems/rtems/tasks.h>
#include <rtems/score/statesimpl.h> #include <rtems/score/statesimpl.h>
#include <rtems/score/threaddispatch.h> #include <rtems/score/threadimpl.h>
rtems_status_code rtems_event_system_receive( rtems_status_code rtems_event_system_receive(
rtems_event_set event_in, rtems_event_set event_in,
@@ -39,12 +39,12 @@ rtems_status_code rtems_event_system_receive(
rtems_status_code sc; rtems_status_code sc;
if ( event_out != NULL ) { 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 ]; RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
Event_Control *event = &api->System_event; Event_Control *event = &api->System_event;
if ( !_Event_sets_Is_empty( event_in ) ) { if ( !_Event_sets_Is_empty( event_in ) ) {
_Thread_Disable_dispatch();
_Event_Seize( _Event_Seize(
event_in, event_in,
option_set, option_set,
@@ -52,14 +52,15 @@ rtems_status_code rtems_event_system_receive(
event_out, event_out,
executing, executing,
event, event,
&_System_event_Sync_state, THREAD_WAIT_CLASS_SYSTEM_EVENT,
STATES_WAITING_FOR_SYSTEM_EVENT STATES_WAITING_FOR_SYSTEM_EVENT,
&lock_context
); );
_Thread_Enable_dispatch();
sc = executing->Wait.return_code; sc = executing->Wait.return_code;
} else { } else {
*event_out = event->pending_events; *event_out = event->pending_events;
_Objects_Release_and_ISR_enable( &executing->Object, &lock_context );
sc = RTEMS_SUCCESSFUL; sc = RTEMS_SUCCESSFUL;
} }
} else { } else {

View File

@@ -37,8 +37,9 @@ rtems_status_code rtems_event_system_send(
Thread_Control *thread; Thread_Control *thread;
Objects_Locations location; Objects_Locations location;
RTEMS_API_Control *api; RTEMS_API_Control *api;
ISR_lock_Context lock_context;
thread = _Thread_Get( id, &location ); thread = _Thread_Acquire( id, &location, &lock_context );
switch ( location ) { switch ( location ) {
case OBJECTS_LOCAL: case OBJECTS_LOCAL:
api = thread->API_Extensions[ THREAD_API_RTEMS ]; api = thread->API_Extensions[ THREAD_API_RTEMS ];
@@ -46,10 +47,9 @@ rtems_status_code rtems_event_system_send(
thread, thread,
event_in, event_in,
&api->System_event, &api->System_event,
&_System_event_Sync_state, THREAD_WAIT_CLASS_SYSTEM_EVENT,
STATES_WAITING_FOR_SYSTEM_EVENT &lock_context
); );
_Objects_Put( &thread->Object );
sc = RTEMS_SUCCESSFUL; sc = RTEMS_SUCCESSFUL;
break; break;
#ifdef RTEMS_MULTIPROCESSING #ifdef RTEMS_MULTIPROCESSING

View File

@@ -54,8 +54,6 @@ static bool _RTEMS_tasks_Create_extension(
api = created->API_Extensions[ THREAD_API_RTEMS ]; api = created->API_Extensions[ THREAD_API_RTEMS ];
_Event_Initialize( &api->Event );
_Event_Initialize( &api->System_event );
_ASR_Create( &api->Signal ); _ASR_Create( &api->Signal );
_Thread_Action_initialize( &api->Signal_action, _Signal_Action_handler ); _Thread_Action_initialize( &api->Signal_action, _Signal_Action_handler );
#if !defined(RTEMS_SMP) #if !defined(RTEMS_SMP)

View File

@@ -16,6 +16,7 @@
#include <tmacros.h> #include <tmacros.h>
#include <intrcritical.h> #include <intrcritical.h>
#include <rtems/score/threadimpl.h>
#include <rtems/rtems/eventimpl.h> #include <rtems/rtems/eventimpl.h>
const char rtems_test_name[] = "SPINTRCRITICAL 10"; const char rtems_test_name[] = "SPINTRCRITICAL 10";
@@ -34,16 +35,28 @@ typedef struct {
bool hit; bool hit;
} test_context; } 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) static void any_satisfy_before_timeout(rtems_id timer, void *arg)
{ {
rtems_status_code sc; rtems_status_code sc;
test_context *ctx = arg; test_context *ctx = arg;
const Thread_Control *thread = ctx->thread; const Thread_Control *thread = ctx->thread;
Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
if (thread->Wait.count != 0) { if (blocks_for_event(flags)) {
ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; ctx->hit = interrupts_blocking_op(flags);
rtems_test_assert(thread->Wait.count == EVENTS);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF *(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); sc = rtems_event_send(thread->Object.id, GREEN);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc == RTEMS_SUCCESSFUL);
rtems_test_assert(thread->Wait.count == 0);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == GREEN *(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); sc = rtems_event_send(thread->Object.id, RED);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc == RTEMS_SUCCESSFUL);
rtems_test_assert(thread->Wait.count == 0);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == GREEN *(rtems_event_set *) thread->Wait.return_argument == GREEN
); );
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); 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_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == GREEN *(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) { if (ctx->hit) {
rtems_test_assert( 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); sc = rtems_timer_reset(timer);
@@ -115,7 +128,6 @@ static void test_any_satisfy_before_timeout(test_context *ctx)
); );
ctx->hit = false; ctx->hit = false;
ctx->thread->Wait.count = 0;
sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx); sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); 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; rtems_status_code sc;
test_context *ctx = arg; test_context *ctx = arg;
const Thread_Control *thread = ctx->thread; const Thread_Control *thread = ctx->thread;
Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
if (thread->Wait.count != 0) { if (blocks_for_event(flags)) {
ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; ctx->hit = interrupts_blocking_op(flags);
rtems_test_assert(thread->Wait.count == EVENTS);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF *(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); sc = rtems_event_send(thread->Object.id, GREEN);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc == RTEMS_SUCCESSFUL);
rtems_test_assert(thread->Wait.count == EVENTS);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF *(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); sc = rtems_event_send(thread->Object.id, RED);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc == RTEMS_SUCCESSFUL);
rtems_test_assert(thread->Wait.count == 0);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == EVENTS *(rtems_event_set *) thread->Wait.return_argument == EVENTS
); );
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); 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_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == EVENTS *(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) { if (ctx->hit) {
rtems_test_assert( 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); sc = rtems_timer_reset(timer);
@@ -208,7 +220,6 @@ static void test_all_satisfy_before_timeout(test_context *ctx)
); );
ctx->hit = false; ctx->hit = false;
ctx->thread->Wait.count = 0;
sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx); sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc == RTEMS_SUCCESSFUL);
@@ -230,20 +241,18 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
rtems_status_code sc; rtems_status_code sc;
test_context *ctx = arg; test_context *ctx = arg;
const Thread_Control *thread = ctx->thread; const Thread_Control *thread = ctx->thread;
Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
if (thread->Wait.count != 0) { if (blocks_for_event(flags)) {
ctx->hit = ctx->hit = interrupts_blocking_op(flags);
_Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
rtems_test_assert(thread->Wait.count == EVENTS);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
); );
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL); 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_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF *(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); sc = rtems_event_send(thread->Object.id, EVENTS);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc == RTEMS_SUCCESSFUL);
rtems_test_assert(thread->Wait.count == 0);
rtems_test_assert( rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF *(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) { if (ctx->hit) {
rtems_test_assert( 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); sc = rtems_timer_reset(timer);
@@ -298,7 +309,6 @@ static void test_timeout_before_all_satisfy(test_context *ctx)
); );
ctx->hit = false; ctx->hit = false;
ctx->thread->Wait.count = 0;
sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx); sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx);
rtems_test_assert(sc == RTEMS_SUCCESSFUL); rtems_test_assert(sc == RTEMS_SUCCESSFUL);

View File

@@ -18,6 +18,7 @@
#include <intrcritical.h> #include <intrcritical.h>
#include <rtems/score/threadimpl.h>
#include <rtems/rtems/eventimpl.h> #include <rtems/rtems/eventimpl.h>
const char rtems_test_name[] = "SPINTRCRITICAL 21"; const char rtems_test_name[] = "SPINTRCRITICAL 21";
@@ -34,8 +35,16 @@ static volatile bool case_hit;
static rtems_id main_task; static rtems_id main_task;
static Thread_Control *main_thread;
static rtems_id other_task; 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( static rtems_timer_service_routine test_event_from_isr(
rtems_id timer, rtems_id timer,
void *arg void *arg
@@ -43,7 +52,7 @@ static rtems_timer_service_routine test_event_from_isr(
{ {
rtems_status_code status; 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 * This event send hits the critical section but sends to
* another task so doesn't impact this critical section. * 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; 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 * We want to catch the task while it is blocking. Otherwise
* just send and make it happy. * just send and make it happy.
@@ -117,6 +126,7 @@ rtems_task Init(
TEST_BEGIN(); TEST_BEGIN();
main_task = rtems_task_self(); main_task = rtems_task_self();
main_thread = _Thread_Get_executing();
status = rtems_task_create( status = rtems_task_create(
0xa5a5a5a5, 0xa5a5a5a5,

View File

@@ -268,8 +268,6 @@ uninitialized =
/*dpmemimpl.h*/ (sizeof _Dual_ported_memory_Information) + /*dpmemimpl.h*/ (sizeof _Dual_ported_memory_Information) +
/*eventimpl.h*/ (sizeof _Event_Sync_state) +
#if defined(RTEMS_MULTIPROCESSING) #if defined(RTEMS_MULTIPROCESSING)
/*eventmp.h*/ 0 + /*eventmp.h*/ 0 +
#endif #endif