diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2007-04-25 15:23:39 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2007-04-25 15:23:39 -0400 |
commit | 50e4938993cbb7ce43566c18d7d6616b2b8c61d6 (patch) | |
tree | f92a3da242cd4fa709835252fcaa23a18d782152 /kernel | |
parent | 3695e6b8dd1eeb288419674df951a35dd69ade52 (diff) |
Fixed GSN-EDF job_arrival() function.
Now the correct job is linked in case that a linked job lowers its
priority. This could happen if a tardy job's successor is immediately
released in the scheduler_tick() function.
The preemption_needed() function was made more robust to handle NULL
pointers correctly (needed for GSN-EDF).
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/edf_common.c | 35 | ||||
-rw-r--r-- | kernel/sched_gsn_edf.c | 15 |
2 files changed, 32 insertions, 18 deletions
diff --git a/kernel/edf_common.c b/kernel/edf_common.c index 6a232a8f01..9aa4f39d1e 100644 --- a/kernel/edf_common.c +++ b/kernel/edf_common.c | |||
@@ -82,17 +82,23 @@ void __add_ready(edf_domain_t* edf, struct task_struct *new) | |||
82 | 82 | ||
83 | struct task_struct* __take_ready(edf_domain_t* edf) | 83 | struct task_struct* __take_ready(edf_domain_t* edf) |
84 | { | 84 | { |
85 | struct task_struct *t = __peek_ready(edf); | ||
86 | |||
87 | /* kick it out of the ready list */ | ||
88 | if (t) | ||
89 | list_del(&t->rt_list); | ||
90 | return t; | ||
91 | } | ||
92 | |||
93 | |||
94 | struct task_struct* __peek_ready(edf_domain_t* edf) | ||
95 | { | ||
85 | struct task_struct *t = NULL; | 96 | struct task_struct *t = NULL; |
86 | /* either not yet released, preempted, or non-rt */ | 97 | /* either not yet released, preempted, or non-rt */ |
87 | if (!list_empty(&edf->ready_queue)) { | 98 | if (!list_empty(&edf->ready_queue)) |
88 | |||
89 | /* take next rt task */ | 99 | /* take next rt task */ |
90 | t = list_entry(edf->ready_queue.next, struct task_struct, | 100 | t = list_entry(edf->ready_queue.next, struct task_struct, |
91 | rt_list); | 101 | rt_list); |
92 | |||
93 | /* kick it out of the ready list */ | ||
94 | list_del(&t->rt_list); | ||
95 | } | ||
96 | return t; | 102 | return t; |
97 | } | 103 | } |
98 | 104 | ||
@@ -225,13 +231,16 @@ void __prepare_new_releases(edf_domain_t *edf, jiffie_t start) | |||
225 | int preemption_needed(edf_domain_t* edf, struct task_struct *t) | 231 | int preemption_needed(edf_domain_t* edf, struct task_struct *t) |
226 | { | 232 | { |
227 | /* we need the read lock for edf_ready_queue */ | 233 | /* we need the read lock for edf_ready_queue */ |
228 | if (!list_empty(&edf->ready_queue) || is_np(t)) | 234 | /* no need to preempt if there is nothing pending */ |
229 | { | 235 | if (list_empty(&edf->ready_queue)) |
230 | if (is_realtime(t)) | 236 | return 0; |
231 | return edf_higher_prio(next_ready(edf), t); | 237 | /* we need to reschedule if t doesn't exist */ |
232 | else | 238 | if (!t) |
233 | return 1; | 239 | return 1; |
234 | } | 240 | /* don't preempt if t is non-preemptable */ |
241 | if (!is_np(t)) | ||
242 | /* make sure to get non-rt stuff out of the way */ | ||
243 | return !is_realtime(t) || edf_higher_prio(next_ready(edf), t); | ||
235 | return 0; | 244 | return 0; |
236 | } | 245 | } |
237 | 246 | ||
diff --git a/kernel/sched_gsn_edf.c b/kernel/sched_gsn_edf.c index dcf976930c..54f3ddc539 100644 --- a/kernel/sched_gsn_edf.c +++ b/kernel/sched_gsn_edf.c | |||
@@ -196,16 +196,21 @@ static noinline void gsnedf_job_arrival(struct task_struct* task) | |||
196 | 196 | ||
197 | BUG_ON(list_empty(&gsnedf_cpu_queue)); | 197 | BUG_ON(list_empty(&gsnedf_cpu_queue)); |
198 | BUG_ON(!task); | 198 | BUG_ON(!task); |
199 | last = list_entry(gsnedf_cpu_queue.prev, cpu_entry_t, list); | ||
200 | 199 | ||
201 | if (is_released(task) && edf_higher_prio(task, last->linked)) { | 200 | /* first queue arriving job */ |
202 | TRACE("arriving task %d linked to %d\n", task->pid, last->cpu); | 201 | requeue(task); |
202 | |||
203 | /* then check for any necessary preemptions */ | ||
204 | last = list_entry(gsnedf_cpu_queue.prev, cpu_entry_t, list); | ||
205 | if (preemption_needed(&gsnedf, last->linked)) { | ||
206 | /* preemption necessary */ | ||
207 | task = __take_ready(&gsnedf); | ||
208 | TRACE("job_arrival: task %d linked to %d\n", task->pid, last->cpu); | ||
203 | if (last->linked) | 209 | if (last->linked) |
204 | requeue(last->linked); | 210 | requeue(last->linked); |
205 | link_task_to_cpu(task, last); | 211 | link_task_to_cpu(task, last); |
206 | preempt(last); | 212 | preempt(last); |
207 | } else | 213 | } |
208 | requeue(task); | ||
209 | } | 214 | } |
210 | 215 | ||
211 | /* check for current job releases */ | 216 | /* check for current job releases */ |