diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2014-02-19 15:30:22 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2014-02-19 15:33:42 -0500 |
commit | 8a74106e25e8e4d38bc1ad651258de170262ee73 (patch) | |
tree | 45541986718a8441d34daa7d88be30d0e2d95017 /litmus | |
parent | b3d2b207a895731c10c5e3b92df9ce1d6d974038 (diff) |
Port C-FL PGM algorithms to G-EDF.
Diffstat (limited to 'litmus')
-rw-r--r-- | litmus/sched_gsn_edf.c | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c index b819b62915f1..b6973e20cf97 100644 --- a/litmus/sched_gsn_edf.c +++ b/litmus/sched_gsn_edf.c | |||
@@ -457,45 +457,67 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev) | |||
457 | if (exists) | 457 | if (exists) |
458 | TRACE_TASK(prev, | 458 | TRACE_TASK(prev, |
459 | "blocks:%d out_of_time:%d np:%d sleep:%d preempt:%d " | 459 | "blocks:%d out_of_time:%d np:%d sleep:%d preempt:%d " |
460 | "state:%d sig:%d\n", | 460 | "state:%d sig:%d boosted:%d\n", |
461 | blocks, out_of_time, np, sleep, preempt, | 461 | blocks, out_of_time, np, sleep, preempt, |
462 | prev->state, signal_pending(prev)); | 462 | prev->state, signal_pending(prev), |
463 | is_priority_boosted(entry->scheduled)); | ||
463 | if (entry->linked && preempt) | 464 | if (entry->linked && preempt) |
464 | TRACE_TASK(prev, "will be preempted by %s/%d\n", | 465 | TRACE_TASK(prev, "will be preempted by %s/%d\n", |
465 | entry->linked->comm, entry->linked->pid); | 466 | entry->linked->comm, entry->linked->pid); |
466 | 467 | ||
467 | #ifdef CONFIG_SCHED_PGM | 468 | #ifdef CONFIG_SCHED_PGM |
468 | if (exists && is_pgm_waiting(entry->scheduled)) { | 469 | if (exists) { |
469 | if (!is_priority_boosted(entry->scheduled)) { | 470 | if (is_pgm_sending(entry->scheduled)) { |
470 | TRACE_TASK(entry->scheduled, "is waiting for PGM tokens.\n"); | 471 | if (!is_pgm_satisfied(entry->scheduled)) { |
471 | BUG_ON(is_pgm_satisfied(entry->scheduled)); | 472 | if (!is_priority_boosted(entry->scheduled)) { |
472 | 473 | TRACE_TASK(entry->scheduled, "is sending PGM tokens and needs boosting.\n"); | |
473 | /* Boost priority so we'll be scheduled immediately | 474 | BUG_ON(is_pgm_satisfied(entry->scheduled)); |
474 | when needed tokens arrive. */ | 475 | |
475 | tsk_rt(entry->scheduled)->priority_boosted = 1; | 476 | /* We are either sending tokens or waiting for tokes. |
476 | tsk_rt(entry->scheduled)->boost_start_time = litmus_clock(); | 477 | If waiting: Boost priority so we'll be scheduled |
477 | 478 | immediately when needed tokens arrive. | |
478 | if (unlikely(!blocks)) { | 479 | If sending: Boost priority so no one (specifically, our |
479 | /* Task has probably blocked on an inbound token socket, but | 480 | consumers) will preempt us while signalling the token |
480 | if not, re-evaluate scheduling decisions */ | 481 | transmission. |
481 | unlink(entry->scheduled); | 482 | */ |
482 | gsnedf_job_arrival(entry->scheduled); | 483 | tsk_rt(entry->scheduled)->priority_boosted = 1; |
484 | tsk_rt(entry->scheduled)->boost_start_time = litmus_clock(); | ||
485 | |||
486 | if (likely(!blocks)) { | ||
487 | unlink(entry->scheduled); | ||
488 | gsnedf_job_arrival(entry->scheduled); | ||
489 | /* we may regain the processor */ | ||
490 | if (preempt) { | ||
491 | preempt = entry->scheduled != entry->linked; | ||
492 | if (!preempt) { | ||
493 | TRACE_TASK(entry->scheduled, "blocked preemption by lazy boosting.\n"); | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | } | ||
483 | } | 498 | } |
484 | } | 499 | else { /* sending is satisfied */ |
485 | else if (is_pgm_satisfied(entry->scheduled)) { | 500 | tsk_rt(entry->scheduled)->ctrl_page->pgm_sending = 0; |
486 | TRACE_TASK(entry->scheduled, "is done waiting for PGM tokens.\n"); | 501 | tsk_rt(entry->scheduled)->ctrl_page->pgm_satisfied = 0; |
487 | BUG_ON(!is_priority_boosted(entry->scheduled)); | 502 | |
488 | 503 | if (is_priority_boosted(entry->scheduled)) { | |
489 | /* clear any boosting */ | 504 | TRACE_TASK(entry->scheduled, |
490 | tsk_rt(entry->scheduled)->priority_boosted = 0; | 505 | "is done sending PGM tokens must relinquish boosting.\n"); |
491 | setup_pgm_release(entry->scheduled); | 506 | /* clear boosting */ |
492 | 507 | tsk_rt(entry->scheduled)->priority_boosted = 0; | |
493 | if (likely(!blocks)) { | 508 | if(likely(!blocks)) { |
494 | /* Task has probably called sched_yield(), so blocking is | 509 | /* recheck priority */ |
495 | unlikely. Re-evaluate scheduling decisions because we | 510 | unlink(entry->scheduled); |
496 | still want to run. */ | 511 | gsnedf_job_arrival(entry->scheduled); |
497 | unlink(entry->scheduled); | 512 | /* we may lose the processor */ |
498 | gsnedf_job_arrival(entry->scheduled); | 513 | if (!preempt) { |
514 | preempt = entry->scheduled != entry->linked; | ||
515 | if (preempt) { | ||
516 | TRACE_TASK(entry->scheduled, "preempted by lazy unboosting.\n"); | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | } | ||
499 | } | 521 | } |
500 | } | 522 | } |
501 | } | 523 | } |
@@ -511,10 +533,13 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev) | |||
511 | * that we are still linked. Multiple calls to request_exit_np() don't | 533 | * that we are still linked. Multiple calls to request_exit_np() don't |
512 | * hurt. | 534 | * hurt. |
513 | */ | 535 | */ |
514 | if (np && (out_of_time || preempt || sleep)) { | 536 | if (np && (out_of_time || sleep)) { |
515 | unlink(entry->scheduled); | 537 | unlink(entry->scheduled); |
516 | request_exit_np(entry->scheduled); | 538 | request_exit_np(entry->scheduled); |
517 | } | 539 | } |
540 | else if (np && preempt) { | ||
541 | request_exit_np(entry->scheduled); | ||
542 | } | ||
518 | 543 | ||
519 | /* Any task that is preemptable and either exhausts its execution | 544 | /* Any task that is preemptable and either exhausts its execution |
520 | * budget or wants to sleep completes. We may have to reschedule after | 545 | * budget or wants to sleep completes. We may have to reschedule after |
@@ -545,12 +570,14 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev) | |||
545 | entry->scheduled->rt_param.scheduled_on = NO_CPU; | 570 | entry->scheduled->rt_param.scheduled_on = NO_CPU; |
546 | TRACE_TASK(entry->scheduled, "scheduled_on = NO_CPU\n"); | 571 | TRACE_TASK(entry->scheduled, "scheduled_on = NO_CPU\n"); |
547 | } | 572 | } |
548 | } else | 573 | } |
574 | else { | ||
549 | /* Only override Linux scheduler if we have a real-time task | 575 | /* Only override Linux scheduler if we have a real-time task |
550 | * scheduled that needs to continue. | 576 | * scheduled that needs to continue. |
551 | */ | 577 | */ |
552 | if (exists) | 578 | if (exists) |
553 | next = prev; | 579 | next = prev; |
580 | } | ||
554 | 581 | ||
555 | sched_state_task_picked(); | 582 | sched_state_task_picked(); |
556 | 583 | ||
@@ -565,7 +592,6 @@ static struct task_struct* gsnedf_schedule(struct task_struct * prev) | |||
565 | TRACE("becomes idle at %llu.\n", litmus_clock()); | 592 | TRACE("becomes idle at %llu.\n", litmus_clock()); |
566 | #endif | 593 | #endif |
567 | 594 | ||
568 | |||
569 | return next; | 595 | return next; |
570 | } | 596 | } |
571 | 597 | ||
@@ -637,6 +663,10 @@ static void gsnedf_task_wake_up(struct task_struct *task) | |||
637 | release_at(task, now); | 663 | release_at(task, now); |
638 | sched_trace_task_release(task); | 664 | sched_trace_task_release(task); |
639 | } | 665 | } |
666 | if (is_pgm_waiting(task)) { | ||
667 | /* shift out release/deadline, if needed */ | ||
668 | setup_pgm_release(task); | ||
669 | } | ||
640 | gsnedf_job_arrival(task); | 670 | gsnedf_job_arrival(task); |
641 | raw_spin_unlock_irqrestore(&gsnedf_lock, flags); | 671 | raw_spin_unlock_irqrestore(&gsnedf_lock, flags); |
642 | } | 672 | } |