diff options
-rw-r--r-- | testsuites/psxtests/psxintrcritical01/init.c | 42 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical01/init.c | 38 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical06/init.c | 28 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical08/init.c | 70 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical09/init.c | 24 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical10/init.c | 120 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical11/init.c | 24 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical13/init.c | 27 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical15/init.c | 33 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical16/init.c | 32 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical18/init.c | 23 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical20/init.c | 82 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical_support/intrcritical.c | 230 | ||||
-rw-r--r-- | testsuites/sptests/spintrcritical_support/intrcritical.h | 21 |
14 files changed, 504 insertions, 290 deletions
diff --git a/testsuites/psxtests/psxintrcritical01/init.c b/testsuites/psxtests/psxintrcritical01/init.c index 2c4620969f..a6a64bad60 100644 --- a/testsuites/psxtests/psxintrcritical01/init.c +++ b/testsuites/psxtests/psxintrcritical01/init.c @@ -19,31 +19,40 @@ const char rtems_test_name[] = "PSXINTRCRITICAL 1"; /* forward declarations to avoid warnings */ rtems_task Init(rtems_task_argument ignored); -rtems_timer_service_routine test_release_from_isr(rtems_id timer, void *arg); #define TEST_NAME "01" #define TEST_STRING "POSIX Timer" -rtems_id Main_task; -timer_t Timer; -struct itimerspec TimerParams; +static timer_t Timer; +static struct itimerspec TimerParams; #define POSIX_TIMER_RELATIVE 0 -rtems_timer_service_routine test_release_from_isr( +static bool test_body( void *arg ) +{ + int rv; + + (void) arg; + + rv = timer_settime(Timer, POSIX_TIMER_RELATIVE, &TimerParams, NULL); + rtems_test_assert( rv == 0 ); + + return false; +} + +static rtems_timer_service_routine test_release_from_isr( rtems_id timer, void *arg ) { - (void) timer_settime(Timer, POSIX_TIMER_RELATIVE, &TimerParams, NULL); + test_body( NULL ); } rtems_task Init( rtems_task_argument ignored ) { - int sc; - int resets; + int sc; TEST_BEGIN(); @@ -59,27 +68,13 @@ rtems_task Init( rtems_test_exit(0); } - Main_task = rtems_task_self(); - /* we don't care if it ever fires */ TimerParams.it_interval.tv_sec = 10; TimerParams.it_interval.tv_nsec = 0; TimerParams.it_value.tv_sec = 10; TimerParams.it_value.tv_nsec = 0; - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - for (resets=0 ; resets<10 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - sc = timer_settime(Timer, POSIX_TIMER_RELATIVE, &TimerParams, NULL); - if ( sc == -1 ) { - perror ("Error in timer setting\n"); - rtems_test_exit(0); - } - - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); TEST_END(); rtems_test_exit(0); @@ -93,6 +88,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 1 #define CONFIGURE_MAXIMUM_TIMERS 1 #define CONFIGURE_MAXIMUM_POSIX_TIMERS 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_MICROSECONDS_PER_TICK 1000 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION diff --git a/testsuites/sptests/spintrcritical01/init.c b/testsuites/sptests/spintrcritical01/init.c index 7db5143469..dc36aee4fd 100644 --- a/testsuites/sptests/spintrcritical01/init.c +++ b/testsuites/sptests/spintrcritical01/init.c @@ -58,9 +58,8 @@ Thread_blocking_operation_States getState(void); const char rtems_test_name[] = "SPINTRCRITICAL " TEST_NAME; -rtems_id Main_task; rtems_id Semaphore; -volatile bool case_hit; +volatile bool case_hit = false; Thread_blocking_operation_States getState(void) { @@ -94,6 +93,21 @@ rtems_timer_service_routine test_release_from_isr( } +static bool test_body( void *arg ) +{ + rtems_status_code status; + + (void) arg; + + status = rtems_semaphore_obtain( + Semaphore, + RTEMS_DEFAULT_OPTIONS, + SEMAPHORE_OBTAIN_TIMEOUT + ); + directive_failed( status, "rtems_semaphore_obtain" ); + + return case_hit; +} rtems_task Init( rtems_task_argument ignored @@ -107,29 +121,14 @@ rtems_task Init( puts( "Init - Variation is: " TEST_STRING ); status = rtems_semaphore_create( rtems_build_name( 'S', 'M', '1', ' ' ), - 1, + 0, SEMAPHORE_ATTRIBUTES, RTEMS_NO_PRIORITY, &Semaphore ); directive_failed( status, "rtems_semaphore_create of SM1" ); - Main_task = rtems_task_self(); - - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - case_hit = false; - - while (!case_hit) { - interrupt_critical_section_test_support_delay(); - - status = rtems_semaphore_obtain( - Semaphore, - RTEMS_DEFAULT_OPTIONS, - SEMAPHORE_OBTAIN_TIMEOUT - ); - directive_failed( status, "rtems_semaphore_obtain" ); - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); if ( case_hit ) { puts( "Init - Case hit" ); @@ -148,6 +147,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 1 #define CONFIGURE_MAXIMUM_TIMERS 1 #define CONFIGURE_MAXIMUM_SEMAPHORES 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_MICROSECONDS_PER_TICK 1000 #if defined(PRIORITY_NO_TIMEOUT_REVERSE) #define CONFIGURE_INIT_TASK_PRIORITY 250 diff --git a/testsuites/sptests/spintrcritical06/init.c b/testsuites/sptests/spintrcritical06/init.c index 96c2a91be4..8d519226ff 100644 --- a/testsuites/sptests/spintrcritical06/init.c +++ b/testsuites/sptests/spintrcritical06/init.c @@ -71,12 +71,24 @@ rtems_task Secondary_task( rtems_test_assert(0); } +static bool test_body( void *arg ) +{ + (void) arg; + + rtems_semaphore_obtain( + Semaphore, + RTEMS_DEFAULT_OPTIONS, + SEMAPHORE_OBTAIN_TIMEOUT + ); + + return false; +} + rtems_task Init( rtems_task_argument ignored ) { rtems_status_code status; - int resets; TEST_BEGIN(); @@ -105,18 +117,7 @@ rtems_task Init( status = rtems_task_start( Secondary_task_id, Secondary_task, 0 ); directive_failed( status, "rtems_task_start" ); - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - for (resets=0 ; resets< 2 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - status = rtems_semaphore_obtain( - Semaphore, - RTEMS_DEFAULT_OPTIONS, - SEMAPHORE_OBTAIN_TIMEOUT - ); - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); TEST_END(); rtems_test_exit(0); @@ -130,6 +131,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 2 #define CONFIGURE_MAXIMUM_TIMERS 1 #define CONFIGURE_MAXIMUM_SEMAPHORES 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_INIT_TASK_PRIORITY INIT_PRIORITY #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_PREEMPT #define CONFIGURE_MICROSECONDS_PER_TICK 2000 diff --git a/testsuites/sptests/spintrcritical08/init.c b/testsuites/sptests/spintrcritical08/init.c index e286e869fb..7a1353daeb 100644 --- a/testsuites/sptests/spintrcritical08/init.c +++ b/testsuites/sptests/spintrcritical08/init.c @@ -13,20 +13,19 @@ #include <tmacros.h> #include <intrcritical.h> +#include <rtems/score/watchdogimpl.h> #include <rtems/rtems/ratemonimpl.h> const char rtems_test_name[] = "SPINTRCRITICAL 8"; /* forward declarations to avoid warnings */ rtems_task Init(rtems_task_argument argument); -rtems_timer_service_routine test_release_from_isr(rtems_id timer, void *arg); -rtems_rate_monotonic_period_states getState(void); -rtems_id Main_task; -rtems_id Period; -volatile bool case_hit; +static rtems_id Period; -rtems_rate_monotonic_period_states getState(void) +static volatile bool case_hit = false; + +static rtems_rate_monotonic_period_states getState(void) { Objects_Locations location; Rate_monotonic_Control *period; @@ -42,13 +41,48 @@ rtems_rate_monotonic_period_states getState(void) return period->state; } -rtems_timer_service_routine test_release_from_isr( +static rtems_timer_service_routine test_release_from_isr( rtems_id timer, void *arg ) { - if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) - case_hit = true; + Chain_Control *chain = &_Watchdog_Ticks_chain; + + if ( !_Chain_Is_empty( chain ) ) { + Watchdog_Control *watchdog = _Watchdog_First( chain ); + + if ( + watchdog->delta_interval == 0 + && watchdog->routine == _Rate_monotonic_Timeout + ) { + Watchdog_States state = _Watchdog_Remove( watchdog ); + + rtems_test_assert( state == WATCHDOG_ACTIVE ); + (*watchdog->routine)( watchdog->id, watchdog->user_data ); + + if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) { + case_hit = true; + } + } + } +} + +static bool test_body( void *arg ) +{ + rtems_status_code sc; + + (void) arg; + + sc = rtems_rate_monotonic_cancel( Period ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + + sc = rtems_rate_monotonic_period( Period, 1 ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + + sc = rtems_rate_monotonic_period( Period, 1 ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL || sc == RTEMS_TIMEOUT ); + + return case_hit; } rtems_task Init( @@ -56,7 +90,6 @@ rtems_task Init( ) { rtems_status_code sc; - int resets; TEST_BEGIN(); @@ -69,21 +102,7 @@ rtems_task Init( ); directive_failed( sc, "rtems_rate_monotonic_create" ); - Main_task = rtems_task_self(); - - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - case_hit = false; - - for (resets=0 ; case_hit == false && resets< 2 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - sc = rtems_rate_monotonic_period( Period, 1 ); - if ( sc == RTEMS_TIMEOUT ) - continue; - directive_failed( sc, "rtems_monotonic_period"); - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); if ( case_hit ) { puts( "Init - It appears the case has been hit" ); @@ -101,6 +120,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 2 #define CONFIGURE_MAXIMUM_TIMERS 1 #define CONFIGURE_MAXIMUM_PERIODS 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_MICROSECONDS_PER_TICK 1000 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION diff --git a/testsuites/sptests/spintrcritical09/init.c b/testsuites/sptests/spintrcritical09/init.c index 90948eccc6..bc942d5f77 100644 --- a/testsuites/sptests/spintrcritical09/init.c +++ b/testsuites/sptests/spintrcritical09/init.c @@ -20,7 +20,7 @@ const char rtems_test_name[] = "SPINTRCRITICAL 9"; static rtems_id Semaphore; -static bool case_hit; +static bool case_hit = false; static Thread_blocking_operation_States getState(void) { @@ -64,12 +64,20 @@ static rtems_timer_service_routine test_release_from_isr( } } +static bool test_body( void *arg ) +{ + (void) arg; + + rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 1 ); + + return case_hit; +} + static rtems_task Init( rtems_task_argument ignored ) { rtems_status_code sc; - int resets; TEST_BEGIN(); @@ -84,16 +92,7 @@ static rtems_task Init( ); directive_failed( sc, "rtems_semaphore_create of SM1" ); - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - case_hit = false; - - for (resets=0 ; resets< 2 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - (void) rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 1 ); - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); if ( case_hit ) { puts( "Init - It appears the case has been hit" ); @@ -112,6 +111,7 @@ static rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 1 #define CONFIGURE_MAXIMUM_TIMERS 1 #define CONFIGURE_MAXIMUM_SEMAPHORES 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_RTEMS_INIT_TASKS_TABLE diff --git a/testsuites/sptests/spintrcritical10/init.c b/testsuites/sptests/spintrcritical10/init.c index f3883f7fa6..8959e5c4e3 100644 --- a/testsuites/sptests/spintrcritical10/init.c +++ b/testsuites/sptests/spintrcritical10/init.c @@ -86,10 +86,28 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg) rtems_test_assert(sc == RTEMS_SUCCESSFUL); } +static bool test_body_any_satisfy_before_timeout(void *arg) +{ + test_context *ctx = arg; + rtems_status_code sc; + rtems_event_set out; + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, 1, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == GREEN); + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, 0, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == RED); + + return ctx->hit; +} + static void test_any_satisfy_before_timeout(test_context *ctx) { rtems_status_code sc; - int resets = 0; puts( "Init - Trying to generate any satisfied before timeout " @@ -98,27 +116,14 @@ static void test_any_satisfy_before_timeout(test_context *ctx) ctx->hit = false; - interrupt_critical_section_test_support_initialize(NULL); - sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx); rtems_test_assert(sc == RTEMS_SUCCESSFUL); - while (!ctx->hit && resets < 2) { - rtems_event_set out; - - if (interrupt_critical_section_test_support_delay()) - resets++; - - out = DEADBEEF; - sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, 1, &out); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - rtems_test_assert(out == GREEN); - - out = DEADBEEF; - sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, 0, &out); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - rtems_test_assert(out == RED); - } + interrupt_critical_section_test( + test_body_any_satisfy_before_timeout, + ctx, + NULL + ); sc = rtems_timer_cancel(ctx->timer); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -178,10 +183,23 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg) rtems_test_assert(sc == RTEMS_SUCCESSFUL); } +static bool test_body_all_satisfy_before_timeout(void *arg) +{ + test_context *ctx = arg; + rtems_status_code sc; + rtems_event_set out; + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == EVENTS); + + return ctx->hit; +} + static void test_all_satisfy_before_timeout(test_context *ctx) { rtems_status_code sc; - int resets = 0; puts( "Init - Trying to generate all satisfied before timeout " @@ -190,22 +208,14 @@ static void test_all_satisfy_before_timeout(test_context *ctx) ctx->hit = false; - interrupt_critical_section_test_support_initialize(NULL); - sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx); rtems_test_assert(sc == RTEMS_SUCCESSFUL); - while (!ctx->hit && resets < 2) { - rtems_event_set out; - - if (interrupt_critical_section_test_support_delay()) - resets++; - - out = DEADBEEF; - sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - rtems_test_assert(out == EVENTS); - } + interrupt_critical_section_test( + test_body_all_satisfy_before_timeout, + ctx, + NULL + ); sc = rtems_timer_cancel(ctx->timer); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -257,10 +267,28 @@ static void timeout_before_satisfied(rtems_id timer, void *arg) rtems_test_assert(sc == RTEMS_SUCCESSFUL); } +static bool test_body_timeout_before_all_satisfy(void *arg) +{ + test_context *ctx = arg; + rtems_event_set out; + rtems_status_code sc; + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out); + rtems_test_assert(sc == RTEMS_TIMEOUT); + rtems_test_assert(out == DEADBEEF); + + out = DEADBEEF; + sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_NO_WAIT, 0, &out); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(out == EVENTS); + + return ctx->hit; +} + static void test_timeout_before_all_satisfy(test_context *ctx) { rtems_status_code sc; - int resets = 0; puts( "Init - Trying to generate timeout before all satisfied " @@ -269,27 +297,14 @@ static void test_timeout_before_all_satisfy(test_context *ctx) ctx->hit = false; - interrupt_critical_section_test_support_initialize(NULL); - sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx); rtems_test_assert(sc == RTEMS_SUCCESSFUL); - while (!ctx->hit && resets < 2) { - rtems_event_set out; - - if (interrupt_critical_section_test_support_delay()) - resets++; - - out = DEADBEEF; - sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out); - rtems_test_assert(sc == RTEMS_TIMEOUT); - rtems_test_assert(out == DEADBEEF); - - out = DEADBEEF; - sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_NO_WAIT, 0, &out); - rtems_test_assert(sc == RTEMS_SUCCESSFUL); - rtems_test_assert(out == EVENTS); - } + interrupt_critical_section_test( + test_body_timeout_before_all_satisfy, + ctx, + NULL + ); sc = rtems_timer_cancel(ctx->timer); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -326,6 +341,7 @@ static rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 1 #define CONFIGURE_MAXIMUM_TIMERS 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_RTEMS_INIT_TASKS_TABLE diff --git a/testsuites/sptests/spintrcritical11/init.c b/testsuites/sptests/spintrcritical11/init.c index 0d8987537c..2a3f83a315 100644 --- a/testsuites/sptests/spintrcritical11/init.c +++ b/testsuites/sptests/spintrcritical11/init.c @@ -47,13 +47,21 @@ rtems_timer_service_routine test_release_from_isr( (void) rtems_event_send( Main_task, EVENTS_TO_SEND ); } +static bool test_body( void *arg ) +{ + rtems_event_set out; + + (void) arg; + + rtems_event_receive( EVENTS_TO_RECEIVE, RTEMS_EVENT_ANY, 1, &out ); + + return false; +} + rtems_task Init( rtems_task_argument ignored ) { - rtems_event_set out; - int resets; - TEST_BEGIN(); puts( "Init - Test may not be able to detect case is hit reliably" ); @@ -62,14 +70,7 @@ rtems_task Init( Main_task = rtems_task_self(); - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - for (resets=0 ; resets< 2 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - (void) rtems_event_receive( EVENTS_TO_RECEIVE, RTEMS_EVENT_ANY, 1, &out ); - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); TEST_END(); rtems_test_exit(0); @@ -83,6 +84,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 2 #define CONFIGURE_MAXIMUM_TIMERS 1 #define CONFIGURE_MAXIMUM_SEMAPHORES 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_RTEMS_INIT_TASKS_TABLE diff --git a/testsuites/sptests/spintrcritical13/init.c b/testsuites/sptests/spintrcritical13/init.c index 5a43dab6ef..7069938191 100644 --- a/testsuites/sptests/spintrcritical13/init.c +++ b/testsuites/sptests/spintrcritical13/init.c @@ -35,7 +35,6 @@ rtems_task Init(rtems_task_argument argument); rtems_timer_service_routine test_release_from_isr(rtems_id timer, void *arg); rtems_timer_service_routine TimerMethod(rtems_id timer, void *arg); -rtems_id Main_task; rtems_id Timer; rtems_timer_service_routine TimerMethod( @@ -53,12 +52,23 @@ rtems_timer_service_routine test_release_from_isr( (void) rtems_timer_fire_after( Timer, 10, TimerMethod, NULL ); } +static bool test_body( void *arg ) +{ + rtems_status_code sc; + + (void) arg; + + sc = TEST_DIRECTIVE( Timer, 10, TimerMethod, NULL ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + + return false; +} + rtems_task Init( rtems_task_argument ignored ) { rtems_status_code sc; - int resets; TEST_BEGIN(); @@ -81,17 +91,7 @@ rtems_task Init( sc = rtems_timer_create( rtems_build_name( 'P', 'E', 'R', '1' ), &Timer); directive_failed( sc, "rtems_timer_create" ); - Main_task = rtems_task_self(); - - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - for (resets=0 ; resets<10 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - sc = TEST_DIRECTIVE( Timer, 10, TimerMethod, NULL ); - directive_failed( sc, "rtems_timer_fire_after"); - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); TEST_END(); rtems_test_exit(0); @@ -108,6 +108,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 2 #endif #define CONFIGURE_MAXIMUM_TIMERS 2 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_MICROSECONDS_PER_TICK 1000 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION diff --git a/testsuites/sptests/spintrcritical15/init.c b/testsuites/sptests/spintrcritical15/init.c index ec84165bf8..b68098778a 100644 --- a/testsuites/sptests/spintrcritical15/init.c +++ b/testsuites/sptests/spintrcritical15/init.c @@ -23,7 +23,6 @@ rtems_task Secondary_task(rtems_task_argument ignored); #define INIT_PRIORITY 2 #define BLOCKER_PRIORITY 1 -rtems_id Main_task; rtems_id Secondary_task_id; rtems_id Semaphore; @@ -39,12 +38,26 @@ rtems_task Secondary_task( } } +static bool test_body( void *arg ) +{ + rtems_status_code sc; + + (void) arg; + + sc = rtems_task_restart( Secondary_task_id, 1 ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + + sc = rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 1 ); + rtems_test_assert( sc == RTEMS_TIMEOUT ); + + return false; +} + rtems_task Init( rtems_task_argument ignored ) { rtems_status_code sc; - int resets; TEST_BEGIN(); puts( @@ -77,20 +90,7 @@ rtems_task Init( sc = rtems_task_start( Secondary_task_id, Secondary_task, 0 ); directive_failed( sc, "rtems_task_start" ); - Main_task = rtems_task_self(); - - interrupt_critical_section_test_support_initialize( NULL ); - - for (resets=0 ; resets<10 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - sc = rtems_task_restart( Secondary_task_id, 1 ); - directive_failed( sc, "rtems_task_restart" ); - - sc = rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 1 ); - fatal_directive_status( sc, RTEMS_TIMEOUT, "rtems_semaphore_obtain" ); - } + interrupt_critical_section_test( test_body, NULL, NULL ); TEST_END(); rtems_test_exit(0); @@ -103,6 +103,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 2 #define CONFIGURE_MAXIMUM_SEMAPHORES 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_MICROSECONDS_PER_TICK 1000 #define CONFIGURE_INIT_TASK_PRIORITY INIT_PRIORITY #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_PREEMPT diff --git a/testsuites/sptests/spintrcritical16/init.c b/testsuites/sptests/spintrcritical16/init.c index f1858000bc..08eeb8b9b4 100644 --- a/testsuites/sptests/spintrcritical16/init.c +++ b/testsuites/sptests/spintrcritical16/init.c @@ -24,9 +24,8 @@ rtems_timer_service_routine test_release_from_isr(rtems_id timer, void *arg); Thread_blocking_operation_States getState(void); Thread_Control *Main_TCB; -rtems_id Main_task; rtems_id Semaphore; -volatile bool case_hit; +volatile bool case_hit = false; Thread_blocking_operation_States getState(void) { @@ -59,12 +58,23 @@ rtems_timer_service_routine test_release_from_isr( } } +static bool test_body( void *arg ) +{ + rtems_status_code sc; + + (void) arg; + + sc = rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 2 ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL || sc == RTEMS_TIMEOUT ); + + return case_hit; +} + rtems_task Init( rtems_task_argument ignored ) { rtems_status_code sc; - int resets; TEST_BEGIN(); puts( @@ -82,22 +92,9 @@ rtems_task Init( ); directive_failed( sc, "rtems_semaphore_create of SM1" ); - Main_task = rtems_task_self(); Main_TCB = _Thread_Get_executing(); - interrupt_critical_section_test_support_initialize( test_release_from_isr ); - - case_hit = false; - - for (resets=0 ; !case_hit && resets<10 ;) { - if ( interrupt_critical_section_test_support_delay() ) - resets++; - - sc = rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 2 ); - if ( sc == RTEMS_SUCCESSFUL ) - break; - fatal_directive_status( sc, RTEMS_TIMEOUT, "rtems_semaphore_obtain" ); - } + interrupt_critical_section_test( test_body, NULL, test_release_from_isr ); if ( case_hit ) { puts( "Init - Case hit" ); @@ -117,6 +114,7 @@ rtems_task Init( #define CONFIGURE_MAXIMUM_TASKS 1 #define CONFIGURE_MAXIMUM_TIMERS 1 #define CONFIGURE_MAXIMUM_SEMAPHORES 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_MICROSECONDS_PER_TICK 1000 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION diff --git a/testsuites/sptests/spintrcritical18/init.c b/testsuites/sptests/spintrcritical18/init.c index c34f4b95c7..f621d21280 100644 --- a/testsuites/sptests/spintrcritical18/init.c +++ b/testsuites/sptests/spintrcritical18/init.c @@ -95,11 +95,19 @@ static void high_priority_task( rtems_task_argument arg ) } } +static bool test_body( void *arg ) +{ + test_context *ctx = arg; + + wake_up( ctx->middle_priority_task ); + + return false; +} + static void Init( rtems_task_argument ignored ) { test_context *ctx = &global_ctx; rtems_status_code sc; - int resets = 0; TEST_BEGIN(); @@ -137,17 +145,7 @@ static void Init( rtems_task_argument ignored ) ); ASSERT_SC(sc); - interrupt_critical_section_test_support_initialize( - active_high_priority_task - ); - - while ( resets < 3 ) { - if ( interrupt_critical_section_test_support_delay() ) { - ++resets; - } - - wake_up( ctx->middle_priority_task ); - } + interrupt_critical_section_test( test_body, ctx, active_high_priority_task ); TEST_END(); @@ -161,6 +159,7 @@ static void Init( rtems_task_argument ignored ) #define CONFIGURE_MAXIMUM_TASKS 3 #define CONFIGURE_MAXIMUM_TIMERS 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_LOW #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES diff --git a/testsuites/sptests/spintrcritical20/init.c b/testsuites/sptests/spintrcritical20/init.c index cae8fdbc4d..daa8ac7f7e 100644 --- a/testsuites/sptests/spintrcritical20/init.c +++ b/testsuites/sptests/spintrcritical20/init.c @@ -63,10 +63,52 @@ static void release_semaphore(rtems_id timer, void *arg) rtems_test_assert(sc == RTEMS_SUCCESSFUL); } +static bool test_body(void *arg) +{ + test_context *ctx = arg; + int busy; + + _Thread_Disable_dispatch(); + + rtems_test_assert( + ctx->semaphore_task_tcb->Wait.return_code + == CORE_SEMAPHORE_STATUS_SUCCESSFUL + ); + + /* + * Spend some time to make it more likely that we hit the test condition + * below. + */ + for (busy = 0; busy < 1000; ++busy) { + __asm__ volatile (""); + } + + if (ctx->semaphore_task_tcb->Wait.queue == NULL) { + ctx->thread_queue_was_null = true; + } + + _Thread_queue_Process_timeout(ctx->semaphore_task_tcb); + + switch (ctx->semaphore_task_tcb->Wait.return_code) { + case CORE_SEMAPHORE_STATUS_SUCCESSFUL: + ctx->status_was_successful = true; + break; + case CORE_SEMAPHORE_TIMEOUT: + ctx->status_was_timeout = true; + break; + default: + rtems_test_assert(0); + break; + } + + _Thread_Enable_dispatch(); + + return false; +} + static void Init(rtems_task_argument ignored) { test_context *ctx = &ctx_instance; - int resets = 0; rtems_status_code sc; TEST_BEGIN(); @@ -99,42 +141,7 @@ static void Init(rtems_task_argument ignored) ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); - interrupt_critical_section_test_support_initialize( - release_semaphore - ); - - while (resets < 3) { - if (interrupt_critical_section_test_support_delay()) { - ++resets; - } - - _Thread_Disable_dispatch(); - - rtems_test_assert( - ctx->semaphore_task_tcb->Wait.return_code - == CORE_SEMAPHORE_STATUS_SUCCESSFUL - ); - - if (ctx->semaphore_task_tcb->Wait.queue == NULL) { - ctx->thread_queue_was_null = true; - } - - _Thread_queue_Process_timeout(ctx->semaphore_task_tcb); - - switch (ctx->semaphore_task_tcb->Wait.return_code) { - case CORE_SEMAPHORE_STATUS_SUCCESSFUL: - ctx->status_was_successful = true; - break; - case CORE_SEMAPHORE_TIMEOUT: - ctx->status_was_timeout = true; - break; - default: - rtems_test_assert(0); - break; - } - - _Thread_Enable_dispatch(); - } + interrupt_critical_section_test(test_body, ctx, release_semaphore); rtems_test_assert(ctx->thread_queue_was_null); rtems_test_assert(ctx->status_was_successful); @@ -153,6 +160,7 @@ static void Init(rtems_task_argument ignored) #define CONFIGURE_MAXIMUM_SEMAPHORES 1 #define CONFIGURE_MAXIMUM_TASKS 2 #define CONFIGURE_MAXIMUM_TIMERS 1 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 #define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_MASTER #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES diff --git a/testsuites/sptests/spintrcritical_support/intrcritical.c b/testsuites/sptests/spintrcritical_support/intrcritical.c index d044d141b4..b6b250726c 100644 --- a/testsuites/sptests/spintrcritical_support/intrcritical.c +++ b/testsuites/sptests/spintrcritical_support/intrcritical.c @@ -14,14 +14,23 @@ #include <tmacros.h> #include <intrcritical.h> -static uint32_t Maximum; -static uint32_t Maximum_current; -static rtems_id Timer; -static rtems_timer_service_routine (*TSR)( rtems_id, void * ); +#define INTERRUPT_CRITICAL_NAME rtems_build_name( 'I', 'C', 'R', 'I' ) -static uint32_t interrupt_critical_remaining_units_of_tick( void ) +typedef struct { + rtems_interval minimum; + rtems_interval maximum; + rtems_interval maximum_current; + rtems_timer_service_routine_entry tsr; + rtems_id timer; + uint64_t t0; + uint64_t t1; +} interrupt_critical_control; + +static interrupt_critical_control interrupt_critical; + +static rtems_interval estimate_busy_loop_maximum( void ) { - uint32_t units = 0; + rtems_interval units = 0; rtems_interval initial = rtems_clock_get_ticks_since_boot(); while ( initial == rtems_clock_get_ticks_since_boot() ) { @@ -31,61 +40,204 @@ static uint32_t interrupt_critical_remaining_units_of_tick( void ) return units; } -static bool interrupt_critical_busy_wait( void ) +static rtems_interval wait_for_tick_change( void ) { - uint32_t max = Maximum_current; - uint32_t unit = 0; rtems_interval initial = rtems_clock_get_ticks_since_boot(); + rtems_interval now; + + do { + now = rtems_clock_get_ticks_since_boot(); + } while ( now == initial ); - while ( unit < max && initial == rtems_clock_get_ticks_since_boot() ) { - ++unit; + return now; +} + +/* + * It is important that we use actually use the same busy() function at the + * various places, since otherwise the obtained maximum value might be wrong. + * So the compiler must not inline this function. + */ +static __attribute__( ( noinline ) ) void busy( rtems_interval max ) +{ + rtems_interval i; + + for ( i = 0; i < max; ++i ) { + __asm__ volatile (""); } +} - if ( max > 0 ) { - Maximum_current = max - 1; +static bool interrupt_critical_busy_wait( void ) +{ + rtems_interval max = interrupt_critical.maximum_current; + bool reset = max <= interrupt_critical.minimum; - return false; + if ( reset ) { + interrupt_critical.maximum_current = interrupt_critical.maximum; } else { - Maximum_current = Maximum; - - return true; + interrupt_critical.maximum_current = max - 1; } + + busy( max ); + + return reset; } void interrupt_critical_section_test_support_initialize( - rtems_timer_service_routine (*tsr)( rtems_id, void * ) + rtems_timer_service_routine_entry tsr ) { - Timer = 0; - TSR = tsr; - if ( tsr ) { - rtems_status_code rc; - - puts( "Support - rtems_timer_create - creating timer 1" ); - rc = rtems_timer_create( rtems_build_name( 'T', 'M', '1', ' ' ), &Timer ); - directive_failed( rc, "rtems_timer_create" ); + rtems_interval last; + rtems_interval now; + rtems_interval a; + rtems_interval b; + rtems_interval m; + + interrupt_critical.tsr = tsr; + + if ( tsr != NULL && interrupt_critical.timer == 0 ) { + rtems_status_code sc = rtems_timer_create( + INTERRUPT_CRITICAL_NAME, + &interrupt_critical.timer + ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); } - /* Wait for tick change */ - interrupt_critical_remaining_units_of_tick(); + /* Choose a lower bound */ + a = 1; + + /* Estimate an upper bound */ + + wait_for_tick_change(); + b = 2 * estimate_busy_loop_maximum(); + + while ( true ) { + last = wait_for_tick_change(); + busy( b ); + now = rtems_clock_get_ticks_since_boot(); + + if ( now != last ) { + break; + } - /* Get units for a hole tick */ - Maximum = interrupt_critical_remaining_units_of_tick(); - Maximum_current = Maximum; + b *= 2; + last = now; + } + + /* Find a good value */ + do { + m = ( a + b ) / 2; + + last = wait_for_tick_change(); + busy( m ); + now = rtems_clock_get_ticks_since_boot(); + + if ( now != last ) { + b = m; + } else { + a = m; + } + } while ( b - a > 1 ); + + interrupt_critical.minimum = 0; + interrupt_critical.maximum = m; + interrupt_critical.maximum_current = m; +} - #if 0 - printf( "%d 0x%08x units\n", Maximum, Maximum ); - #endif +static void timer_fire_after(void) +{ + if ( interrupt_critical.tsr != NULL ) { + rtems_status_code sc = rtems_timer_fire_after( + interrupt_critical.timer, + 1, + interrupt_critical.tsr, + NULL + ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + } } bool interrupt_critical_section_test_support_delay(void) { - if (TSR) { - rtems_status_code rc; + timer_fire_after(); - rc = rtems_timer_fire_after( Timer, 1, TSR, NULL ); - directive_failed( rc, "timer_fire_after failed" ); + return interrupt_critical_busy_wait(); +} + +static bool is_idle( const Thread_Control *thread ) +{ + return thread->Start.entry_point + == (Thread_Entry) rtems_configuration_get_idle_task(); +} + +static void thread_switch( Thread_Control *executing, Thread_Control *heir ) +{ + (void) executing; + (void) heir; + + if ( interrupt_critical.t1 == 0 && is_idle( heir ) ) { + interrupt_critical.t1 = rtems_clock_get_uptime_nanoseconds(); } +} - return interrupt_critical_busy_wait(); +static const rtems_extensions_table extensions = { + .thread_switch = thread_switch +}; + +bool interrupt_critical_section_test( + bool ( *test_body )( void * ), + void *test_body_arg, + rtems_timer_service_routine_entry tsr +) +{ + bool done; + rtems_status_code sc; + rtems_id id; + uint64_t delta; + rtems_interval busy_delta; + int retries = 3; + + interrupt_critical_section_test_support_initialize( tsr ); + + sc = rtems_extension_create( + INTERRUPT_CRITICAL_NAME, + &extensions, + &id + ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + + wait_for_tick_change(); + timer_fire_after(); + + /* Get estimate for test body duration */ + interrupt_critical.t0 = rtems_clock_get_uptime_nanoseconds(); + done = ( *test_body )( test_body_arg ); + if ( interrupt_critical.t1 == 0 ) { + interrupt_critical.t1 = rtems_clock_get_uptime_nanoseconds(); + } + + /* Update minimum */ + + delta = interrupt_critical.t1 - interrupt_critical.t0; + busy_delta = (rtems_interval) + ( ( interrupt_critical.maximum * ( 2 * delta ) ) + / rtems_configuration_get_nanoseconds_per_tick() ); + + if ( busy_delta < interrupt_critical.maximum ) { + interrupt_critical.minimum = interrupt_critical.maximum - busy_delta; + } + + sc = rtems_extension_delete( id ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + + while ( !done && retries >= 0 ) { + wait_for_tick_change(); + + if ( interrupt_critical_section_test_support_delay() ) { + --retries; + } + + done = ( *test_body )( test_body_arg ); + } + + return done; } diff --git a/testsuites/sptests/spintrcritical_support/intrcritical.h b/testsuites/sptests/spintrcritical_support/intrcritical.h index 7989b3f7e2..aca1ee0f2c 100644 --- a/testsuites/sptests/spintrcritical_support/intrcritical.h +++ b/testsuites/sptests/spintrcritical_support/intrcritical.h @@ -16,7 +16,7 @@ * @param[in] tsr is the optional timer service routine to fire */ void interrupt_critical_section_test_support_initialize( - rtems_timer_service_routine (*tsr)( rtems_id, void * ) + rtems_timer_service_routine_entry tsr ); /** @@ -29,5 +29,24 @@ void interrupt_critical_section_test_support_initialize( */ bool interrupt_critical_section_test_support_delay(void); +/** + * @brief Interrupt critical section test. + * + * This function first estimates the test body duration and then repeatedly + * calls the test body with varying times to the next clock tick interrupt. + * + * @param[in] test_body The test body function. In case the test body returns + * true, then the test iteration stops. + * @param[in] test_body_arg The argument for the test body function. + * @param[in] tsr An optional timer service routine. + * + * @return The test body return status. + */ +bool interrupt_critical_section_test( + bool ( *test_body )( void * ), + void *test_body_arg, + rtems_timer_service_routine_entry tsr +); + #endif |