diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2020-03-04 11:01:27 -0500 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2020-03-04 11:01:27 -0500 |
| commit | 1f4fabf52690ef8f84275b720b25e7a0adc74440 (patch) | |
| tree | 76cf747b27343f0a6e24280ffdeb72bf93070b82 /litmus | |
| parent | f6e8a4fe3a975fdbf3e3137d2debfaa84631a6cb (diff) | |
Rewrite edfsc_task_exit(). Task termination now works.
Correcting the deadline timer to not touch potentially invalid
memory is still TODO.
Diffstat (limited to 'litmus')
| -rw-r--r-- | litmus/sched_edfsc.c | 92 |
1 files changed, 55 insertions, 37 deletions
diff --git a/litmus/sched_edfsc.c b/litmus/sched_edfsc.c index fff134e5f1bc..a3452662ad23 100644 --- a/litmus/sched_edfsc.c +++ b/litmus/sched_edfsc.c | |||
| @@ -1009,53 +1009,71 @@ static void edfsc_task_block(struct task_struct *t) | |||
| 1009 | // TODO | 1009 | // TODO |
| 1010 | } | 1010 | } |
| 1011 | 1011 | ||
| 1012 | /** | ||
| 1013 | * This is called by LITMUS before our task is switched to another scheduler | ||
| 1014 | * During task termination (do_exit()), LITMUS first switches the scheduler | ||
| 1015 | * to SCHED_FIFO before running the normal Linux task termination proceedure. | ||
| 1016 | * After we return from this, `t` may or may not still exist. So we should have | ||
| 1017 | * no outstanding handles to any part of the task struct afer this point. | ||
| 1018 | */ | ||
| 1012 | static void edfsc_task_exit(struct task_struct* t) | 1019 | static void edfsc_task_exit(struct task_struct* t) |
| 1013 | { | 1020 | { |
| 1014 | unsigned long flags; | 1021 | unsigned long flags; |
| 1015 | lt_t now; | 1022 | lt_t now, unaccount_time = 0; |
| 1023 | cpu_entry_t* entry; | ||
| 1024 | |||
| 1016 | printk("edfsc_task_exit\n"); | 1025 | printk("edfsc_task_exit\n"); |
| 1026 | BUG_ON(is_container(t)); | ||
| 1017 | raw_spin_lock_irqsave(&g_lock, flags); | 1027 | raw_spin_lock_irqsave(&g_lock, flags); |
| 1018 | now = litmus_clock(); | 1028 | // XXX: Superfluous. We never see `t` as one of our tasks again. |
| 1019 | |||
| 1020 | tsk_rt(t)->edfsc_params.will_remove = 1; | 1029 | tsk_rt(t)->edfsc_params.will_remove = 1; |
| 1021 | 1030 | ||
| 1022 | // If the task has no pending job | 1031 | // Remove this task from all members of its scheduling domain |
| 1023 | if (!is_released(t, now)) { | 1032 | unlink(t); |
| 1024 | // If the deadline of its last job is in the future, reserve the | 1033 | if (is_queued(t)) { |
| 1025 | // utilization until its deadline | 1034 | remove(tsk_rt(t)->domain, t); |
| 1026 | if (lt_after(tsk_rt(t)->edfsc_params.prev_deadline, now)) { | 1035 | } else if (is_fixed(t)) { |
| 1027 | if (is_queued(t)) | 1036 | // If we're fixed and not on the ready queues, we should be currently running |
| 1028 | remove(tsk_rt(t)->domain, t); | 1037 | BUG_ON(((cont_domain_t*)tsk_rt(t)->domain)->scheduled != t); |
| 1029 | //hrtimer_start(&(tsk_rt(t)->edfsc_params.deadline_timer), | 1038 | BUG_ON(t != current); |
| 1030 | // ns_to_ktime(tsk_rt(t)->edfsc_params.prev_deadline), | 1039 | ((cont_domain_t*)tsk_rt(t)->domain)->scheduled = NULL; |
| 1031 | // HRTIMER_MODE_ABS_PINNED); | ||
| 1032 | hrtimer_start(&t->edfsc_deadline_timer, | ||
| 1033 | ns_to_ktime(tsk_rt(t)->edfsc_params.prev_deadline), | ||
| 1034 | HRTIMER_MODE_ABS_PINNED); | ||
| 1035 | // Else remove it and we're done | ||
| 1036 | } else { | ||
| 1037 | if (is_queued(t)) | ||
| 1038 | remove(tsk_rt(t)->domain, t); | ||
| 1039 | // XXX not sure if this needs an additional condition guarding it | ||
| 1040 | remove_task(t); | ||
| 1041 | } | ||
| 1042 | // If the task has a pending job, we can immediatly stop LITMUS from | ||
| 1043 | // scheduling it but still have to reserve its utilization until the deadline | ||
| 1044 | } else { | 1040 | } else { |
| 1045 | //reserve the utilization, but remove it from being scheduled by litmus | 1041 | // We're in the global domain and not on the ready queues, so we must be running |
| 1046 | unlink(t); | 1042 | BUG_ON(t != current); |
| 1047 | if (tsk_rt(t)->scheduled_on != NO_CPU) { | 1043 | BUG_ON(tsk_rt(t)->scheduled_on == NO_CPU); |
| 1048 | (&per_cpu(edfsc_cpu_entries, tsk_rt(t)->scheduled_on))->scheduled = NULL; | 1044 | entry = &per_cpu(edfsc_cpu_entries, tsk_rt(t)->scheduled_on); |
| 1049 | tsk_rt(t)->scheduled_on = NO_CPU; | 1045 | BUG_ON(entry->scheduled != t); |
| 1050 | } | 1046 | entry->scheduled = NULL; |
| 1051 | //hrtimer_start(&(tsk_rt(t)->edfsc_params.deadline_timer), | ||
| 1052 | // ns_to_ktime(get_deadline(t)), | ||
| 1053 | // HRTIMER_MODE_ABS_PINNED); | ||
| 1054 | hrtimer_start(&t->edfsc_deadline_timer, | ||
| 1055 | ns_to_ktime(get_deadline(t)), | ||
| 1056 | HRTIMER_MODE_ABS_PINNED); | ||
| 1057 | } | 1047 | } |
| 1058 | 1048 | ||
| 1049 | /* To preserve EDF-sc scheduling invariants, we can only release a task's | ||
| 1050 | * utilization at the greater of the period or deadline boundry. Thus, here | ||
| 1051 | * we schedule a timer to handle this unaccounting of utilization. | ||
| 1052 | */ | ||
| 1053 | now = litmus_clock(); | ||
| 1054 | if (is_released(t, now)) { | ||
| 1055 | /* If a task has already been released, no future jobs are pending and we can | ||
| 1056 | * just unaccount at the current deadline. | ||
| 1057 | */ | ||
| 1058 | unaccount_time = get_deadline(t); | ||
| 1059 | } else { | ||
| 1060 | /* If the task has yet to be released, but we still haven't reached the | ||
| 1061 | * deadline of its last-finished job, wait for that deadline. Otherwise | ||
| 1062 | * we're after a deadline and before a release, so just remove now. | ||
| 1063 | */ | ||
| 1064 | if (lt_after(tsk_rt(t)->edfsc_params.prev_deadline, now)) | ||
| 1065 | unaccount_time = tsk_rt(t)->edfsc_params.prev_deadline; | ||
| 1066 | else | ||
| 1067 | unaccount_time = 0; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | if (unaccount_time == 0) | ||
| 1071 | remove_task(t); | ||
| 1072 | else | ||
| 1073 | // FIXME: This timer uses task struct data that may or may not exist at expiration | ||
| 1074 | hrtimer_start(&t->edfsc_deadline_timer, ns_to_ktime(unaccount_time), | ||
| 1075 | HRTIMER_MODE_ABS_PINNED); | ||
| 1076 | |||
| 1059 | raw_spin_unlock_irqrestore(&g_lock, flags); | 1077 | raw_spin_unlock_irqrestore(&g_lock, flags); |
| 1060 | } | 1078 | } |
| 1061 | 1079 | ||
