Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  COPYRIGHT (c) 1989-2013.
0005  *  On-Line Applications Research Corporation (OAR).
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 /*
0030  *  WARNING!!!!!!!!!
0031  *
0032  *  THIS TEST USES INTERNAL RTEMS VARIABLES!!!
0033  */
0034 
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038 
0039 #define CONFIGURE_INIT
0040 #include "system.h"
0041 
0042 #include <bsp.h>
0043 #include <rtems/btimer.h>
0044 #include <rtems/score/schedulerpriorityimpl.h>
0045 
0046 #define _RTEMS_TMTEST27
0047 #include <tm27.h>
0048 
0049 const char rtems_test_name[] = "TIME TEST 27";
0050 
0051 rtems_task Task_1(
0052   rtems_task_argument argument
0053 );
0054 
0055 rtems_task Task_2(
0056   rtems_task_argument argument
0057 );
0058 
0059 volatile uint32_t   Interrupt_occurred;
0060 volatile uint32_t   Interrupt_enter_time, Interrupt_enter_nested_time;
0061 volatile uint32_t   Interrupt_return_time, Interrupt_return_nested_time;
0062 uint32_t   Interrupt_nest;
0063 uint32_t   timer_overhead;
0064 
0065 static void set_thread_executing( Thread_Control *thread )
0066 {
0067   _Per_CPU_Get_snapshot()->executing = thread;
0068 }
0069 
0070 rtems_task Init(
0071   rtems_task_argument argument
0072 )
0073 {
0074   rtems_status_code status;
0075 
0076   Print_Warning();
0077 
0078   TEST_BEGIN();
0079 
0080   if (
0081     _Scheduler_Table[ 0 ].Operations.initialize
0082       != _Scheduler_priority_Initialize
0083   ) {
0084     puts("  Error ==> " );
0085     puts("Test only supported for deterministic priority scheduler\n" );
0086     TEST_END();
0087     rtems_test_exit( 0 );
0088   }
0089 
0090 #define LOW_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 1u)
0091   status = rtems_task_create(
0092     rtems_build_name( 'T', 'A', '1', ' ' ),
0093     LOW_PRIORITY,
0094     RTEMS_MINIMUM_STACK_SIZE,
0095     RTEMS_DEFAULT_MODES,
0096     RTEMS_DEFAULT_ATTRIBUTES,
0097     &Task_id[ 1 ]
0098   );
0099   directive_failed( status, "rtems_task_create Task_1" );
0100 
0101   status = rtems_task_start( Task_id[ 1 ], Task_1, 0 );
0102   directive_failed( status, "rtems_task_start Task_1" );
0103 
0104   status = rtems_task_create(
0105     rtems_build_name( 'T', 'A', '2', ' ' ),
0106     LOW_PRIORITY,
0107     RTEMS_MINIMUM_STACK_SIZE,
0108     RTEMS_DEFAULT_MODES,
0109     RTEMS_DEFAULT_ATTRIBUTES,
0110     &Task_id[ 2 ]
0111   );
0112   directive_failed( status, "rtems_task_create of Task_2" );
0113 
0114   status = rtems_task_start( Task_id[ 2 ], Task_2, 0 );
0115   directive_failed( status, "rtems_task_start of Task_2" );
0116 
0117   benchmark_timer_initialize();
0118   benchmark_timer_read();
0119   benchmark_timer_initialize();
0120   timer_overhead = benchmark_timer_read();
0121 
0122   rtems_task_exit();
0123 }
0124 
0125 /*  The Isr_handler() and Isr_handler_inner() routines are structured
0126  *  so that there will be as little entry overhead as possible included
0127  *  in the interrupt entry time.
0128  */
0129 
0130 static void Isr_handler_inner( void )
0131 {
0132 
0133   /*enable_tracing();*/
0134   Clear_tm27_intr();
0135   switch ( Interrupt_nest ) {
0136     case 0:
0137       Interrupt_enter_time = end_time;
0138       break;
0139     case 1:
0140       Interrupt_enter_time = end_time;
0141       Interrupt_nest = 2;
0142       Interrupt_occurred = 0;
0143       Lower_tm27_intr();
0144       benchmark_timer_initialize();
0145       Cause_tm27_intr();
0146       /* goes to a nested copy of Isr_handler */
0147 #if (MUST_WAIT_FOR_INTERRUPT == 1)
0148        while ( Interrupt_occurred == 0 );
0149 #endif
0150       Interrupt_return_nested_time = benchmark_timer_read();
0151       break;
0152     case 2:
0153       Interrupt_enter_nested_time = end_time;
0154       break;
0155   }
0156 
0157   benchmark_timer_initialize();
0158 }
0159 
0160 #ifdef TM27_USE_VECTOR_HANDLER
0161 static rtems_isr Isr_handler( rtems_vector_number arg )
0162 #else
0163 static void Isr_handler( void *arg )
0164 #endif
0165 {
0166   (void) arg;
0167 
0168   end_time = benchmark_timer_read();
0169 
0170   Interrupt_occurred = 1;
0171   Isr_handler_inner();
0172 }
0173 
0174 rtems_task Task_1(
0175   rtems_task_argument argument
0176 )
0177 {
0178   Scheduler_priority_Context *scheduler_context =
0179     _Scheduler_priority_Get_context( _Thread_Scheduler_get_home( _Thread_Get_executing() ) );
0180 #if defined(RTEMS_SMP)
0181   rtems_interrupt_level level;
0182 #endif
0183 
0184   Install_tm27_vector( Isr_handler );
0185 
0186   /*
0187    *  No preempt .. no nesting
0188    */
0189 
0190   Interrupt_nest = 0;
0191 
0192   Interrupt_occurred = 0;
0193 
0194   benchmark_timer_initialize();
0195   Cause_tm27_intr();
0196   /* goes to Isr_handler */
0197 
0198 #if (MUST_WAIT_FOR_INTERRUPT == 1)
0199   while ( Interrupt_occurred == 0 );
0200 #endif
0201   Interrupt_return_time = benchmark_timer_read();
0202 
0203   put_time(
0204     "rtems interrupt: entry overhead returns to interrupted task",
0205     Interrupt_enter_time,
0206     1,
0207     0,
0208     timer_overhead
0209   );
0210 
0211   put_time(
0212     "rtems interrupt: exit overhead returns to interrupted task",
0213     Interrupt_return_time,
0214     1,
0215     0,
0216     timer_overhead
0217   );
0218 
0219   /*
0220    *  No preempt .. nested
0221    */
0222 
0223   _Thread_Dispatch_disable();
0224 
0225   Interrupt_nest = 1;
0226 
0227   Interrupt_occurred = 0;
0228   benchmark_timer_initialize();
0229   Cause_tm27_intr();
0230   /* goes to Isr_handler */
0231 
0232 #if (MUST_WAIT_FOR_INTERRUPT == 1)
0233   while ( Interrupt_occurred == 0 );
0234 #endif
0235   Interrupt_return_time = benchmark_timer_read();
0236 
0237   _Thread_Dispatch_enable( _Per_CPU_Get() );
0238 
0239   put_time(
0240     "rtems interrupt: entry overhead returns to nested interrupt",
0241     Interrupt_enter_nested_time,
0242     1,
0243     0,
0244     0
0245   );
0246 
0247   put_time(
0248     "rtems interrupt: exit overhead returns to nested interrupt",
0249     Interrupt_return_nested_time,
0250     1,
0251     0,
0252     0
0253   );
0254 
0255   /*
0256    *  Does a preempt .. not nested
0257    */
0258 
0259 #if defined(RTEMS_SMP)
0260   _ISR_Local_disable(level);
0261 #endif
0262 
0263   set_thread_executing(
0264     (Thread_Control *) _Chain_First(&scheduler_context->Ready[LOW_PRIORITY])
0265   );
0266 
0267   _Thread_Dispatch_necessary = 1;
0268 
0269 #if defined(RTEMS_SMP)
0270   _ISR_Local_enable(level);
0271 #endif
0272 
0273   Interrupt_occurred = 0;
0274   benchmark_timer_initialize();
0275   Cause_tm27_intr();
0276 
0277   /*
0278    *  goes to Isr_handler and then returns
0279    */
0280 
0281   TEST_END();
0282   rtems_test_exit( 0 );
0283 }
0284 
0285 /*
0286  *  NOTE:  When this task is executing, some of the assumptions made
0287  *         regarding the placement of the currently executing task's TCB
0288  *         on the ready chains have been violated.  At least the assumption
0289  *         that this task is at the head of the chain for its priority
0290  *         has been violated.
0291  */
0292 
0293 rtems_task Task_2(
0294   rtems_task_argument argument
0295 )
0296 {
0297   Thread_Control *executing = _Thread_Get_executing();
0298   const Scheduler_Control    *scheduler;
0299   Scheduler_priority_Context *scheduler_context;
0300   ISR_lock_Context state_lock_context;
0301   ISR_lock_Context scheduler_lock_context;
0302 
0303   _Thread_State_acquire( executing, &state_lock_context );
0304   scheduler = _Thread_Scheduler_get_home( executing );
0305   scheduler_context = _Scheduler_priority_Get_context( scheduler );
0306   _Thread_State_release( executing, &state_lock_context );
0307 
0308 #if (MUST_WAIT_FOR_INTERRUPT == 1)
0309   while ( Interrupt_occurred == 0 );
0310 #endif
0311   end_time = benchmark_timer_read();
0312 
0313   put_time(
0314     "rtems interrupt: entry overhead returns to preempting task",
0315     Interrupt_enter_time,
0316     1,
0317     0,
0318     timer_overhead
0319   );
0320 
0321   put_time(
0322     "rtems interrupt: exit overhead returns to preempting task",
0323     end_time,
0324     1,
0325     0,
0326     0
0327   );
0328 
0329   fflush( stdout );
0330 
0331   /*
0332    *  Switch back to the other task to exit the test.
0333    */
0334 
0335   _Thread_State_acquire( executing, &state_lock_context );
0336   _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
0337 
0338   set_thread_executing(
0339     (Thread_Control *) _Chain_First(&scheduler_context->Ready[LOW_PRIORITY])
0340   );
0341 
0342   _Thread_Dispatch_necessary = 1;
0343 
0344   _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
0345   _Thread_State_release( executing, &state_lock_context );
0346 
0347   _Thread_Dispatch();
0348 
0349 }