aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZelin Tong <ztong@ludwig.cs.unc.edu>2020-03-04 13:54:43 -0500
committerZelin Tong <ztong@ludwig.cs.unc.edu>2020-03-04 13:54:43 -0500
commitade4ca95d6619e92b348259395a30d978842a77a (patch)
tree943dcc02954e3e57f642dfca2e737982cc4bab37
parenta3591651158fb7839bf5b7a84620d5f3fe31f326 (diff)
parent1f4fabf52690ef8f84275b720b25e7a0adc74440 (diff)
Merge branch 'edfsc-wip' of rtsrv.cs.unc.edu:/public/litmus-rt-edfsc into edfsc-wip
-rw-r--r--litmus/sched_edfsc.c94
1 files changed, 57 insertions, 37 deletions
diff --git a/litmus/sched_edfsc.c b/litmus/sched_edfsc.c
index 14a775453a78..ea1b308667c7 100644
--- a/litmus/sched_edfsc.c
+++ b/litmus/sched_edfsc.c
@@ -1001,52 +1001,72 @@ static void edfsc_task_block(struct task_struct *t)
1001 // TODO 1001 // TODO
1002} 1002}
1003 1003
1004/**
1005 * This is called by LITMUS before our task is switched to another scheduler
1006 * During task termination (do_exit()), LITMUS first switches the scheduler
1007 * to SCHED_FIFO before running the normal Linux task termination proceedure.
1008 * After we return from this, `t` may or may not still exist. So we should have
1009 * no outstanding handles to any part of the task struct afer this point.
1010 */
1004static void edfsc_task_exit(struct task_struct* t) 1011static void edfsc_task_exit(struct task_struct* t)
1005{ 1012{
1006 unsigned long flags; 1013 unsigned long flags;
1007 lt_t now; 1014 lt_t now, unaccount_time = 0;
1008 raw_spin_lock_irqsave(&g_lock, flags); 1015 cpu_entry_t* entry;
1009 now = litmus_clock(); 1016
1010 1017
1018 BUG_ON(is_container(t));
1019 raw_spin_lock_irqsave(&g_lock, flags);
1020 // XXX: Superfluous. We never see `t` as one of our tasks again.
1011 tsk_rt(t)->edfsc_params.will_remove = 1; 1021 tsk_rt(t)->edfsc_params.will_remove = 1;
1012 1022
1013 // If the task has no pending job 1023
1014 if (!is_released(t, now)) { 1024 // Remove this task from all members of its scheduling domain
1015 // If the deadline of its last job is in the future, reserve the 1025 unlink(t);
1016 // utilization until its deadline 1026 if (is_queued(t)) {
1017 if (lt_after(tsk_rt(t)->edfsc_params.prev_deadline, now)) { 1027 remove(tsk_rt(t)->domain, t);
1018 if (is_queued(t)) 1028 } else if (is_fixed(t)) {
1019 remove(tsk_rt(t)->domain, t); 1029 // If we're fixed and not on the ready queues, we should be currently running
1020 //hrtimer_start(&(tsk_rt(t)->edfsc_params.deadline_timer), 1030 BUG_ON(((cont_domain_t*)tsk_rt(t)->domain)->scheduled != t);
1021 // ns_to_ktime(tsk_rt(t)->edfsc_params.prev_deadline), 1031 BUG_ON(t != current);
1022 // HRTIMER_MODE_ABS_PINNED); 1032 ((cont_domain_t*)tsk_rt(t)->domain)->scheduled = NULL;
1023 hrtimer_start(&t->edfsc_deadline_timer,
1024 ns_to_ktime(tsk_rt(t)->edfsc_params.prev_deadline),
1025 HRTIMER_MODE_ABS_PINNED);
1026 // Else remove it and we're done
1027 } else {
1028 if (is_queued(t))
1029 remove(tsk_rt(t)->domain, t);
1030 // XXX not sure if this needs an additional condition guarding it
1031 remove_task(t);
1032 }
1033 // If the task has a pending job, we can immediatly stop LITMUS from
1034 // scheduling it but still have to reserve its utilization until the deadline
1035 } else { 1033 } else {
1036 //reserve the utilization, but remove it from being scheduled by litmus 1034 // We're in the global domain and not on the ready queues, so we must be running
1037 unlink(t); 1035 BUG_ON(t != current);
1038 if (tsk_rt(t)->scheduled_on != NO_CPU) { 1036 BUG_ON(tsk_rt(t)->scheduled_on == NO_CPU);
1039 (&per_cpu(edfsc_cpu_entries, tsk_rt(t)->scheduled_on))->scheduled = NULL; 1037 entry = &per_cpu(edfsc_cpu_entries, tsk_rt(t)->scheduled_on);
1040 tsk_rt(t)->scheduled_on = NO_CPU; 1038 BUG_ON(entry->scheduled != t);
1041 } 1039 entry->scheduled = NULL;
1042 //hrtimer_start(&(tsk_rt(t)->edfsc_params.deadline_timer), 1040 }
1043 // ns_to_ktime(get_deadline(t)), 1041
1044 // HRTIMER_MODE_ABS_PINNED); 1042 /* To preserve EDF-sc scheduling invariants, we can only release a task's
1045 hrtimer_start(&t->edfsc_deadline_timer, 1043 * utilization at the greater of the period or deadline boundry. Thus, here
1046 ns_to_ktime(get_deadline(t)), 1044 * we schedule a timer to handle this unaccounting of utilization.
1047 HRTIMER_MODE_ABS_PINNED); 1045 */
1046 now = litmus_clock();
1047 if (is_released(t, now)) {
1048 /* If a task has already been released, no future jobs are pending and we can
1049 * just unaccount at the current deadline.
1050 */
1051 unaccount_time = get_deadline(t);
1052 } else {
1053 /* If the task has yet to be released, but we still haven't reached the
1054 * deadline of its last-finished job, wait for that deadline. Otherwise
1055 * we're after a deadline and before a release, so just remove now.
1056 */
1057 if (lt_after(tsk_rt(t)->edfsc_params.prev_deadline, now))
1058 unaccount_time = tsk_rt(t)->edfsc_params.prev_deadline;
1059 else
1060 unaccount_time = 0;
1048 } 1061 }
1049 1062
1063 if (unaccount_time == 0)
1064 remove_task(t);
1065 else
1066 // FIXME: This timer uses task struct data that may or may not exist at expiration
1067 hrtimer_start(&t->edfsc_deadline_timer, ns_to_ktime(unaccount_time),
1068 HRTIMER_MODE_ABS_PINNED);
1069
1050 raw_spin_unlock_irqrestore(&g_lock, flags); 1070 raw_spin_unlock_irqrestore(&g_lock, flags);
1051} 1071}
1052 1072