Back to home page

LXR

 
 

    


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

0001 /**
0002  * @brief A heuristic example to demonstrate how the postponed jobs are handled in RMS.
0003  *
0004  * Given two tasks with implicit deadline under fixed-priority scheudling.
0005  * Task 1 has (6, 10) and task 2 has (1, 2), where (execution time, deadline/period).
0006  * To force deadline misses, we reverse the rate-monotonic priority assignment
0007  * and only execute the highest priority task twice.
0008  *
0009  * In the original implementation in v4.11, no matter how many periods are
0010  * expired, RMS manager only releases a job with a shifted deadline assignment
0011  * in the watchdog. As the results written in sprmsched01.scn, we can see that
0012  * the timeout of task 2 period will be detected right after Job3 of Task2 is finished.
0013  * If the overrun handling is correct, the status of task 2 period will return back to
0014  * RTEMS_SUCCESSFUL after periodically releasing those postponed jobs (the last one is Job 9).
0015  *
0016  * Otherwise, we can see that the release time of Job 4 is no longer periodic,
0017  * and the RTEMS returns back to RTEMS_SUCCESSFUL right after Job 4 is finished
0018  * without releasing all the other postponed jobs.
0019  *
0020  */
0021 
0022 /*
0023  *  COPYRIGHT (c) 2016-2017 Kuan-Hsun Chen.
0024  *
0025  *  The license and distribution terms for this file may be
0026  *  found in the file LICENSE in this distribution or at
0027  *  http://www.rtems.com/license/LICENSE.
0028  */
0029 
0030 #ifdef HAVE_CONFIG_H
0031 #include "config.h"
0032 #endif
0033 
0034 #include <rtems/cpuuse.h>
0035 #include <tmacros.h>
0036 #include "test_support.h"
0037 
0038 const char rtems_test_name[] = "SPRMSCHED 1";
0039 
0040 static const uint32_t Periods[] = { 1000, 200 };
0041 static const uint32_t Iterations[] = { 600, 100 };
0042 static const rtems_name Task_name[] = {
0043   rtems_build_name( 'T', 'A', '1', ' ' ),
0044   rtems_build_name( 'T', 'A', '2', ' ' )
0045 };
0046 static const rtems_task_priority Prio[3] = { 2, 5 };
0047 static const uint32_t testnumber = 9; /* stop condition */
0048 
0049 static uint32_t tsk_counter[] = { 0, 0 };
0050 static rtems_id   Task_id[ 2 ];
0051 
0052 /**
0053  * @brief Task body
0054  */
0055 static rtems_task Task(
0056   rtems_task_argument argument
0057 )
0058 {
0059   rtems_status_code                          status;
0060   rtems_id                                   RM_period;
0061   rtems_id                                   selfid=rtems_task_self();
0062   rtems_rate_monotonic_period_status         period_status;
0063   uint32_t                                   flag=0;
0064 
0065   /*create period*/
0066   status = rtems_rate_monotonic_create( Task_name[ argument ], &RM_period );
0067   directive_failed( status, "rtems_rate_monotonic_create" );
0068 
0069   while ( FOREVER ) {
0070     status = rtems_rate_monotonic_period( RM_period, Periods[ argument ] );
0071 
0072     /* Do some work */
0073     rtems_test_spin_for_ticks( Iterations[ argument ] );
0074 
0075     if( argument == 1 ){
0076       if( status == RTEMS_TIMEOUT ){
0077         if( flag == 0 ){
0078           puts( "First time RTEMS_TIMEOUT" );
0079           puts( "Task 2 should have 3 postponed jobs due to preemption." );
0080           rtems_test_assert( period_status.postponed_jobs_count == 3 );
0081           flag = 1;
0082         }
0083       } else if ( flag == 1 && status == RTEMS_SUCCESSFUL ) {
0084         puts( "RTEMS_SUCCESSFUL" );
0085         puts( "Overrun handling is finished, now Task 2 becomes normal." );
0086         rtems_test_assert( period_status.postponed_jobs_count == 0 );
0087         flag = 0;
0088       }
0089 
0090       /* Check the status */
0091       status = rtems_rate_monotonic_get_status( RM_period, &period_status );
0092       directive_failed( status, "rate_monotonic_get_status" );
0093 
0094       if( tsk_counter[ argument ] == testnumber ){
0095         TEST_END();
0096         status = rtems_rate_monotonic_delete( RM_period );
0097         directive_failed( status, "rtems_rate_monotonic_delete" );
0098         rtems_test_exit( 0 );
0099       }
0100     }
0101 
0102     tsk_counter[ argument ]+=1;
0103     if ( argument == 0 ){
0104       if( tsk_counter[ argument ] == 2 ){
0105         puts( "Task 1 has released two jobs" );
0106         status = rtems_rate_monotonic_delete( RM_period );
0107         directive_failed( status, "rtems_rate_monotonic_delete" );
0108         status = rtems_task_delete( selfid );
0109         directive_failed( status, "rtems_task_delete" );
0110       }
0111     }
0112   }
0113 }
0114 
0115 static rtems_task Init(
0116     rtems_task_argument argument
0117 )
0118 {
0119   uint32_t     index;
0120   rtems_status_code status;
0121 
0122   TEST_BEGIN();
0123 
0124   /* Create two tasks */
0125   for ( index = 0; index < RTEMS_ARRAY_SIZE(Task_name); ++index ){
0126     status = rtems_task_create(
0127       Task_name[ index ], Prio[index], RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES,
0128       RTEMS_DEFAULT_ATTRIBUTES, &Task_id[ index ]
0129     );
0130     directive_failed( status, "rtems_task_create loop" );
0131   }
0132 
0133 
0134   /* After creating the periods for tasks, start to run them sequencially. */
0135   for ( index = 0; index < RTEMS_ARRAY_SIZE(Task_name); ++index ){
0136     status = rtems_task_start( Task_id[ index ], Task, index);
0137     directive_failed( status, "rtems_task_start loop");
0138   }
0139   rtems_task_exit();
0140 }
0141 
0142 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0143 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0144 #define CONFIGURE_MICROSECONDS_PER_TICK     1000
0145 #define CONFIGURE_MAXIMUM_TASKS             3
0146 #define CONFIGURE_MAXIMUM_PERIODS           2
0147 
0148 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0149 
0150 #define CONFIGURE_INITIAL_EXTENSIONS \
0151   RTEMS_TEST_INITIAL_EXTENSION
0152 
0153 #define CONFIGURE_INIT
0154 
0155 #include <rtems/confdefs.h>