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

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
* 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
*
@@ -71,30 +57,23 @@ RTEMS_EVENT_EXTERN Thread_blocking_operation_States _System_event_Sync_state;
void _Event_Manager_initialization( void );
void _Event_Seize(
rtems_event_set event_in,
rtems_option option_set,
rtems_interval ticks,
rtems_event_set *event_out,
Thread_Control *executing,
Event_Control *event,
Thread_blocking_operation_States *sync_state,
States_Control wait_state
rtems_event_set event_in,
rtems_option option_set,
rtems_interval ticks,
rtems_event_set *event_out,
Thread_Control *executing,
Event_Control *event,
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_Control *the_thread,
rtems_event_set event_in,
Event_Control *event,
Thread_Wait_flags wait_class,
ISR_lock_Context *lock_context
);
/**

View File

@@ -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.
*/

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/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 {

View File

@@ -31,24 +31,25 @@
*/
void _Event_Seize(
rtems_event_set event_in,
rtems_option option_set,
rtems_interval ticks,
rtems_event_set *event_out,
Thread_Control *executing,
Event_Control *event,
Thread_blocking_operation_States *sync_state,
States_Control wait_state
rtems_event_set event_in,
rtems_option option_set,
rtems_interval ticks,
rtems_event_set *event_out,
Thread_Control *executing,
Event_Control *event,
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;
rtems_event_set seized_events;
rtems_event_set pending_events;
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
@@ -76,41 +79,39 @@ void _Event_Seize(
* NOTE: Since interrupts are disabled, this isn't that much of an
* issue but better safe than sorry.
*/
executing->Wait.option = option_set;
executing->Wait.count = event_in;
executing->Wait.return_argument = event_out;
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 );
}

View File

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

View File

@@ -23,75 +23,100 @@
#include <rtems/score/threadimpl.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
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
)
{
ISR_Level level;
rtems_event_set pending_events;
rtems_event_set event_condition;
rtems_event_set seized_events;
rtems_option option_set;
rtems_event_set event_condition;
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 );
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 (
!_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 );
} else {
_Watchdog_Deactivate( &the_thread->Timer );
_ISR_Enable( level );
(void) _Watchdog_Remove( &the_thread->Timer );
_Thread_Unblock( the_thread );
}
return;
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 {
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
)
{
Thread_Control *the_thread;
Objects_Locations location;
ISR_Level level;
Thread_blocking_operation_States *sync_state;
Thread_Control *the_thread;
Objects_Locations location;
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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