diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2013-01-21 20:00:29 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2013-01-21 20:00:29 -0500 |
commit | 95717fa9f4b9f725928e898c42fb0e711e896311 (patch) | |
tree | 6c552bd879cdafcd90b6bdacdc167338dd3189bf /litmus/edf_common.c | |
parent | 84aa3706d63edda13560ff812740cac0adf744e1 (diff) |
Fixed case where blocked tasks are released.
Fixed bug where AUX tasks were being added to the
ready queue while those AUX tasks were actually blocked.
Bug stems from the fact that the AUX tasks do not
make themselves realtime, but another thread does this
instead. Also fixed minor bugs elsewhere.
NOTE: ONLY FIXES C-EDF. OTHER PLUGINS REMAIN TO BE FIXED.
Diffstat (limited to 'litmus/edf_common.c')
-rw-r--r-- | litmus/edf_common.c | 114 |
1 files changed, 45 insertions, 69 deletions
diff --git a/litmus/edf_common.c b/litmus/edf_common.c index 441fbfddf0c2..ef22eb93dbf3 100644 --- a/litmus/edf_common.c +++ b/litmus/edf_common.c | |||
@@ -67,11 +67,14 @@ int edf_higher_prio(struct task_struct* first, struct task_struct* second) | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | |||
71 | /* check for NULL tasks */ | 70 | /* check for NULL tasks */ |
72 | if (!first || !second) { | 71 | if (!first || !second) { |
73 | return first && !second; | 72 | return first && !second; |
74 | } | 73 | } |
74 | /* check for non-realtime */ | ||
75 | if (!is_realtime(first) || !is_realtime(second)) { | ||
76 | return is_realtime(first) && !is_realtime(second); | ||
77 | } | ||
75 | 78 | ||
76 | /* There is some goofy stuff in this code here. There are three subclasses | 79 | /* There is some goofy stuff in this code here. There are three subclasses |
77 | * within the SCHED_LITMUS scheduling class: | 80 | * within the SCHED_LITMUS scheduling class: |
@@ -92,49 +95,31 @@ int edf_higher_prio(struct task_struct* first, struct task_struct* second) | |||
92 | 95 | ||
93 | #if defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_BOOSTED) | 96 | #if defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_BOOSTED) |
94 | /* run aux tasks at max priority */ | 97 | /* run aux tasks at max priority */ |
95 | /* TODO: Actually use prio-boosting. */ | 98 | if (tsk_rt(first)->is_aux_task != tsk_rt(second)->is_aux_task) { |
96 | if (first->rt_param.is_aux_task != second->rt_param.is_aux_task) | 99 | return (tsk_rt(first)->is_aux_task > tsk_rt(second)->is_aux_task); |
97 | { | ||
98 | return (first->rt_param.is_aux_task > second->rt_param.is_aux_task); | ||
99 | } | ||
100 | else if(first->rt_param.is_aux_task && second->rt_param.is_aux_task) | ||
101 | { | ||
102 | if(first->group_leader == second->group_leader) { | ||
103 | TRACE_CUR("aux tie break!\n"); // tie-break by BASE priority of the aux tasks | ||
104 | goto aux_tie_break; | ||
105 | } | ||
106 | first = first->group_leader; | ||
107 | second = second->group_leader; | ||
108 | } | 100 | } |
109 | #elif defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE) | 101 | #elif defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE) |
110 | { | 102 | { |
111 | int first_lo_aux = first->rt_param.is_aux_task && !first->rt_param.inh_task; | 103 | int first_lo_aux = tsk_rt(first)->is_aux_task && !tsk_rt(first)->inh_task; |
112 | int second_lo_aux = second->rt_param.is_aux_task && !second->rt_param.inh_task; | 104 | int second_lo_aux = tsk_rt(second)->is_aux_task && !tsk_rt(second)->inh_task; |
113 | 105 | ||
114 | /* prioritize aux tasks without inheritance below real-time tasks */ | 106 | /* prioritize aux tasks without inheritance below real-time tasks */ |
115 | if (first_lo_aux || second_lo_aux) { | 107 | if (first_lo_aux || second_lo_aux) { |
116 | // one of these is an aux task without inheritance. | 108 | // one of these is an aux task without inheritance. |
117 | if(first_lo_aux && second_lo_aux) { | 109 | if (first_lo_aux != second_lo_aux) { |
118 | TRACE_CUR("aux tie break!\n"); // tie-break by BASE priority of the aux tasks | 110 | int temp = (first_lo_aux < second_lo_aux); // non-lo-aux has higher priority. |
119 | goto aux_tie_break; | ||
120 | } | ||
121 | else { | ||
122 | |||
123 | // make the aux thread lowest priority real-time task | ||
124 | int temp = 0; | ||
125 | if (first_lo_aux && is_realtime(second)) { | ||
126 | // temp = 0; | ||
127 | } | ||
128 | else if(second_lo_aux && is_realtime(first)) { | ||
129 | temp = 1; | ||
130 | } | ||
131 | TRACE_CUR("%s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, temp); | 111 | TRACE_CUR("%s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, temp); |
132 | return temp; | 112 | return temp; |
133 | } | 113 | } |
114 | else { | ||
115 | /* both MUST be lo_aux. tie-break. */ | ||
116 | TRACE_CUR("aux tie break!\n"); | ||
117 | goto aux_tie_break; | ||
118 | } | ||
134 | } | 119 | } |
135 | 120 | ||
136 | if (first->rt_param.is_aux_task && second->rt_param.is_aux_task && | 121 | if (tsk_rt(first)->is_aux_task && tsk_rt(second)->is_aux_task && |
137 | first->rt_param.inh_task == second->rt_param.inh_task) { | 122 | tsk_rt(first)->inh_task == tsk_rt(second)->inh_task) { |
138 | // inh_task is !NULL for both tasks since neither was a lo_aux task. | 123 | // inh_task is !NULL for both tasks since neither was a lo_aux task. |
139 | // Both aux tasks inherit from the same task, so tie-break | 124 | // Both aux tasks inherit from the same task, so tie-break |
140 | // by base priority of the aux tasks. | 125 | // by base priority of the aux tasks. |
@@ -146,33 +131,26 @@ int edf_higher_prio(struct task_struct* first, struct task_struct* second) | |||
146 | 131 | ||
147 | #ifdef CONFIG_LITMUS_SOFTIRQD | 132 | #ifdef CONFIG_LITMUS_SOFTIRQD |
148 | { | 133 | { |
149 | int first_lo_klmirqd = first->rt_param.is_interrupt_thread && !first->rt_param.inh_task; | 134 | int first_lo_klmirqd = tsk_rt(first)->is_interrupt_thread && !tsk_rt(first)->inh_task; |
150 | int second_lo_klmirqd = second->rt_param.is_interrupt_thread && !second->rt_param.inh_task; | 135 | int second_lo_klmirqd = tsk_rt(second)->is_interrupt_thread && !tsk_rt(second)->inh_task; |
151 | 136 | ||
152 | /* prioritize aux tasks without inheritance below real-time tasks */ | 137 | /* prioritize aux tasks without inheritance below real-time tasks */ |
153 | if (first_lo_klmirqd || second_lo_klmirqd) { | 138 | if (first_lo_klmirqd || second_lo_klmirqd) { |
154 | // one of these is an klmirqd thread without inheritance. | 139 | // one of these is an klmirqd thread without inheritance. |
155 | if(first_lo_klmirqd && second_lo_klmirqd) { | 140 | if (first_lo_klmirqd != second_lo_klmirqd) { |
156 | TRACE_CUR("klmirqd tie break!\n"); // tie-break by BASE priority of the aux tasks | 141 | int temp = (first_lo_klmirqd < second_lo_klmirqd); // non-klmirqd has higher priority |
157 | goto klmirqd_tie_break; | ||
158 | } | ||
159 | else { | ||
160 | // make the klmirqd thread the lowest-priority real-time task | ||
161 | // but (above low-prio aux tasks and Linux tasks) | ||
162 | int temp = 0; | ||
163 | if (first_lo_klmirqd && is_realtime(second)) { | ||
164 | // temp = 0; | ||
165 | } | ||
166 | else if(second_lo_klmirqd && is_realtime(first)) { | ||
167 | temp = 1; | ||
168 | } | ||
169 | TRACE_CUR("%s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, temp); | 142 | TRACE_CUR("%s/%d >> %s/%d --- %d\n", first->comm, first->pid, second->comm, second->pid, temp); |
170 | return temp; | 143 | return temp; |
171 | } | 144 | } |
145 | else { | ||
146 | /* both MUST be klmirqd. tie-break. */ | ||
147 | TRACE_CUR("klmirqd tie break!\n"); | ||
148 | goto klmirqd_tie_break; | ||
149 | } | ||
172 | } | 150 | } |
173 | 151 | ||
174 | if (first->rt_param.is_interrupt_thread && second->rt_param.is_interrupt_thread && | 152 | if (tsk_rt(first)->is_interrupt_thread && tsk_rt(second)->is_interrupt_thread && |
175 | first->rt_param.inh_task == second->rt_param.inh_task) { | 153 | tsk_rt(first)->inh_task == tsk_rt(second)->inh_task) { |
176 | // inh_task is !NULL for both tasks since neither was a lo_klmirqd task. | 154 | // inh_task is !NULL for both tasks since neither was a lo_klmirqd task. |
177 | // Both klmirqd tasks inherit from the same task, so tie-break | 155 | // Both klmirqd tasks inherit from the same task, so tie-break |
178 | // by base priority of the klmirqd tasks. | 156 | // by base priority of the klmirqd tasks. |
@@ -187,19 +165,19 @@ int edf_higher_prio(struct task_struct* first, struct task_struct* second) | |||
187 | /* Check for EFFECTIVE priorities. Change task | 165 | /* Check for EFFECTIVE priorities. Change task |
188 | * used for comparison in such a case. | 166 | * used for comparison in such a case. |
189 | */ | 167 | */ |
190 | if (unlikely(first->rt_param.inh_task) | 168 | if (unlikely(tsk_rt(first)->inh_task) |
191 | #ifdef CONFIG_LITMUS_NESTED_LOCKING | 169 | #ifdef CONFIG_LITMUS_NESTED_LOCKING |
192 | && (first_mode == EFFECTIVE) | 170 | && (first_mode == EFFECTIVE) |
193 | #endif | 171 | #endif |
194 | ) { | 172 | ) { |
195 | first_task = first->rt_param.inh_task; | 173 | first_task = tsk_rt(first)->inh_task; |
196 | } | 174 | } |
197 | if (unlikely(second->rt_param.inh_task) | 175 | if (unlikely(tsk_rt(second)->inh_task) |
198 | #ifdef CONFIG_LITMUS_NESTED_LOCKING | 176 | #ifdef CONFIG_LITMUS_NESTED_LOCKING |
199 | && (second_mode == EFFECTIVE) | 177 | && (second_mode == EFFECTIVE) |
200 | #endif | 178 | #endif |
201 | ) { | 179 | ) { |
202 | second_task = second->rt_param.inh_task; | 180 | second_task = tsk_rt(second)->inh_task; |
203 | } | 181 | } |
204 | 182 | ||
205 | /* Check for priority boosting. Tie-break by start of boosting. | 183 | /* Check for priority boosting. Tie-break by start of boosting. |
@@ -222,17 +200,14 @@ int edf_higher_prio(struct task_struct* first, struct task_struct* second) | |||
222 | 200 | ||
223 | #endif | 201 | #endif |
224 | 202 | ||
225 | #ifdef CONFIG_REALTIME_AUX_TASKS | 203 | #ifdef CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE |
226 | aux_tie_break: | 204 | aux_tie_break: |
227 | #endif | 205 | #endif |
228 | #ifdef CONFIG_LITMUS_SOFTIRQD | 206 | #ifdef CONFIG_LITMUS_SOFTIRQD |
229 | klmirqd_tie_break: | 207 | klmirqd_tie_break: |
230 | #endif | 208 | #endif |
231 | 209 | ||
232 | if (!is_realtime(second_task)) { | 210 | if (earlier_deadline(first_task, second_task)) { |
233 | return 1; | ||
234 | } | ||
235 | else if (earlier_deadline(first_task, second_task)) { | ||
236 | return 1; | 211 | return 1; |
237 | } | 212 | } |
238 | else if (get_deadline(first_task) == get_deadline(second_task)) { | 213 | else if (get_deadline(first_task) == get_deadline(second_task)) { |
@@ -297,10 +272,10 @@ klmirqd_tie_break: | |||
297 | } | 272 | } |
298 | else if (first_task->pid == second_task->pid) { | 273 | else if (first_task->pid == second_task->pid) { |
299 | #ifdef CONFIG_LITMUS_SOFTIRQD | 274 | #ifdef CONFIG_LITMUS_SOFTIRQD |
300 | if (first_task->rt_param.is_interrupt_thread < second_task->rt_param.is_interrupt_thread) { | 275 | if (tsk_rt(first_task)->is_interrupt_thread < tsk_rt(second_task)->is_interrupt_thread) { |
301 | return 1; | 276 | return 1; |
302 | } | 277 | } |
303 | else if (first_task->rt_param.is_interrupt_thread == second_task->rt_param.is_interrupt_thread) { | 278 | else if (tsk_rt(first_task)->is_interrupt_thread == tsk_rt(second_task)->is_interrupt_thread) { |
304 | #endif | 279 | #endif |
305 | 280 | ||
306 | #if defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE) | 281 | #if defined(CONFIG_REALTIME_AUX_TASK_PRIORITY_INHERITANCE) |
@@ -311,7 +286,7 @@ klmirqd_tie_break: | |||
311 | #endif | 286 | #endif |
312 | 287 | ||
313 | /* Something could be wrong if you get this far. */ | 288 | /* Something could be wrong if you get this far. */ |
314 | if (unlikely(first->rt_param.inh_task == second->rt_param.inh_task)) { | 289 | if (unlikely(tsk_rt(first)->inh_task == tsk_rt(second)->inh_task)) { |
315 | /* Both tasks have the same inherited priority. | 290 | /* Both tasks have the same inherited priority. |
316 | * Likely in a bug-condition. | 291 | * Likely in a bug-condition. |
317 | */ | 292 | */ |
@@ -324,22 +299,22 @@ klmirqd_tie_break: | |||
324 | } | 299 | } |
325 | else { | 300 | else { |
326 | /* At least one task must inherit */ | 301 | /* At least one task must inherit */ |
327 | BUG_ON(!first->rt_param.inh_task && | 302 | BUG_ON(!tsk_rt(first)->inh_task && |
328 | !second->rt_param.inh_task); | 303 | !tsk_rt(second)->inh_task); |
329 | 304 | ||
330 | /* The task withOUT the inherited priority wins. */ | 305 | /* The task withOUT the inherited priority wins. */ |
331 | if (second->rt_param.inh_task) { | 306 | if (tsk_rt(second)->inh_task) { |
332 | /* | 307 | /* |
333 | * common with aux tasks. | 308 | * common with aux tasks. |
334 | TRACE_CUR("unusual comparison: " | 309 | TRACE_CUR("unusual comparison: " |
335 | "first = %s/%d first_task = %s/%d " | 310 | "first = %s/%d first_task = %s/%d " |
336 | "second = %s/%d second_task = %s/%d\n", | 311 | "second = %s/%d second_task = %s/%d\n", |
337 | first->comm, first->pid, | 312 | first->comm, first->pid, |
338 | (first->rt_param.inh_task) ? first->rt_param.inh_task->comm : "(nil)", | 313 | (tsk_rt(first)->inh_task) ? tsk_rt(first)->inh_task->comm : "(nil)", |
339 | (first->rt_param.inh_task) ? first->rt_param.inh_task->pid : 0, | 314 | (tsk_rt(first)->inh_task) ? tsk_rt(first)->inh_task->pid : 0, |
340 | second->comm, second->pid, | 315 | second->comm, second->pid, |
341 | (second->rt_param.inh_task) ? second->rt_param.inh_task->comm : "(nil)", | 316 | (tsk_rt(second)->inh_task) ? tsk_rt(second)->inh_task->comm : "(nil)", |
342 | (second->rt_param.inh_task) ? second->rt_param.inh_task->pid : 0); | 317 | (tsk_rt(second)->inh_task) ? tsk_rt(second)->inh_task->pid : 0); |
343 | */ | 318 | */ |
344 | return 1; | 319 | return 1; |
345 | } | 320 | } |
@@ -426,3 +401,4 @@ int edf_preemption_needed(rt_domain_t* rt, struct task_struct *t) | |||
426 | /* make sure to get non-rt stuff out of the way */ | 401 | /* make sure to get non-rt stuff out of the way */ |
427 | return !is_realtime(t) || edf_higher_prio(__next_ready(rt), t); | 402 | return !is_realtime(t) || edf_higher_prio(__next_ready(rt), t); |
428 | } | 403 | } |
404 | |||