1 | /** |
---|
2 | * @brief A heuristic example to demonstrate how the postponed jobs are handled in EDF. |
---|
3 | * |
---|
4 | * Given two tasks with implicit deadline under EDF policy. |
---|
5 | * Task 1 has (400, 500) and task 2 has (450, 550), where (required ticks, period/deadline). |
---|
6 | * For the simplicity, we only execute the first task three times. |
---|
7 | * In the original implementation in v4.11, no matter how many periods are |
---|
8 | * expired, only one job will be released with a shifted deadline assignment. |
---|
9 | * |
---|
10 | * In this example, task 2 will be blocked by the second and third jobs |
---|
11 | * of task 1, so that there are two jobs are postponed. |
---|
12 | * Due to the domino effects, the following jobs of task 2 will be postponed until Job 9. |
---|
13 | * |
---|
14 | * If the overrun handling is correct, the period of task 2 changes back to |
---|
15 | * normal status at Job 9. |
---|
16 | * Otherwise, the release time of job 3 is no longer periodic |
---|
17 | * and there is no more postponed jobs. |
---|
18 | * |
---|
19 | */ |
---|
20 | |
---|
21 | /* |
---|
22 | * COPYRIGHT (c) 2016-2017 Kuan-Hsun Chen. |
---|
23 | * |
---|
24 | * The license and distribution terms for this file may be |
---|
25 | * found in the file LICENSE in this distribution or at |
---|
26 | * http://www.rtems.com/license/LICENSE. |
---|
27 | */ |
---|
28 | |
---|
29 | #ifdef HAVE_CONFIG_H |
---|
30 | #include "config.h" |
---|
31 | #endif |
---|
32 | |
---|
33 | #include <rtems/cpuuse.h> |
---|
34 | #include <tmacros.h> |
---|
35 | #include "test_support.h" |
---|
36 | |
---|
37 | const char rtems_test_name[] = "SPEDFSCHED 4"; |
---|
38 | |
---|
39 | static const uint32_t Periods[] = { 500, 550 }; |
---|
40 | static const uint32_t Iterations[] = { 400, 450 }; |
---|
41 | static const rtems_name Task_name[] = { |
---|
42 | rtems_build_name( 'T', 'A', '1', ' ' ), |
---|
43 | rtems_build_name( 'T', 'A', '2', ' ' ) |
---|
44 | }; |
---|
45 | static const rtems_task_priority Prio[3] = { 2, 5 }; |
---|
46 | static const uint32_t testnumber = 9; /* stop condition */ |
---|
47 | |
---|
48 | static uint32_t tsk_counter[] = { 0, 0 }; |
---|
49 | static rtems_id Task_id[ 2 ]; |
---|
50 | |
---|
51 | /** |
---|
52 | * @brief Task body |
---|
53 | */ |
---|
54 | static rtems_task Task( |
---|
55 | rtems_task_argument argument |
---|
56 | ) |
---|
57 | { |
---|
58 | rtems_status_code status; |
---|
59 | rtems_id RM_period; |
---|
60 | rtems_id selfid=rtems_task_self(); |
---|
61 | rtems_rate_monotonic_period_status period_status; |
---|
62 | uint32_t flag=0; |
---|
63 | |
---|
64 | /* create period */ |
---|
65 | status = rtems_rate_monotonic_create( Task_name[ argument ], &RM_period ); |
---|
66 | directive_failed( status, "rtems_rate_monotonic_create" ); |
---|
67 | |
---|
68 | rtems_test_spin_until_next_tick(); |
---|
69 | |
---|
70 | while ( FOREVER ) { |
---|
71 | status = rtems_rate_monotonic_period( RM_period, Periods[ argument ] ); |
---|
72 | |
---|
73 | /* Do some work */ |
---|
74 | rtems_test_spin_for_ticks( Iterations[ argument ] ); |
---|
75 | |
---|
76 | if( argument == 1 ){ |
---|
77 | if( status == RTEMS_TIMEOUT ){ |
---|
78 | if( flag == 0 ){ |
---|
79 | puts( "First time RTEMS_TIMEOUT" ); |
---|
80 | puts( "Task 2 should have 2 postponed job due to preemption." ); |
---|
81 | rtems_test_assert( period_status.postponed_jobs_count == 2 ); |
---|
82 | flag = 1; |
---|
83 | } |
---|
84 | } else if ( flag == 1 && status == RTEMS_SUCCESSFUL ) { |
---|
85 | puts( "RTEMS_SUCCESSFUL" ); |
---|
86 | puts( "Overrun handling is finished, now Task 2 becomes normal." ); |
---|
87 | rtems_test_assert( period_status.postponed_jobs_count == 0 ); |
---|
88 | flag = 0; |
---|
89 | } |
---|
90 | |
---|
91 | /* Check the status */ |
---|
92 | status = rtems_rate_monotonic_get_status( RM_period, &period_status ); |
---|
93 | directive_failed( status, "rate_monotonic_get_status" ); |
---|
94 | |
---|
95 | if( tsk_counter[ argument ] == testnumber ){ |
---|
96 | TEST_END(); |
---|
97 | status = rtems_rate_monotonic_delete( RM_period ); |
---|
98 | directive_failed( status, "rtems_rate_monotonic_delete" ); |
---|
99 | rtems_test_exit( 0 ); |
---|
100 | } |
---|
101 | } |
---|
102 | |
---|
103 | tsk_counter[ argument ]+=1; |
---|
104 | if ( argument == 0 ){ |
---|
105 | if( tsk_counter[ argument ] == 3 ){ |
---|
106 | puts("Task 1 has released 3 jobs and finished."); |
---|
107 | status = rtems_rate_monotonic_delete( RM_period ); |
---|
108 | directive_failed( status, "rtems_rate_monotonic_delete" ); |
---|
109 | status = rtems_task_delete( selfid ); |
---|
110 | directive_failed( status, "rtems_task_delete" ); |
---|
111 | } |
---|
112 | } |
---|
113 | } |
---|
114 | } |
---|
115 | |
---|
116 | static rtems_task Init( |
---|
117 | rtems_task_argument argument |
---|
118 | ) |
---|
119 | { |
---|
120 | uint32_t index; |
---|
121 | rtems_status_code status; |
---|
122 | |
---|
123 | TEST_BEGIN(); |
---|
124 | |
---|
125 | |
---|
126 | /* Create two tasks */ |
---|
127 | for ( index = 0; index < RTEMS_ARRAY_SIZE(Task_name); ++index ){ |
---|
128 | status = rtems_task_create( |
---|
129 | Task_name[ index ], Prio[index], RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, |
---|
130 | RTEMS_DEFAULT_ATTRIBUTES, &Task_id[ index ] |
---|
131 | ); |
---|
132 | directive_failed( status, "rtems_task_create loop" ); |
---|
133 | } |
---|
134 | |
---|
135 | /* After creating the periods for tasks, start to run them sequencially. */ |
---|
136 | for ( index = 0; index < RTEMS_ARRAY_SIZE(Task_name); ++index ){ |
---|
137 | status = rtems_task_start( Task_id[ index ], Task, index); |
---|
138 | directive_failed( status, "rtems_task_start loop"); |
---|
139 | } |
---|
140 | rtems_task_exit(); |
---|
141 | } |
---|
142 | |
---|
143 | #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER |
---|
144 | #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER |
---|
145 | #define CONFIGURE_MICROSECONDS_PER_TICK 1000 |
---|
146 | #define CONFIGURE_MAXIMUM_TASKS 3 |
---|
147 | #define CONFIGURE_MAXIMUM_PERIODS 2 |
---|
148 | |
---|
149 | #define CONFIGURE_RTEMS_INIT_TASKS_TABLE |
---|
150 | |
---|
151 | #define CONFIGURE_SCHEDULER_EDF |
---|
152 | |
---|
153 | #define CONFIGURE_INITIAL_EXTENSIONS \ |
---|
154 | RTEMS_TEST_INITIAL_EXTENSION |
---|
155 | |
---|
156 | #define CONFIGURE_INIT |
---|
157 | |
---|
158 | #include <rtems/confdefs.h> |
---|