File indexing completed on 2025-05-11 08:24:45
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
0032
0033
0034
0035
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #define CONFIGURE_INIT
0041 #include "system.h"
0042
0043 #include <rtems/sysinit.h>
0044
0045 const char rtems_test_name[] = "SP 37";
0046
0047
0048 void test_interrupt_inline(void);
0049 void check_isr_in_progress_inline(void);
0050 rtems_task blocked_task(rtems_task_argument argument);
0051 rtems_timer_service_routine test_unblock_task(
0052 rtems_id timer,
0053 void *arg
0054 );
0055 rtems_timer_service_routine test_unblock_task(
0056 rtems_id timer,
0057 void *arg
0058 );
0059 void check_isr_worked(
0060 char *s,
0061 int result
0062 );
0063 rtems_timer_service_routine test_isr_in_progress(
0064 rtems_id timer,
0065 void *arg
0066 );
0067
0068
0069
0070 #define TEST_ISR_EVENT RTEMS_EVENT_0
0071
0072 static uint32_t boot_isr_level;
0073
0074 static void set_boot_isr_level( void )
0075 {
0076 boot_isr_level = _ISR_Get_level();
0077 }
0078
0079 RTEMS_SYSINIT_ITEM(
0080 set_boot_isr_level,
0081 RTEMS_SYSINIT_DEVICE_DRIVERS,
0082 RTEMS_SYSINIT_ORDER_MIDDLE
0083 );
0084
0085 typedef struct {
0086 ISR_Level actual_level;
0087 rtems_id master_task_id;
0088 } test_isr_level_context;
0089
0090 static void isr_level_check_task( rtems_task_argument arg )
0091 {
0092 test_isr_level_context *ctx = (test_isr_level_context *) arg;
0093 rtems_status_code sc;
0094
0095 ctx->actual_level = _ISR_Get_level();
0096
0097 sc = rtems_event_send( ctx->master_task_id, TEST_ISR_EVENT );
0098 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0099
0100 ( void ) rtems_task_suspend( RTEMS_SELF );
0101 rtems_test_assert( 0 );
0102 }
0103
0104 static void test_isr_level_for_new_threads( ISR_Level last_proper_level )
0105 {
0106 ISR_Level mask = CPU_MODES_INTERRUPT_MASK;
0107 ISR_Level current;
0108 test_isr_level_context ctx = {
0109 .master_task_id = rtems_task_self()
0110 };
0111
0112 for ( current = 0 ; current <= mask ; ++current ) {
0113 rtems_mode initial_modes;
0114 rtems_id id;
0115 rtems_status_code sc;
0116 rtems_event_set events;
0117
0118 initial_modes = RTEMS_INTERRUPT_LEVEL(current);
0119
0120 #if CPU_ENABLE_ROBUST_THREAD_DISPATCH == TRUE
0121 if ( initial_modes != 0 ) {
0122 break;
0123 }
0124 #endif
0125
0126 ctx.actual_level = 0xffffffff;
0127
0128 sc = rtems_task_create(
0129 rtems_build_name('I', 'S', 'R', 'L'),
0130 RTEMS_MINIMUM_PRIORITY,
0131 RTEMS_MINIMUM_STACK_SIZE,
0132 initial_modes,
0133 RTEMS_DEFAULT_ATTRIBUTES,
0134 &id
0135 );
0136 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0137
0138 sc = rtems_task_start(
0139 id,
0140 isr_level_check_task,
0141 (rtems_task_argument) &ctx
0142 );
0143 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0144
0145 sc = rtems_event_receive(
0146 TEST_ISR_EVENT,
0147 RTEMS_EVENT_ALL | RTEMS_WAIT,
0148 RTEMS_NO_TIMEOUT,
0149 &events
0150 );
0151 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0152 rtems_test_assert( events == TEST_ISR_EVENT );
0153
0154 if ( current <= last_proper_level ) {
0155 rtems_test_assert( ctx.actual_level == current );
0156 } else {
0157 rtems_test_assert( ctx.actual_level == last_proper_level );
0158 }
0159
0160 sc = rtems_task_delete( id ) ;
0161 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0162 }
0163 }
0164
0165 static void test_isr_level( void )
0166 {
0167 ISR_Level mask = CPU_MODES_INTERRUPT_MASK;
0168 ISR_Level normal = _ISR_Get_level();
0169 ISR_Level current = 0;
0170 ISR_Level last_proper_level;
0171
0172
0173 rtems_test_assert( boot_isr_level != 0 );
0174
0175 _ISR_Set_level( current );
0176 rtems_test_assert( _ISR_Get_level() == current );
0177
0178 for ( current = current + 1 ; current <= mask ; ++current ) {
0179 ISR_Level actual;
0180
0181 _ISR_Set_level( current );
0182
0183 actual = _ISR_Get_level();
0184 rtems_test_assert( actual == current || actual == ( current - 1 ) );
0185
0186 if ( _ISR_Get_level() != current ) {
0187 break;
0188 }
0189 }
0190
0191 last_proper_level = current - 1;
0192
0193 for ( current = current + 1 ; current <= mask ; ++current ) {
0194 _ISR_Set_level( current );
0195 rtems_test_assert( _ISR_Get_level() == current );
0196 }
0197
0198 _ISR_Set_level( normal );
0199
0200
0201
0202
0203
0204 test_isr_level_for_new_threads( last_proper_level );
0205 }
0206
0207 static void test_isr_locks( void )
0208 {
0209 static const char name[] = "test";
0210 ISR_Level normal_interrupt_level = _ISR_Get_level();
0211 #if ISR_LOCK_NEEDS_OBJECT
0212 ISR_lock_Control initialized = ISR_LOCK_INITIALIZER( name );
0213 ISR_lock_Control zero_initialized;
0214 union {
0215 ISR_lock_Control lock;
0216 uint8_t bytes[ sizeof( ISR_lock_Control ) ];
0217 } container;
0218 size_t i;
0219 const uint8_t *bytes;
0220 #endif
0221 ISR_lock_Context lock_context;
0222 ISR_Level interrupt_level;
0223
0224 #if ISR_LOCK_NEEDS_OBJECT
0225 memset( &container, 0xff, sizeof( container ) );
0226 #endif
0227
0228 _ISR_lock_Initialize( &container.lock, name );
0229
0230 #if ISR_LOCK_NEEDS_OBJECT
0231 bytes = (const uint8_t *) &initialized;
0232
0233 for ( i = 0; i < sizeof( container ); ++i ) {
0234 if ( container.bytes[ i ] != 0xff ) {
0235 rtems_test_assert( container.bytes[ i ] == bytes[ i ] );
0236 }
0237 }
0238
0239 memset( &zero_initialized, 0, sizeof( zero_initialized ) );
0240 _ISR_lock_Set_name( &zero_initialized, name );
0241 bytes = (const uint8_t *) &zero_initialized;
0242
0243 for ( i = 0; i < sizeof( container ); ++i ) {
0244 if ( container.bytes[ i ] != 0xff ) {
0245 rtems_test_assert( container.bytes[ i ] == bytes[ i ] );
0246 }
0247 }
0248 #endif
0249
0250 _ISR_lock_ISR_disable_and_acquire( &container.lock, &lock_context );
0251 rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
0252 _ISR_lock_Release_and_ISR_enable( &container.lock, &lock_context );
0253
0254 rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
0255
0256 _ISR_lock_ISR_disable( &lock_context );
0257 rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
0258 _ISR_lock_ISR_enable( &lock_context );
0259
0260 rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
0261
0262 #if defined(RTEMS_DEBUG)
0263 _ISR_lock_ISR_disable( &lock_context );
0264 #endif
0265 interrupt_level = _ISR_Get_level();
0266 _ISR_lock_Acquire( &container.lock, &lock_context );
0267 rtems_test_assert( interrupt_level == _ISR_Get_level() );
0268 #if !defined(RTEMS_DEBUG)
0269 rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
0270 #endif
0271 _ISR_lock_Release( &container.lock, &lock_context );
0272 rtems_test_assert( interrupt_level == _ISR_Get_level() );
0273 #if defined(RTEMS_DEBUG)
0274 _ISR_lock_ISR_enable( &lock_context );
0275 #endif
0276
0277 rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
0278
0279 _ISR_lock_Destroy( &container.lock );
0280 _ISR_lock_Destroy( &initialized );
0281 }
0282
0283 static rtems_mode get_interrupt_level( void )
0284 {
0285 rtems_status_code sc;
0286 rtems_mode mode;
0287
0288 sc = rtems_task_mode( RTEMS_CURRENT_MODE, RTEMS_CURRENT_MODE, &mode );
0289 rtems_test_assert( sc == RTEMS_SUCCESSFUL );
0290
0291 return mode & RTEMS_INTERRUPT_MASK;
0292 }
0293
0294 static void test_interrupt_locks( void )
0295 {
0296 rtems_mode normal_interrupt_level = get_interrupt_level();
0297 rtems_interrupt_lock initialized = RTEMS_INTERRUPT_LOCK_INITIALIZER("test");
0298 union {
0299 rtems_interrupt_lock lock;
0300 uint8_t bytes[ sizeof( rtems_interrupt_lock ) ];
0301 } container = {0};
0302 rtems_interrupt_lock_context lock_context;
0303 size_t i;
0304 const uint8_t *initialized_bytes;
0305
0306 rtems_interrupt_lock_initialize( &container.lock, "test" );
0307 initialized_bytes = (const uint8_t *) &initialized;
0308
0309 for ( i = 0; i < sizeof( container ); ++i ) {
0310 if ( container.bytes[ i ] != 0xff ) {
0311 rtems_test_assert( container.bytes[ i ] == initialized_bytes[ i] );
0312 }
0313 }
0314
0315 rtems_interrupt_lock_acquire( &container.lock, &lock_context );
0316 rtems_test_assert( normal_interrupt_level != get_interrupt_level() );
0317 rtems_interrupt_lock_release( &container.lock, &lock_context );
0318
0319 rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
0320
0321 rtems_interrupt_lock_acquire_isr( &container.lock, &lock_context );
0322 rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
0323 rtems_interrupt_lock_release_isr( &container.lock, &lock_context );
0324
0325 rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
0326
0327 rtems_interrupt_lock_destroy( &container.lock );
0328 rtems_interrupt_lock_destroy( &initialized );
0329 }
0330
0331 static void test_clock_tick_functions( void )
0332 {
0333 rtems_interrupt_level level;
0334 Watchdog_Interval saved_ticks;
0335
0336 rtems_interrupt_local_disable( level );
0337
0338 saved_ticks = _Watchdog_Ticks_since_boot;
0339
0340 _Watchdog_Ticks_since_boot = 0xdeadbeef;
0341 rtems_test_assert( rtems_clock_get_ticks_since_boot() == 0xdeadbeef );
0342
0343 rtems_test_assert( rtems_clock_tick_later( 0 ) == 0xdeadbeef );
0344 rtems_test_assert( rtems_clock_tick_later( 0x8160311e ) == 0x600df00d );
0345
0346 _Watchdog_Ticks_since_boot = 0;
0347 rtems_test_assert( rtems_clock_tick_later_usec( 0 ) == 1 );
0348 rtems_test_assert( rtems_clock_tick_later_usec( 1 ) == 2 );
0349 rtems_test_assert( rtems_clock_tick_later_usec( US_PER_TICK ) == 2 );
0350 rtems_test_assert( rtems_clock_tick_later_usec( US_PER_TICK + 1 ) == 3 );
0351
0352 _Watchdog_Ticks_since_boot = 0;
0353 rtems_test_assert( !rtems_clock_tick_before( 0xffffffff ) );
0354 rtems_test_assert( !rtems_clock_tick_before( 0 ) );
0355 rtems_test_assert( rtems_clock_tick_before( 1 ) );
0356
0357 _Watchdog_Ticks_since_boot = 1;
0358 rtems_test_assert( !rtems_clock_tick_before( 0 ) );
0359 rtems_test_assert( !rtems_clock_tick_before( 1 ) );
0360 rtems_test_assert( rtems_clock_tick_before( 2 ) );
0361
0362 _Watchdog_Ticks_since_boot = 0x7fffffff;
0363 rtems_test_assert( !rtems_clock_tick_before( 0x7ffffffe ) );
0364 rtems_test_assert( !rtems_clock_tick_before( 0x7fffffff ) );
0365 rtems_test_assert( rtems_clock_tick_before( 0x80000000 ) );
0366
0367 _Watchdog_Ticks_since_boot = 0x80000000;
0368 rtems_test_assert( !rtems_clock_tick_before( 0x7fffffff ) );
0369 rtems_test_assert( !rtems_clock_tick_before( 0x80000000 ) );
0370 rtems_test_assert( rtems_clock_tick_before( 0x80000001 ) );
0371
0372 _Watchdog_Ticks_since_boot = 0xffffffff;
0373 rtems_test_assert( !rtems_clock_tick_before( 0xfffffffe ) );
0374 rtems_test_assert( !rtems_clock_tick_before( 0xffffffff ) );
0375 rtems_test_assert( rtems_clock_tick_before( 0 ) );
0376
0377 _Watchdog_Ticks_since_boot = saved_ticks;
0378
0379 rtems_interrupt_local_enable( level );
0380 }
0381
0382 void test_interrupt_inline(void)
0383 {
0384 rtems_interrupt_level level;
0385 rtems_interrupt_level level_1;
0386 rtems_mode level_mode_body;
0387 rtems_mode level_mode_macro;
0388 bool in_isr;
0389 uint32_t isr_level_0;
0390 uint32_t isr_level_1;
0391 uint32_t isr_level_2;
0392
0393 puts( "interrupt is in progress (use body)" );
0394 in_isr = rtems_interrupt_is_in_progress();
0395 if ( in_isr ) {
0396 puts( "interrupt reported to be is in progress (body)" );
0397 rtems_test_exit( 0 );
0398 }
0399
0400 #if !defined(RTEMS_SMP)
0401 puts( "interrupt disable (use inline)" );
0402 rtems_interrupt_disable( level );
0403
0404 puts( "interrupt flash (use inline)" );
0405 rtems_interrupt_flash( level );
0406
0407 puts( "interrupt enable (use inline)" );
0408 rtems_interrupt_enable( level );
0409 #endif
0410
0411 isr_level_0 = _ISR_Get_level();
0412 rtems_test_assert( isr_level_0 == 0 );
0413
0414 rtems_interrupt_local_disable( level );
0415 isr_level_1 = _ISR_Get_level();
0416 rtems_test_assert( isr_level_1 != isr_level_0 );
0417 rtems_test_assert( _ISR_Is_enabled( level ) );
0418
0419 rtems_interrupt_local_disable( level_1 );
0420 isr_level_2 = _ISR_Get_level();
0421 rtems_test_assert( isr_level_2 == isr_level_1 );
0422 rtems_test_assert( !_ISR_Is_enabled( level_1 ) );
0423
0424 rtems_interrupt_local_enable( level_1 );
0425 rtems_test_assert( _ISR_Get_level() == isr_level_1 );
0426
0427 rtems_interrupt_local_enable( level );
0428 rtems_test_assert( _ISR_Get_level() == isr_level_0 );
0429
0430 puts( "interrupt level mode (use inline)" );
0431 level_mode_body = rtems_interrupt_level_body( level );
0432 level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
0433 if ( level_mode_macro == level_mode_body ) {
0434 puts( "test case working.." );
0435 }
0436 }
0437
0438 volatile int isr_in_progress_body;
0439
0440 volatile int isr_in_progress_inline;
0441
0442 void check_isr_in_progress_inline(void)
0443 {
0444 isr_in_progress_inline = rtems_interrupt_is_in_progress() ? 1 : 2;
0445 }
0446
0447 void check_isr_worked(
0448 char *s,
0449 int result
0450 )
0451 {
0452 switch (result) {
0453 case 0:
0454 printf( "isr_in_progress(%s) timer did not fire\n", s );
0455 rtems_test_exit(0);
0456 break;
0457 case 1:
0458 printf( "isr_in_progress(%s) from ISR -- OK\n", s );
0459 break;
0460 default:
0461 printf( "isr_in_progress(%s) from ISR -- returned bad value\n", s);
0462 rtems_test_exit(0);
0463 break;
0464 }
0465 }
0466
0467 volatile int blocked_task_status;
0468 rtems_id blocked_task_id;
0469
0470 rtems_task blocked_task(
0471 rtems_task_argument argument
0472 )
0473 {
0474 rtems_status_code status;
0475
0476 puts( "Blocking task... suspending self" );
0477 blocked_task_status = 1;
0478 status = rtems_task_suspend( RTEMS_SELF );
0479 directive_failed( status, "rtems_task_suspend" );
0480
0481 blocked_task_status = 3;
0482 rtems_task_exit();
0483 }
0484
0485
0486
0487
0488
0489
0490
0491 rtems_timer_service_routine test_unblock_task(
0492 rtems_id timer,
0493 void *arg
0494 )
0495 {
0496 bool in_isr;
0497 rtems_status_code status;
0498 Per_CPU_Control *cpu_self;
0499
0500 in_isr = rtems_interrupt_is_in_progress();
0501 status = rtems_task_is_suspended( blocked_task_id );
0502 if ( in_isr ) {
0503 status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
0504 directive_failed( status, "timer_fire_after failed" );
0505 return;
0506 }
0507
0508 if ( (status != RTEMS_ALREADY_SUSPENDED) ) {
0509 status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
0510 directive_failed( status, "timer_fire_after failed" );
0511 return;
0512 }
0513
0514 blocked_task_status = 2;
0515 cpu_self = _Thread_Dispatch_disable();
0516 status = rtems_task_resume( blocked_task_id );
0517 _Thread_Dispatch_enable( cpu_self );
0518 directive_failed( status, "rtems_task_resume" );
0519 }
0520
0521 #undef rtems_interrupt_disable
0522 extern rtems_interrupt_level rtems_interrupt_disable(void);
0523 #undef rtems_interrupt_enable
0524 extern void rtems_interrupt_enable(rtems_interrupt_level previous_level);
0525 #undef rtems_interrupt_flash
0526 extern void rtems_interrupt_flash(rtems_interrupt_level previous_level);
0527 #undef rtems_interrupt_is_in_progress
0528 extern bool rtems_interrupt_is_in_progress(void);
0529
0530 static void test_interrupt_body(void)
0531 {
0532 #if !defined(RTEMS_SMP)
0533 rtems_interrupt_level level_0;
0534 rtems_interrupt_level level_1;
0535 rtems_mode level_mode_body;
0536 rtems_mode level_mode_macro;
0537 bool in_isr;
0538
0539 puts( "interrupt disable (use body)" );
0540 level_0 = rtems_interrupt_disable();
0541
0542 puts( "interrupt disable (use body)" );
0543 level_1 = rtems_interrupt_disable();
0544
0545 puts( "interrupt flash (use body)" );
0546 rtems_interrupt_flash( level_1 );
0547
0548 puts( "interrupt enable (use body)" );
0549 rtems_interrupt_enable( level_1 );
0550
0551 puts( "interrupt level mode (use body)" );
0552 level_mode_body = rtems_interrupt_level_body( level_0 );
0553 level_mode_macro = RTEMS_INTERRUPT_LEVEL( level_0 );
0554 if ( level_mode_macro == level_mode_body ) {
0555 puts("test seems to work");
0556 }
0557
0558
0559
0560
0561 puts( "interrupt is in progress (use body)" );
0562 in_isr = rtems_interrupt_is_in_progress();
0563
0564 puts( "interrupt enable (use body)" );
0565 rtems_interrupt_enable( level_0 );
0566
0567 if ( in_isr ) {
0568 puts( "interrupt reported to be is in progress (body)" );
0569 rtems_test_exit( 0 );
0570 }
0571 #endif
0572 }
0573
0574 rtems_timer_service_routine test_isr_in_progress(
0575 rtems_id timer,
0576 void *arg
0577 )
0578 {
0579 check_isr_in_progress_inline();
0580
0581 isr_in_progress_body = rtems_interrupt_is_in_progress() ? 1 : 2;
0582 }
0583
0584 rtems_task Init(
0585 rtems_task_argument argument
0586 )
0587 {
0588 rtems_time_of_day time;
0589 rtems_status_code status;
0590 rtems_id timer;
0591 int i;
0592
0593 TEST_BEGIN();
0594
0595 test_isr_level();
0596 test_isr_locks();
0597 test_interrupt_locks();
0598
0599 build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
0600 status = rtems_clock_set( &time );
0601 directive_failed( status, "rtems_clock_set" );
0602
0603
0604
0605
0606 status = rtems_timer_create( 1, &timer );
0607 directive_failed( status, "rtems_timer_create" );
0608
0609
0610
0611
0612 status = rtems_clock_tick();
0613 directive_failed( status, "rtems_clock_tick" );
0614 puts( "clock_tick from task level" );
0615
0616 test_clock_tick_functions();
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628 blocked_task_status = -1;
0629
0630 status = rtems_task_create(
0631 rtems_build_name( 'T', 'A', '1', ' ' ),
0632 1,
0633 RTEMS_MINIMUM_STACK_SIZE,
0634 RTEMS_DEFAULT_MODES,
0635 RTEMS_DEFAULT_ATTRIBUTES,
0636 &blocked_task_id
0637 );
0638 directive_failed( status, "rtems_task_create" );
0639
0640 status = rtems_task_start( blocked_task_id, blocked_task, 0 );
0641 directive_failed( status, "rtems_task_start" );
0642
0643 status = rtems_task_wake_after( 10 );
0644 directive_failed( status, "rtems_task_wake_after" );
0645
0646 status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
0647 directive_failed( status, "timer_fire_after failed" );
0648
0649
0650 for ( i=0 ; i<100 && blocked_task_status != 3 ; i++ ) {
0651 status = rtems_clock_tick();
0652 directive_failed( status, "rtems_clock_tick" );
0653 }
0654 switch ( blocked_task_status ) {
0655 case -1:
0656 puts(
0657 "clock_tick with task preempt -- task blocked, timer did not fire"
0658 );
0659 rtems_test_exit(0);
0660 break;
0661 case 1:
0662 puts( "clock_tick with task preempt -- timer fired case 1" );
0663 rtems_test_exit(0);
0664 break;
0665 case 2:
0666 puts( "clock_tick with task preempt -- timer fired case 2" );
0667 rtems_test_exit(0);
0668 break;
0669 case 3:
0670 puts( "clock_tick from task level with preempt -- OK" );
0671 break;
0672 }
0673
0674 test_interrupt_inline();
0675 test_interrupt_body();
0676
0677
0678
0679
0680 status = rtems_timer_fire_after( timer, 10, test_isr_in_progress, NULL );
0681 directive_failed( status, "timer_fire_after failed" );
0682
0683 status = rtems_task_wake_after( 11 );
0684 directive_failed( status, "wake_after failed" );
0685
0686 check_isr_worked( "inline", isr_in_progress_inline );
0687
0688 check_isr_worked( "body", isr_in_progress_body );
0689
0690 TEST_END();
0691 rtems_test_exit( 0 );
0692 }