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 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include <rtems/test.h>
0033 #include <rtems/test-info.h>
0034
0035 const char rtems_test_name[] = "SPINTRCRITICAL 18";
0036
0037 #define WAKE_UP RTEMS_EVENT_0
0038
0039 #define PRIORITY_LOW 3
0040
0041 #define PRIORITY_MIDDLE 2
0042
0043 #define PRIORITY_HIGH 1
0044
0045 typedef struct {
0046 rtems_id middle_priority_task;
0047 rtems_id high_priority_task;
0048 bool high_priority_task_activated;
0049 volatile bool early;
0050 volatile bool switching;
0051 volatile bool late;
0052 long potential_hits;
0053 } test_context;
0054
0055 static void wake_up( rtems_id task )
0056 {
0057 rtems_status_code sc;
0058
0059 sc = rtems_event_send( task, WAKE_UP );
0060 T_quiet_rsc_success( sc );
0061 }
0062
0063 static void wait_for_wake_up( void )
0064 {
0065 rtems_status_code sc;
0066 rtems_event_set events;
0067
0068 sc = rtems_event_receive(
0069 WAKE_UP,
0070 RTEMS_EVENT_ALL | RTEMS_WAIT,
0071 RTEMS_NO_TIMEOUT,
0072 &events
0073 );
0074 T_quiet_rsc_success( sc );
0075 T_quiet_eq_u32( events, WAKE_UP );
0076 }
0077
0078 static T_interrupt_test_state active_high_priority_task( void *arg )
0079 {
0080 test_context *ctx = arg;
0081 T_interrupt_test_state state;
0082
0083 state = T_interrupt_test_get_state();
0084
0085 if ( state != T_INTERRUPT_TEST_ACTION ) {
0086 return T_INTERRUPT_TEST_CONTINUE;
0087 }
0088
0089 T_quiet_false( ctx->high_priority_task_activated );
0090 ctx->high_priority_task_activated = true;
0091 wake_up( ctx->high_priority_task );
0092
0093 if ( ctx->early ) {
0094 state = T_INTERRUPT_TEST_EARLY;
0095 } else if ( ctx->late ) {
0096 state = T_INTERRUPT_TEST_LATE;
0097 } else {
0098 ++ctx->potential_hits;
0099
0100 if ( ctx->potential_hits > 13 ) {
0101 state = T_INTERRUPT_TEST_DONE;
0102 } else {
0103 state = T_INTERRUPT_TEST_CONTINUE;
0104 }
0105 }
0106
0107 return state;
0108 }
0109
0110 static void middle_priority_task( rtems_task_argument arg )
0111 {
0112 test_context *ctx = (test_context *) arg;
0113
0114 while ( true ) {
0115 wait_for_wake_up();
0116 ctx->late = true;
0117
0118 T_quiet_false( ctx->high_priority_task_activated );
0119 }
0120 }
0121
0122 static void high_priority_task( rtems_task_argument arg )
0123 {
0124 test_context *ctx = (test_context *) arg;
0125
0126 while ( true ) {
0127 wait_for_wake_up();
0128
0129 T_quiet_true( ctx->high_priority_task_activated );
0130 ctx->high_priority_task_activated = false;
0131 }
0132 }
0133
0134 static void prepare( void *arg )
0135 {
0136 test_context *ctx = arg;
0137
0138 ctx->early = true;
0139 ctx->switching = false;
0140 ctx->late = false;
0141 }
0142
0143 static void action( void *arg )
0144 {
0145 test_context *ctx = arg;
0146
0147 ctx->early = false;
0148 wake_up( ctx->middle_priority_task );
0149 }
0150
0151 static void blocked( void *arg )
0152 {
0153 test_context *ctx = arg;
0154 T_interrupt_test_state state;
0155
0156 state = T_interrupt_test_change_state(
0157 T_INTERRUPT_TEST_ACTION,
0158 T_INTERRUPT_TEST_LATE
0159 );
0160
0161 if ( state == T_INTERRUPT_TEST_ACTION ) {
0162 ctx->switching = true;
0163 T_busy( 100 );
0164 ctx->switching = false;
0165 }
0166 }
0167
0168 static const T_interrupt_test_config config = {
0169 .prepare = prepare,
0170 .action = action,
0171 .interrupt = active_high_priority_task,
0172 .blocked = blocked,
0173 .max_iteration_count = 10000
0174 };
0175
0176 T_TEST_CASE(InterruptDuringThreadDispatch)
0177 {
0178 T_interrupt_test_state state;
0179 test_context ctx;
0180 rtems_status_code sc;
0181
0182 memset( &ctx, 0, sizeof( ctx ) );
0183
0184 sc = rtems_task_create(
0185 rtems_build_name( 'H', 'I', 'G', 'H' ),
0186 PRIORITY_HIGH,
0187 RTEMS_MINIMUM_STACK_SIZE,
0188 RTEMS_DEFAULT_MODES,
0189 RTEMS_DEFAULT_ATTRIBUTES,
0190 &ctx.high_priority_task
0191 );
0192 T_assert_rsc_success( sc );
0193
0194 sc = rtems_task_start(
0195 ctx.high_priority_task,
0196 high_priority_task,
0197 (rtems_task_argument) &ctx
0198 );
0199 T_assert_rsc_success( sc );
0200
0201 sc = rtems_task_create(
0202 rtems_build_name( 'M', 'I', 'D', 'L' ),
0203 PRIORITY_MIDDLE,
0204 RTEMS_MINIMUM_STACK_SIZE,
0205 RTEMS_DEFAULT_MODES,
0206 RTEMS_DEFAULT_ATTRIBUTES,
0207 &ctx.middle_priority_task
0208 );
0209 T_assert_rsc_success( sc );
0210
0211 sc = rtems_task_start(
0212 ctx.middle_priority_task,
0213 middle_priority_task,
0214 (rtems_task_argument) &ctx
0215 );
0216 T_assert_rsc_success( sc );
0217
0218 state = T_interrupt_test( &config, &ctx );
0219 T_eq_int( state, T_INTERRUPT_TEST_DONE );
0220
0221 sc = rtems_task_delete( ctx.high_priority_task );
0222 T_rsc_success( sc );
0223
0224 sc = rtems_task_delete( ctx.middle_priority_task );
0225 T_rsc_success( sc );
0226 }
0227
0228 static rtems_task Init( rtems_task_argument argument )
0229 {
0230 rtems_test_run( argument, TEST_STATE );
0231 }
0232
0233 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0234 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0235
0236 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0237
0238 #define CONFIGURE_MAXIMUM_TASKS 3
0239
0240 #define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_LOW
0241 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
0242 #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
0243
0244 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0245
0246 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0247
0248 #define CONFIGURE_INIT
0249
0250 #include <rtems/confdefs.h>