diff options
author | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-05-09 16:44:29 -0400 |
---|---|---|
committer | John M. Calandrino <jmc@jupiter-cs.cs.unc.edu> | 2007-05-09 16:44:29 -0400 |
commit | a0615764712672e852ee44aabfaaaa0911f4a7c3 (patch) | |
tree | 12300d760b5ed76d56689edab3c8417cb8abddeb /kernel | |
parent | d1f5f5e7f672ff07fbe2d5051c7360f8a89f7ddc (diff) |
Various changes that I don't want to lose, but the code does not work.
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/edf_common.c | 8 | ||||
-rw-r--r-- | kernel/litmus.c | 3 | ||||
-rw-r--r-- | kernel/sched.c | 6 | ||||
-rw-r--r-- | kernel/sched_gsn_edf.c | 163 | ||||
-rw-r--r-- | kernel/sched_plugin.c | 8 |
5 files changed, 143 insertions, 45 deletions
diff --git a/kernel/edf_common.c b/kernel/edf_common.c index 20d990e30f..e41d9b2250 100644 --- a/kernel/edf_common.c +++ b/kernel/edf_common.c | |||
@@ -54,9 +54,11 @@ int edf_higher_prio(struct task_struct* first, | |||
54 | second_task = second->rt_param.inh_task; | 54 | second_task = second->rt_param.inh_task; |
55 | 55 | ||
56 | return !second_task || !is_realtime(second_task) || | 56 | return !second_task || !is_realtime(second_task) || |
57 | earlier_deadline(first_task, second_task) || | 57 | earlier_deadline(first_task, second_task) || |
58 | (get_deadline(first_task) == get_deadline(second_task) && | 58 | (get_deadline(first_task) == get_deadline(second_task) && |
59 | first_task->pid < second_task->pid); | 59 | (first_task->pid < second_task->pid || |
60 | (first_task->pid == second_task->pid && | ||
61 | !second->rt_param.inh_task))); | ||
60 | } | 62 | } |
61 | 63 | ||
62 | 64 | ||
diff --git a/kernel/litmus.c b/kernel/litmus.c index a437d603fc..91984777fa 100644 --- a/kernel/litmus.c +++ b/kernel/litmus.c | |||
@@ -431,7 +431,7 @@ long litmus_dummy_exit_np(struct task_struct *task); | |||
431 | long litmus_dummy_inherit_priority(struct pi_semaphore *sem, | 431 | long litmus_dummy_inherit_priority(struct pi_semaphore *sem, |
432 | struct task_struct *new_waiter); | 432 | struct task_struct *new_waiter); |
433 | long litmus_dummy_return_priority(struct pi_semaphore *sem); | 433 | long litmus_dummy_return_priority(struct pi_semaphore *sem); |
434 | 434 | long litmus_dummy_handle_priority_change(struct task_struct *t); | |
435 | 435 | ||
436 | #define CHECK(func) {\ | 436 | #define CHECK(func) {\ |
437 | if (!curr_sched_plugin->func) \ | 437 | if (!curr_sched_plugin->func) \ |
@@ -481,6 +481,7 @@ out: | |||
481 | CHECK(exit_np); | 481 | CHECK(exit_np); |
482 | CHECK(inherit_priority); | 482 | CHECK(inherit_priority); |
483 | CHECK(return_priority); | 483 | CHECK(return_priority); |
484 | CHECK(handle_priority_change); | ||
484 | 485 | ||
485 | #ifdef CONFIG_MAGIC_SYSRQ | 486 | #ifdef CONFIG_MAGIC_SYSRQ |
486 | /* offer some debugging help */ | 487 | /* offer some debugging help */ |
diff --git a/kernel/sched.c b/kernel/sched.c index 8a2599f705..9ee6d0df53 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -3574,6 +3574,9 @@ need_resched_nonpreemptible: | |||
3574 | } | 3574 | } |
3575 | } | 3575 | } |
3576 | 3576 | ||
3577 | /* debug */ | ||
3578 | TRACE("in schedule, calling plugin, %d %d\n", prev?prev->pid:0, prev?prev->state:0); | ||
3579 | |||
3577 | next = NULL; | 3580 | next = NULL; |
3578 | /* consult the real-time plugin */ | 3581 | /* consult the real-time plugin */ |
3579 | curr_sched_plugin->schedule(prev, &next, rq); | 3582 | curr_sched_plugin->schedule(prev, &next, rq); |
@@ -3850,7 +3853,7 @@ static void __pi_wake_up_common(struct pi_semaphore *s, unsigned int mode, | |||
3850 | /* Holder releases lock, restores priority, and finds | 3853 | /* Holder releases lock, restores priority, and finds |
3851 | * new semaphore priority. | 3854 | * new semaphore priority. |
3852 | */ | 3855 | */ |
3853 | curr_sched_plugin->return_priority(s); | 3856 | // curr_sched_plugin->return_priority(s); |
3854 | } | 3857 | } |
3855 | 3858 | ||
3856 | /** | 3859 | /** |
@@ -3907,6 +3910,7 @@ void fastcall __pi_wake_up(struct pi_semaphore *s, unsigned int mode, | |||
3907 | spin_lock_irqsave(&s->wait.lock, flags); | 3910 | spin_lock_irqsave(&s->wait.lock, flags); |
3908 | __pi_wake_up_common(s, mode, nr_exclusive, 0, key); | 3911 | __pi_wake_up_common(s, mode, nr_exclusive, 0, key); |
3909 | spin_unlock_irqrestore(&s->wait.lock, flags); | 3912 | spin_unlock_irqrestore(&s->wait.lock, flags); |
3913 | // curr_sched_plugin->handle_priority_change(current); | ||
3910 | } | 3914 | } |
3911 | 3915 | ||
3912 | /* | 3916 | /* |
diff --git a/kernel/sched_gsn_edf.c b/kernel/sched_gsn_edf.c index 29ec018149..2717ce60d6 100644 --- a/kernel/sched_gsn_edf.c +++ b/kernel/sched_gsn_edf.c | |||
@@ -14,12 +14,25 @@ | |||
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | 16 | ||
17 | //#include <linux/spinlock.h> | ||
17 | #include <linux/queuelock.h> | 18 | #include <linux/queuelock.h> |
18 | #include <linux/litmus.h> | 19 | #include <linux/litmus.h> |
19 | #include <linux/sched_plugin.h> | 20 | #include <linux/sched_plugin.h> |
20 | #include <linux/edf_common.h> | 21 | #include <linux/edf_common.h> |
21 | #include <linux/sched_trace.h> | 22 | #include <linux/sched_trace.h> |
22 | 23 | ||
24 | /* temp... */ | ||
25 | //#define queue_lock(a) spin_lock(a) | ||
26 | //#define queue_unlock(a) spin_unlock(a) | ||
27 | //#define queue_lock_irq(a) spin_lock_irq(a) | ||
28 | //#define queue_unlock_irq(a) spin_unlock_irq(a) | ||
29 | //#define queue_lock_irqsave(a,b) spin_lock_irqsave(a,b) | ||
30 | //#define queue_unlock_irqrestore(a,b) spin_unlock_irqrestore(a,b) | ||
31 | //#define queue_lock_init(a) spin_lock_init(a) | ||
32 | //typedef spinlock_t queuelock_t; | ||
33 | int in_gsnedf_schedule[NR_CPUS] = {0, 0, 0, 0}; | ||
34 | int in_gsnedf_scheduler_tick[NR_CPUS] = {0, 0, 0, 0}; | ||
35 | int in_gsnedf_finish_switch[NR_CPUS] = {0, 0, 0, 0}; | ||
23 | 36 | ||
24 | /* cpu_entry_t - maintain the linked and scheduled state | 37 | /* cpu_entry_t - maintain the linked and scheduled state |
25 | */ | 38 | */ |
@@ -92,7 +105,7 @@ static void update_cpu_position(cpu_entry_t *entry) | |||
92 | 105 | ||
93 | /* link_task_to_cpu - Update the link of a CPU. | 106 | /* link_task_to_cpu - Update the link of a CPU. |
94 | * Handles the case where the to-be-linked task is already | 107 | * Handles the case where the to-be-linked task is already |
95 | * scheduled on a differenty CPU. | 108 | * scheduled on a different CPU. |
96 | */ | 109 | */ |
97 | static noinline void link_task_to_cpu(struct task_struct* linked, | 110 | static noinline void link_task_to_cpu(struct task_struct* linked, |
98 | cpu_entry_t *entry) | 111 | cpu_entry_t *entry) |
@@ -104,12 +117,20 @@ static noinline void link_task_to_cpu(struct task_struct* linked, | |||
104 | 117 | ||
105 | BUG_ON(linked && !is_realtime(linked)); | 118 | BUG_ON(linked && !is_realtime(linked)); |
106 | 119 | ||
120 | /* Currently linked task is set to be unlinked. */ | ||
121 | if (entry->linked) { | ||
122 | entry->linked->rt_param.linked_on = NO_CPU; | ||
123 | TRACE("unlinked %d from CPU%d\n", entry->linked->pid, entry->cpu); | ||
124 | } | ||
125 | |||
126 | /* Link new task to CPU. */ | ||
107 | if (linked) { | 127 | if (linked) { |
108 | set_rt_flags(linked, RT_F_RUNNING); | 128 | set_rt_flags(linked, RT_F_RUNNING); |
109 | /* handle task is already scheduled somewhere! */ | 129 | /* handle task is already scheduled somewhere! */ |
110 | on_cpu = linked->rt_param.scheduled_on; | 130 | on_cpu = linked->rt_param.scheduled_on; |
111 | if (on_cpu != NO_CPU) { | 131 | if (on_cpu != NO_CPU) { |
112 | TRACE("to be linked task is already running!\n"); | 132 | TRACE("to be linked task is already running!\n"); |
133 | TRACE("to be linked = %d, sched = %d\n", entry->cpu, on_cpu) | ||
113 | sched = &per_cpu(gsnedf_cpu_entries, on_cpu); | 134 | sched = &per_cpu(gsnedf_cpu_entries, on_cpu); |
114 | /* this should only happen if it is not linked already */ | 135 | /* this should only happen if it is not linked already */ |
115 | BUG_ON(sched->linked == linked); | 136 | BUG_ON(sched->linked == linked); |
@@ -124,6 +145,8 @@ static noinline void link_task_to_cpu(struct task_struct* linked, | |||
124 | linked->rt_param.linked_on = sched->cpu; | 145 | linked->rt_param.linked_on = sched->cpu; |
125 | sched->linked = linked; | 146 | sched->linked = linked; |
126 | update_cpu_position(sched); | 147 | update_cpu_position(sched); |
148 | TRACE("task %d linked to CPU%d\n", linked->pid, linked->rt_param.linked_on); | ||
149 | TRACE("CPU%d linked to task %d\n", sched->cpu, sched->linked->pid); | ||
127 | linked = tmp; | 150 | linked = tmp; |
128 | } | 151 | } |
129 | } | 152 | } |
@@ -132,18 +155,27 @@ static noinline void link_task_to_cpu(struct task_struct* linked, | |||
132 | } | 155 | } |
133 | entry->linked = linked; | 156 | entry->linked = linked; |
134 | update_cpu_position(entry); | 157 | update_cpu_position(entry); |
158 | |||
159 | if (linked) { | ||
160 | TRACE("task %d linked to CPU%d\n", linked?linked->pid:0, linked?linked->rt_param.linked_on:0); | ||
161 | TRACE("CPU%d linked to task %d\n", entry->cpu, entry->linked?entry->linked->pid:0); | ||
162 | } | ||
135 | } | 163 | } |
136 | 164 | ||
137 | /* unlink - Make sure a task is not linked any longer to an entry | 165 | /* unlink - Make sure a task is not linked any longer to an entry |
138 | * where it was linked before. Must hold gsnedf_lock. | 166 | * where it was linked before. Must hold gsnedf_lock. |
139 | */ | 167 | */ |
140 | static noinline void unlink(struct task_struct* t, cpu_entry_t *entry) | 168 | static noinline void unlink(struct task_struct* t) |
141 | { | 169 | { |
142 | if (entry && entry->linked == t) { | 170 | cpu_entry_t *entry; |
171 | |||
172 | BUG_ON(!t); | ||
173 | |||
174 | if (t->rt_param.linked_on != NO_CPU) { | ||
143 | /* unlink */ | 175 | /* unlink */ |
176 | entry = &per_cpu(gsnedf_cpu_entries, t->rt_param.linked_on); | ||
144 | t->rt_param.linked_on = NO_CPU; | 177 | t->rt_param.linked_on = NO_CPU; |
145 | link_task_to_cpu(NULL, entry); | 178 | link_task_to_cpu(NULL, entry); |
146 | |||
147 | } else if (in_list(&t->rt_list)) { | 179 | } else if (in_list(&t->rt_list)) { |
148 | /* This is an interesting situation: t is scheduled, | 180 | /* This is an interesting situation: t is scheduled, |
149 | * but was just recently unlinked. It cannot be | 181 | * but was just recently unlinked. It cannot be |
@@ -153,8 +185,8 @@ static noinline void unlink(struct task_struct* t, cpu_entry_t *entry) | |||
153 | * case. | 185 | * case. |
154 | */ | 186 | */ |
155 | list_del(&t->rt_list); | 187 | list_del(&t->rt_list); |
156 | } | 188 | } |
157 | } | 189 | } |
158 | 190 | ||
159 | 191 | ||
160 | /* preempt - force a CPU to reschedule | 192 | /* preempt - force a CPU to reschedule |
@@ -188,9 +220,12 @@ static noinline void requeue(struct task_struct* task) | |||
188 | */ | 220 | */ |
189 | if (is_released(task) && get_rt_mode() == MODE_RT_RUN) | 221 | if (is_released(task) && get_rt_mode() == MODE_RT_RUN) |
190 | __add_ready(&gsnedf, task); | 222 | __add_ready(&gsnedf, task); |
191 | else | 223 | else { |
224 | TRACE("release added due to sleeping task\n"); | ||
192 | /* it has got to wait */ | 225 | /* it has got to wait */ |
193 | __add_release(&gsnedf, task); | 226 | __add_release(&gsnedf, task); |
227 | } | ||
228 | |||
194 | } else | 229 | } else |
195 | /* this is a forced preemption | 230 | /* this is a forced preemption |
196 | * thus the task stays in the ready_queue | 231 | * thus the task stays in the ready_queue |
@@ -218,6 +253,8 @@ static noinline void gsnedf_job_arrival(struct task_struct* task) | |||
218 | TRACE("job_arrival: task %d linked to %d\n", task->pid, last->cpu); | 253 | TRACE("job_arrival: task %d linked to %d\n", task->pid, last->cpu); |
219 | if (last->linked) | 254 | if (last->linked) |
220 | requeue(last->linked); | 255 | requeue(last->linked); |
256 | |||
257 | TRACE("GSNEDF_JA: LINK %d to %d\n", task?task->pid:0, last->cpu); | ||
221 | link_task_to_cpu(task, last); | 258 | link_task_to_cpu(task, last); |
222 | preempt(last); | 259 | preempt(last); |
223 | } | 260 | } |
@@ -258,6 +295,10 @@ static reschedule_check_t gsnedf_scheduler_tick(void) | |||
258 | reschedule_check_t want_resched = NO_RESCHED; | 295 | reschedule_check_t want_resched = NO_RESCHED; |
259 | cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); | 296 | cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); |
260 | 297 | ||
298 | /* debug */ | ||
299 | // queue_lock_irqsave(&gsnedf_lock, flags); | ||
300 | in_gsnedf_scheduler_tick[smp_processor_id()] = 1; | ||
301 | |||
261 | /* expire tasks even if not in real-time mode | 302 | /* expire tasks even if not in real-time mode |
262 | * this makes sure that at the end of real-time mode | 303 | * this makes sure that at the end of real-time mode |
263 | * no task "runs away forever". | 304 | * no task "runs away forever". |
@@ -277,13 +318,16 @@ static reschedule_check_t gsnedf_scheduler_tick(void) | |||
277 | prepare_for_next_period(t); | 318 | prepare_for_next_period(t); |
278 | queue_lock_irqsave(&gsnedf_lock, flags); | 319 | queue_lock_irqsave(&gsnedf_lock, flags); |
279 | /* unlink */ | 320 | /* unlink */ |
280 | unlink(t, entry); | 321 | TRACE("UNLINKING FROM GSNEDF_SCHEDULER_TICK\n"); |
322 | unlink(t); | ||
281 | /* requeue */ | 323 | /* requeue */ |
282 | gsnedf_job_arrival(t); | 324 | gsnedf_job_arrival(t); |
283 | queue_unlock_irqrestore(&gsnedf_lock, flags); | 325 | queue_unlock_irqrestore(&gsnedf_lock, flags); |
284 | } | 326 | } |
285 | } | 327 | } |
286 | if (get_rt_mode() == MODE_RT_RUN) { | 328 | if (get_rt_mode() == MODE_RT_RUN) { |
329 | in_gsnedf_scheduler_tick[smp_processor_id()] = 666; | ||
330 | |||
287 | queue_lock_irqsave(&gsnedf_lock, flags); | 331 | queue_lock_irqsave(&gsnedf_lock, flags); |
288 | 332 | ||
289 | /* (1) try to release pending jobs */ | 333 | /* (1) try to release pending jobs */ |
@@ -296,7 +340,12 @@ static reschedule_check_t gsnedf_scheduler_tick(void) | |||
296 | set_will_schedule(); | 340 | set_will_schedule(); |
297 | } | 341 | } |
298 | queue_unlock_irqrestore(&gsnedf_lock, flags); | 342 | queue_unlock_irqrestore(&gsnedf_lock, flags); |
299 | } | 343 | } |
344 | |||
345 | /* debug */ | ||
346 | // queue_unlock_irqrestore(&gsnedf_lock, flags); | ||
347 | in_gsnedf_scheduler_tick[smp_processor_id()] = 0; | ||
348 | |||
300 | return want_resched; | 349 | return want_resched; |
301 | } | 350 | } |
302 | 351 | ||
@@ -310,6 +359,8 @@ static int gsnedf_schedule(struct task_struct * prev, | |||
310 | { | 359 | { |
311 | cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); | 360 | cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); |
312 | 361 | ||
362 | in_gsnedf_schedule[smp_processor_id()] = 1; | ||
363 | |||
313 | /* will be released in finish_switch */ | 364 | /* will be released in finish_switch */ |
314 | queue_lock(&gsnedf_lock); | 365 | queue_lock(&gsnedf_lock); |
315 | clear_will_schedule(); | 366 | clear_will_schedule(); |
@@ -318,12 +369,16 @@ static int gsnedf_schedule(struct task_struct * prev, | |||
318 | 369 | ||
319 | /* (1) check for blocking jobs */ | 370 | /* (1) check for blocking jobs */ |
320 | if (prev == entry->linked && | 371 | if (prev == entry->linked && |
321 | (get_rt_mode() != MODE_RT_RUN || !is_running(prev))) | 372 | (get_rt_mode() != MODE_RT_RUN || !is_running(prev))) { |
373 | TRACE("UNLINK (NULL) FROM GSNEDF_SCHEDULE prev=%x entry->linked=%x prev->state=%d\n", prev, entry->linked, prev?prev->state:-666); | ||
322 | link_task_to_cpu(NULL, entry); | 374 | link_task_to_cpu(NULL, entry); |
375 | } | ||
323 | 376 | ||
324 | /* (2) if not linked then get rt task */ | 377 | /* (2) if not linked then get rt task */ |
325 | if (get_rt_mode() == MODE_RT_RUN && !entry->linked) | 378 | if (get_rt_mode() == MODE_RT_RUN && !entry->linked) { |
379 | TRACE("GSNEDF_SCHED: LINK TO %d\n", entry->cpu); | ||
326 | link_task_to_cpu(__take_ready(&gsnedf), entry); | 380 | link_task_to_cpu(__take_ready(&gsnedf), entry); |
381 | } | ||
327 | 382 | ||
328 | /* (3) if linked different from scheduled | 383 | /* (3) if linked different from scheduled |
329 | * select linked as next | 384 | * select linked as next |
@@ -354,6 +409,10 @@ static int gsnedf_schedule(struct task_struct * prev, | |||
354 | */ | 409 | */ |
355 | if (prev == *next || (!is_realtime(prev) && !*next)) | 410 | if (prev == *next || (!is_realtime(prev) && !*next)) |
356 | queue_unlock(&gsnedf_lock); | 411 | queue_unlock(&gsnedf_lock); |
412 | // if (prev == *next) | ||
413 | // queue_unlock(&gsnedf_lock); | ||
414 | |||
415 | in_gsnedf_schedule[smp_processor_id()] = 0; | ||
357 | 416 | ||
358 | return 0; | 417 | return 0; |
359 | } | 418 | } |
@@ -365,6 +424,8 @@ static void gsnedf_finish_switch(struct task_struct *prev) | |||
365 | { | 424 | { |
366 | cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); | 425 | cpu_entry_t* entry = &__get_cpu_var(gsnedf_cpu_entries); |
367 | 426 | ||
427 | in_gsnedf_finish_switch[smp_processor_id()] = 1; | ||
428 | |||
368 | if (is_realtime(current)) | 429 | if (is_realtime(current)) |
369 | entry->scheduled = current; | 430 | entry->scheduled = current; |
370 | else | 431 | else |
@@ -374,8 +435,18 @@ static void gsnedf_finish_switch(struct task_struct *prev) | |||
374 | current->rt_param.scheduled_on = smp_processor_id(); | 435 | current->rt_param.scheduled_on = smp_processor_id(); |
375 | 436 | ||
376 | /* unlock in case schedule() left it locked */ | 437 | /* unlock in case schedule() left it locked */ |
377 | if (is_realtime(current) || is_realtime(prev)) | 438 | if (is_realtime(current) || is_realtime(prev)) { |
378 | queue_unlock(&gsnedf_lock); | 439 | // /* spinlock stuff to change ownership... */ |
440 | // if (gsnedf_lock.owner != current) { | ||
441 | // gsnedf_lock.owner = current; | ||
442 | // spin_acquire(&gsnedf_lock.dep_map, 0, 0, _THIS_IP_); | ||
443 | // queue_unlock(&gsnedf_lock); | ||
444 | // } else | ||
445 | /* unlock... */ | ||
446 | queue_unlock(&gsnedf_lock); | ||
447 | } | ||
448 | |||
449 | in_gsnedf_finish_switch[smp_processor_id()] = 0; | ||
379 | } | 450 | } |
380 | 451 | ||
381 | 452 | ||
@@ -455,12 +526,11 @@ static void gsnedf_wake_up_task(struct task_struct *task) | |||
455 | static void gsnedf_task_blocks(struct task_struct *t) | 526 | static void gsnedf_task_blocks(struct task_struct *t) |
456 | { | 527 | { |
457 | unsigned long flags; | 528 | unsigned long flags; |
458 | cpu_entry_t* entry; | ||
459 | 529 | ||
460 | /* unlink if necessary */ | 530 | /* unlink if necessary */ |
461 | queue_lock_irqsave(&gsnedf_lock, flags); | 531 | queue_lock_irqsave(&gsnedf_lock, flags); |
462 | entry = &__get_cpu_var(gsnedf_cpu_entries); | 532 | TRACE("UNLINK FROM GSNEDF_TASK_BLOCKS\n"); |
463 | unlink(t, entry); | 533 | unlink(t); |
464 | queue_unlock_irqrestore(&gsnedf_lock, flags); | 534 | queue_unlock_irqrestore(&gsnedf_lock, flags); |
465 | 535 | ||
466 | BUG_ON(!is_realtime(t)); | 536 | BUG_ON(!is_realtime(t)); |
@@ -515,16 +585,24 @@ static long gsnedf_exit_np(struct task_struct * t) | |||
515 | return ret; | 585 | return ret; |
516 | } | 586 | } |
517 | 587 | ||
518 | static noinline void handle_priority_change(struct task_struct *t) | 588 | static noinline long gsnedf_handle_priority_change(struct task_struct *t) |
519 | { | 589 | { |
520 | int link_cpu; | 590 | unsigned long flags; |
521 | 591 | int ret = 0; | |
522 | link_cpu = t->rt_param.linked_on; | ||
523 | 592 | ||
524 | unlink(t, link_cpu != NO_CPU ? &per_cpu(gsnedf_cpu_entries, link_cpu) : | 593 | queue_lock_irqsave(&gsnedf_lock, flags); |
525 | NULL); | 594 | |
595 | /* debug: a task can only unlink and reschedule itself! */ | ||
596 | if (t && t == current) { | ||
597 | TRACE("HPC: UL %d %d\n", current->pid, t->pid); | ||
598 | unlink(t); | ||
599 | TRACE("HPC: JA %d %d\n", current->pid, t->pid); | ||
600 | gsnedf_job_arrival(t); /* requeue/link as appropriate */ | ||
601 | } | ||
602 | |||
603 | queue_unlock_irqrestore(&gsnedf_lock, flags); | ||
526 | 604 | ||
527 | gsnedf_job_arrival(t); /* requeue/link as appropriate */ | 605 | return ret; |
528 | } | 606 | } |
529 | 607 | ||
530 | static long gsnedf_inherit_priority(struct pi_semaphore *sem, | 608 | static long gsnedf_inherit_priority(struct pi_semaphore *sem, |
@@ -540,14 +618,21 @@ static long gsnedf_inherit_priority(struct pi_semaphore *sem, | |||
540 | * not yet been determined. Need to also compare against your | 618 | * not yet been determined. Need to also compare against your |
541 | * own task priority! | 619 | * own task priority! |
542 | */ | 620 | */ |
543 | if (sem->holder && !sem->holder->rt_param.inh_task) { | 621 | if (sem->holder && sem->holder == current && |
544 | sem->holder->rt_param.inh_task = sem->holder; | 622 | !sem->holder->rt_param.inh_task) { |
623 | TRACE("IP: INH %d %d\n", current->pid, sem->holder->pid); | ||
624 | sem->holder->rt_param.inh_task = sem->holder; | ||
545 | if (sem->hp_sem_task && | 625 | if (sem->hp_sem_task && |
546 | edf_higher_prio(sem->hp_sem_task, sem->holder)) { | 626 | edf_higher_prio(sem->hp_sem_task, sem->holder)) { |
547 | sem->holder->rt_param.inh_task = sem->hp_sem_task; | 627 | sem->holder->rt_param.inh_task = sem->hp_sem_task; |
548 | handle_priority_change(sem->holder); | 628 | TRACE("IP: INH %d %d UL\n", sem->holder->rt_param.inh_task->pid, sem->hp_sem_task->pid); |
549 | } else | 629 | unlink(sem->holder); |
630 | TRACE("IP: JA %d %d\n", current->pid, sem->holder->pid); | ||
631 | gsnedf_job_arrival(sem->holder); /* requeue/link */ | ||
632 | } else { | ||
550 | sem->hp_sem_task = sem->holder; | 633 | sem->hp_sem_task = sem->holder; |
634 | TRACE("IP: NO %d %d\n", sem->holder->pid, sem->hp_sem_task->pid); | ||
635 | } | ||
551 | } | 636 | } |
552 | 637 | ||
553 | /* Check if new waiting task increases priority of | 638 | /* Check if new waiting task increases priority of |
@@ -559,12 +644,12 @@ static long gsnedf_inherit_priority(struct pi_semaphore *sem, | |||
559 | /* Holder priority changed... make sure to | 644 | /* Holder priority changed... make sure to |
560 | * update system as a result. | 645 | * update system as a result. |
561 | */ | 646 | */ |
562 | if (sem->holder) { | 647 | if (sem->holder) { |
563 | sem->holder->rt_param.inh_task = new_waiter; | 648 | sem->holder->rt_param.inh_task = new_waiter; |
564 | handle_priority_change(sem->holder); | 649 | TRACE("IP: PR %d %d %d\n", new_waiter->pid, sem->holder->pid, sem->holder->rt_param.inh_task->pid); |
565 | } | 650 | } |
566 | } | 651 | } |
567 | 652 | ||
568 | queue_unlock_irqrestore(&gsnedf_lock, flags); | 653 | queue_unlock_irqrestore(&gsnedf_lock, flags); |
569 | return ret; | 654 | return ret; |
570 | } | 655 | } |
@@ -577,9 +662,11 @@ static long gsnedf_return_priority(struct pi_semaphore *sem) | |||
577 | struct list_head *tmp, *next; | 662 | struct list_head *tmp, *next; |
578 | unsigned long flags; | 663 | unsigned long flags; |
579 | int ret = 0; | 664 | int ret = 0; |
580 | 665 | ||
581 | queue_lock_irqsave(&gsnedf_lock, flags); | 666 | queue_lock_irqsave(&gsnedf_lock, flags); |
582 | 667 | ||
668 | TRACE("RP: %d %d %d\n", current->pid, sem->hp_sem_task->pid, current->rt_param.inh_task->pid); | ||
669 | |||
583 | /* Find new highest-priority semaphore task | 670 | /* Find new highest-priority semaphore task |
584 | * if holder task is the current hp_sem_task. | 671 | * if holder task is the current hp_sem_task. |
585 | */ | 672 | */ |
@@ -607,12 +694,9 @@ static long gsnedf_return_priority(struct pi_semaphore *sem) | |||
607 | /* Remove current task as holder. */ | 694 | /* Remove current task as holder. */ |
608 | sem->holder = NULL; | 695 | sem->holder = NULL; |
609 | 696 | ||
610 | /* Holder priority changed... make sure to update system | 697 | TRACE("RP: %d %d %d *\n", current->pid, sem->hp_sem_task?sem->hp_sem_task->pid:0, current->rt_param.inh_task?current->rt_param.inh_task->pid:0); |
611 | * as a result. | ||
612 | */ | ||
613 | handle_priority_change(current); | ||
614 | 698 | ||
615 | queue_unlock_irqrestore(&gsnedf_lock, flags); | 699 | queue_unlock_irqrestore(&gsnedf_lock, flags); |
616 | return ret; | 700 | return ret; |
617 | } | 701 | } |
618 | 702 | ||
@@ -673,7 +757,8 @@ static sched_plugin_t s_plugin __cacheline_aligned_in_smp = { | |||
673 | .enter_np = gsnedf_enter_np, \ | 757 | .enter_np = gsnedf_enter_np, \ |
674 | .exit_np = gsnedf_exit_np, \ | 758 | .exit_np = gsnedf_exit_np, \ |
675 | .inherit_priority = gsnedf_inherit_priority, \ | 759 | .inherit_priority = gsnedf_inherit_priority, \ |
676 | .return_priority = gsnedf_return_priority \ | 760 | .return_priority = gsnedf_return_priority, \ |
761 | .handle_priority_change = gsnedf_handle_priority_change \ | ||
677 | } | 762 | } |
678 | 763 | ||
679 | 764 | ||
diff --git a/kernel/sched_plugin.c b/kernel/sched_plugin.c index 8170d6e1df..82ee3f9458 100644 --- a/kernel/sched_plugin.c +++ b/kernel/sched_plugin.c | |||
@@ -89,6 +89,11 @@ long litmus_dummy_return_priority(struct pi_semaphore *sem) | |||
89 | return -EPERM; | 89 | return -EPERM; |
90 | } | 90 | } |
91 | 91 | ||
92 | long litmus_dummy_handle_priority_change(struct task_struct *t) | ||
93 | { | ||
94 | return -EPERM; | ||
95 | } | ||
96 | |||
92 | 97 | ||
93 | /* The default scheduler plugin. It doesn't do anything and lets Linux do its | 98 | /* The default scheduler plugin. It doesn't do anything and lets Linux do its |
94 | * job. | 99 | * job. |
@@ -109,7 +114,8 @@ sched_plugin_t linux_sched_plugin = { | |||
109 | .finish_switch = litmus_dummy_finish_switch, | 114 | .finish_switch = litmus_dummy_finish_switch, |
110 | .scheduler_setup = litmus_dummy_scheduler_setup, | 115 | .scheduler_setup = litmus_dummy_scheduler_setup, |
111 | .inherit_priority = litmus_dummy_inherit_priority, | 116 | .inherit_priority = litmus_dummy_inherit_priority, |
112 | .return_priority = litmus_dummy_return_priority | 117 | .return_priority = litmus_dummy_return_priority, |
118 | .handle_priority_change = litmus_dummy_handle_priority_change | ||
113 | }; | 119 | }; |
114 | 120 | ||
115 | /* | 121 | /* |