diff options
Diffstat (limited to 'litmus/sched_mc.c')
-rw-r--r-- | litmus/sched_mc.c | 92 |
1 files changed, 27 insertions, 65 deletions
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c index 84fdc304b434..f3ace9fe560a 100644 --- a/litmus/sched_mc.c +++ b/litmus/sched_mc.c | |||
@@ -61,8 +61,6 @@ DEFINE_PER_CPU(struct cpu_entry, cpus); | |||
61 | static int interrupt_cpu; | 61 | static int interrupt_cpu; |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #define FTRACE_CPU 6 | ||
65 | |||
66 | #define domain_data(dom) (container_of(dom, struct domain_data, domain)) | 64 | #define domain_data(dom) (container_of(dom, struct domain_data, domain)) |
67 | #define is_global(dom) (domain_data(dom)->heap) | 65 | #define is_global(dom) (domain_data(dom)->heap) |
68 | #define is_global_task(t) (is_global(get_task_domain(t))) | 66 | #define is_global_task(t) (is_global(get_task_domain(t))) |
@@ -151,11 +149,9 @@ static void fix_crit_position(struct crit_entry *ce) | |||
151 | if (is_global(ce->domain)) { | 149 | if (is_global(ce->domain)) { |
152 | if (CS_ACTIVATE == ce->state) { | 150 | if (CS_ACTIVATE == ce->state) { |
153 | ce->state = CS_ACTIVE; | 151 | ce->state = CS_ACTIVE; |
154 | TRACE_CRIT_ENTRY(ce, "CS_ACTIVE\n"); | ||
155 | update_crit_position(ce); | 152 | update_crit_position(ce); |
156 | } else if (CS_REMOVE == ce->state) { | 153 | } else if (CS_REMOVE == ce->state) { |
157 | ce->state = CS_REMOVED; | 154 | ce->state = CS_REMOVED; |
158 | TRACE_CRIT_ENTRY(ce, "CS_REMOVED\n"); | ||
159 | update_crit_position(ce); | 155 | update_crit_position(ce); |
160 | } | 156 | } |
161 | } | 157 | } |
@@ -389,7 +385,6 @@ static void link_task_to_cpu(struct cpu_entry *entry, struct task_struct *task) | |||
389 | for (; i < entry_level(entry) + 1; i++) { | 385 | for (; i < entry_level(entry) + 1; i++) { |
390 | ce = &entry->crit_entries[i]; | 386 | ce = &entry->crit_entries[i]; |
391 | if (!can_use(ce)) { | 387 | if (!can_use(ce)) { |
392 | TRACE_CRIT_ENTRY(ce, "CS_ACTIVATE\n"); | ||
393 | ce->state = CS_ACTIVATE; | 388 | ce->state = CS_ACTIVATE; |
394 | } | 389 | } |
395 | } | 390 | } |
@@ -462,7 +457,6 @@ static void update_crit_levels(struct cpu_entry *entry) | |||
462 | */ | 457 | */ |
463 | readmit[i] = (!global_preempted) ? ce->linked : NULL; | 458 | readmit[i] = (!global_preempted) ? ce->linked : NULL; |
464 | 459 | ||
465 | TRACE_CRIT_ENTRY(ce, "CS_REMOVE\n"); | ||
466 | ce->state = CS_REMOVE; | 460 | ce->state = CS_REMOVE; |
467 | if (ce->linked) | 461 | if (ce->linked) |
468 | link_task_to_crit(ce, NULL); | 462 | link_task_to_crit(ce, NULL); |
@@ -479,22 +473,6 @@ static void update_crit_levels(struct cpu_entry *entry) | |||
479 | } | 473 | } |
480 | } | 474 | } |
481 | 475 | ||
482 | static inline int cache_next(struct domain *dom) | ||
483 | { | ||
484 | struct task_struct *t; | ||
485 | t = dom->peek_ready(dom); | ||
486 | return 1; | ||
487 | /* if (t && tsk_mc_crit(t) != CRIT_LEVEL_A && budget_exhausted(t)) { */ | ||
488 | /* TRACE_TASK(t, "Cached and moved to release\n"); */ | ||
489 | /* prepare_for_next_server(t, 1); */ | ||
490 | /* dom->take_ready(dom); */ | ||
491 | /* dom->requeue(dom, t); */ | ||
492 | /* return 0; */ | ||
493 | /* } else { */ | ||
494 | /* return 1; */ | ||
495 | /* } */ | ||
496 | } | ||
497 | |||
498 | /** | 476 | /** |
499 | * check_for_preempt() - Causes a preemption if higher-priority tasks are ready. | 477 | * check_for_preempt() - Causes a preemption if higher-priority tasks are ready. |
500 | * Caller must hold domain lock. | 478 | * Caller must hold domain lock. |
@@ -513,10 +491,8 @@ static void check_for_preempt(struct domain *dom) | |||
513 | entry = crit_cpu(ce); | 491 | entry = crit_cpu(ce); |
514 | recheck = 1; | 492 | recheck = 1; |
515 | 493 | ||
516 | /* Dodge exhausted tasks */ | 494 | /* Cache next task */ |
517 | if (!cache_next(dom)) { | 495 | dom->peek_ready(dom); |
518 | continue; | ||
519 | } | ||
520 | 496 | ||
521 | raw_spin_lock(&entry->lock); | 497 | raw_spin_lock(&entry->lock); |
522 | if (!can_use(ce)) | 498 | if (!can_use(ce)) |
@@ -535,8 +511,11 @@ static void check_for_preempt(struct domain *dom) | |||
535 | } else /* Partitioned */ { | 511 | } else /* Partitioned */ { |
536 | ce = domain_data(dom)->crit_entry; | 512 | ce = domain_data(dom)->crit_entry; |
537 | entry = crit_cpu(ce); | 513 | entry = crit_cpu(ce); |
514 | |||
515 | /* Cache next task */ | ||
516 | dom->peek_ready(dom); | ||
517 | |||
538 | raw_spin_lock(&entry->lock); | 518 | raw_spin_lock(&entry->lock); |
539 | while (!cache_next(dom)); | ||
540 | if (can_use(ce) && dom->preempt_needed(dom, ce->linked)) { | 519 | if (can_use(ce) && dom->preempt_needed(dom, ce->linked)) { |
541 | preempt(dom, ce); | 520 | preempt(dom, ce); |
542 | update_crit_levels(entry); | 521 | update_crit_levels(entry); |
@@ -552,7 +531,7 @@ static void check_for_preempt(struct domain *dom) | |||
552 | */ | 531 | */ |
553 | static void remove_from_all(struct task_struct* task) | 532 | static void remove_from_all(struct task_struct* task) |
554 | { | 533 | { |
555 | int update = 0, old; | 534 | int update = 0; |
556 | struct cpu_entry *entry; | 535 | struct cpu_entry *entry; |
557 | struct crit_entry *ce; | 536 | struct crit_entry *ce; |
558 | struct domain *dom = get_task_domain(task); | 537 | struct domain *dom = get_task_domain(task); |
@@ -601,43 +580,38 @@ static void remove_from_all(struct task_struct* task) | |||
601 | */ | 580 | */ |
602 | static void job_completion(struct task_struct *task, int forced) | 581 | static void job_completion(struct task_struct *task, int forced) |
603 | { | 582 | { |
604 | lt_t now; | 583 | int behind; |
605 | int ghost = is_ghost(task); | 584 | TRACE_MC_TASK(task, "Completed\n"); |
606 | int behind = tsk_mc_crit(task) != CRIT_LEVEL_A && job_behind(task); | ||
607 | TRACE_MC_TASK(task, "Completed, ghost %d, forced %d, behind %d\n", | ||
608 | ghost, forced, behind); | ||
609 | |||
610 | /* if (!is_ghost(task)) { */ | ||
611 | /* and no more forced!!! */ | ||
612 | if (!ghost && !forced) | ||
613 | sched_trace_task_completion(task, forced); | ||
614 | /* } */ | ||
615 | BUG_ON(!task); | ||
616 | 585 | ||
617 | /* Logically stop the task execution */ | 586 | /* Logically stop the task execution */ |
618 | set_rt_flags(task, RT_F_SLEEP); | 587 | set_rt_flags(task, RT_F_SLEEP); |
619 | remove_from_all(task); | 588 | remove_from_all(task); |
620 | 589 | ||
621 | now = litmus_clock(); | 590 | /* Level-A tasks cannot ever get behind */ |
622 | 591 | behind = tsk_mc_crit(task) != CRIT_LEVEL_A && behind_server(task); | |
623 | 592 | ||
624 | if (!forced && !ghost) { | 593 | if (!forced && !is_ghost(task)) { |
594 | /* Task voluntarily ceased execution. Move on to next period */ | ||
625 | task_release(task); | 595 | task_release(task); |
626 | } | 596 | sched_trace_task_completion(task, forced); |
627 | 597 | ||
628 | if (!forced && !ghost) { | 598 | /* Convert to ghost job */ |
629 | tsk_mc_data(task)->mc_job.ghost_budget = | 599 | tsk_mc_data(task)->mc_job.ghost_budget = budget_remaining(task); |
630 | budget_remaining(task); | ||
631 | tsk_mc_data(task)->mc_job.is_ghost = 1; | 600 | tsk_mc_data(task)->mc_job.is_ghost = 1; |
632 | } | 601 | } |
633 | 602 | ||
634 | if (forced || behind || tsk_mc_data(task)->mc_job.ghost_budget == 0) { | 603 | /* If the task has no ghost budget, convert back from ghost. |
635 | TRACE_MC_TASK(task, "making not a ghost\n"); | 604 | * If the task is behind, undo ghost conversion so that it |
605 | * can catch up. | ||
606 | */ | ||
607 | if (behind || tsk_mc_data(task)->mc_job.ghost_budget == 0) { | ||
608 | TRACE_MC_TASK(task, "Not a ghost task\n"); | ||
636 | tsk_mc_data(task)->mc_job.is_ghost = 0; | 609 | tsk_mc_data(task)->mc_job.is_ghost = 0; |
637 | tsk_mc_data(task)->mc_job.ghost_budget = 0; | 610 | tsk_mc_data(task)->mc_job.ghost_budget = 0; |
638 | } | 611 | } |
639 | 612 | ||
640 | if (forced || (!behind && !is_ghost(task))) { | 613 | /* If server has run out of budget, wait until next release */ |
614 | if (budget_exhausted(task)) { | ||
641 | server_release(task); | 615 | server_release(task); |
642 | } | 616 | } |
643 | 617 | ||
@@ -812,13 +786,8 @@ static void mc_task_new(struct task_struct *t, int on_rq, int running) | |||
812 | tsk_mc_data(t)->mc_job.is_ghost = 0; | 786 | tsk_mc_data(t)->mc_job.is_ghost = 0; |
813 | if (running) { | 787 | if (running) { |
814 | BUG_ON(entry->scheduled); | 788 | BUG_ON(entry->scheduled); |
815 | if (entry->cpu != FTRACE_CPU) { | 789 | entry->scheduled = t; |
816 | entry->scheduled = t; | 790 | tsk_rt(t)->scheduled_on = entry->cpu; |
817 | tsk_rt(t)->scheduled_on = entry->cpu; | ||
818 | } else { | ||
819 | t->rt_param.scheduled_on = NO_CPU; | ||
820 | preempt_if_preemptable(NULL, entry->cpu); | ||
821 | } | ||
822 | } else { | 791 | } else { |
823 | t->rt_param.scheduled_on = NO_CPU; | 792 | t->rt_param.scheduled_on = NO_CPU; |
824 | } | 793 | } |
@@ -928,9 +897,6 @@ static struct task_struct* mc_schedule(struct task_struct* prev) | |||
928 | int i, out_of_time, sleep, preempt, exists, blocks, global, lower; | 897 | int i, out_of_time, sleep, preempt, exists, blocks, global, lower; |
929 | struct task_struct *dtask = NULL, *ready_task = NULL, *next = NULL; | 898 | struct task_struct *dtask = NULL, *ready_task = NULL, *next = NULL; |
930 | 899 | ||
931 | if (entry->cpu == FTRACE_CPU) | ||
932 | return NULL; | ||
933 | |||
934 | local_irq_save(flags); | 900 | local_irq_save(flags); |
935 | 901 | ||
936 | /* Litmus gave up because it couldn't access the stack of the CPU | 902 | /* Litmus gave up because it couldn't access the stack of the CPU |
@@ -1005,7 +971,6 @@ static struct task_struct* mc_schedule(struct task_struct* prev) | |||
1005 | raw_spin_lock(dom->lock); | 971 | raw_spin_lock(dom->lock); |
1006 | 972 | ||
1007 | /* Peek at task here to avoid lock use */ | 973 | /* Peek at task here to avoid lock use */ |
1008 | while (!cache_next(dom)); | ||
1009 | dtask = dom->peek_ready(dom); | 974 | dtask = dom->peek_ready(dom); |
1010 | 975 | ||
1011 | raw_spin_lock(&entry->lock); | 976 | raw_spin_lock(&entry->lock); |
@@ -1100,7 +1065,6 @@ static long mc_activate_plugin(void) | |||
1100 | struct domain_data *dom_data; | 1065 | struct domain_data *dom_data; |
1101 | struct domain *dom; | 1066 | struct domain *dom; |
1102 | struct domain_data *our_domains[NR_CPUS]; | 1067 | struct domain_data *our_domains[NR_CPUS]; |
1103 | struct event_group *event_group; | ||
1104 | int cpu, n = 0; | 1068 | int cpu, n = 0; |
1105 | long ret; | 1069 | long ret; |
1106 | 1070 | ||
@@ -1196,9 +1160,7 @@ static void init_global_domain(struct domain_data *dom_data, enum crit_level lev | |||
1196 | ce = &entry->crit_entries[level]; | 1160 | ce = &entry->crit_entries[level]; |
1197 | init_crit_entry(ce, level, dom_data, node); | 1161 | init_crit_entry(ce, level, dom_data, node); |
1198 | bheap_node_init(&ce->node, ce); | 1162 | bheap_node_init(&ce->node, ce); |
1199 | 1163 | bheap_insert(cpu_lower_prio, heap, node); | |
1200 | if (cpu != FTRACE_CPU) | ||
1201 | bheap_insert(cpu_lower_prio, heap, node); | ||
1202 | } | 1164 | } |
1203 | } | 1165 | } |
1204 | 1166 | ||