Back to home page

LXR

 
 

    


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

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