aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/sched_mc.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-10-09 21:59:25 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-10-09 21:59:25 -0400
commit1b6e7d3a78db7ea7eb0e20f1bca5b49079739a7c (patch)
treecb630040484d93c86a819bc61d9e0822df664793 /litmus/sched_mc.c
parenta744599d42a19e0b74c95a77abec6ee79f869b0f (diff)
Moved budget accounting into MC plugin.
This commit is broken as it allows locking tasks to early release.
Diffstat (limited to 'litmus/sched_mc.c')
-rw-r--r--litmus/sched_mc.c61
1 files changed, 19 insertions, 42 deletions
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c
index 76479fd08d3a..3fb223255792 100644
--- a/litmus/sched_mc.c
+++ b/litmus/sched_mc.c
@@ -281,21 +281,19 @@ static inline void start_crit(struct crit_entry *ce)
281 * Time accounting for ghost tasks. 281 * Time accounting for ghost tasks.
282 * Must be called before a decision is made involving the task's budget. 282 * Must be called before a decision is made involving the task's budget.
283 */ 283 */
284static void update_ghost_time(struct task_struct *p) 284static void update_server_time(struct task_struct *p)
285{ 285{
286 u64 clock = litmus_clock(); 286 u64 clock = litmus_clock();
287 u64 delta = clock - p->se.exec_start; 287 u64 delta = clock - p->rt_param.last_exec_time;
288 BUG_ON(!is_ghost(p));
289 if (unlikely ((s64)delta < 0)) { 288 if (unlikely ((s64)delta < 0)) {
290 delta = 0; 289 delta = 0;
291 } 290 }
292 if (budget_remaining(p) <= delta) { 291 if (budget_remaining(p) <= delta) {
293 tsk_rt(p)->job_params.exec_time = get_exec_cost(p); 292 tsk_rt(p)->job_params.exec_time = get_exec_cost(p);
294 p->se.exec_start = clock;
295 } else { 293 } else {
296 tsk_rt(p)->job_params.exec_time += delta; 294 tsk_rt(p)->job_params.exec_time += delta;
297 p->se.exec_start = clock;
298 } 295 }
296 p->rt_param.last_exec_time = clock;
299} 297}
300 298
301/** 299/**
@@ -305,8 +303,6 @@ static void update_ghost_time(struct task_struct *p)
305static void link_task_to_crit(struct crit_entry *ce, 303static void link_task_to_crit(struct crit_entry *ce,
306 struct task_struct *task) 304 struct task_struct *task)
307{ 305{
308 lt_t when_to_fire;
309
310 TRACE_CRIT_ENTRY(ce, "Linking " TS "\n", TA(task)); 306 TRACE_CRIT_ENTRY(ce, "Linking " TS "\n", TA(task));
311 BUG_ON(!can_use(ce) && task); 307 BUG_ON(!can_use(ce) && task);
312 BUG_ON(task && tsk_rt(task)->linked_on != NO_CPU); 308 BUG_ON(task && tsk_rt(task)->linked_on != NO_CPU);
@@ -323,7 +319,7 @@ static void link_task_to_crit(struct crit_entry *ce,
323 cancel_ghost(ce); 319 cancel_ghost(ce);
324 if (!budget_exhausted(ce->linked)) { 320 if (!budget_exhausted(ce->linked)) {
325 /* Job isn't finished, so do accounting */ 321 /* Job isn't finished, so do accounting */
326 update_ghost_time(ce->linked); 322 update_server_time(ce->linked);
327 } 323 }
328 } 324 }
329 sched_trace_server_switch_away(ce_sid(ce), 0, -ce->linked->pid, 325 sched_trace_server_switch_away(ce_sid(ce), 0, -ce->linked->pid,
@@ -683,6 +679,7 @@ static void job_completion(struct task_struct *task, int forced)
683 TRACE_MC_TASK(task, "Completed\n"); 679 TRACE_MC_TASK(task, "Completed\n");
684 680
685 /* Logically stop the task execution */ 681 /* Logically stop the task execution */
682 remove_from_all(task);
686 set_rt_flags(task, RT_F_SLEEP); 683 set_rt_flags(task, RT_F_SLEEP);
687 684
688 if (!forced) { 685 if (!forced) {
@@ -715,15 +712,10 @@ static void job_completion(struct task_struct *task, int forced)
715 set_rt_flags(task, RT_F_RUNNING); 712 set_rt_flags(task, RT_F_RUNNING);
716 } 713 }
717 714
718 /* If the server was not released, then the task's priority remains 715
719 * unchanged and it should be left where it is 716 if (is_running(task)) {
720 */ 717 /* Requeue non-blocking tasks */
721 if (release_server) { 718 job_arrival(task);
722 remove_from_all(task);
723 if (is_running(task)) {
724 /* Requeue non-blocking tasks */
725 job_arrival(task);
726 }
727 } 719 }
728} 720}
729 721
@@ -739,31 +731,10 @@ static enum hrtimer_restart mc_ghost_exhausted(struct hrtimer *timer)
739{ 731{
740 struct crit_entry *ce = container_of(timer, struct crit_entry, timer); 732 struct crit_entry *ce = container_of(timer, struct crit_entry, timer);
741#endif 733#endif
742
743 unsigned long flags;
744 struct task_struct *tmp = NULL;
745
746 local_irq_save(flags);
747 TRACE_CRIT_ENTRY(ce, "Firing here at %llu\n", litmus_clock()); 734 TRACE_CRIT_ENTRY(ce, "Firing here at %llu\n", litmus_clock());
748 735
749 /* Due to race conditions, we cannot just set the linked 736 litmus_reschedule(crit_cpu(ce)->cpu);
750 * task's budget to 0 as it may no longer be the task
751 * for which this timer was armed. Instead, update the running
752 * task time and see if this causes exhaustion.
753 */
754 raw_spin_lock(&crit_cpu(ce)->lock);
755 if (ce->linked && is_ghost(ce->linked)) {
756 update_ghost_time(ce->linked);
757 if (budget_exhausted(ce->linked)) {
758 tmp = ce->linked;
759 }
760 }
761 raw_spin_unlock(&crit_cpu(ce)->lock);
762
763 if (tmp)
764 job_completion(tmp, 1);
765 737
766 local_irq_restore(flags);
767#ifndef CONFIG_MERGE_TIMERS 738#ifndef CONFIG_MERGE_TIMERS
768 return HRTIMER_NORESTART; 739 return HRTIMER_NORESTART;
769#endif 740#endif
@@ -924,6 +895,7 @@ static void mc_task_new(struct task_struct *t, int on_rq, int running)
924 BUG_ON(entry->scheduled); 895 BUG_ON(entry->scheduled);
925 entry->scheduled = t; 896 entry->scheduled = t;
926 tsk_rt(t)->scheduled_on = entry->cpu; 897 tsk_rt(t)->scheduled_on = entry->cpu;
898 tsk_rt(t)->last_exec_time = litmus_clock();
927 } else { 899 } else {
928 t->rt_param.scheduled_on = NO_CPU; 900 t->rt_param.scheduled_on = NO_CPU;
929 } 901 }
@@ -1101,6 +1073,11 @@ static struct task_struct* mc_schedule(struct task_struct* prev)
1101 BUG_ON(entry->scheduled && !is_realtime(prev)); 1073 BUG_ON(entry->scheduled && !is_realtime(prev));
1102 BUG_ON(is_realtime(prev) && !entry->scheduled); 1074 BUG_ON(is_realtime(prev) && !entry->scheduled);
1103 1075
1076 if (entry->scheduled != NULL) {
1077 prev->rt_param.scheduled_on = NO_CPU;
1078 update_server_time(prev);
1079 }
1080
1104 /* Determine state */ 1081 /* Determine state */
1105 exists = entry->scheduled != NULL; 1082 exists = entry->scheduled != NULL;
1106 blocks = exists && !is_running(entry->scheduled); 1083 blocks = exists && !is_running(entry->scheduled);
@@ -1114,8 +1091,6 @@ static struct task_struct* mc_schedule(struct task_struct* prev)
1114 TRACE(TS " block:%d oot:%d sleep:%d preempt:%d, now: %llu\n", 1091 TRACE(TS " block:%d oot:%d sleep:%d preempt:%d, now: %llu\n",
1115 TA(prev), blocks, out_of_time, sleep, preempt, litmus_clock()); 1092 TA(prev), blocks, out_of_time, sleep, preempt, litmus_clock());
1116 1093
1117 if (exists)
1118 prev->rt_param.scheduled_on = NO_CPU;
1119 1094
1120 raw_spin_unlock(&entry->lock); 1095 raw_spin_unlock(&entry->lock);
1121 1096
@@ -1169,7 +1144,9 @@ static struct task_struct* mc_schedule(struct task_struct* prev)
1169 raw_spin_unlock_irqrestore(&entry->lock, flags); 1144 raw_spin_unlock_irqrestore(&entry->lock, flags);
1170 1145
1171 if (next) { 1146 if (next) {
1172 BUG_ON(!is_released(next, litmus_clock())); 1147 tsk_rt(next)->last_exec_time = litmus_clock();
1148 BUG_ON(!is_released(next, tsk_rt(next)->last_exec_time));
1149 BUG_ON(is_ghost(next));
1173 TRACE_MC_TASK(next, "Picked this task\n"); 1150 TRACE_MC_TASK(next, "Picked this task\n");
1174 } else if (exists && !next) 1151 } else if (exists && !next)
1175 STRACE("CPU %d becomes idle at %llu\n", 1152 STRACE("CPU %d becomes idle at %llu\n",