diff options
author | Zelin Tong <ztong@ludwig.cs.unc.edu> | 2020-02-26 18:14:07 -0500 |
---|---|---|
committer | Zelin Tong <ztong@ludwig.cs.unc.edu> | 2020-02-26 18:14:07 -0500 |
commit | 25fb933628b3f3953fb8b6d206a0c53855a8bae9 (patch) | |
tree | a336bda4a391b855d2bc966ae2575332fda5574f | |
parent | 72e55e5c572abe93440829702592acb5334a052e (diff) |
End of day commit 2/26/2020
changed edfsc_cschedule found no fixed task to be next, it will now
return the container instead of null
To explain the other changes, first I must explain the problem.
When a container has no fixed tasks, but still has budget, there is
nothing in litmus that enforces its budget or updates its exec_time in
job_params.
This means we will have to enforce the container budget in
this case ourselves with an enforcement timer. Furthermore, we also have
to update the exec_time ourselves since only actual task have their
exec_time updated automatically by litmus
the new functions are added and gschedule changed to fix the above
problem
-rw-r--r-- | litmus/sched_edfsc.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/litmus/sched_edfsc.c b/litmus/sched_edfsc.c index 125b2e314176..449d6b3431a2 100644 --- a/litmus/sched_edfsc.c +++ b/litmus/sched_edfsc.c | |||
@@ -32,6 +32,8 @@ typedef struct cont_domain { | |||
32 | lt_t changed_budget; //change to scheduled task's exec time due to container budget constraints | 32 | lt_t changed_budget; //change to scheduled task's exec time due to container budget constraints |
33 | u64 f_util, future_f_util; | 33 | u64 f_util, future_f_util; |
34 | struct bheap_node *hn; | 34 | struct bheap_node *hn; |
35 | struct hrtimer idle_enforcement_timer; | ||
36 | int timer_armed; | ||
35 | } cont_domain_t; | 37 | } cont_domain_t; |
36 | 38 | ||
37 | typedef struct { | 39 | typedef struct { |
@@ -458,6 +460,7 @@ static int fifo_prio(struct bheap_node* _a, struct bheap_node* _b) | |||
458 | // takes in the container_domain pointer in container task_struct | 460 | // takes in the container_domain pointer in container task_struct |
459 | // assuming prev is previous task running on the processor before calling schedule | 461 | // assuming prev is previous task running on the processor before calling schedule |
460 | // global lock in effect | 462 | // global lock in effect |
463 | // returns container if no fixed task is next | ||
461 | static struct task_struct* edfsc_cschedule(cont_domain_t* cedf, struct task_struct * prev) | 464 | static struct task_struct* edfsc_cschedule(cont_domain_t* cedf, struct task_struct * prev) |
462 | { | 465 | { |
463 | rt_domain_t *edf = &cedf->domain; | 466 | rt_domain_t *edf = &cedf->domain; |
@@ -576,7 +579,31 @@ static struct task_struct* edfsc_cschedule(cont_domain_t* cedf, struct task_stru | |||
576 | 579 | ||
577 | printk("/edfsc_cschedule\n"); | 580 | printk("/edfsc_cschedule\n"); |
578 | 581 | ||
579 | return next; | 582 | return (next) ? next : cedf->container; |
583 | } | ||
584 | |||
585 | void manage_idle_enforcement_timer(struct task_struct* t) | ||
586 | { | ||
587 | lt_t now; | ||
588 | |||
589 | cont_domain_t* domain = tsk_rt(t)->edfsc_params.domain; | ||
590 | if (t && budget_precisely_enforced(t)) { | ||
591 | BUG_ON(budget_exhausted(t) && !is_np(t)); | ||
592 | if (likely(!is_np(t))) { | ||
593 | now = litmus_clock(); | ||
594 | //hrtimer_start cancels the timer so don't have to check | ||
595 | //if it is already armed | ||
596 | hrtimer_start(&(domain->idle_enforcement_timer), | ||
597 | ns_to_ktime(now + budget_remaining(t)), | ||
598 | HRTIMER_MODE_ABS_PINNED); | ||
599 | domain->timer_armed = 1; | ||
600 | domain->scheduled_last_exec_time = now; | ||
601 | } | ||
602 | } | ||
603 | else if (domain->timer_armed) { | ||
604 | hrtimer_try_to_cancel(&(domain->idle_enforcement_timer)); | ||
605 | domain->timer_armed = 0; | ||
606 | } | ||
580 | } | 607 | } |
581 | 608 | ||
582 | //assuming prev is previous task running on the processor before calling schedule | 609 | //assuming prev is previous task running on the processor before calling schedule |
@@ -603,6 +630,12 @@ static struct task_struct *edfsc_gschedule(struct task_struct *prev) | |||
603 | BUG_ON(entry->scheduled && !is_realtime(prev)); | 630 | BUG_ON(entry->scheduled && !is_realtime(prev)); |
604 | BUG_ON(is_realtime(prev) && !entry->scheduled); | 631 | BUG_ON(is_realtime(prev) && !entry->scheduled); |
605 | 632 | ||
633 | //TODO | ||
634 | // condition when a container is "scheduled" but there are no realtime tasks | ||
635 | if (is_container(entry->scheduled) && (!prev || !is_realtime(prev))) | ||
636 | tsk_rt(entry->scheduled)->job_params.exec_time += litmus_clock() | ||
637 | - tsk_rt(entry->scheduled)->edfsc_params.domain->scheduled_last_exec_time; | ||
638 | |||
606 | // update container budget if prev was a fixed or background scheduled task | 639 | // update container budget if prev was a fixed or background scheduled task |
607 | if (entry->scheduled && prev && is_realtime(prev) && prev != entry->scheduled) { | 640 | if (entry->scheduled && prev && is_realtime(prev) && prev != entry->scheduled) { |
608 | // FIXME prev or entry->scheduled can be NULL, right? | 641 | // FIXME prev or entry->scheduled can be NULL, right? |
@@ -723,7 +756,14 @@ static struct task_struct *edfsc_gschedule(struct task_struct *prev) | |||
723 | TRACE("becomes idle at %llu.\n", litmus_clock()); | 756 | TRACE("becomes idle at %llu.\n", litmus_clock()); |
724 | #endif | 757 | #endif |
725 | 758 | ||
726 | return next; | 759 | if (is_container(next)) { |
760 | if (budget_precisely_enforced(next)) { | ||
761 | manage_idle_enforcement_timer(next); | ||
762 | } | ||
763 | return NULL; | ||
764 | } | ||
765 | else | ||
766 | return next; | ||
727 | } | 767 | } |
728 | 768 | ||
729 | /* | 769 | /* |
@@ -940,6 +980,7 @@ static void edfsc_task_new(struct task_struct* t, int on_rq, int is_scheduled) | |||
940 | * nothing was running before, update our state, and then reschedule. | 980 | * nothing was running before, update our state, and then reschedule. |
941 | * The task will be fixed to a container during the reschedule. | 981 | * The task will be fixed to a container during the reschedule. |
942 | */ | 982 | */ |
983 | //Something needs fixing here | ||
943 | BUG_ON(entry->scheduled); | 984 | BUG_ON(entry->scheduled); |
944 | entry->scheduled = t; | 985 | entry->scheduled = t; |
945 | preempt(entry); | 986 | preempt(entry); |
@@ -1111,6 +1152,20 @@ static struct sched_plugin edfsc_plugin __cacheline_aligned_in_smp = { | |||
1111 | .get_domain_proc_info = edfsc_get_domain_proc_info, | 1152 | .get_domain_proc_info = edfsc_get_domain_proc_info, |
1112 | }; | 1153 | }; |
1113 | 1154 | ||
1155 | //timeout for timer enforcing budget of empty container | ||
1156 | static enum hrtimer_restart on_idle_enforcement_timeout(struct hrtimer *timer) | ||
1157 | { | ||
1158 | cont_domain_t* domain = container_of(timer, cont_domain_t, idle_enforcement_timer); | ||
1159 | |||
1160 | unsigned long flags; | ||
1161 | |||
1162 | local_irq_save(flags); | ||
1163 | domain->timer_armed = 0; | ||
1164 | litmus_reschedule_local(); | ||
1165 | local_irq_restore(flags); | ||
1166 | |||
1167 | return HRTIMER_NORESTART; | ||
1168 | } | ||
1114 | 1169 | ||
1115 | static int __init init_edfsc(void) | 1170 | static int __init init_edfsc(void) |
1116 | { | 1171 | { |
@@ -1141,6 +1196,8 @@ static int __init init_edfsc(void) | |||
1141 | edf_domain_init(&container_domains[i].domain, c_check_resched, NULL); | 1196 | edf_domain_init(&container_domains[i].domain, c_check_resched, NULL); |
1142 | container_domains[i].scheduled = NULL; | 1197 | container_domains[i].scheduled = NULL; |
1143 | container_domains[i].container = &container_tasks[i]; | 1198 | container_domains[i].container = &container_tasks[i]; |
1199 | hrtimer_init(&(container_domains[i].idle_enforcement_timer), CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | ||
1200 | container_domains[i].idle_enforcement_timer.function = on_idle_enforcement_timeout; | ||
1144 | 1201 | ||
1145 | container_tasks[i].policy = SCHED_LITMUS; | 1202 | container_tasks[i].policy = SCHED_LITMUS; |
1146 | tsk_rt(&container_tasks[i])->scheduled_on = NO_CPU; | 1203 | tsk_rt(&container_tasks[i])->scheduled_on = NO_CPU; |
@@ -1149,6 +1206,7 @@ static int __init init_edfsc(void) | |||
1149 | LITMUS_QUANTUM_LENGTH_NS; | 1206 | LITMUS_QUANTUM_LENGTH_NS; |
1150 | tsk_rt(&container_tasks[i])->task_params.relative_deadline = | 1207 | tsk_rt(&container_tasks[i])->task_params.relative_deadline = |
1151 | LITMUS_QUANTUM_LENGTH_NS; | 1208 | LITMUS_QUANTUM_LENGTH_NS; |
1209 | tsk_rt(&container_tasks[i])->task_params.budget_policy == PRECISE_ENFORCEMENT; | ||
1152 | tsk_rt(&container_tasks[i])->edfsc_params.container_task = NULL; | 1210 | tsk_rt(&container_tasks[i])->edfsc_params.container_task = NULL; |
1153 | tsk_rt(&container_tasks[i])->domain = &gsched_domain; | 1211 | tsk_rt(&container_tasks[i])->domain = &gsched_domain; |
1154 | tsk_rt(&container_tasks[i])->edfsc_params.domain = &container_domains[i]; | 1212 | tsk_rt(&container_tasks[i])->edfsc_params.domain = &container_domains[i]; |