aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/sched_mc.c
diff options
context:
space:
mode:
Diffstat (limited to 'litmus/sched_mc.c')
-rw-r--r--litmus/sched_mc.c92
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);
61static int interrupt_cpu; 61static 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
482static 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 */
553static void remove_from_all(struct task_struct* task) 532static 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 */
602static void job_completion(struct task_struct *task, int forced) 581static 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