diff options
Diffstat (limited to 'litmus/sched_mc.c')
-rw-r--r-- | litmus/sched_mc.c | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c index baded0d58cb9..da8a82119612 100644 --- a/litmus/sched_mc.c +++ b/litmus/sched_mc.c | |||
@@ -477,6 +477,22 @@ static void update_crit_levels(struct cpu_entry *entry) | |||
477 | } | 477 | } |
478 | } | 478 | } |
479 | 479 | ||
480 | static inline int cache_next(struct domain *dom) | ||
481 | { | ||
482 | struct task_struct *t; | ||
483 | t = dom->peek_ready(dom); | ||
484 | return 1; | ||
485 | /* if (t && tsk_mc_crit(t) != CRIT_LEVEL_A && budget_exhausted(t)) { */ | ||
486 | /* TRACE_TASK(t, "Cached and moved to release\n"); */ | ||
487 | /* prepare_for_next_server(t, 1); */ | ||
488 | /* dom->take_ready(dom); */ | ||
489 | /* dom->requeue(dom, t); */ | ||
490 | /* return 0; */ | ||
491 | /* } else { */ | ||
492 | /* return 1; */ | ||
493 | /* } */ | ||
494 | } | ||
495 | |||
480 | /** | 496 | /** |
481 | * check_for_preempt() - Causes a preemption if higher-priority tasks are ready. | 497 | * check_for_preempt() - Causes a preemption if higher-priority tasks are ready. |
482 | * Caller must hold domain lock. | 498 | * Caller must hold domain lock. |
@@ -495,8 +511,10 @@ static void check_for_preempt(struct domain *dom) | |||
495 | entry = crit_cpu(ce); | 511 | entry = crit_cpu(ce); |
496 | recheck = 1; | 512 | recheck = 1; |
497 | 513 | ||
498 | /* Cache ready task */ | 514 | /* Dodge exhausted tasks */ |
499 | dom->peek_ready(dom); | 515 | if (!cache_next(dom)) { |
516 | continue; | ||
517 | } | ||
500 | 518 | ||
501 | raw_spin_lock(&entry->lock); | 519 | raw_spin_lock(&entry->lock); |
502 | if (!can_use(ce)) | 520 | if (!can_use(ce)) |
@@ -516,6 +534,7 @@ static void check_for_preempt(struct domain *dom) | |||
516 | ce = domain_data(dom)->crit_entry; | 534 | ce = domain_data(dom)->crit_entry; |
517 | entry = crit_cpu(ce); | 535 | entry = crit_cpu(ce); |
518 | raw_spin_lock(&entry->lock); | 536 | raw_spin_lock(&entry->lock); |
537 | while (!cache_next(dom)); | ||
519 | if (can_use(ce) && dom->preempt_needed(dom, ce->linked)) { | 538 | if (can_use(ce) && dom->preempt_needed(dom, ce->linked)) { |
520 | preempt(dom, ce); | 539 | preempt(dom, ce); |
521 | update_crit_levels(entry); | 540 | update_crit_levels(entry); |
@@ -570,7 +589,6 @@ static void remove_from_all(struct task_struct* task) | |||
570 | /* Ensure the task isn't returned by its domain */ | 589 | /* Ensure the task isn't returned by its domain */ |
571 | dom->remove(dom, task); | 590 | dom->remove(dom, task); |
572 | 591 | ||
573 | BUG_ON(is_queued(task)); | ||
574 | raw_spin_unlock(dom->lock); | 592 | raw_spin_unlock(dom->lock); |
575 | } | 593 | } |
576 | 594 | ||
@@ -582,8 +600,15 @@ static void remove_from_all(struct task_struct* task) | |||
582 | static void job_completion(struct task_struct *task, int forced) | 600 | static void job_completion(struct task_struct *task, int forced) |
583 | { | 601 | { |
584 | lt_t now; | 602 | lt_t now; |
585 | TRACE_MC_TASK(task, "Completed\n"); | 603 | int ghost = is_ghost(task); |
586 | sched_trace_task_completion(task, forced); | 604 | int behind = tsk_mc_crit(task) != CRIT_LEVEL_A && job_behind(task); |
605 | TRACE_MC_TASK(task, "Completed, ghost %d, forced %d, behind %d\n", | ||
606 | ghost, forced, behind); | ||
607 | |||
608 | /* if (!is_ghost(task)) { */ | ||
609 | /* and no more forced!!! */ | ||
610 | sched_trace_task_completion(task, forced); | ||
611 | /* } */ | ||
587 | BUG_ON(!task); | 612 | BUG_ON(!task); |
588 | 613 | ||
589 | /* Logically stop the task execution */ | 614 | /* Logically stop the task execution */ |
@@ -592,23 +617,25 @@ static void job_completion(struct task_struct *task, int forced) | |||
592 | 617 | ||
593 | now = litmus_clock(); | 618 | now = litmus_clock(); |
594 | 619 | ||
595 | /* If it's not a ghost job, do ghost job conversion */ | 620 | |
596 | if (!is_ghost(task) && !job_behind(task)) { | 621 | if (!forced && !ghost) { |
597 | TRACE_MC_TASK(task, "is not a ghost task\n"); | 622 | task_release(task); |
598 | tsk_mc_data(task)->mc_job.ghost_budget = budget_remaining(task); | 623 | } |
624 | |||
625 | if (!forced && !ghost) { | ||
626 | tsk_mc_data(task)->mc_job.ghost_budget = | ||
627 | budget_remaining(task); | ||
599 | tsk_mc_data(task)->mc_job.is_ghost = 1; | 628 | tsk_mc_data(task)->mc_job.is_ghost = 1; |
600 | } | 629 | } |
601 | 630 | ||
602 | /* If the task is a ghost job with no budget, it either exhausted | 631 | if (forced || behind || tsk_mc_data(task)->mc_job.ghost_budget == 0) { |
603 | * its ghost budget or there was no ghost budget after the job | 632 | TRACE_MC_TASK(task, "making not a ghost\n"); |
604 | * conversion. Revert back to a normal task and complete the period. | ||
605 | */ | ||
606 | if (tsk_mc_data(task)->mc_job.ghost_budget == 0) { | ||
607 | TRACE_MC_TASK(task, "has zero ghost budget\n"); | ||
608 | tsk_mc_data(task)->mc_job.is_ghost = 0; | 633 | tsk_mc_data(task)->mc_job.is_ghost = 0; |
609 | prepare_for_next_server(task, forced); | 634 | tsk_mc_data(task)->mc_job.ghost_budget = 0; |
610 | if (is_released(task, litmus_clock())) | 635 | } |
611 | sched_trace_task_release(task); | 636 | |
637 | if (forced || (!behind && !is_ghost(task))) { | ||
638 | server_release(task); | ||
612 | } | 639 | } |
613 | 640 | ||
614 | /* Requeue non-blocking tasks */ | 641 | /* Requeue non-blocking tasks */ |
@@ -967,6 +994,7 @@ static struct task_struct* mc_schedule(struct task_struct* prev) | |||
967 | raw_spin_lock(dom->lock); | 994 | raw_spin_lock(dom->lock); |
968 | 995 | ||
969 | /* Peek at task here to avoid lock use */ | 996 | /* Peek at task here to avoid lock use */ |
997 | while (!cache_next(dom)); | ||
970 | dtask = dom->peek_ready(dom); | 998 | dtask = dom->peek_ready(dom); |
971 | 999 | ||
972 | raw_spin_lock(&entry->lock); | 1000 | raw_spin_lock(&entry->lock); |