Library rt.analysis.jitter.bertogna_fp_theory
Require Import
rt.util.all.
Require Import rt.model.jitter.task rt.model.jitter.job rt.model.jitter.task_arrival
rt.model.jitter.schedule rt.model.jitter.platform rt.model.jitter.platform_fp
rt.model.jitter.workload rt.model.jitter.schedulability rt.model.jitter.priority
rt.model.jitter.response_time rt.model.jitter.interference.
Require Import rt.analysis.jitter.workload_bound rt.analysis.jitter.interference_bound_fp.
Module ResponseTimeAnalysisFP.
Export JobWithJitter SporadicTaskset ScheduleOfSporadicTaskWithJitter Workload Interference
Platform PlatformFP Schedulability ResponseTime Priority SporadicTaskArrival
WorkloadBoundJitter Interference InterferenceBoundFP.
Section ResponseTimeBound.
Context {sporadic_task: eqType}.
Variable task_cost: sporadic_task → time.
Variable task_period: sporadic_task → time.
Variable task_deadline: sporadic_task → time.
Variable task_jitter: sporadic_task → time.
Context {Job: eqType}.
Variable job_cost: Job → time.
Variable job_deadline: Job → time.
Variable job_task: Job → sporadic_task.
Variable job_jitter: Job → time.
(* Assume any job arrival sequence... *)
Context {arr_seq: arrival_sequence Job}.
(* ... in which jobs arrive sporadically and have valid parameters. *)
Hypothesis H_sporadic_tasks:
sporadic_task_model task_period arr_seq job_task.
Hypothesis H_valid_job_parameters:
∀ (j: JobIn arr_seq),
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost
job_deadline job_task job_jitter j.
(* Consider any schedule such that...*)
Variable num_cpus: nat.
Variable sched: schedule num_cpus arr_seq.
(* ...jobs do not execute before their arrival times nor longer
than their execution costs. *)
Hypothesis H_jobs_execute_after_jitter:
jobs_execute_after_jitter job_jitter sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
(* Also assume that jobs are sequential and that there exists
at least one processor. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
(* Assume that we have a task set (with no duplicates) where all jobs
come from the task set and all tasks have valid parameters and constrained deadlines. *)
Variable ts: taskset_of sporadic_task.
Hypothesis H_ts_is_a_set: uniq ts.
Hypothesis H_all_jobs_from_taskset:
∀ (j: JobIn arr_seq), job_task j \in ts.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
Hypothesis H_constrained_deadlines:
∀ tsk, tsk \in ts → task_deadline tsk ≤ task_period tsk.
(* Next, consider a task tsk that is to be analyzed. *)
Variable tsk: sporadic_task.
Hypothesis task_in_ts: tsk \in ts.
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
task_misses_no_deadline job_cost job_deadline job_task sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
is_response_time_bound_of_task job_cost job_task tsk sched.
(* Assume a known response-time bound for any interfering task *)
Let task_with_response_time := (sporadic_task × time)%type.
Variable hp_bounds: seq task_with_response_time.
(* For FP scheduling, assume there exists a fixed task priority. *)
Variable higher_eq_priority: FP_policy sporadic_task.
Let can_interfere_with_tsk := fp_can_interfere_with higher_eq_priority tsk.
(* Assume that hp_bounds has exactly the tasks that interfere with tsk,... *)
Hypothesis H_hp_bounds_has_interfering_tasks:
[seq tsk_hp <- ts | can_interfere_with_tsk tsk_hp] = unzip1 hp_bounds.
(* ...and that all values in the pairs contain valid response-time bounds *)
Hypothesis H_response_time_of_interfering_tasks_is_known:
∀ hp_tsk R,
(hp_tsk, R) \in hp_bounds →
response_time_bounded_by hp_tsk (task_jitter hp_tsk + R).
(* Assume that the response-time bounds are larger than task costs. *)
Hypothesis H_response_time_bounds_ge_cost:
∀ hp_tsk R,
(hp_tsk, R) \in hp_bounds → R ≥ task_cost hp_tsk.
(* Assume that no deadline is missed by any interfering task, i.e.,
response-time bound R_other <= deadline. *)
Hypothesis H_interfering_tasks_miss_no_deadlines:
∀ hp_tsk R,
(hp_tsk, R) \in hp_bounds → task_jitter hp_tsk + R ≤ task_deadline hp_tsk.
(* Assume that the scheduler is work-conserving and enforces priorities. *)
Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
Hypothesis H_enforces_priority:
enforces_FP_policy job_cost job_task job_jitter sched higher_eq_priority.
(* Let R be the fixed point of Bertogna and Cirinei's recurrence, ...*)
Variable R: time.
Hypothesis H_response_time_recurrence_holds :
R = task_cost tsk +
div_floor
(total_interference_bound_fp task_cost task_period task_jitter
tsk hp_bounds R higher_eq_priority)
num_cpus.
(* ... and assume that jitter + R is no larger than the deadline of tsk.*)
Hypothesis H_response_time_no_larger_than_deadline:
task_jitter tsk + R ≤ task_deadline tsk.
(* In order to prove that R is a response-time bound, we first present some lemmas. *)
Section Lemmas.
(* Consider any job j of tsk. *)
Variable j: JobIn arr_seq.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* Let t1 be the first point in time where j can actually be scheduled. *)
Let t1 := job_arrival j + job_jitter j.
(* Assume that job j is the first job of tsk not to complete by the response time bound. *)
Hypothesis H_j_not_completed: ~~ completed job_cost sched j (t1 + R).
Hypothesis H_previous_jobs_of_tsk_completed :
∀ (j0: JobIn arr_seq),
job_task j0 = tsk →
job_arrival j0 < job_arrival j →
completed job_cost sched j0 (job_arrival j0 + task_jitter tsk + R).
(* Let's call x the interference incurred by job j due to tsk_other, ...*)
Let x (tsk_other: sporadic_task) :=
task_interference job_cost job_task job_jitter sched j tsk_other t1 (t1 + R).
(* and X the total interference incurred by job j due to any task. *)
Let X := total_interference job_cost job_jitter sched j t1 (t1 + R).
(* Recall Bertogna and Cirinei's workload bound. *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
W_jitter task_cost task_period task_jitter tsk_other R_other R.
(* Also, let ts_interf be the subset of tasks that interfere with tsk. *)
Let ts_interf := [seq tsk_other <- ts | can_interfere_with_tsk tsk_other].
Section LemmasAboutInterferingTasks.
(* Let (tsk_other, R_other) be any pair of higher-priority task and
response-time bound computed in previous iterations. *)
Variable tsk_other: sporadic_task.
Variable R_other: time.
Hypothesis H_response_time_of_tsk_other: (tsk_other, R_other) \in hp_bounds.
(* Note that tsk_other is in task set ts ...*)
Lemma bertogna_fp_tsk_other_in_ts: tsk_other \in ts.
(*... and interferes with task tsk. *)
Lemma bertogna_fp_tsk_other_interferes: can_interfere_with_tsk tsk_other.
(* Since tsk_other cannot interfere more than it executes, we show that
the interference caused by tsk_other is no larger than workload bound W. *)
Lemma bertogna_fp_workload_bounds_interference :
x tsk_other ≤ workload_bound tsk_other R_other.
End LemmasAboutInterferingTasks.
(* Next we prove some lemmas that help to derive a contradiction.*)
Section DerivingContradiction.
(* 0) Since job j did not complete by its response time bound, it follows that
the total interference X >= R - e_k + 1. *)
Lemma bertogna_fp_too_much_interference : X ≥ R - task_cost tsk + 1.
Let scheduled_task_other_than_tsk (t: time) (tsk_other: sporadic_task) :=
task_is_scheduled job_task sched tsk_other t &&
can_interfere_with_tsk tsk_other.
(* 1) At all times that j is backlogged, all processors are busy with other tasks. *)
Lemma bertogna_fp_scheduling_invariant:
∀ t,
t1 ≤ t < t1 + R →
backlogged job_cost job_jitter sched j t →
count (scheduled_task_other_than_tsk t) ts = num_cpus.
(* 2) Prove that during the scheduling window of j, any job that is scheduled while j is
backlogged comes from a different task. *)
Lemma bertogna_fp_interference_by_different_tasks :
∀ t j_other,
t1 ≤ t < t1 + R →
backlogged job_cost job_jitter sched j t →
scheduled sched j_other t →
job_task j_other != tsk.
(* 3) Next, we prove that the sum of the interference of each task is equal
to the total interference multiplied by the number of processors. This
holds because interference only occurs when all processors are busy. *)
Lemma bertogna_fp_all_cpus_busy :
\sum_(tsk_k <- ts_interf) x tsk_k = X × num_cpus.
(* Let (cardGE delta) be the number of interfering tasks whose interference
is larger than delta. *)
Let cardGE (delta: time) := count (fun i ⇒ x i ≥ delta) ts_interf.
(* 4) If there is at least one of such tasks (e.g., cardGE > 0), then the
cumulative interference caused by the complementary set of interfering
tasks fills at least (num_cpus - cardGE) processors. *)
Lemma bertogna_fp_helper_lemma :
∀ delta,
0 < cardGE delta < num_cpus →
\sum_(i <- ts_interf | x i < delta) x i ≥ delta × (num_cpus - cardGE delta).
(* 5) Next, we prove that, for any interval delta, if the sum of per-task
interference exceeds delta * num_cpus, the same applies for the
sum of the minimum between the interference and delta. *)
Lemma bertogna_fp_minimum_exceeds_interference :
∀ delta,
\sum_(tsk_k <- ts_interf) x tsk_k ≥ delta × num_cpus →
\sum_(tsk_k <- ts_interf) minn (x tsk_k) delta ≥
delta × num_cpus.
(* 6) Now, we prove that the Bertogna's interference bound
is not enough to cover the sum of the "minimum" term over
all tasks (artifact of the proof by contradiction). *)
Lemma bertogna_fp_sum_exceeds_total_interference:
\sum_((tsk_k, R_k) <- hp_bounds)
minn (x tsk_k) (R - task_cost tsk + 1) >
total_interference_bound_fp task_cost task_period task_jitter tsk hp_bounds
R higher_eq_priority.
(* 7) After concluding that the sum of the minimum exceeds (R' - e_i + 1),
we prove that there exists a tuple (tsk_k, R_k) such that
min (x_k, R' - e_i + 1) > min (W_k, R' - e_i + 1). *)
Lemma bertogna_fp_exists_task_that_exceeds_bound :
∃ tsk_k R_k,
(tsk_k, R_k) \in hp_bounds ∧
(minn (x tsk_k) (R - task_cost tsk + 1) >
minn (workload_bound tsk_k R_k) (R - task_cost tsk + 1)).
End DerivingContradiction.
End Lemmas.
(* Using the lemmas above, we prove that R' bounds the response time of task tsk. *)
Theorem bertogna_cirinei_response_time_bound_fp :
response_time_bounded_by tsk (task_jitter tsk + R).
End ResponseTimeBound.
End ResponseTimeAnalysisFP.
Require Import rt.model.jitter.task rt.model.jitter.job rt.model.jitter.task_arrival
rt.model.jitter.schedule rt.model.jitter.platform rt.model.jitter.platform_fp
rt.model.jitter.workload rt.model.jitter.schedulability rt.model.jitter.priority
rt.model.jitter.response_time rt.model.jitter.interference.
Require Import rt.analysis.jitter.workload_bound rt.analysis.jitter.interference_bound_fp.
Module ResponseTimeAnalysisFP.
Export JobWithJitter SporadicTaskset ScheduleOfSporadicTaskWithJitter Workload Interference
Platform PlatformFP Schedulability ResponseTime Priority SporadicTaskArrival
WorkloadBoundJitter Interference InterferenceBoundFP.
Section ResponseTimeBound.
Context {sporadic_task: eqType}.
Variable task_cost: sporadic_task → time.
Variable task_period: sporadic_task → time.
Variable task_deadline: sporadic_task → time.
Variable task_jitter: sporadic_task → time.
Context {Job: eqType}.
Variable job_cost: Job → time.
Variable job_deadline: Job → time.
Variable job_task: Job → sporadic_task.
Variable job_jitter: Job → time.
(* Assume any job arrival sequence... *)
Context {arr_seq: arrival_sequence Job}.
(* ... in which jobs arrive sporadically and have valid parameters. *)
Hypothesis H_sporadic_tasks:
sporadic_task_model task_period arr_seq job_task.
Hypothesis H_valid_job_parameters:
∀ (j: JobIn arr_seq),
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost
job_deadline job_task job_jitter j.
(* Consider any schedule such that...*)
Variable num_cpus: nat.
Variable sched: schedule num_cpus arr_seq.
(* ...jobs do not execute before their arrival times nor longer
than their execution costs. *)
Hypothesis H_jobs_execute_after_jitter:
jobs_execute_after_jitter job_jitter sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
(* Also assume that jobs are sequential and that there exists
at least one processor. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
(* Assume that we have a task set (with no duplicates) where all jobs
come from the task set and all tasks have valid parameters and constrained deadlines. *)
Variable ts: taskset_of sporadic_task.
Hypothesis H_ts_is_a_set: uniq ts.
Hypothesis H_all_jobs_from_taskset:
∀ (j: JobIn arr_seq), job_task j \in ts.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
Hypothesis H_constrained_deadlines:
∀ tsk, tsk \in ts → task_deadline tsk ≤ task_period tsk.
(* Next, consider a task tsk that is to be analyzed. *)
Variable tsk: sporadic_task.
Hypothesis task_in_ts: tsk \in ts.
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
task_misses_no_deadline job_cost job_deadline job_task sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
is_response_time_bound_of_task job_cost job_task tsk sched.
(* Assume a known response-time bound for any interfering task *)
Let task_with_response_time := (sporadic_task × time)%type.
Variable hp_bounds: seq task_with_response_time.
(* For FP scheduling, assume there exists a fixed task priority. *)
Variable higher_eq_priority: FP_policy sporadic_task.
Let can_interfere_with_tsk := fp_can_interfere_with higher_eq_priority tsk.
(* Assume that hp_bounds has exactly the tasks that interfere with tsk,... *)
Hypothesis H_hp_bounds_has_interfering_tasks:
[seq tsk_hp <- ts | can_interfere_with_tsk tsk_hp] = unzip1 hp_bounds.
(* ...and that all values in the pairs contain valid response-time bounds *)
Hypothesis H_response_time_of_interfering_tasks_is_known:
∀ hp_tsk R,
(hp_tsk, R) \in hp_bounds →
response_time_bounded_by hp_tsk (task_jitter hp_tsk + R).
(* Assume that the response-time bounds are larger than task costs. *)
Hypothesis H_response_time_bounds_ge_cost:
∀ hp_tsk R,
(hp_tsk, R) \in hp_bounds → R ≥ task_cost hp_tsk.
(* Assume that no deadline is missed by any interfering task, i.e.,
response-time bound R_other <= deadline. *)
Hypothesis H_interfering_tasks_miss_no_deadlines:
∀ hp_tsk R,
(hp_tsk, R) \in hp_bounds → task_jitter hp_tsk + R ≤ task_deadline hp_tsk.
(* Assume that the scheduler is work-conserving and enforces priorities. *)
Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
Hypothesis H_enforces_priority:
enforces_FP_policy job_cost job_task job_jitter sched higher_eq_priority.
(* Let R be the fixed point of Bertogna and Cirinei's recurrence, ...*)
Variable R: time.
Hypothesis H_response_time_recurrence_holds :
R = task_cost tsk +
div_floor
(total_interference_bound_fp task_cost task_period task_jitter
tsk hp_bounds R higher_eq_priority)
num_cpus.
(* ... and assume that jitter + R is no larger than the deadline of tsk.*)
Hypothesis H_response_time_no_larger_than_deadline:
task_jitter tsk + R ≤ task_deadline tsk.
(* In order to prove that R is a response-time bound, we first present some lemmas. *)
Section Lemmas.
(* Consider any job j of tsk. *)
Variable j: JobIn arr_seq.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* Let t1 be the first point in time where j can actually be scheduled. *)
Let t1 := job_arrival j + job_jitter j.
(* Assume that job j is the first job of tsk not to complete by the response time bound. *)
Hypothesis H_j_not_completed: ~~ completed job_cost sched j (t1 + R).
Hypothesis H_previous_jobs_of_tsk_completed :
∀ (j0: JobIn arr_seq),
job_task j0 = tsk →
job_arrival j0 < job_arrival j →
completed job_cost sched j0 (job_arrival j0 + task_jitter tsk + R).
(* Let's call x the interference incurred by job j due to tsk_other, ...*)
Let x (tsk_other: sporadic_task) :=
task_interference job_cost job_task job_jitter sched j tsk_other t1 (t1 + R).
(* and X the total interference incurred by job j due to any task. *)
Let X := total_interference job_cost job_jitter sched j t1 (t1 + R).
(* Recall Bertogna and Cirinei's workload bound. *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
W_jitter task_cost task_period task_jitter tsk_other R_other R.
(* Also, let ts_interf be the subset of tasks that interfere with tsk. *)
Let ts_interf := [seq tsk_other <- ts | can_interfere_with_tsk tsk_other].
Section LemmasAboutInterferingTasks.
(* Let (tsk_other, R_other) be any pair of higher-priority task and
response-time bound computed in previous iterations. *)
Variable tsk_other: sporadic_task.
Variable R_other: time.
Hypothesis H_response_time_of_tsk_other: (tsk_other, R_other) \in hp_bounds.
(* Note that tsk_other is in task set ts ...*)
Lemma bertogna_fp_tsk_other_in_ts: tsk_other \in ts.
(*... and interferes with task tsk. *)
Lemma bertogna_fp_tsk_other_interferes: can_interfere_with_tsk tsk_other.
(* Since tsk_other cannot interfere more than it executes, we show that
the interference caused by tsk_other is no larger than workload bound W. *)
Lemma bertogna_fp_workload_bounds_interference :
x tsk_other ≤ workload_bound tsk_other R_other.
End LemmasAboutInterferingTasks.
(* Next we prove some lemmas that help to derive a contradiction.*)
Section DerivingContradiction.
(* 0) Since job j did not complete by its response time bound, it follows that
the total interference X >= R - e_k + 1. *)
Lemma bertogna_fp_too_much_interference : X ≥ R - task_cost tsk + 1.
Let scheduled_task_other_than_tsk (t: time) (tsk_other: sporadic_task) :=
task_is_scheduled job_task sched tsk_other t &&
can_interfere_with_tsk tsk_other.
(* 1) At all times that j is backlogged, all processors are busy with other tasks. *)
Lemma bertogna_fp_scheduling_invariant:
∀ t,
t1 ≤ t < t1 + R →
backlogged job_cost job_jitter sched j t →
count (scheduled_task_other_than_tsk t) ts = num_cpus.
(* 2) Prove that during the scheduling window of j, any job that is scheduled while j is
backlogged comes from a different task. *)
Lemma bertogna_fp_interference_by_different_tasks :
∀ t j_other,
t1 ≤ t < t1 + R →
backlogged job_cost job_jitter sched j t →
scheduled sched j_other t →
job_task j_other != tsk.
(* 3) Next, we prove that the sum of the interference of each task is equal
to the total interference multiplied by the number of processors. This
holds because interference only occurs when all processors are busy. *)
Lemma bertogna_fp_all_cpus_busy :
\sum_(tsk_k <- ts_interf) x tsk_k = X × num_cpus.
(* Let (cardGE delta) be the number of interfering tasks whose interference
is larger than delta. *)
Let cardGE (delta: time) := count (fun i ⇒ x i ≥ delta) ts_interf.
(* 4) If there is at least one of such tasks (e.g., cardGE > 0), then the
cumulative interference caused by the complementary set of interfering
tasks fills at least (num_cpus - cardGE) processors. *)
Lemma bertogna_fp_helper_lemma :
∀ delta,
0 < cardGE delta < num_cpus →
\sum_(i <- ts_interf | x i < delta) x i ≥ delta × (num_cpus - cardGE delta).
(* 5) Next, we prove that, for any interval delta, if the sum of per-task
interference exceeds delta * num_cpus, the same applies for the
sum of the minimum between the interference and delta. *)
Lemma bertogna_fp_minimum_exceeds_interference :
∀ delta,
\sum_(tsk_k <- ts_interf) x tsk_k ≥ delta × num_cpus →
\sum_(tsk_k <- ts_interf) minn (x tsk_k) delta ≥
delta × num_cpus.
(* 6) Now, we prove that the Bertogna's interference bound
is not enough to cover the sum of the "minimum" term over
all tasks (artifact of the proof by contradiction). *)
Lemma bertogna_fp_sum_exceeds_total_interference:
\sum_((tsk_k, R_k) <- hp_bounds)
minn (x tsk_k) (R - task_cost tsk + 1) >
total_interference_bound_fp task_cost task_period task_jitter tsk hp_bounds
R higher_eq_priority.
(* 7) After concluding that the sum of the minimum exceeds (R' - e_i + 1),
we prove that there exists a tuple (tsk_k, R_k) such that
min (x_k, R' - e_i + 1) > min (W_k, R' - e_i + 1). *)
Lemma bertogna_fp_exists_task_that_exceeds_bound :
∃ tsk_k R_k,
(tsk_k, R_k) \in hp_bounds ∧
(minn (x tsk_k) (R - task_cost tsk + 1) >
minn (workload_bound tsk_k R_k) (R - task_cost tsk + 1)).
End DerivingContradiction.
End Lemmas.
(* Using the lemmas above, we prove that R' bounds the response time of task tsk. *)
Theorem bertogna_cirinei_response_time_bound_fp :
response_time_bounded_by tsk (task_jitter tsk + R).
End ResponseTimeBound.
End ResponseTimeAnalysisFP.