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) 2020 embedded brains GmbH & Co. KG
0005  *
0006  *  COPYRIGHT (c) 1989-2012.
0007  *  On-Line Applications Research Corporation (OAR).
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
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      * Depending on the time to the next clock tick and the CPU time available
0134      * to a simulator, we may get sporadic RTEMS_TIMEOUT here.  In the next
0135      * round we are synchronized with the clock tick.
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 /* configuration information */
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 /* global variables */