[rtems commit] tests: Rework interrupt critical tests
Sebastian Huber
sebh at rtems.org
Wed Sep 10 05:08:05 UTC 2014
Module: rtems
Branch: master
Commit: 802808900053e732881795d0d748d8fdc2a54e13
Changeset: http://git.rtems.org/rtems/commit/?id=802808900053e732881795d0d748d8fdc2a54e13
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Mon Sep 8 15:18:07 2014 +0200
tests: Rework interrupt critical tests
This avoids test durations of more than one hour on fast targets, since
fast targets can count a lot during one clock tick period, so the minor
loop iteration count was quite high. Estimate now the test body
duration to iterate only through the interesting time window.
Add and use interrupt_critical_section_test().
---
testsuites/psxtests/psxintrcritical01/init.c | 42 ++--
testsuites/sptests/spintrcritical01/init.c | 38 ++--
testsuites/sptests/spintrcritical06/init.c | 28 ++-
testsuites/sptests/spintrcritical08/init.c | 70 ++++--
testsuites/sptests/spintrcritical09/init.c | 24 +-
testsuites/sptests/spintrcritical10/init.c | 120 ++++++-----
testsuites/sptests/spintrcritical11/init.c | 24 +-
testsuites/sptests/spintrcritical13/init.c | 27 ++-
testsuites/sptests/spintrcritical15/init.c | 33 ++--
testsuites/sptests/spintrcritical16/init.c | 32 ++--
testsuites/sptests/spintrcritical18/init.c | 23 +-
testsuites/sptests/spintrcritical20/init.c | 82 ++++---
.../sptests/spintrcritical_support/intrcritical.c | 230 ++++++++++++++++----
.../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 2c46209..a6a64ba 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 7db5143..dc36aee 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 96c2a91..8d51922 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 e286e86..7a1353d 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 90948ec..bc942d5 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 f3883f7..8959e5c 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 0d89875..2a3f83a 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 5a43dab..7069938 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 ec84165..b680987 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 f185800..08eeb8b 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 c34f4b9..f621d21 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 cae8fdb..daa8ac7 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 d044d14..b6b2507 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 7989b3f..aca1ee0 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
More information about the vc
mailing list