File indexing completed on 2025-05-11 08:24:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #ifdef HAVE_CONFIG_H
0032 #include "config.h"
0033 #endif
0034
0035 #include <string.h>
0036
0037 #include <rtems/test.h>
0038 #include <rtems/test-info.h>
0039
0040 #include <rtems/score/watchdogimpl.h>
0041 #include <rtems/rtems/ratemonimpl.h>
0042
0043 const char rtems_test_name[] = "SPINTRCRITICAL 8";
0044
0045 typedef struct {
0046 rtems_id period;
0047 Thread_Control *thread;
0048 } test_context;
0049
0050 static rtems_rate_monotonic_period_states getState(test_context *ctx)
0051 {
0052 Rate_monotonic_Control *the_period;
0053 ISR_lock_Context lock_context;
0054
0055 the_period = _Rate_monotonic_Get( ctx->period, &lock_context );
0056 T_quiet_assert_not_null( the_period );
0057 _ISR_lock_ISR_enable( &lock_context );
0058
0059 return the_period->state;
0060 }
0061
0062 static T_interrupt_test_state interrupt( void *arg )
0063 {
0064 test_context *ctx;
0065 Per_CPU_Control *cpu_self;
0066 Watchdog_Header *header;
0067 Watchdog_Control *watchdog;
0068 T_interrupt_test_state state;
0069 Thread_Wait_flags flags;
0070 ISR_Level level;
0071 rtems_rate_monotonic_period_states previous_period_state;
0072
0073 state = T_interrupt_test_get_state();
0074
0075 if ( state != T_INTERRUPT_TEST_ACTION ) {
0076 return T_INTERRUPT_TEST_CONTINUE;
0077 }
0078
0079 ctx = arg;
0080 cpu_self = _Per_CPU_Get();
0081 header = &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_TICKS ];
0082 watchdog = (Watchdog_Control *) header->first;
0083 T_quiet_assert_not_null( watchdog );
0084 T_quiet_eq_u64( watchdog->expire, cpu_self->Watchdog.ticks );
0085 T_quiet_eq_ptr( watchdog->routine, _Rate_monotonic_Timeout );
0086
0087 flags = _Thread_Wait_flags_get( ctx->thread );
0088
0089 _ISR_Local_disable( level );
0090 _Watchdog_Per_CPU_remove( watchdog, cpu_self, header );
0091 _ISR_Local_enable( level );
0092
0093 previous_period_state = getState( ctx );
0094 ( *watchdog->routine )( watchdog );
0095
0096 if ( flags == RATE_MONOTONIC_INTEND_TO_BLOCK ) {
0097 T_quiet_eq_int( previous_period_state, RATE_MONOTONIC_ACTIVE );
0098 T_quiet_eq_int( getState( ctx ), RATE_MONOTONIC_ACTIVE );
0099 state = T_INTERRUPT_TEST_DONE;
0100 } else if ( flags == THREAD_WAIT_STATE_READY ) {
0101 T_quiet_true(
0102 previous_period_state == RATE_MONOTONIC_ACTIVE
0103 || previous_period_state == RATE_MONOTONIC_EXPIRED
0104 );
0105 state = T_INTERRUPT_TEST_EARLY;
0106 } else {
0107 T_quiet_eq_int( flags, RATE_MONOTONIC_BLOCKED );
0108 T_quiet_true(
0109 previous_period_state == RATE_MONOTONIC_ACTIVE
0110 || previous_period_state == RATE_MONOTONIC_EXPIRED
0111 );
0112 state = T_INTERRUPT_TEST_LATE;
0113 }
0114
0115 return state;
0116 }
0117
0118 static void prepare( void *arg )
0119 {
0120 test_context *ctx;
0121 rtems_status_code sc;
0122
0123 ctx = arg;
0124
0125 do {
0126 sc = rtems_rate_monotonic_cancel( ctx->period );
0127 T_quiet_rsc_success( sc );
0128
0129 sc = rtems_rate_monotonic_period( ctx->period, 1 );
0130 T_quiet_rsc_success( sc );
0131
0132
0133
0134
0135
0136
0137 sc = rtems_rate_monotonic_period( ctx->period, 1 );
0138 } while ( sc != RTEMS_SUCCESSFUL );
0139 }
0140
0141 static void action( void *arg )
0142 {
0143 test_context *ctx;
0144 rtems_status_code sc;
0145
0146 ctx = arg;
0147
0148 sc = rtems_rate_monotonic_period( ctx->period, 1 );
0149 T_quiet_true( sc == RTEMS_SUCCESSFUL || sc == RTEMS_TIMEOUT );
0150
0151 T_interrupt_test_busy_wait_for_interrupt();
0152 }
0153
0154 static const T_interrupt_test_config config = {
0155 .prepare = prepare,
0156 .action = action,
0157 .interrupt = interrupt,
0158 .max_iteration_count = 10000
0159 };
0160
0161 T_TEST_CASE( RateMonotonicPeriodInterrupt )
0162 {
0163 test_context ctx;
0164 rtems_status_code sc;
0165 T_interrupt_test_state state;
0166
0167 memset( &ctx, 0 , sizeof( ctx ) );
0168 ctx.thread = _Thread_Get_executing();
0169
0170 sc = rtems_rate_monotonic_create(
0171 rtems_build_name( 'P', 'E', 'R', '1' ),
0172 &ctx.period
0173 );
0174 T_rsc_success( sc );
0175
0176 state = T_interrupt_test( &config, &ctx );
0177 T_eq_int( state, T_INTERRUPT_TEST_DONE );
0178
0179 sc = rtems_rate_monotonic_delete( ctx.period );
0180 T_rsc_success( sc );
0181 }
0182
0183 static rtems_task Init( rtems_task_argument argument )
0184 {
0185 rtems_test_run( argument, TEST_STATE );
0186 }
0187
0188
0189
0190 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0191 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0192
0193 #define CONFIGURE_MAXIMUM_TASKS 1
0194 #define CONFIGURE_MAXIMUM_PERIODS 1
0195
0196 #define CONFIGURE_MICROSECONDS_PER_TICK 10000
0197 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0198
0199 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0200
0201 #define CONFIGURE_INIT
0202 #include <rtems/confdefs.h>
0203
0204