Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:47

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2012, 2020 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
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>