From a58b283a005e9d7f0b99f22a1cbe7192b34e5404 Mon Sep 17 00:00:00 2001
From: Felipe Cerqueira
Date: Mon, 31 Oct 2016 15:31:11 +0100
Subject: [PATCH] Remove JobIn to simplify specification

Makefile  5 +
analysis/apa/bertogna_edf_comp.v  50 +
analysis/apa/bertogna_edf_theory.v  181 +++
analysis/apa/bertogna_fp_comp.v  51 +
analysis/apa/bertogna_fp_theory.v  191 ++++
analysis/apa/interference_bound_edf.v  173 +++
analysis/apa/workload_bound.v  112 ++
analysis/global/basic/bertogna_edf_comp.v  52 +
analysis/global/basic/bertogna_edf_theory.v  171 +++
analysis/global/basic/bertogna_fp_comp.v  47 +
analysis/global/basic/bertogna_fp_theory.v  143 ++
.../global/basic/interference_bound_edf.v  181 +++
analysis/global/basic/workload_bound.v  107 ++
analysis/global/jitter/bertogna_edf_comp.v  43 +
analysis/global/jitter/bertogna_edf_theory.v  191 ++++
analysis/global/jitter/bertogna_fp_comp.v  42 +
analysis/global/jitter/bertogna_fp_theory.v  164 +++
.../global/jitter/interference_bound_edf.v  187 +++
analysis/global/jitter/workload_bound.v  158 +++
analysis/global/parallel/bertogna_edf_comp.v  42 +
.../global/parallel/bertogna_edf_theory.v  85 +
analysis/global/parallel/bertogna_fp_comp.v  51 +
analysis/global/parallel/bertogna_fp_theory.v  89 +
.../global/parallel/interference_bound_edf.v  128 +++
analysis/global/parallel/workload_bound.v  110 ++
analysis/uni/basic/fp_rta_comp.v  60 +
analysis/uni/basic/fp_rta_theory.v  40 +
analysis/uni/basic/workload_bound_fp.v  48 +
analysis/uni/jitter/fp_rta_comp.v  54 +
analysis/uni/jitter/fp_rta_theory.v  52 +
analysis/uni/jitter/workload_bound_fp.v  69 ++
analysis/uni/susp/dynamic/oblivious/fp_rta.v  50 +
.../uni/susp/dynamic/oblivious/reduction.v  265 +++++
implementation/apa/arrival_sequence.v  48 +
implementation/apa/bertogna_edf_example.v  34 +
implementation/apa/bertogna_fp_example.v  36 +
implementation/apa/job.v  12 +
implementation/apa/schedule.v  532 ++++++++
implementation/arrival_sequence.v  49 +
.../global/basic/bertogna_edf_example.v  29 +
.../global/basic/bertogna_fp_example.v  24 +
implementation/global/basic/schedule.v  389 +++++
.../global/jitter/arrival_sequence.v  48 +
.../global/jitter/bertogna_edf_example.v  32 +
.../global/jitter/bertogna_fp_example.v  24 +
implementation/global/jitter/job.v  8 +
implementation/global/jitter/schedule.v  387 +++++
.../global/parallel/bertogna_edf_example.v  24 +
.../global/parallel/bertogna_fp_example.v  20 +
implementation/job.v  12 +
implementation/uni/basic/fp_rta_example.v  16 +
implementation/uni/basic/schedule.v  334 +++++
implementation/uni/jitter/arrival_sequence.v  49 +
implementation/uni/jitter/fp_rta_example.v  25 +
implementation/uni/jitter/job.v  16 +
implementation/uni/jitter/schedule.v  132 ++
.../uni/susp/dynamic/arrival_sequence.v  51 +
implementation/uni/susp/dynamic/job.v  16 +
.../susp/dynamic/oblivious/fp_rta_example.v  22 +
implementation/uni/susp/schedule.v  159 +++
model/arrival/basic/arrival_bounds.v  35 +
model/arrival/basic/arrival_sequence.v  313 ++++++
model/arrival/basic/jobin_eqdec.v  29 
model/arrival/basic/task_arrival.v  65 ++
model/arrival/jitter/arrival_bounds.v  40 +
model/arrival/jitter/arrival_sequence.v  201 ++++++
model/arrival/jitter/task_arrival.v  45 +
model/priority.v  96 ++
model/schedule/apa/affinity.v  3 +
model/schedule/apa/constrained_deadlines.v  105 ++
model/schedule/apa/interference.v  11 +
model/schedule/apa/interference_edf.v  21 +
model/schedule/apa/platform.v  27 +
.../global/basic/constrained_deadlines.v  183 +++
model/schedule/global/basic/interference.v  22 +
.../schedule/global/basic/interference_edf.v  19 +
model/schedule/global/basic/platform.v  43 +
model/schedule/global/basic/schedule.v  106 ++
.../global/jitter/constrained_deadlines.v  224 ++++
model/schedule/global/jitter/interference.v  24 +
.../schedule/global/jitter/interference_edf.v  22 +
model/schedule/global/jitter/platform.v  49 +
model/schedule/global/jitter/schedule.v  94 ++
model/schedule/global/response_time.v  223 ++++
model/schedule/global/schedulability.v  60 +
.../global/transformation/construction.v  151 +++++
model/schedule/global/workload.v  29 +
model/schedule/partitioned/schedulability.v  34 +
model/schedule/partitioned/schedule.v  125 +
model/schedule/uni/basic/busy_interval.v  183 +++
model/schedule/uni/basic/platform.v  59 +
model/schedule/uni/jitter/busy_interval.v  212 ++++
model/schedule/uni/jitter/platform.v  27 +
model/schedule/uni/jitter/schedule.v  49 +
model/schedule/uni/jitter/service.v  89 
model/schedule/uni/jitter/workload.v  87 
model/schedule/uni/response_time.v  34 +
model/schedule/uni/schedulability.v  33 +
model/schedule/uni/schedule.v  90 +
model/schedule/uni/schedule_of_task.v  3 +
model/schedule/uni/service.v  84 ++
model/schedule/uni/susp/last_execution.v  26 +
model/schedule/uni/susp/platform.v  27 +
model/schedule/uni/susp/schedule.v  10 +
.../schedule/uni/susp/suspension_intervals.v  68 +
.../uni/transformation/construction.v  14 +
model/schedule/uni/workload.v  35 +
util/sorting.v  17 +
108 files changed, 4947 insertions(+), 4519 deletions()
delete mode 100644 model/arrival/basic/jobin_eqdec.v
create mode 100644 model/schedule/global/transformation/construction.v
delete mode 100644 model/schedule/uni/jitter/service.v
delete mode 100644 model/schedule/uni/jitter/workload.v
diff git a/Makefile b/Makefile
index 0a09328..e456fc9 100644
 a/Makefile
+++ b/Makefile
@@ 14,7 +14,7 @@
#
# This Makefile was generated by the command line :
# coq_makefile f _CoqProject ./util/ssromega.v ./util/seqset.v ./util/sorting.v ./util/step_function.v ./util/minmax.v ./util/powerset.v ./util/all.v ./util/ord_quantifier.v ./util/nat.v ./util/sum.v ./util/bigord.v ./util/counting.v ./util/tactics.v ./util/induction.v ./util/list.v ./util/divround.v ./util/bigcat.v ./util/fixedpoint.v ./util/notation.v ./analysis/global/jitter/bertogna_fp_comp.v ./analysis/global/jitter/interference_bound_edf.v ./analysis/global/jitter/workload_bound.v ./analysis/global/jitter/bertogna_edf_comp.v ./analysis/global/jitter/bertogna_fp_theory.v ./analysis/global/jitter/interference_bound.v ./analysis/global/jitter/interference_bound_fp.v ./analysis/global/jitter/bertogna_edf_theory.v ./analysis/global/parallel/bertogna_fp_comp.v ./analysis/global/parallel/interference_bound_edf.v ./analysis/global/parallel/workload_bound.v ./analysis/global/parallel/bertogna_edf_comp.v ./analysis/global/parallel/bertogna_fp_theory.v ./analysis/global/parallel/interference_bound.v ./analysis/global/parallel/interference_bound_fp.v ./analysis/global/parallel/bertogna_edf_theory.v ./analysis/global/basic/bertogna_fp_comp.v ./analysis/global/basic/interference_bound_edf.v ./analysis/global/basic/workload_bound.v ./analysis/global/basic/bertogna_edf_comp.v ./analysis/global/basic/bertogna_fp_theory.v ./analysis/global/basic/interference_bound.v ./analysis/global/basic/interference_bound_fp.v ./analysis/global/basic/bertogna_edf_theory.v ./analysis/apa/bertogna_fp_comp.v ./analysis/apa/interference_bound_edf.v ./analysis/apa/workload_bound.v ./analysis/apa/bertogna_edf_comp.v ./analysis/apa/bertogna_fp_theory.v ./analysis/apa/interference_bound.v ./analysis/apa/interference_bound_fp.v ./analysis/apa/bertogna_edf_theory.v ./analysis/uni/susp/dynamic/oblivious/fp_rta.v ./analysis/uni/susp/dynamic/oblivious/reduction.v ./analysis/uni/jitter/workload_bound_fp.v ./analysis/uni/jitter/fp_rta_comp.v ./analysis/uni/jitter/fp_rta_theory.v ./analysis/uni/basic/workload_bound_fp.v ./analysis/uni/basic/fp_rta_comp.v ./analysis/uni/basic/fp_rta_theory.v ./model/suspension.v ./model/schedule/partitioned/schedulability.v ./model/schedule/partitioned/schedule.v ./model/schedule/global/workload.v ./model/schedule/global/schedulability.v ./model/schedule/global/jitter/interference_edf.v ./model/schedule/global/jitter/interference.v ./model/schedule/global/jitter/job.v ./model/schedule/global/jitter/constrained_deadlines.v ./model/schedule/global/jitter/schedule.v ./model/schedule/global/jitter/platform.v ./model/schedule/global/response_time.v ./model/schedule/global/basic/interference_edf.v ./model/schedule/global/basic/interference.v ./model/schedule/global/basic/constrained_deadlines.v ./model/schedule/global/basic/schedule.v ./model/schedule/global/basic/platform.v ./model/schedule/apa/interference_edf.v ./model/schedule/apa/interference.v ./model/schedule/apa/affinity.v ./model/schedule/apa/constrained_deadlines.v ./model/schedule/apa/platform.v ./model/schedule/uni/workload.v ./model/schedule/uni/transformation/construction.v ./model/schedule/uni/susp/suspension_intervals.v ./model/schedule/uni/susp/last_execution.v ./model/schedule/uni/susp/schedule.v ./model/schedule/uni/susp/platform.v ./model/schedule/uni/schedulability.v ./model/schedule/uni/jitter/workload.v ./model/schedule/uni/jitter/busy_interval.v ./model/schedule/uni/jitter/schedule.v ./model/schedule/uni/jitter/platform.v ./model/schedule/uni/jitter/service.v ./model/schedule/uni/schedule_of_task.v ./model/schedule/uni/response_time.v ./model/schedule/uni/schedule.v ./model/schedule/uni/basic/busy_interval.v ./model/schedule/uni/basic/platform.v ./model/schedule/uni/service.v ./model/arrival/jitter/arrival_sequence.v ./model/arrival/jitter/task_arrival.v ./model/arrival/jitter/job.v ./model/arrival/jitter/arrival_bounds.v ./model/arrival/basic/arrival_sequence.v ./model/arrival/basic/task.v ./model/arrival/basic/task_arrival.v ./model/arrival/basic/job.v ./model/arrival/basic/arrival_bounds.v ./model/priority.v ./model/time.v ./implementation/arrival_sequence.v ./implementation/task.v ./implementation/global/jitter/arrival_sequence.v ./implementation/global/jitter/task.v ./implementation/global/jitter/bertogna_edf_example.v ./implementation/global/jitter/job.v ./implementation/global/jitter/bertogna_fp_example.v ./implementation/global/jitter/schedule.v ./implementation/global/parallel/bertogna_edf_example.v ./implementation/global/parallel/bertogna_fp_example.v ./implementation/global/basic/bertogna_edf_example.v ./implementation/global/basic/bertogna_fp_example.v ./implementation/global/basic/schedule.v ./implementation/job.v ./implementation/apa/arrival_sequence.v ./implementation/apa/task.v ./implementation/apa/bertogna_edf_example.v ./implementation/apa/job.v ./implementation/apa/bertogna_fp_example.v ./implementation/apa/schedule.v ./implementation/uni/susp/dynamic/arrival_sequence.v ./implementation/uni/susp/dynamic/task.v ./implementation/uni/susp/dynamic/job.v ./implementation/uni/susp/dynamic/oblivious/fp_rta_example.v ./implementation/uni/susp/schedule.v ./implementation/uni/jitter/arrival_sequence.v ./implementation/uni/jitter/task.v ./implementation/uni/jitter/job.v ./implementation/uni/jitter/fp_rta_example.v ./implementation/uni/jitter/schedule.v ./implementation/uni/basic/fp_rta_example.v ./implementation/uni/basic/schedule.v o Makefile
+# coq_makefile f _CoqProject ./util/ssromega.v ./util/seqset.v ./util/sorting.v ./util/step_function.v ./util/minmax.v ./util/powerset.v ./util/all.v ./util/ord_quantifier.v ./util/nat.v ./util/sum.v ./util/bigord.v ./util/counting.v ./util/tactics.v ./util/induction.v ./util/list.v ./util/divround.v ./util/bigcat.v ./util/fixedpoint.v ./util/notation.v ./analysis/global/jitter/bertogna_fp_comp.v ./analysis/global/jitter/interference_bound_edf.v ./analysis/global/jitter/workload_bound.v ./analysis/global/jitter/bertogna_edf_comp.v ./analysis/global/jitter/bertogna_fp_theory.v ./analysis/global/jitter/interference_bound.v ./analysis/global/jitter/interference_bound_fp.v ./analysis/global/jitter/bertogna_edf_theory.v ./analysis/global/parallel/bertogna_fp_comp.v ./analysis/global/parallel/interference_bound_edf.v ./analysis/global/parallel/workload_bound.v ./analysis/global/parallel/bertogna_edf_comp.v ./analysis/global/parallel/bertogna_fp_theory.v ./analysis/global/parallel/interference_bound.v ./analysis/global/parallel/interference_bound_fp.v ./analysis/global/parallel/bertogna_edf_theory.v ./analysis/global/basic/bertogna_fp_comp.v ./analysis/global/basic/interference_bound_edf.v ./analysis/global/basic/workload_bound.v ./analysis/global/basic/bertogna_edf_comp.v ./analysis/global/basic/bertogna_fp_theory.v ./analysis/global/basic/interference_bound.v ./analysis/global/basic/interference_bound_fp.v ./analysis/global/basic/bertogna_edf_theory.v ./analysis/apa/bertogna_fp_comp.v ./analysis/apa/interference_bound_edf.v ./analysis/apa/workload_bound.v ./analysis/apa/bertogna_edf_comp.v ./analysis/apa/bertogna_fp_theory.v ./analysis/apa/interference_bound.v ./analysis/apa/interference_bound_fp.v ./analysis/apa/bertogna_edf_theory.v ./analysis/uni/susp/dynamic/oblivious/fp_rta.v ./analysis/uni/susp/dynamic/oblivious/reduction.v ./analysis/uni/jitter/workload_bound_fp.v ./analysis/uni/jitter/fp_rta_comp.v ./analysis/uni/jitter/fp_rta_theory.v ./analysis/uni/basic/workload_bound_fp.v ./analysis/uni/basic/fp_rta_comp.v ./analysis/uni/basic/fp_rta_theory.v ./model/suspension.v ./model/schedule/partitioned/schedulability.v ./model/schedule/partitioned/schedule.v ./model/schedule/global/workload.v ./model/schedule/global/transformation/construction.v ./model/schedule/global/schedulability.v ./model/schedule/global/jitter/interference_edf.v ./model/schedule/global/jitter/interference.v ./model/schedule/global/jitter/job.v ./model/schedule/global/jitter/constrained_deadlines.v ./model/schedule/global/jitter/schedule.v ./model/schedule/global/jitter/platform.v ./model/schedule/global/response_time.v ./model/schedule/global/basic/interference_edf.v ./model/schedule/global/basic/interference.v ./model/schedule/global/basic/constrained_deadlines.v ./model/schedule/global/basic/schedule.v ./model/schedule/global/basic/platform.v ./model/schedule/apa/interference_edf.v ./model/schedule/apa/interference.v ./model/schedule/apa/affinity.v ./model/schedule/apa/constrained_deadlines.v ./model/schedule/apa/platform.v ./model/schedule/uni/workload.v ./model/schedule/uni/transformation/construction.v ./model/schedule/uni/susp/suspension_intervals.v ./model/schedule/uni/susp/last_execution.v ./model/schedule/uni/susp/schedule.v ./model/schedule/uni/susp/platform.v ./model/schedule/uni/schedulability.v ./model/schedule/uni/jitter/busy_interval.v ./model/schedule/uni/jitter/schedule.v ./model/schedule/uni/jitter/platform.v ./model/schedule/uni/schedule_of_task.v ./model/schedule/uni/response_time.v ./model/schedule/uni/schedule.v ./model/schedule/uni/basic/busy_interval.v ./model/schedule/uni/basic/platform.v ./model/schedule/uni/service.v ./model/arrival/jitter/arrival_sequence.v ./model/arrival/jitter/task_arrival.v ./model/arrival/jitter/job.v ./model/arrival/jitter/arrival_bounds.v ./model/arrival/basic/arrival_sequence.v ./model/arrival/basic/task.v ./model/arrival/basic/task_arrival.v ./model/arrival/basic/job.v ./model/arrival/basic/arrival_bounds.v ./model/priority.v ./model/time.v ./implementation/arrival_sequence.v ./implementation/task.v ./implementation/global/jitter/arrival_sequence.v ./implementation/global/jitter/task.v ./implementation/global/jitter/bertogna_edf_example.v ./implementation/global/jitter/job.v ./implementation/global/jitter/bertogna_fp_example.v ./implementation/global/jitter/schedule.v ./implementation/global/parallel/bertogna_edf_example.v ./implementation/global/parallel/bertogna_fp_example.v ./implementation/global/basic/bertogna_edf_example.v ./implementation/global/basic/bertogna_fp_example.v ./implementation/global/basic/schedule.v ./implementation/job.v ./implementation/apa/arrival_sequence.v ./implementation/apa/task.v ./implementation/apa/bertogna_edf_example.v ./implementation/apa/job.v ./implementation/apa/bertogna_fp_example.v ./implementation/apa/schedule.v ./implementation/uni/susp/dynamic/arrival_sequence.v ./implementation/uni/susp/dynamic/task.v ./implementation/uni/susp/dynamic/job.v ./implementation/uni/susp/dynamic/oblivious/fp_rta_example.v ./implementation/uni/susp/schedule.v ./implementation/uni/jitter/arrival_sequence.v ./implementation/uni/jitter/task.v ./implementation/uni/jitter/job.v ./implementation/uni/jitter/fp_rta_example.v ./implementation/uni/jitter/schedule.v ./implementation/uni/basic/fp_rta_example.v ./implementation/uni/basic/schedule.v o Makefile
#
.DEFAULT_GOAL := all
@@ 157,6 +157,7 @@ VFILES:=util/ssromega.v\
model/schedule/partitioned/schedulability.v\
model/schedule/partitioned/schedule.v\
model/schedule/global/workload.v\
+ model/schedule/global/transformation/construction.v\
model/schedule/global/schedulability.v\
model/schedule/global/jitter/interference_edf.v\
model/schedule/global/jitter/interference.v\
@@ 182,11 +183,9 @@ VFILES:=util/ssromega.v\
model/schedule/uni/susp/schedule.v\
model/schedule/uni/susp/platform.v\
model/schedule/uni/schedulability.v\
 model/schedule/uni/jitter/workload.v\
model/schedule/uni/jitter/busy_interval.v\
model/schedule/uni/jitter/schedule.v\
model/schedule/uni/jitter/platform.v\
 model/schedule/uni/jitter/service.v\
model/schedule/uni/schedule_of_task.v\
model/schedule/uni/response_time.v\
model/schedule/uni/schedule.v\
diff git a/analysis/apa/bertogna_edf_comp.v b/analysis/apa/bertogna_edf_comp.v
index e57397b..cca933c 100755
 a/analysis/apa/bertogna_edf_comp.v
+++ b/analysis/apa/bertogna_edf_comp.v
@@ 16,6 +16,7 @@ Module ResponseTimeIterationEDF.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 883,46 +884,51 @@ Module ResponseTimeIterationEDF.
forall tsk, tsk \in ts > is_subaffinity (alpha' tsk) (alpha tsk).
(* Next, consider any arrival sequence such that...*)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j > job_task j \in ts.
(* ...they have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Then, consider any schedule with at least one CPU such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs only execute after they arrived and no longer
than their execution costs,... *)
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* ...and jobs are sequential. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* Assume a workconserving APA scheduler that respects EDF policy. *)
Hypothesis H_respects_affinity: respects_affinity job_task sched alpha.
 Hypothesis H_work_conserving: apa_work_conserving job_cost job_task sched alpha.
 Hypothesis H_edf_policy: respects_JLFP_policy_under_weak_APA job_cost job_task sched alpha (EDF job_deadline).
+ Hypothesis H_work_conserving: apa_work_conserving job_arrival job_cost job_task arr_seq
+ sched alpha.
+ Hypothesis H_edf_policy:
+ respects_JLFP_policy_under_weak_APA job_arrival job_cost job_task
+ arr_seq sched alpha (EDF job_arrival job_deadline).
(* To avoid a long list of parameters, we provide some local definitions. *)
Definition no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Definition no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in edf_claimed_bounds is safe. The proof follows by direct application of
@@ 933,12 +939,12 @@ Module ResponseTimeIterationEDF.
response_time_bounded_by tsk R.
Proof.
have BOUND := bertogna_cirinei_response_time_bound_edf.
 intros tsk R IN j JOBj.
+ intros tsk R IN j ARRj JOBj.
destruct (edf_claimed_bounds ts) as [rt_bounds ] eqn:SOME; last by done.
unfold edf_rta_iteration in *.
unfold is_response_time_bound_of_task in *.
apply BOUND with (task_cost := task_cost) (task_period := task_period)
 (task_deadline := task_deadline) (job_deadline := job_deadline)
+ (arr_seq := arr_seq) (task_deadline := task_deadline) (job_deadline := job_deadline)
(job_task := job_task) (ts := ts) (tsk := tsk) (rt_bounds := rt_bounds) (alpha := alpha) (alpha' := alpha'); try (by ins).
by unfold edf_claimed_bounds in SOME; desf; rewrite edf_claimed_bounds_unzip1_iteration.
by ins; apply edf_claimed_bounds_finds_fixed_point_for_each_bound with (ts := ts).
@@ 960,10 +966,10 @@ Module ResponseTimeIterationEDF.
edf_schedulable,
valid_sporadic_job in *.
rename H_valid_job_parameters into JOBPARAMS.
 intros tsk INtsk j JOBtsk.
+ intros tsk INtsk j ARRj JOBtsk.
destruct (edf_claimed_bounds ts) as [rt_bounds ] eqn:SOME; last by ins.
exploit (HAS rt_bounds tsk); [by ins  by ins  clear HAS; intro HAS; des].
 have COMPLETED := RLIST tsk R HAS j JOBtsk.
+ have COMPLETED := RLIST tsk R HAS j ARRj JOBtsk.
exploit (DL rt_bounds tsk R);
[by ins  by ins  clear DL; intro DL].
@@ 972,7 +978,7 @@ Module ResponseTimeIterationEDF.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
apply extend_sum; rewrite // leq_add2l.
 specialize (JOBPARAMS j); des; rewrite JOBPARAMS1.
+ specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS1.
by rewrite JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
@@ 983,12 +989,12 @@ Module ResponseTimeIterationEDF.
are spawned by the task set, we conclude that no job misses
its deadline. *)
Theorem jobs_schedulable_by_edf_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j, arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_edf_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/apa/bertogna_edf_theory.v b/analysis/apa/bertogna_edf_theory.v
index 13ae204..d232320 100644
 a/analysis/apa/bertogna_edf_theory.v
+++ b/analysis/apa/bertogna_edf_theory.v
@@ 26,18 +26,20 @@ Module ResponseTimeAnalysisEDF.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider a task set ts where all tasks have valid parameters
@@ 50,35 +52,37 @@ Module ResponseTimeAnalysisEDF.
(* ... and assume that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Also assume that every task has a nonempty processor affinity alpha. *)
Context {num_cpus: nat}.
Variable alpha: task_affinity sporadic_task num_cpus.
(* Next, consider any schedule such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs are sequential and do not execute before their
arrival times nor longer than their execution costs. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Assume that the schedule is an workconserving APA schedule that
respects EDF priorities. *)
Hypothesis H_respects_affinity: respects_affinity job_task sched alpha.
 Hypothesis H_work_conserving: apa_work_conserving job_cost job_task sched alpha.
+ Hypothesis H_work_conserving: apa_work_conserving job_arrival job_cost job_task arr_seq
+ sched alpha.
Hypothesis H_edf_policy:
 respects_JLFP_policy_under_weak_APA job_cost job_task sched alpha (EDF job_deadline).
+ respects_JLFP_policy_under_weak_APA job_arrival job_cost job_task arr_seq
+ sched alpha (EDF job_arrival job_deadline).
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Now we consider the responsetime recurrence. In the computation of
the responsetime bound, we assume that each task under analysis has
@@ 119,7 +123,8 @@ Module ResponseTimeAnalysisEDF.
Hypothesis H_tsk_R_in_rt_bounds: (tsk, R) \in rt_bounds.
(* Consider any job j of tsk ... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* ... that did not complete on time, ... *)
@@ 127,7 +132,8 @@ Module ResponseTimeAnalysisEDF.
(* ... and that is the first job not to satisfy its responsetime bound. *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_other: JobIn arr_seq) tsk_other R_other,
+ forall j_other tsk_other R_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
(tsk_other, R_other) \in rt_bounds >
job_arrival j_other + R_other < job_arrival j + R >
@@ 135,11 +141,11 @@ Module ResponseTimeAnalysisEDF.
(* 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 sched alpha j
+ task_interference job_arrival job_cost job_task sched alpha j
tsk_other (job_arrival j) (job_arrival j + R).
(* and X the total interference incurred by job j due to any task. *)
 Let X := total_interference job_cost sched j (job_arrival j) (job_arrival j + R).
+ Let X := total_interference job_arrival job_cost sched j (job_arrival j) (job_arrival j + R).
(* Recall Bertogna and Cirinei's workload bound ... *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
@@ 201,7 +207,8 @@ Module ResponseTimeAnalysisEDF.
(job_arrival j) (job_arrival j + R));
first by apply task_interference_le_workload.
by apply workload_bounded_by_W with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline); try (by ins); last 2 first;
+ (job_arrival0 := job_arrival) (arr_seq0 := arr_seq)
+ (job_cost0 := job_cost) (job_deadline0 := job_deadline); try (by ins); last 2 first;
[ by apply bertogna_edf_R_other_ge_cost
 by ins; apply NOMISS
 by ins; apply TASK_PARAMS
@@ 214,7 +221,7 @@ Module ResponseTimeAnalysisEDF.
x tsk_other <= edf_specific_bound tsk_other R_other.
Proof.
apply interference_bound_edf_bounds_interference with (job_deadline0 := job_deadline)
 (ts0 := ts); try (by done);
+ (arr_seq0 := arr_seq) (ts0 := ts); try (by done);
[ by apply bertogna_edf_tsk_other_in_ts
 by apply H_tasks_miss_no_deadlines
 by apply H_tasks_miss_no_deadlines  ].
@@ 246,12 +253,12 @@ Module ResponseTimeAnalysisEDF.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(job_arrival j <= t < job_arrival j + R)
 backlogged job_cost sched j t) +
+ backlogged job_arrival job_cost sched j t) +
service sched j (job_arrival j + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_j_arrives); des; rewrite JOBtsk.
}
unfold service; rewrite service_before_arrival_eq_service_during //.
rewrite big_split /=.
@@ 259,7 +266,7 @@ Module ResponseTimeAnalysisEDF.
first by rewrite big_const_nat iter_addn mul1n addn0 addKn.
rewrite big_nat_cond [\sum_(_ <= _ < _  true) _]big_nat_cond.
apply leq_sum; move => i /andP [/andP [GEi LTi] _].
 destruct (backlogged job_cost sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 278,7 +285,8 @@ Module ResponseTimeAnalysisEDF.
Lemma bertogna_edf_interference_by_different_tasks :
forall t j_other,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ arrives_in arr_seq j_other >
+ backlogged job_arrival job_cost sched j t >
scheduled sched j_other t >
job_task j_other != tsk.
Proof.
@@ 290,18 +298,19 @@ Module ResponseTimeAnalysisEDF.
H_all_previous_jobs_completed_on_time into BEFOREok,
H_tasks_miss_no_deadlines into NOMISS,
H_constrained_deadlines into RESTR.
 move => t j_other /andP [LEt GEt] BACK SCHED.
+ move => t j_other /andP [LEt GEt] ARRother BACK SCHED.
apply/eqP; red; intro SAMEtsk.
move: SCHED => /existsP [cpu SCHED].
assert (SCHED': scheduled sched j_other t).
by apply/existsP; exists cpu.
clear SCHED; rename SCHED' into SCHED.
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival) (job_cost0 := job_cost)
+ in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
move: (BEFOREother) => LT; rewrite (ltn_add2r R) in LT.
 specialize (BEFOREok j_other tsk R SAMEtsk INbounds LT).
+ specialize (BEFOREok j_other tsk R ARRother SAMEtsk INbounds LT).
move: PENDING => /andP [_ /negP NOTCOMP]; apply NOTCOMP.
apply completion_monotonic with (t0 := job_arrival j_other + R); try (by done).
apply leq_trans with (n := job_arrival j); last by done.
@@ 309,12 +318,12 @@ Module ResponseTimeAnalysisEDF.
first by rewrite leq_add2l; apply NOMISS.
apply leq_trans with (n := job_arrival j_other + task_period tsk);
first by rewrite leq_add2l; apply RESTR; rewrite JOBtsk FROMTS.
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; try (by done); [  by rewrite JOBtsk  by apply ltnW].
by red; intro EQ; subst; rewrite ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge.
apply leq_ltn_trans with (n := t); first by done.
@@ 333,7 +342,8 @@ Module ResponseTimeAnalysisEDF.
With this lemma, we can conclude that during job j's scheduling
window there cannot be multiple pending jobs of each task.*)
Lemma bertogna_edf_all_previous_jobs_complete_by_their_period:
 forall t (j0: JobIn arr_seq),
+ forall t j0,
+ arrives_in arr_seq j0 >
t < job_arrival j + R >
job_arrival j0 + task_period (job_task j0) <= t >
completed job_cost sched j0
@@ 344,7 +354,7 @@ Module ResponseTimeAnalysisEDF.
H_tasks_miss_no_deadlines into NOMISS,
H_all_jobs_from_taskset into FROMTS,
H_all_previous_jobs_completed_on_time into BEFOREok.
 intros t j0 LEt LE.
+ intros t j0 ARR0 LEt LE.
cut ((job_task j0) \in unzip1 rt_bounds = true); last by rewrite UNZIP FROMTS.
move => /mapP [p IN EQ]; destruct p as [tsk' R0]; simpl in *; subst tsk'.
apply completion_monotonic with (t0 := job_arrival j0 + R0); first by done.
@@ 370,7 +380,7 @@ Module ResponseTimeAnalysisEDF.
Proof.
have DIFFTASK := bertogna_edf_interference_by_different_tasks.
rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
+ H_valid_task_parameters into PARAMS, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
H_work_conserving into WORK,
H_tsk_R_in_rt_bounds into INbounds,
@@ 382,9 +392,9 @@ Module ResponseTimeAnalysisEDF.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost sched j t) eqn:BACK; last first.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last first.
{
rewrite (eq_bigr (fun i => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
@@ 401,7 +411,9 @@ Module ResponseTimeAnalysisEDF.
destruct (cpu \in alpha (job_task j)) eqn:ALPHA; rewrite ?JOBtsk ALPHA;
last by rewrite big_filter (eq_bigr (fun x => 0));
[by simpl_sum_const  by ins].
 move: (WORK j t BACK cpu ALPHA) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ move: (WORK j t H_j_arrives BACK cpu ALPHA) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (FROMSEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
rewrite (eq_bigr (fun i => 0));
@@ 416,7 +428,7 @@ Module ResponseTimeAnalysisEDF.
apply/existsP; exists cpu; rewrite JOBtsk ALPHA andTb.
by apply APA with (t := t); apply/eqP.
}
 apply DIFFTASK with (t := t); [by auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu; apply/eqP.
Qed.
@@ 442,9 +454,9 @@ Module ResponseTimeAnalysisEDF.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond /=.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond /=.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost sched j t) eqn:BACK; last first.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last first.
{
rewrite (eq_bigr (fun i => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
@@ 460,11 +472,14 @@ Module ResponseTimeAnalysisEDF.
unfold can_execute_on in *.
destruct (cpu \in alpha' (job_task j)) eqn:ALPHA'; rewrite ?JOBtsk ALPHA';
last by done.
 move: (SUB (job_task j) (FROMTS j) cpu ALPHA') => SUBj.
 move: (WORK j t BACK cpu SUBj) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ feed (SUB (job_task j)); first by apply FROMTS.
+ specialize (SUB cpu ALPHA').
+ move: (WORK j t H_j_arrives BACK cpu SUB) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (H_jobs_come_from_arrival_sequence j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite (bigD1_seq (job_task j_other)) /=; last by apply filter_uniq; destruct ts.
{
 by rewrite {1}/task_scheduled_on SUBj SCHED eq_refl andTb.
+ by rewrite {1}/task_scheduled_on SUB SCHED eq_refl andTb.
}
{
rewrite mem_filter; apply/andP; split; last by apply FROMTS.
@@ 473,7 +488,7 @@ Module ResponseTimeAnalysisEDF.
apply/existsP; exists cpu; apply/andP; split; first by rewrite JOBtsk.
by apply APA with (t := t); apply/eqP.
}
 apply DIFFTASK with (t := t); [by auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu; apply/eqP.
}
Qed.
@@ 489,18 +504,18 @@ Module ResponseTimeAnalysisEDF.
Lemma bertogna_edf_alpha'_is_full:
forall t,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ backlogged job_arrival job_cost sched j t >
count (scheduled_on_alpha_tsk t) (other_tasks_in alpha') >= #alpha' tsk.
Proof.
have COMP := bertogna_edf_all_previous_jobs_complete_by_their_period.
rename H_work_conserving into WORK, H_respects_affinity into APA,
H_affinity_subset into SUB, H_job_of_tsk into JOBtsk,
 H_all_jobs_from_taskset into FROMTS,
+ H_all_jobs_from_taskset into FROMTS, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_valid_task_parameters into PARAMS,
H_sequential_jobs into SEQ.
move => t /andP [GEt LTt] BACK.
move: WORK => WORK.
 specialize (WORK j t BACK).
+ specialize (WORK j t H_j_arrives BACK).
rewrite size_filter.
apply leq_trans with (n := size (alpha' tsk));
first by apply card_size.
@@ 514,7 +529,7 @@ Module ResponseTimeAnalysisEDF.
by move: WORK => [j_other /eqP SCHED]; rewrite SCHED.
}
{
 apply leq_trans with (n := size (map (fun j: JobIn arr_seq => job_task j) (pmap (fun cpu => sched cpu t) (enum (alpha' tsk)))));
+ apply leq_trans with (n := size (map (fun j => job_task j) (pmap (fun cpu => sched cpu t) (enum (alpha' tsk)))));
first by rewrite size_map.
apply uniq_leq_size.
{
@@ 522,7 +537,7 @@ Module ResponseTimeAnalysisEDF.
{
apply pmap_inj_in_uniq; last by apply enum_uniq.
intros cpu1 cpu2 IN1 IN2 SCHED2.
 destruct (sched cpu1 t) eqn:SCHED1; symmetry in SCHED2;
+ destruct (sched cpu1 t) as [j0] eqn:SCHED1; symmetry in SCHED2;
first by apply SEQ with (j := j0) (t := t).
rewrite 2!mem_enum in IN1 IN2.
exploit (WORK cpu1); first by apply SUB; rewrite ?FROMTS ?JOBtsk.
@@ 532,21 +547,26 @@ Module ResponseTimeAnalysisEDF.
intros j1 j2 SCHED1 SCHED2 SAMEtsk.
rewrite 2!mem_pmap in SCHED1 SCHED2.
move: SCHED1 SCHED2 => /mapP [cpu1 IN1 SCHED1] /mapP [cpu2 IN2 SCHED2].
 assert (PENDING1: pending job_cost sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu1; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu2; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu1; rewrite /scheduled_on SCHED1.
}
 assert (SCHED2': pending job_cost sched j2 t).
+ assert (SCHED2': pending job_arrival job_cost sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu2; rewrite /scheduled_on SCHED2.
}
apply platform_at_most_one_pending_job_of_each_task with (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline) (tsk0 := tsk)
 (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t);
 rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
 intros j0 tsk0 TSK0 LE.
+ (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t)
+ (job_arrival0 := job_arrival) (arr_seq0 := arr_seq);
+ rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
+ intros j0 tsk0 ARR0 TSK0 LE.
by apply (COMP t); rewrite ?TSK0.
}
}
@@ 561,6 +581,8 @@ Module ResponseTimeAnalysisEDF.
first by apply SUB; rewrite ?JOBtsk ?FROMTS ?JOBtsk.
by rewrite /task_scheduled_on SCHED' EQtsk'.
}
+ have ARR': arrives_in arr_seq j'.
+ by apply (FROMSEQ j' t); apply/existsP; exists cpu; apply/eqP.
rewrite EQtsk' mem_filter; apply/andP; split; last by apply FROMTS.
apply/andP; split; last first.
{
@@ 575,15 +597,16 @@ Module ResponseTimeAnalysisEDF.
by apply/existsP; exists cpu; rewrite /scheduled_on SCHED'.
}
move: (SCHEDULED') => PENDING'.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING';
 try by done.
+ apply scheduled_implies_pending with (job_cost0 := job_cost) (job_arrival0:=job_arrival)
+ in PENDING'; try by done.
assert (BUG: j = j').
{
apply platform_at_most_one_pending_job_of_each_task with (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline) (tsk0 := tsk)
 (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t);
 rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
 intros j0 tsk0 TSK0 LE.
+ (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t)
+ (job_arrival0 := job_arrival) (arr_seq0 := arr_seq);
+ rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
+ intros j0 tsk0 ARR0 TSK0 LE.
by apply (COMP t); rewrite ?TSK0.
}
by rewrite BUG SCHEDULED' in NOTSCHED.
@@ 611,7 +634,7 @@ Module ResponseTimeAnalysisEDF.
have INV := bertogna_edf_alpha'_is_full.
rename H_all_jobs_from_taskset into FROMTS,
H_valid_task_parameters into PARAMS,
 H_job_of_tsk into JOBtsk,
+ H_job_of_tsk into JOBtsk, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_sporadic_tasks into SPO,
H_tsk_R_in_rt_bounds into INbounds,
H_all_previous_jobs_completed_on_time into BEFOREok,
@@ 623,12 +646,12 @@ Module ResponseTimeAnalysisEDF.
rewrite has_count in HAS.
set some_interference_A := fun t =>
 has (fun tsk_k => backlogged job_cost sched j t &&
+ has (fun tsk_k => backlogged job_arrival job_cost sched j t &&
(x tsk_k >= delta) &&
scheduled_on_alpha_tsk t tsk_k)
(other_tasks_in alpha').
set total_interference_B := fun t =>
 backlogged job_cost sched j t *
+ backlogged job_arrival job_cost sched j t *
count (fun tsk_k => (x tsk_k < delta) &&
scheduled_on_alpha_tsk t tsk_k) (other_tasks_in alpha').
@@ 640,7 +663,7 @@ Module ResponseTimeAnalysisEDF.
apply leq_trans with (n := x tsk_a); first by apply LEa.
unfold x, task_interference, some_interference_A.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
last by rewrite (eq_bigr (fun x => 0)); [by simpl_sum_const  by ins].
destruct ([exists cpu, can_execute_on alpha (job_task j) cpu &&
task_scheduled_on job_task sched tsk_a cpu t]) eqn:SCHED;
@@ 670,21 +693,26 @@ Module ResponseTimeAnalysisEDF.
subst tsk_a; symmetry in JOB'.
assert (BUG: j1 = j2).
{
 assert (PENDING1: pending job_cost sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu'; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu; rewrite /scheduled_on SCHED1.
}
 assert (SCHED2': pending job_cost sched j2 t).
+ assert (SCHED2': pending job_arrival job_cost sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu'; rewrite /scheduled_on SCHED2.
}
apply platform_at_most_one_pending_job_of_each_task with (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline) (tsk0 := tsk)
 (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t);
 rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
 intros j0 tsk0 TSK0 LE.
+ (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t)
+ (job_arrival0 := job_arrival) (arr_seq0 := arr_seq);
+ rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
+ intros j0 tsk0 ARR0 TSK0 LE.
by apply (COMP t); rewrite ?TSK0.
}
by subst j2; apply SEQ with (j := j1) (t := t).
@@ 696,7 +724,7 @@ Module ResponseTimeAnalysisEDF.
rewrite big_distrl /=.
apply leq_sum_nat; move => t LEt _.
unfold some_interference_A, total_interference_B.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
[rewrite mul1n /=  by rewrite has_pred0 //].
destruct (has (fun tsk_k : sporadic_task => (delta <= x tsk_k) &&
@@ 724,7 +752,7 @@ Module ResponseTimeAnalysisEDF.
{
unfold x at 2, total_interference_B.
rewrite exchange_big /=; apply leq_sum; intros t _.
 destruct (backlogged job_cost sched j t) eqn:BACK; last by ins.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last by ins.
rewrite mul1n sum1_count.
rewrite big_mkcond [\sum_(i < other_tasks_in alpha'  _ < _) _]big_mkcond /=.
apply leq_sum_seq; move => tsk_k IN _.
@@ 929,7 +957,7 @@ Module ResponseTimeAnalysisEDF.
Theorem bertogna_cirinei_response_time_bound_edf :
response_time_bounded_by tsk R.
Proof.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
remember (job_arrival j + R) as ctime.
@@ 940,14 +968,15 @@ Module ResponseTimeAnalysisEDF.
(* Now, we apply strong induction on the absolute responsetime bound. *)
induction ctime as [ctime IH] using strong_ind.
 intros j tsk' JOBtsk R' EQc INbounds; subst ctime.
+ intros j ARRj tsk' JOBtsk R' EQc INbounds; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq) tsk R0,
 job_task j0 = tsk >
 (tsk, R0) \in rt_bounds >
 job_arrival j0 + R0 < job_arrival j + R' >
 service sched j0 (job_arrival j0 + R0) == job_cost j0).
+ assert (BEFOREok: forall j0 tsk R0,
+ arrives_in arr_seq j0 >
+ job_task j0 = tsk >
+ (tsk, R0) \in rt_bounds >
+ job_arrival j0 + R0 < job_arrival j + R' >
+ service sched j0 (job_arrival j0 + R0) == job_cost j0).
{
by ins; apply IH with (tsk := tsk0) (R := R0).
}
@@ 961,7 +990,7 @@ Module ResponseTimeAnalysisEDF.
apply negbT in NOTCOMP; exfalso.
(* Next, we derive a contradiction using the previous lemmas. *)
 exploit (bertogna_edf_exists_task_that_exceeds_bound tsk' R' INbounds j JOBtsk NOTCOMP).
+ exploit (bertogna_edf_exists_task_that_exceeds_bound tsk' R' INbounds j ARRj JOBtsk NOTCOMP).
{
by ins; apply IH with (tsk := tsk_other) (R := R_other).
}
@@ 969,7 +998,7 @@ Module ResponseTimeAnalysisEDF.
unfold interference_bound_edf, interference_bound_generic in LTmin.
rewrite minnAC in LTmin; apply min_lt_same in LTmin.
have BASICBOUND := bertogna_edf_workload_bounds_interference R' j BEFOREok tsk_other R_other HP.
 have EDFBOUND := (bertogna_edf_specific_bound_holds tsk' R' INbounds j JOBtsk BEFOREok tsk_other R_other HP).
+ have EDFBOUND := (bertogna_edf_specific_bound_holds tsk' R' INbounds j ARRj JOBtsk BEFOREok tsk_other R_other HP).
unfold minn in LTmin; clear LTmin HP BASICBOUND EDFBOUND tsk; desf.
{
by apply (leq_ltn_trans BASICBOUND) in LTmin; rewrite ltnn in LTmin.
diff git a/analysis/apa/bertogna_fp_comp.v b/analysis/apa/bertogna_fp_comp.v
index 7cc2ffb..3724b65 100644
 a/analysis/apa/bertogna_fp_comp.v
+++ b/analysis/apa/bertogna_fp_comp.v
@@ 16,6 +16,7 @@ Module ResponseTimeIterationFP.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 503,47 +504,50 @@ Module ResponseTimeIterationFP.
Hypothesis H_priority_transitive: FP_is_transitive higher_priority.
(* Next, consider any arrival sequence such that...*)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...jobs have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Then, consider any schedule such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs only execute after they arrived and no longer
than their execution costs,... *)
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* ...and jobs are sequential. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* Assume a workconserving APA scheduler that respects the FP policy. *)
Hypothesis H_respects_affinity: respects_affinity job_task sched alpha.
 Hypothesis H_work_conserving: apa_work_conserving job_cost job_task sched alpha.
+ Hypothesis H_work_conserving: apa_work_conserving job_arrival job_cost job_task arr_seq
+ sched alpha.
Hypothesis H_respects_FP_policy:
 respects_FP_policy_under_weak_APA job_cost job_task sched alpha higher_priority.
+ respects_FP_policy_under_weak_APA job_arrival job_cost job_task arr_seq sched
+ alpha higher_priority.
(* To avoid a long list of parameters, we provide some local definitions. *)
Let no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in fp_claimed_bounds is safe. The proof follows by induction on the task set:
@@ 580,20 +584,13 @@ Module ResponseTimeIterationFP.
clear EQ.
assert (PAIR: forall idx, (TASK idx, RESP idx) = NTH idx).
 {
by intros i; unfold TASK, RESP; destruct (NTH i).
 }
assert (SUBST: forall i, i < size hp_bounds > TASK i = nth tsk ts i).
 {

by intros i LTi; rewrite /TASK /NTH UNZIP (nth_map elem) //.
 }
assert (SIZE: size hp_bounds = size ts).
 {
by rewrite UNZIP size_map.
 }
induction idx as [idx IH'] using strong_ind.
@@ 688,7 +685,7 @@ Module ResponseTimeIterationFP.
job_misses_no_deadline, completed,
fp_schedulable, valid_sporadic_job in *.
rename H_valid_job_parameters into JOBPARAMS.
 move => tsk INtsk j JOBtsk.
+ move => tsk INtsk j ARRj JOBtsk.
destruct (fp_claimed_bounds ts) as [rt_bounds ]; last by ins.
feed (UNZIP rt_bounds); first by done.
@@ 697,14 +694,14 @@ Module ResponseTimeIterationFP.
rewrite set_mem UNZIP in INtsk; move: INtsk => /mapP EX.
by destruct EX as [p]; destruct p as [tsk' R]; simpl in *; subst tsk'; exists R.
} des.
 exploit (RLIST tsk R); [by ins  by apply JOBtsk  intro COMPLETED].
+ exploit (RLIST tsk R EX j ARRj); [by apply JOBtsk  intro COMPLETED].
exploit (DL rt_bounds tsk R); [by ins  by ins  clear DL; intro DL].
rewrite eqn_leq; apply/andP; split; first by apply cumulative_service_le_job_cost.
apply leq_trans with (n := service sched j (job_arrival j + R)); last first.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
apply extend_sum; rewrite // leq_add2l.
 specialize (JOBPARAMS j); des; rewrite JOBPARAMS1.
+ specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS1.
by rewrite JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
@@ 715,12 +712,12 @@ Module ResponseTimeIterationFP.
are spawned by the task set, we also conclude that no job in
the schedule misses its deadline. *)
Theorem jobs_schedulable_by_fp_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j, arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_fp_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/apa/bertogna_fp_theory.v b/analysis/apa/bertogna_fp_theory.v
index 74b7716..30f4b32 100644
 a/analysis/apa/bertogna_fp_theory.v
+++ b/analysis/apa/bertogna_fp_theory.v
@@ 27,18 +27,20 @@ Module ResponseTimeAnalysisFP.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Assume that we have a task set where all tasks have valid
@@ 51,22 +53,23 @@ Module ResponseTimeAnalysisFP.
(* ... and that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j > job_task j \in ts.
(* Also assume that every task has a nonempty processor affinity alpha. *)
Context {num_cpus: nat}.
Variable alpha: task_affinity sporadic_task num_cpus.
(* Next, consider any schedule such that...*)
 Variable sched: schedule num_cpus arr_seq.

+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
(* ...jobs are sequential and do not execute before their
arrival times nor longer than their execution costs. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Consider a given FP policy, ... *)
Variable higher_eq_priority: FP_policy sporadic_task.
@@ 74,15 +77,17 @@ Module ResponseTimeAnalysisFP.
(* ... and assume that the schedule is an APA workconserving
schedule that respects this policy. *)
Hypothesis H_respects_affinity: respects_affinity job_task sched alpha.
 Hypothesis H_work_conserving: apa_work_conserving job_cost job_task sched alpha.
+ Hypothesis H_work_conserving: apa_work_conserving job_arrival job_cost job_task
+ arr_seq sched alpha.
Hypothesis H_respects_FP_policy:
 respects_FP_policy_under_weak_APA job_cost job_task sched alpha higher_eq_priority.
+ respects_FP_policy_under_weak_APA job_arrival job_cost job_task arr_seq
+ sched alpha higher_eq_priority.
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Next, we consider the responsetime recurrence.
Let tsk be a task in ts that is to be analyzed. *)
@@ 105,7 +110,7 @@ Module ResponseTimeAnalysisFP.
Hypothesis H_response_time_of_interfering_tasks_is_known:
forall hp_tsk R,
(hp_tsk, R) \in hp_bounds >
 is_response_time_bound_of_task job_cost job_task hp_tsk sched R.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched hp_tsk R.
(* ... for every higherpriority task in (alpha tsk). *)
Hypothesis H_hp_bounds_has_interfering_tasks:
@@ 143,24 +148,26 @@ Module ResponseTimeAnalysisFP.
Section Lemmas.
(* Consider any job j of tsk. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* 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 (job_arrival j + R).
Hypothesis H_previous_jobs_of_tsk_completed :
 forall (j0: JobIn arr_seq),
+ forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
completed job_cost sched j0 (job_arrival j0 + 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 sched alpha j tsk_other
+ task_interference job_arrival job_cost job_task sched alpha j tsk_other
(job_arrival j) (job_arrival j + R).
(* and X the total interference incurred by job j due to any task. *)
 Let X := total_interference job_cost sched j (job_arrival j) (job_arrival j + R).
+ Let X := total_interference job_arrival job_cost sched j (job_arrival j) (job_arrival j + R).
(* Recall Bertogna and Cirinei's workload bound. *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
@@ 213,14 +220,17 @@ Module ResponseTimeAnalysisFP.
}
move: SCHED => /existsP [t /existsP [cpu SCHED]].
unfold task_scheduled_on in SCHED.
 destruct (sched cpu t) as [j0 ]; last by done.
+ destruct (sched cpu t) as [j0 ] eqn:SCHED'; last by done.
assert (INts: tsk_other \in ts).
 by move: SCHED => /eqP <; rewrite FROMTS.
+ {
+ move: SCHED => /eqP <. apply FROMTS, (H_jobs_come_from_arrival_sequence j0 t).
+ by apply/existsP; exists cpu; apply/eqP.
+ }
apply leq_trans with (n := workload job_task sched tsk_other
(job_arrival j) (job_arrival j + R));
first by apply task_interference_le_workload.
 by apply workload_bounded_by_W with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline);
+ by apply workload_bounded_by_W with (task_deadline0 := task_deadline) (arr_seq0 := arr_seq)
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (job_deadline0 := job_deadline);
try (by ins); last 2 first;
[ by ins; apply GE_COST
 by ins; apply NOMISS
@@ 255,12 +265,12 @@ Module ResponseTimeAnalysisFP.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(job_arrival j <= t < job_arrival j + R)
 backlogged job_cost sched j t) +
+ backlogged job_arrival job_cost sched j t) +
service sched j (job_arrival j + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_j_arrives); des; rewrite JOBtsk.
}
unfold service; rewrite service_before_arrival_eq_service_during //.
rewrite big_split /=.
@@ 268,7 +278,7 @@ Module ResponseTimeAnalysisFP.
first by rewrite big_const_nat iter_addn mul1n addn0 addKn.
rewrite big_nat_cond [\sum_(_ <= _ < _  true) _]big_nat_cond.
apply leq_sum; move => i /andP [/andP [GEi LTi] _].
 destruct (backlogged job_cost sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 287,7 +297,8 @@ Module ResponseTimeAnalysisFP.
Lemma bertogna_fp_interference_by_different_tasks :
forall t j_other,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ arrives_in arr_seq j_other >
+ backlogged job_arrival job_cost sched j t >
scheduled sched j_other t >
job_task j_other != tsk.
Proof.
@@ 298,18 +309,19 @@ Module ResponseTimeAnalysisFP.
H_previous_jobs_of_tsk_completed into BEFOREok,
H_response_time_no_larger_than_deadline into NOMISS,
H_constrained_deadlines into RESTR.
 move => t j_other /andP [LEt GEt] BACK SCHED.
+ move => t j_other /andP [LEt GEt] ARRother BACK SCHED.
apply/eqP; red; intro SAMEtsk.
move: SCHED => /existsP [cpu SCHED].
assert (SCHED': scheduled sched j_other t).
by apply/existsP; exists cpu.
clear SCHED; rename SCHED' into SCHED.
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
move: (BEFOREother) => LT; rewrite (ltn_add2r R) in LT.
 specialize (BEFOREok j_other SAMEtsk BEFOREother).
+ specialize (BEFOREok j_other ARRother SAMEtsk BEFOREother).
move: PENDING => /andP [_ /negP NOTCOMP]; apply NOTCOMP.
apply completion_monotonic with (t0 := job_arrival j_other + R); try (by done).
apply leq_trans with (n := job_arrival j); last by done.
@@ 317,12 +329,12 @@ Module ResponseTimeAnalysisFP.
first by rewrite leq_add2l; apply NOMISS.
apply leq_trans with (n := job_arrival j_other + task_period tsk);
first by rewrite leq_add2l; apply RESTR; rewrite JOBtsk FROMTS.
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; try (by done); [  by rewrite JOBtsk  by apply ltnW].
by red; intro EQ; subst j_other; rewrite ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge.
apply leq_ltn_trans with (n := t); first by done.
@@ 341,7 +353,8 @@ Module ResponseTimeAnalysisFP.
With this lemma, we can conclude that during job j's scheduling
window there cannot be multiple pending jobs of higherpriority tasks.*)
Lemma bertogna_fp_previous_interfering_jobs_complete_by_their_period:
 forall (j0: JobIn arr_seq),
+ forall j0,
+ arrives_in arr_seq j0 >
hp_task_in (alpha tsk) (job_task j0) >
completed job_cost sched j0
(job_arrival j0 + task_period (job_task j0)).
@@ 353,7 +366,7 @@ Module ResponseTimeAnalysisFP.
H_interfering_tasks_miss_no_deadlines into NOMISS',
H_previous_jobs_of_tsk_completed into BEFOREok,
H_response_time_of_interfering_tasks_is_known into RESP.
 intros j0 INTERF.
+ intros j0 ARR0 INTERF.
exploit (HAS (job_task j0));
[by rewrite FROMTS  by done  move => [R0 INbounds]].
apply completion_monotonic with (t := job_arrival j0 + R0); first by done.
@@ 379,7 +392,7 @@ Module ResponseTimeAnalysisFP.
rename H_all_jobs_from_taskset into FROMTS,
H_valid_task_parameters into PARAMS,
H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
 H_work_conserving into WORK,
+ H_work_conserving into WORK, H_jobs_come_from_arrival_sequence into SEQ,
H_previous_jobs_of_tsk_completed into BEFOREok,
H_response_time_no_larger_than_deadline into NOMISS,
H_constrained_deadlines into RESTR,
@@ 387,9 +400,9 @@ Module ResponseTimeAnalysisFP.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost sched j t) eqn:BACK; last first.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last first.
{
rewrite (eq_bigr (fun i => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
@@ 406,7 +419,7 @@ Module ResponseTimeAnalysisFP.
destruct (cpu \in alpha (job_task j)) eqn:ALPHA; rewrite ?JOBtsk ALPHA;
last by rewrite big_filter (eq_bigr (fun x => 0));
[by simpl_sum_const  by ins].
 move: (WORK j t BACK cpu ALPHA) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ move: (WORK j t H_j_arrives BACK cpu ALPHA) => [j_other /eqP SCHED]; unfold scheduled_on in *.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
rewrite (eq_bigr (fun i => 0));
@@ 414,6 +427,8 @@ Module ResponseTimeAnalysisFP.
rewrite big_const_seq iter_addn mul0n 2!addn0; apply/eqP; rewrite eqb1.
by unfold task_scheduled_on; rewrite SCHED.
}
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (SEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite mem_filter; apply/andP; split; last by apply FROMTS.
unfold higher_priority_task_in, affinity_intersects.
apply/andP; split; last first.
@@ 423,7 +438,7 @@ Module ResponseTimeAnalysisFP.
}
apply/andP; split; last first.
{
 apply DIFFTASK with (t := t); [by auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu; apply/eqP.
}
by rewrite JOBtsk; apply FP with (cpu := cpu) (t := t); try (by apply/eqP).
@@ 439,7 +454,7 @@ Module ResponseTimeAnalysisFP.
Proof.
have DIFFTASK := bertogna_fp_interference_by_different_tasks.
rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
+ H_valid_task_parameters into PARAMS, H_jobs_come_from_arrival_sequence into SEQ,
H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
H_work_conserving into WORK,
H_response_time_no_larger_than_deadline into NOMISS,
@@ 449,9 +464,9 @@ Module ResponseTimeAnalysisFP.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond /=.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond /=.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost sched j t) eqn:BACK; last first.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last first.
{
rewrite (eq_bigr (fun i => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
@@ 467,11 +482,14 @@ Module ResponseTimeAnalysisFP.
unfold can_execute_on in *.
destruct (cpu \in alpha' (job_task j)) eqn:ALPHA'; rewrite ?JOBtsk ALPHA';
last by done.
 move: (SUB (job_task j) (FROMTS j) cpu ALPHA') => SUBj.
 move: (WORK j t BACK cpu SUBj) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ feed (SUB (job_task j)); first by apply FROMTS.
+ specialize (SUB cpu ALPHA').
+ move: (WORK j t H_j_arrives BACK cpu SUB) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (SEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite (bigD1_seq (job_task j_other)) /=; last by apply filter_uniq; destruct ts.
{
 by rewrite {1}/task_scheduled_on SUBj SCHED eq_refl andTb.
+ by rewrite {1}/task_scheduled_on SUB SCHED eq_refl andTb.
}
{
rewrite mem_filter; apply/andP; split; last by apply FROMTS.
@@ 482,7 +500,7 @@ Module ResponseTimeAnalysisFP.
}
apply/andP; split; last first.
{
 apply DIFFTASK with (t := t); [by auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu; apply/eqP.
}
by rewrite JOBtsk; apply FP with (cpu := cpu) (t := t); try (by apply/eqP).
@@ 501,21 +519,21 @@ Module ResponseTimeAnalysisFP.
Lemma bertogna_fp_alpha'_is_full:
forall t,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ backlogged job_arrival job_cost sched j t >
count (scheduled_on_alpha_tsk t) (hp_tasks_in alpha') >= #alpha' tsk.
Proof.
have DIFFTASK := bertogna_fp_interference_by_different_tasks.
have COMP := bertogna_fp_previous_interfering_jobs_complete_by_their_period.
rename H_work_conserving into WORK, H_respects_affinity into APA,
H_affinity_subset into SUB, H_job_of_tsk into JOBtsk,
 H_all_jobs_from_taskset into FROMTS,
+ H_all_jobs_from_taskset into FROMTS, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_valid_task_parameters into PARAMS,
H_previous_jobs_of_tsk_completed into BEFOREok,
H_sequential_jobs into SEQ, H_constrained_deadlines into CONSTR,
H_respects_FP_policy into FP.
move => t /andP [GEt LTt] BACK.
move: WORK => WORK.
 specialize (WORK j t BACK).
+ specialize (WORK j t H_j_arrives BACK).
rewrite size_filter.
apply leq_trans with (n := size (alpha' tsk));
first by apply card_size.
@@ 529,7 +547,7 @@ Module ResponseTimeAnalysisFP.
by move: WORK => [j_other /eqP SCHED]; rewrite SCHED.
}
{
 apply leq_trans with (n := size (map (fun j: JobIn arr_seq => job_task j) (pmap (fun cpu => sched cpu t) (enum (alpha' tsk)))));
+ apply leq_trans with (n := size (map (fun j => job_task j) (pmap (fun cpu => sched cpu t) (enum (alpha' tsk)))));
first by rewrite size_map.
apply uniq_leq_size.
{
@@ 537,7 +555,7 @@ Module ResponseTimeAnalysisFP.
{
apply pmap_inj_in_uniq; last by apply enum_uniq.
intros cpu1 cpu2 IN1 IN2 SCHED2.
 destruct (sched cpu1 t) eqn:SCHED1; symmetry in SCHED2;
+ destruct (sched cpu1 t) as [j0 ] eqn:SCHED1; symmetry in SCHED2;
first by apply SEQ with (j := j0) (t := t).
rewrite 2!mem_enum in IN1 IN2.
exploit (WORK cpu1); first by apply SUB; rewrite JOBtsk.
@@ 547,20 +565,24 @@ Module ResponseTimeAnalysisFP.
intros j1 j2 SCHED1 SCHED2 SAMEtsk.
rewrite 2!mem_pmap in SCHED1 SCHED2.
move: SCHED1 SCHED2 => /mapP [cpu1 IN1 SCHED1] /mapP [cpu2 IN2 SCHED2].
 assert (PENDING1: pending job_cost sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu1; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu2; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu1; rewrite /scheduled_on SCHED1.
}
 assert (SCHED2': pending job_cost sched j2 t).
+ assert (SCHED2': pending job_arrival job_cost sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu2; rewrite /scheduled_on SCHED2.
}
apply platform_fp_no_multiple_jobs_of_interfering_tasks with
 (task_period0 := task_period) (tsk0 := tsk) (alpha0 := alpha)
 (higher_eq_priority0 := higher_eq_priority) (t0 := t)
+ (arr_seq0 := arr_seq) (task_period0 := task_period) (tsk0 := tsk) (alpha0 := alpha)
+ (job_arrival0 := job_arrival) (higher_eq_priority0 := higher_eq_priority) (t0 := t)
(job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched);
rewrite ?JOBtsk ?SAMEtsk //.
{
@@ 575,12 +597,12 @@ Module ResponseTimeAnalysisFP.
}
apply/andP; split.
{
 rewrite JOBtsk; apply FP with (cpu := cpu2) (t := t);
 [by done  by apply/eqP; rewrite SCHED2 ].
+ rewrite JOBtsk; apply FP with (cpu := cpu2) (t := t); try (by done);
+ first by apply/eqP; rewrite SCHED2.
by apply SUB; rewrite ?FROMTS // mem_enum JOBtsk.
}
{
 apply DIFFTASK with (t := t); [auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu2; apply/eqP; rewrite SCHED2.
}
}
@@ 596,6 +618,8 @@ Module ResponseTimeAnalysisFP.
apply/existsP; exists cpu; apply/andP; split; first by apply SUB.
by rewrite /task_scheduled_on SCHED' EQtsk'.
}
+ have ARR': arrives_in arr_seq j'.
+ by apply (FROMSEQ j' t); apply/existsP; exists cpu; apply/eqP.
rewrite EQtsk' mem_filter; apply/andP; split; last by apply FROMTS.
apply/andP; split; last first.
{
@@ 605,7 +629,7 @@ Module ResponseTimeAnalysisFP.
apply/andP; split.
{
by rewrite JOBtsk; apply FP with (cpu := cpu) (t := t);
 [ by apply/eqP; rewrite SCHED'  apply SUB; rewrite JOBtsk].
+ try (by done); [by apply/eqP; rewrite SCHED'  apply SUB; rewrite JOBtsk].
}
{
apply/eqP; intro SAMEtsk.
@@ 615,14 +639,14 @@ Module ResponseTimeAnalysisFP.
by apply/existsP; exists cpu; rewrite /scheduled_on SCHED'.
}
move: (SCHEDULED') => PENDING'.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING';
 try by done.
+ apply scheduled_implies_pending with (job_cost0 := job_cost)
+ (job_arrival0 := job_arrival) in PENDING'; try by done.
assert (BUG: j' = j).
{
apply platform_fp_no_multiple_jobs_of_tsk with (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_task0 := job_task)
 (sched0 := sched) (tsk0 := tsk) (t0 := t);
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (job_task0 := job_task)
+ (arr_seq0 := arr_seq) (sched0 := sched) (tsk0 := tsk) (t0 := t);
try (by done);
[by apply PARAMS  by apply/andP; split  ].
{
@@ 631,7 +655,7 @@ Module ResponseTimeAnalysisFP.
last by apply CONSTR; rewrite JOBtsk FROMTS.
}
{
 intros j0 JOB0 LT0.
+ intros j0 JOB0 ARR0 LT0.
apply completion_monotonic with (t0 := job_arrival j0 + R);
[by done   by apply BEFOREok].
by rewrite leq_add2l; apply leq_trans with (n := task_deadline tsk);
@@ 662,7 +686,7 @@ Module ResponseTimeAnalysisFP.
have INV := bertogna_fp_alpha'_is_full.
have DIFFTASK := bertogna_fp_interference_by_different_tasks.
have COMP := bertogna_fp_previous_interfering_jobs_complete_by_their_period.
 rename H_all_jobs_from_taskset into FROMTS,
+ rename H_all_jobs_from_taskset into FROMTS, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_valid_task_parameters into PARAMS,
H_job_of_tsk into JOBtsk, H_affinity_subset into SUB,
H_sporadic_tasks into SPO, H_respects_affinity into APA,
@@ 673,12 +697,12 @@ Module ResponseTimeAnalysisFP.
rewrite has_count in HAS.
set some_interference_A := fun t =>
 has (fun tsk_k => backlogged job_cost sched j t &&
+ has (fun tsk_k => backlogged job_arrival job_cost sched j t &&
(x tsk_k >= delta) &&
scheduled_on_alpha_tsk t tsk_k)
(hp_tasks_in alpha').
set total_interference_B := fun t =>
 backlogged job_cost sched j t *
+ backlogged job_arrival job_cost sched j t *
count (fun tsk_k => (x tsk_k < delta) &&
scheduled_on_alpha_tsk t tsk_k) (hp_tasks_in alpha').
@@ 690,7 +714,7 @@ Module ResponseTimeAnalysisFP.
apply leq_trans with (n := x tsk_a); first by apply LEa.
unfold x, task_interference, some_interference_A.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
last by rewrite (eq_bigr (fun x => 0)); [by simpl_sum_const  by ins].
destruct ([exists cpu, can_execute_on alpha (job_task j) cpu &&
task_scheduled_on job_task sched tsk_a cpu t]) eqn:SCHED;
@@ 720,20 +744,24 @@ Module ResponseTimeAnalysisFP.
subst tsk_a; symmetry in JOB'.
assert (BUG: j1 = j2).
{
 assert (PENDING1: pending job_cost sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu'; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu; rewrite /scheduled_on SCHED1.
}
 assert (SCHED2': pending job_cost sched j2 t).
+ assert (SCHED2': pending job_arrival job_cost sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu'; rewrite /scheduled_on SCHED2.
}
apply platform_fp_no_multiple_jobs_of_interfering_tasks with
 (task_period0 := task_period) (tsk0 := tsk) (alpha0 := alpha)
 (higher_eq_priority0 := higher_eq_priority) (t0 := t)
 (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched);
+ (arr_seq0 := arr_seq) (task_period0 := task_period) (tsk0 := tsk) (alpha0 := alpha)
+ (job_arrival0 := job_arrival) (higher_eq_priority0 := higher_eq_priority) (t0 := t)
+ (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched); try (by done);
rewrite ?JOBtsk ?SAMEtsk //.
{
by intros j0 tsk0 TSK0 LE; subst tsk0; apply COMP.
@@ 748,10 +776,10 @@ Module ResponseTimeAnalysisFP.
apply/andP; split.
{
by rewrite JOBtsk; apply FP with (cpu := cpu) (t := t);
 [by done  by apply/eqP  by done].
+ try (by done); apply/eqP.
}
{
 apply DIFFTASK with (t := t); [auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu; apply/eqP.
}
}
@@ 765,7 +793,7 @@ Module ResponseTimeAnalysisFP.
rewrite big_distrl /=.
apply leq_sum_nat; move => t LEt _.
unfold some_interference_A, total_interference_B.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
[rewrite mul1n /=  by rewrite has_pred0 //].
destruct (has (fun tsk_k : sporadic_task => (delta <= x tsk_k) &&
@@ 793,7 +821,7 @@ Module ResponseTimeAnalysisFP.
{
unfold x at 2, total_interference_B.
rewrite exchange_big /=; apply leq_sum; intros t _.
 destruct (backlogged job_cost sched j t) eqn:BACK; last by ins.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last by ins.
rewrite mul1n sum1_count.
rewrite big_mkcond [\sum_(i < hp_tasks_in alpha'  _ < _) _]big_mkcond /=.
apply leq_sum_seq; move => tsk_k IN _.
@@ 984,7 +1012,7 @@ Module ResponseTimeAnalysisFP.
H_response_time_recurrence_holds into REC,
H_response_time_of_interfering_tasks_is_known into RESP,
H_response_time_no_larger_than_deadline into LEdl.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
remember (job_arrival j + R) as ctime.
@@ 993,10 +1021,11 @@ Module ResponseTimeAnalysisFP.
generalize dependent j.
induction ctime as [ctime IH] using strong_ind.
 intros j JOBtsk EQc; subst ctime.
+ intros j ARRj JOBtsk EQc; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq),
+ assert (BEFOREok: forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
service sched j0 (job_arrival j0 + R) == job_cost j0).
@@ 1014,7 +1043,7 @@ Module ResponseTimeAnalysisFP.
apply negbT in NOTCOMP; exfalso.
(* We derive a contradiction using the previous lemmas. *)
 specialize (EX j JOBtsk NOTCOMP BEFOREok).
+ specialize (EX j ARRj JOBtsk NOTCOMP BEFOREok).
destruct EX as [tsk_k [R_k [HPk LTmin]]].
unfold minn at 1 in LTmin.
specialize (WORKLOAD j tsk_k R_k HPk).
diff git a/analysis/apa/interference_bound_edf.v b/analysis/apa/interference_bound_edf.v
index 3ce36ae..3d94edc 100644
 a/analysis/apa/interference_bound_edf.v
+++ b/analysis/apa/interference_bound_edf.v
@@ 123,30 +123,32 @@ Module InterferenceBoundEDF.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs do not execute before their arrival times nor longer
than their execution costs. *)
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival 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. *)
@@ 160,28 +162,31 @@ Module InterferenceBoundEDF.
and tasks have valid parameters and constrained deadlines. *)
Variable ts: taskset_of sporadic_task.
Hypothesis all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
Hypothesis H_constrained_deadlines:
forall tsk, tsk \in ts > task_deadline tsk <= task_period tsk.
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Assume that the scheduler is a workconserving EDF scheduler. *)
 Hypothesis H_work_conserving: apa_work_conserving job_cost job_task sched alpha.
+ Hypothesis H_work_conserving: apa_work_conserving job_arrival job_cost job_task arr_seq
+ sched alpha.
Hypothesis H_edf_weak_APA_scheduler:
 respects_JLFP_policy_under_weak_APA job_cost job_task sched alpha (EDF job_deadline).
+ respects_JLFP_policy_under_weak_APA job_arrival job_cost job_task arr_seq
+ sched alpha (EDF job_arrival job_deadline).
(* Let tsk_i be the task to be analyzed, ...*)
Variable tsk_i: sporadic_task.
Hypothesis H_tsk_i_in_task_set: tsk_i \in ts.
(* ... and j_i one of its jobs. *)
 Variable j_i: JobIn arr_seq.
+ Variable j_i: Job.
+ Hypothesis H_j_i_arrives: arrives_in arr_seq j_i.
Hypothesis H_job_of_tsk_i: job_task j_i = tsk_i.
(* Let tsk_k denote any interfering task, ... *)
@@ 198,7 +203,8 @@ Module InterferenceBoundEDF.
(* Assume that the jobs of tsk_k satisfy the responsetime bound before the end of the interval *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_k: JobIn arr_seq),
+ forall j_k,
+ arrives_in arr_seq j_k >
job_task j_k = tsk_k >
job_arrival j_k + R_k < job_arrival j_i + delta >
completed job_cost sched j_k (job_arrival j_k + R_k).
@@ 209,7 +215,7 @@ Module InterferenceBoundEDF.
(* Let's call x the task interference incurred by job j due to tsk_k. *)
Let x :=
 task_interference job_cost job_task sched alpha j_i
+ task_interference job_arrival job_cost job_task sched alpha j_i
tsk_k (job_arrival j_i) (job_arrival j_i + delta).
(* Also, recall the EDFspecific interference bound for EDF. *)
@@ 226,17 +232,16 @@ Module InterferenceBoundEDF.
Let n_k := div_floor D_i p_k.
(* Let's give a simpler name to job interference. *)
 Let interference_caused_by := job_interference job_cost job_task sched alpha j_i.
+ Let interference_caused_by := job_interference job_arrival job_cost job_task sched alpha j_i.
(* Identify the subset of jobs that actually cause interference *)
Let interfering_jobs :=
 filter (fun (x: JobIn arr_seq) =>
 (job_task x == tsk_k) && (interference_caused_by x t1 t2 != 0))
+ filter (fun j' => (job_task j' == tsk_k) && (interference_caused_by j' t1 t2 != 0))
(jobs_scheduled_between sched t1 t2).
(* Now, consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
 Let sorted_jobs := (sort earlier_arrival interfering_jobs).
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
+ Let sorted_jobs := sort earlier_arrival interfering_jobs.
(* Now we proceed with the proof. The first step consists in simplifying the sum corresponding to the workload. *)
Section SimplifyJobSequence.
@@ 284,13 +289,18 @@ Module InterferenceBoundEDF.
Lemma interference_bound_edf_all_jobs_from_tsk_k :
forall j,
j \in sorted_jobs >
+ arrives_in arr_seq j /\
job_task j = tsk_k /\
interference_caused_by j t1 t2 != 0 /\
j \in jobs_scheduled_between sched t1 t2.
Proof.
intros j LT.
rewrite interference_bound_edf_job_in_same_sequence mem_filter in LT.
 by move: LT => /andP [/andP [/eqP JOBi SERVi] INi]; repeat split.
+ move: LT => /andP [/andP [/eqP JOBi SERVi] INi]; repeat split; try (by done).
+ unfold jobs_scheduled_between in *; rewrite mem_undup in INi.
+ apply mem_bigcat_nat_exists in INi; des.
+ rewrite mem_scheduled_jobs_eq_scheduled in INi.
+ by apply (H_jobs_come_from_arrival_sequence j i).
Qed.
(* ...and consecutive jobs are ordered by arrival. *)
@@ 312,8 +322,11 @@ Module InterferenceBoundEDF.
interference_caused_by j t1 t2 <= task_cost tsk_k.
Proof.
rename H_valid_job_parameters into PARAMS.
 intros j; rewrite mem_filter; move => /andP [/andP [/eqP JOBj _] _].
 specialize (PARAMS j); des.
+ intros j IN.
+ feed (interference_bound_edf_all_jobs_from_tsk_k j);
+ first by rewrite interference_bound_edf_job_in_same_sequence.
+ move => [ARRj [TSKj [_ SCHEDj]]].
+ specialize (PARAMS j ARRj); des.
apply leq_trans with (n := service_during sched j t1 t2);
first by apply job_interference_le_service.
by apply cumulative_service_le_task_cost with (job_task0 := job_task)
@@ 359,7 +372,7 @@ Module InterferenceBoundEDF.
Qed.
(* Let j_fst be the first job, and a_fst its arrival time. *)
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let a_fst := job_arrival j_fst.
@@ 368,6 +381,7 @@ Module InterferenceBoundEDF.
(* The first job is an interfering job of task tsk_k. *)
Lemma interference_bound_edf_j_fst_is_job_of_tsk_k :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk_k /\
interference_caused_by j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 383,8 +397,8 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask _].
 by specialize (PARAMS j_fst); des; rewrite PARAMS1 FSTtask.
+ destruct FST as [FSTarr [FSTtask _]].
+ by specialize (PARAMS j_fst FSTarr); des; rewrite PARAMS1 FSTtask.
Qed.
(* The deadline of j_i is the deadline of tsk_i. *)
@@ 394,7 +408,7 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS,
H_job_of_tsk_i into JOBtsk.
 by specialize (PARAMS j_i); des; rewrite PARAMS1 JOBtsk.
+ by specialize (PARAMS j_i H_j_i_arrives); des; rewrite PARAMS1 JOBtsk.
Qed.
(* If j_fst completes by its responsetime bound, then t1 <= a_fst + R_k,
@@ 406,13 +420,13 @@ Module InterferenceBoundEDF.
intros RBOUND.
rewrite leqNgt; apply/negP; unfold not; intro BUG.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ FSTserv _]].
+ destruct FST as [FSTarr [_ [ FSTserv _]]].
move: FSTserv => /negP FSTserv; apply FSTserv.
rewrite leqn0; apply leq_trans with (n := service_during sched j_fst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k);
 try (by done); apply ltnW.
+ by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k)
+ (job_arrival0 := job_arrival); try (by done); apply ltnW.
Qed.
End FactsAboutFirstJob.
@@ 451,21 +465,22 @@ Module InterferenceBoundEDF.
completed job_cost sched j_fst (a_fst + R_k).
Lemma interference_bound_edf_holds_for_single_job_that_completes_on_time :
 job_interference job_cost job_task sched alpha j_i j_fst t1 t2 <= D_i  (D_k  R_k).
+ job_interference job_arrival job_cost job_task sched alpha j_i j_fst t1 t2
+ <= D_i  (D_k  R_k).
Proof.
rename H_j_fst_completed_by_rt_bound into RBOUND.
have AFTERt1 :=
interference_bound_edf_j_fst_completion_implies_rt_bound_inside_interval RBOUND.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ LEdl _]].
+ destruct FST as [FSTarr [_ [ LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
destruct (D_k  R_k <= D_i) eqn:LEdk; last first.
{
apply negbT in LEdk; rewrite ltnNge in LEdk.
apply leq_trans with (n := 0); last by done.
 apply leq_trans with (n := job_interference job_cost job_task sched alpha j_i j_fst
 (a_fst + R_k) t2).
+ apply leq_trans with (n := job_interference job_arrival job_cost job_task sched
+ alpha j_i j_fst (a_fst + R_k) t2).
{
apply extend_sum; last by apply leqnn.
rewrite (leq_add2r D_i).
@@ 478,8 +493,8 @@ Module InterferenceBoundEDF.
apply leq_trans with (n := service_during sched j_fst (a_fst + R_k) t2);
first by apply job_interference_le_service.
unfold service_during; rewrite leqn0; apply/eqP.
 by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k);
 try (by done); apply leqnn.
+ by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k)
+ (job_arrival0 := job_arrival); try (by done); apply leqnn.
}
{
rewrite (leq_add2r (D_k  R_k)) subh1 // addnBA // subnn addn0.
@@ 489,7 +504,7 @@ Module InterferenceBoundEDF.
rewrite addnC subnBA; last by apply leq_addr.
by rewrite addnC addnBA // subnn addn0.
}
 apply leq_trans with (n := job_interference job_cost job_task sched alpha j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost job_task sched alpha j_i j_fst t1
(a_fst + D_k) + (D_k  R_k)).
{
rewrite leq_add2r.
@@ 504,14 +519,14 @@ Module InterferenceBoundEDF.
apply negbT in LEt2; rewrite ltnNge in LEt2.
rewrite > big_cat_nat with (n := a_fst + R_k);
[simpl  by apply AFTERt1  by apply ltnW].
 apply leq_trans with (n := job_interference job_cost job_task sched alpha j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost job_task sched alpha j_i j_fst t1
(a_fst + R_k) + service_during sched j_fst (a_fst + R_k) t2).
{
rewrite leq_add2l.
by apply job_interference_le_service.
}
unfold service_during.
 rewrite (cumulative_service_after_job_rt_zero job_cost _ _ _ R_k) //.
+ rewrite (cumulative_service_after_job_rt_zero job_arrival job_cost _ _ _ R_k) //.
rewrite addn0; apply extend_sum; first by apply leqnn.
by rewrite leq_add2l; apply H_R_k_le_deadline.
}
@@ 520,11 +535,11 @@ Module InterferenceBoundEDF.
unfold job_interference.
rewrite > big_cat_nat with (n := a_fst + R_k);
[simpl by apply AFTERt1  by rewrite leq_add2l; apply H_R_k_le_deadline].
 apply leq_trans with (n := job_interference job_cost job_task sched alpha j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost job_task sched alpha j_i j_fst t1
(a_fst+R_k) + service_during sched j_fst (a_fst+R_k) (a_fst+D_k) + (D_kR_k));
first by rewrite leq_add2r leq_add2l job_interference_le_service.
unfold service_during.
 rewrite (cumulative_service_after_job_rt_zero job_cost _ _ _ R_k) // addn0.
+ rewrite (cumulative_service_after_job_rt_zero job_arrival job_cost _ _ _ R_k) // addn0.
apply leq_trans with (n := (\sum_(t1 <= t < a_fst + R_k) 1) +
\sum_(a_fst + R_k <= t < a_fst + D_k) 1).
{
@@ 556,7 +571,7 @@ Module InterferenceBoundEDF.
job_arrival j_fst + R_k >= job_arrival j_i + delta.
Proof.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask _].
+ destruct FST as [FSTarr [FSTtask _]].
rewrite leqNgt; apply/negP; intro LT.
move: H_j_fst_not_complete_by_rt_bound => /negP BUG; apply BUG.
by apply H_all_previous_jobs_completed_on_time.
@@ 578,7 +593,7 @@ Module InterferenceBoundEDF.
}
apply/eqP; rewrite [_ _ _ _ == 0]negbK; apply/negP; red; intro BUG.
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in BUG; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in BUG; try (by done).
rewrite interference_bound_edf_j_fst_deadline
interference_bound_edf_j_i_deadline in BUG.
by apply (leq_trans LTdk) in BUG; rewrite ltnn in BUG.
@@ 592,10 +607,10 @@ Module InterferenceBoundEDF.
Proof.
intro LEdk.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask [LEdl _]].
+ destruct FST as [FSTarr [FSTtask [LEdl _]]].
have LTr := interference_bound_edf_response_time_bound_of_j_fst_after_interval.
apply subh3; last by apply LEdk.
 apply leq_trans with (n := job_interference job_cost job_task sched alpha j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost job_task sched alpha j_i j_fst t1
(job_arrival j_fst + R_k) + (D_k  R_k));
first by rewrite leq_add2r; apply extend_sum; [by apply leqnn].
apply leq_trans with (n := \sum_(t1 <= t < a_fst + R_k) 1 +
@@ 622,7 +637,7 @@ Module InterferenceBoundEDF.
unfold D_i, D_k, t1, a_fst; rewrite interference_bound_edf_j_fst_deadline
interference_bound_edf_j_i_deadline.
by apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl.
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl.
Qed.
End ResponseTimeOfSingleJobNotBounded.
@@ 678,7 +693,8 @@ Module InterferenceBoundEDF.
Section FactsAboutFirstAndLastJobs.
(* The last job is an interfering job of task tsk_k. *)
 Lemma interference_bound_edf_j_lst_is_job_of_tsk_k :
+ Lemma interference_bound_edf_j_lst_is_job_of_tsk_k:
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk_k /\
interference_caused_by j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 694,8 +710,8 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [LSTtask _].
 by specialize (PARAMS j_lst); des; rewrite PARAMS1 LSTtask.
+ destruct LST as [LSTarr [LSTtask _]].
+ by specialize (PARAMS j_lst LSTarr); des; rewrite PARAMS1 LSTtask.
Qed.
(* The first job arrives before the last job. *)
@@ 718,12 +734,12 @@ Module InterferenceBoundEDF.
apply mem_nth; instantiate (1 := num_mid_jobs.+1).
by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
}
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
+ instantiate (1 := elem); move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
apply LSTserv; apply/eqP; rewrite leqn0.
apply leq_trans with (n := service_during sched j_lst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP; unfold service_during.
 by apply cumulative_service_before_job_arrival_zero.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
Qed.
(* Since there are multiple jobs, j_fst is far enough from the end of
@@ 738,7 +754,7 @@ Module InterferenceBoundEDF.
{
by apply mem_nth; instantiate (1 := 1); rewrite H_at_least_two_jobs.
}
 instantiate (1 := elem); move => [SNDtsk [/eqP SNDserv _]].
+ instantiate (1 := elem); move => [SNDarr [SNDtsk [/eqP SNDserv _]]].
apply H_all_previous_jobs_completed_on_time; try (by done).
apply leq_ltn_trans with (n := job_arrival j_snd); last first.
{
@@ 747,7 +763,7 @@ Module InterferenceBoundEDF.
sched j_snd t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 by apply cumulative_service_before_job_arrival_zero.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
}
apply leq_trans with (n := a_fst + p_k).
{
@@ 757,8 +773,8 @@ Module InterferenceBoundEDF.
(* Since jobs are sporadic, we know that the first job arrives
at least p_k units before the second. *)
 unfold p_k; rewrite FST.
 apply H_sporadic_tasks; [ by rewrite SNDtsk  ]; last first.
+ unfold p_k; rewrite FST0.
+ apply H_sporadic_tasks; try (by done); [ by rewrite SNDtsk  ]; last first.
{
apply interference_bound_edf_jobs_ordered_by_arrival.
by rewrite H_at_least_two_jobs.
@@ 794,14 +810,13 @@ Module InterferenceBoundEDF.
assert (ARRle: job_arrival cur <= job_arrival next).
by unfold cur, next; apply interference_bound_edf_jobs_ordered_by_arrival.
 (* Show that both cur and next are in the arrival sequence *)
 assert (INnth: cur \in interfering_jobs /\ next \in interfering_jobs).
 {
 rewrite 2!interference_bound_edf_job_in_same_sequence; split.
 by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs; ins.
 by apply mem_nth; destruct sorted_jobs; ins.
 }
 rewrite 2?mem_filter in INnth; des.
+ feed (interference_bound_edf_all_jobs_from_tsk_k cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (interference_bound_edf_all_jobs_from_tsk_k next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
(* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
@@ 809,15 +824,15 @@ Module InterferenceBoundEDF.
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /interfering_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk.
}
 by rewrite subh3 // addnC /p_k INnth.
+ by rewrite subh3 // addnC /p_k CURtsk.
Qed.
(* Using the lemma above, we prove that the ratio n_k is at least the number of
@@ 843,9 +858,9 @@ Module InterferenceBoundEDF.
by rewrite leq_add2l; apply H_R_k_le_deadline.
}
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LEdl _]].
+ destruct LST as [LSTarr [_ [ LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
unfold D_i, D_k in DIST; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline in LEdl.
by rewrite ltnNge LEdl in DIST.
@@ 926,11 +941,11 @@ Module InterferenceBoundEDF.
apply leq_trans with (n := t1 + D_i);
last by rewrite addnA [D_i + _]addnC addnA leq_add2r addnC AFTERt1.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LSTserv _]].
+ destruct LST as [LSTarr [_ [ LSTserv _]]].
unfold D_i, D_k, a_lst, t1; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline.
by apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LSTserv.
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LSTserv.
Qed.
(* To conclude that the interference bound holds, it suffices to show that
@@ 956,7 +971,7 @@ Module InterferenceBoundEDF.
}
destruct (leqP t2 (a_fst + R_k)) as [LEt2  GTt2].
{
 apply leq_trans with (n := job_interference job_cost job_task sched alpha j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost job_task sched alpha j_i j_fst t1
(a_fst + R_k));
first by apply extend_sum; rewrite ?leqnn.
simpl_sum_const; rewrite {1}[_ + R_k](addKn t1) addnBA //.
@@ 974,8 +989,8 @@ Module InterferenceBoundEDF.
apply leq_trans with (n := service_during sched j_fst (a_fst + R_k) t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k);
 [ by done   by apply leqnn].
+ apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k)
+ (job_arrival0 := job_arrival); [ by done   by apply leqnn].
by apply interference_bound_edf_j_fst_completed_on_time.
}
Qed.
@@ 1048,11 +1063,11 @@ Module InterferenceBoundEDF.
apply (leq_trans interference_bound_edf_bounding_interference_with_interval_lengths).
rewrite interference_bound_edf_simpl_by_concatenation_of_intervals leq_subLR.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LSTserv _]].
+ destruct LST as [LSTarr [_ [ LSTserv _]]].
unfold D_i, D_k, a_lst, t1; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline.
by apply interference_under_edf_implies_shorter_deadlines
 with (job_deadline0 := job_deadline) in LSTserv.
+ with (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LSTserv.
Qed.
End InterferenceOfFirstJob.
@@ 1106,7 +1121,7 @@ Module InterferenceBoundEDF.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
+ assert (EX: exists elem: Job, True).
destruct sorted_jobs as [ j]; [by rewrite ltn0 in NUM  by exists j].
destruct EX as [elem _].
@@ 1118,7 +1133,7 @@ Module InterferenceBoundEDF.
first by rewrite big_geq.
(* Then, we show the same for a single job, or for multiple jobs. *)
 rewrite SIZE; destruct n as [ num_mid_jobs].
+ destruct n as [ num_mid_jobs].
{
rewrite big_nat_recr // big_geq //.
rewrite [nth]lock /= lock add0n.
diff git a/analysis/apa/workload_bound.v b/analysis/apa/workload_bound.v
index 4a718ab..c32ea14 100644
 a/analysis/apa/workload_bound.v
+++ b/analysis/apa/workload_bound.v
@@ 122,6 +122,7 @@ Module WorkloadBound.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
Variable job_deadline: Job > time.
@@ 130,22 +131,23 @@ Module WorkloadBound.
(* Assume that all jobs have valid parameters *)
Hypothesis H_jobs_have_valid_parameters :
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider any schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* Assumption: jobs only execute if they arrived.
This is used to eliminate jobs that arrive after end of the interval t1 + delta. *)
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
(* Assumption: jobs do not execute after they completed.
This is used to eliminate jobs that complete before the start of the interval t1. *)
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Assumption: Jobs are sequential.
This is required to use interval lengths as a measure of service. *)
@@ 154,13 +156,12 @@ Module WorkloadBound.
(* Assumption: sporadic task model.
This is necessary to conclude that consecutive jobs ordered by arrival times
are separated by at least 'period' times units. *)
 Hypothesis H_sporadic_tasks: sporadic_task_model task_period arr_seq job_task.
+ Hypothesis H_sporadic_tasks: sporadic_task_model task_period job_arrival job_task arr_seq.
(* Before starting the proof, let's give simpler names to the definitions. *)
Let job_has_completed_by := completed job_cost sched.
 Let workload_of (tsk: sporadic_task) (t1 t2: time) :=
 workload job_task sched tsk t1 t2.
+ Let workload_of (tsk: sporadic_task) (t1 t2: time) := workload job_task sched tsk t1 t2.
(* Now we define the theorem. Let tsk be any task in the taskset. *)
Variable tsk: sporadic_task.
@@ 190,10 +191,11 @@ Module WorkloadBound.
Variable R_tsk: time.
Hypothesis H_response_time_bound :
 forall (j: JobIn arr_seq),
 job_task j = tsk >
 job_arrival j + R_tsk < t1 + delta >
 job_has_completed_by j (job_arrival j + R_tsk).
+ forall j,
+ arrives_in arr_seq j >
+ job_task j = tsk >
+ job_arrival j + R_tsk < t1 + delta >
+ job_has_completed_by j (job_arrival j + R_tsk).
(* ... such that R_tsk >= task_cost tsk and R_tsk <= task_deadline tsk. *)
Hypothesis H_response_time_ge_cost: R_tsk >= task_cost tsk.
@@ 215,8 +217,8 @@ Module WorkloadBound.
jobs_of_task_scheduled_between job_task sched tsk t1 t2.
(* Now, let's consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
 Let sorted_jobs := (sort earlier_arrival scheduled_jobs).
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
+ Let sorted_jobs := sort earlier_arrival scheduled_jobs.
(* The first step consists in simplifying the sum corresponding
to the workload. *)
@@ 246,13 +248,19 @@ Module WorkloadBound.
Lemma workload_bound_all_jobs_from_tsk :
forall j_i,
j_i \in sorted_jobs >
+ arrives_in arr_seq j_i /\
job_task j_i = tsk /\
service_during sched j_i t1 t2 != 0 /\
j_i \in jobs_scheduled_between sched t1 t2.
Proof.
+ rename H_jobs_come_from_arrival_sequence into FROMarr.
intros j_i LTi.
rewrite workload_bound_job_in_same_sequence mem_filter in LTi; des.
 repeat split; [by done   by done].
+ have IN := LTi0.
+ unfold jobs_scheduled_between in *; rewrite mem_undup in IN.
+ apply mem_bigcat_nat_exists in IN; des.
+ rewrite mem_scheduled_jobs_eq_scheduled in IN.
+ repeat split; try (by done); first by apply (FROMarr j_i i).
unfold jobs_scheduled_between in *; rewrite mem_undup in LTi0.
apply mem_bigcat_nat_exists in LTi0; des.
rewrite mem_scheduled_jobs_eq_scheduled in LTi0.
@@ 294,7 +302,7 @@ Module WorkloadBound.
apply leq_sum; intros j_i; move/andP => [INi _].
apply workload_bound_all_jobs_from_tsk in INi; des.
eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute  by apply INi ].
+ [by apply H_completed_jobs_dont_execute  by apply INi0 ].
by apply H_jobs_have_valid_parameters.
}
Qed.
@@ 308,11 +316,12 @@ Module WorkloadBound.
(* Assume that there's at least one job in the sorted list. *)
Hypothesis H_at_least_one_job: size sorted_jobs > 0.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
(* The first job is an interfering job of task tsk. *)
Lemma workload_bound_j_fst_is_job_of_tsk :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk /\
service_during sched j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 334,14 +343,14 @@ Module WorkloadBound.
rewrite [service_during _ _ _ _]add0n [_* task_cost tsk]mulSnr.
apply leq_add; first by done.
by eapply cumulative_service_le_task_cost;
 [ by apply INfst
+ [ by apply INfst0
 by apply H_jobs_have_valid_parameters].
}
{
rewrite 2!mul0n addn0 subn0 leq_min; apply/andP; split.
{
by eapply cumulative_service_le_task_cost;
 [ by apply INfst
+ [ by apply INfst0
 by apply H_jobs_have_valid_parameters].
}
{
@@ 362,12 +371,13 @@ Module WorkloadBound.
Variable num_mid_jobs: nat.
Hypothesis H_at_least_two_jobs : size sorted_jobs = num_mid_jobs.+2.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let j_lst := nth elem sorted_jobs num_mid_jobs.+1.
(* The last job is an interfering job of task tsk. *)
Lemma workload_bound_j_lst_is_job_of_tsk :
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk /\
service_during sched j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 386,11 +396,11 @@ Module WorkloadBound.
apply mem_nth; instantiate (1 := 0).
apply ltn_trans with (n := 1); [by done  by rewrite H_at_least_two_jobs].
}
 instantiate (1 := elem); move => [FSTtsk [/eqP FSTserv FSTin]].
+ instantiate (1 := elem); move => [FSTarr [FSTtsk [/eqP FSTserv FSTin]]].
apply FSTserv.
 apply (cumulative_service_after_job_rt_zero job_cost) with (R := R_tsk);
+ apply (cumulative_service_after_job_rt_zero job_arrival job_cost) with (R := R_tsk);
try (by done); last by apply ltnW.
 apply H_response_time_bound; first by done.
+ apply H_response_time_bound; try (by done).
by apply leq_trans with (n := t1); last by apply leq_addr.
Qed.
@@ 404,8 +414,9 @@ Module WorkloadBound.
apply mem_nth; instantiate (1 := num_mid_jobs.+1).
by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
}
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
 by unfold service_during; apply LSTserv, cumulative_service_before_job_arrival_zero.
+ instantiate (1 := elem); move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
+ unfold service_during; apply LSTserv.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
Qed.
(* Next, we upperbound the service of the first and last jobs using their arrival times. *)
@@ 431,11 +442,11 @@ Module WorkloadBound.
[ by apply workload_bound_response_time_of_first_job_inside_interval
 by apply ltnW].
rewrite {2}[\sum_(_ <= _ < _) _]addn0 /= leq_add2l leqn0; apply/eqP.
 apply (cumulative_service_after_job_rt_zero job_cost) with (R := R_tsk); try (by done).
 apply H_response_time_bound; last by done.
+ apply (cumulative_service_after_job_rt_zero job_arrival job_cost) with (R := R_tsk); try (by done).
exploit workload_bound_all_jobs_from_tsk.
by apply mem_nth; instantiate (1 := 0); rewrite H_at_least_two_jobs.
 by instantiate (1 := elem); move => [FSTtsk _].
+ instantiate (1 := elem); move => [FSTarr [FSTtsk _]].
+ by apply H_response_time_bound.
}
}
{
@@ 454,7 +465,7 @@ Module WorkloadBound.
[ by apply ltnW
 by apply ltnW, workload_bound_last_job_arrives_before_end_of_interval].
rewrite /= [\sum_(_ <= _ < _) 1]add0n; apply leq_add.
 rewrite cumulative_service_before_job_arrival_zero;
+ rewrite (cumulative_service_before_job_arrival_zero job_arrival);
[by apply leqnn  by ins  by apply leqnn].
by apply leq_sum; ins; apply service_at_most_one.
}
@@ 490,15 +501,14 @@ Module WorkloadBound.
last by rewrite big_const_nat iter_addn addn0 mulnC subn0.
rewrite big_nat_cond [\sum_(0 <= i < num_mid_jobs) task_cost _]big_nat_cond.
apply leq_sum; intros i; rewrite andbT; move => /andP LT; des.
 eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute   by apply H_jobs_have_valid_parameters].
exploit workload_bound_all_jobs_from_tsk.
{
instantiate (1 := nth elem sorted_jobs i.+1).
apply mem_nth; rewrite H_at_least_two_jobs.
by rewrite ltnS; apply leq_trans with (n := num_mid_jobs).
}
 by ins; des.
+ move => [ARR [TSK _]].
+ by eapply cumulative_service_le_task_cost; eauto 2.
Qed.
(* Conclude that the distance between first and last is at least num_mid_jobs + 1 periods. *)
@@ 521,14 +531,13 @@ Module WorkloadBound.
assert (ARRle: job_arrival cur <= job_arrival next).
by unfold cur, next; apply workload_bound_jobs_ordered_by_arrival.
 (* Show that both cur and next are in the arrival sequence *)
 assert (INnth: cur \in scheduled_jobs /\ next \in scheduled_jobs).
 {
 rewrite 2!workload_bound_job_in_same_sequence; split.
 by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs; ins.
 by apply mem_nth; destruct sorted_jobs; ins.
 }
 rewrite 2?mem_filter in INnth; des.
+ feed (workload_bound_all_jobs_from_tsk cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (workload_bound_all_jobs_from_tsk next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
(* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
@@ 536,15 +545,15 @@ Module WorkloadBound.
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /scheduled_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk.
}
 by rewrite subh3 // addnC INnth.
+ by rewrite subh3 // addnC CURtsk.
Qed.
(* Prove that n_k is at least the number of the middle jobs *)
@@ 635,18 +644,23 @@ Module WorkloadBound.
service_during sched (nth elem sorted_jobs i.+1) t1 t2
<= workload_bound.
Proof.
+ have MID := workload_bound_service_of_middle_jobs.
+ rename H_jobs_have_valid_parameters into JOBPARAMS.
unfold workload_bound, W; fold n_k.
move => NK; rewrite NK.
rewrite {2}addn1 mulnDl mul1n [_* _ + _]addnC addnA addn_minl.
 apply leq_add; last by apply workload_bound_service_of_middle_jobs.
+ apply leq_add; last by apply MID.
rewrite leq_min; apply/andP; split.
{
assert (SIZE: 0 < size sorted_jobs).
by rewrite H_at_least_two_jobs.
have INfst := workload_bound_j_fst_is_job_of_tsk SIZE elem;
have INlst := workload_bound_j_lst_is_job_of_tsk; des.
 by apply leq_add; apply cumulative_service_le_task_cost with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline) (job_task0 := job_task).
+ have PARAMSfst := JOBPARAMS j_fst INfst; des.
+ have PARAMSlst := JOBPARAMS j_lst INlst; des.
+ by apply leq_add; apply cumulative_service_le_task_cost with
+ (task_deadline0 := task_deadline)
+ (job_cost0 := job_cost) (job_deadline0 := job_deadline) (job_task0 := job_task).
}
{
rewrite subnAC subnK; last first.
@@ 689,8 +703,8 @@ Module WorkloadBound.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
 destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists j].
+ assert (EX: exists elem: Job, True).
+ destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists s].
destruct EX as [elem _].
(* Now we index the sum to access the first and last elements. *)
diff git a/analysis/global/basic/bertogna_edf_comp.v b/analysis/global/basic/bertogna_edf_comp.v
index de4d42c..75d70e9 100755
 a/analysis/global/basic/bertogna_edf_comp.v
+++ b/analysis/global/basic/bertogna_edf_comp.v
@@ 20,6 +20,7 @@ Module ResponseTimeIterationEDF.
Let task_with_response_time := (sporadic_task * time)%type.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 869,45 +870,47 @@ Module ResponseTimeIterationEDF.
forall tsk, tsk \in ts > task_deadline tsk <= task_period tsk.
(* Next, consider any arrival sequence such that...*)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...they have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
 (* Then, consider any platform with at least one CPU such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ (* Then, consider any schedule of this arrival sequence such that... *)
+ Variable sched: schedule Job num_cpus.
Hypothesis H_at_least_one_cpu: num_cpus > 0.

+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
(* ...jobs only execute after they arrived and no longer
than their execution costs. *)
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Also assume that jobs are sequential. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* Assume a workconserving scheduler with EDF policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
 Hypothesis H_edf_policy: respects_JLFP_policy job_cost sched (EDF job_deadline).
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
+ Hypothesis H_edf_policy: respects_JLFP_policy job_arrival job_cost arr_seq sched
+ (EDF job_arrival job_deadline).
Definition no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Definition no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in edf_claimed_bounds is safe. The proof follows by direct application of
@@ 923,7 +926,7 @@ Module ResponseTimeIterationEDF.
have BOUND := bertogna_cirinei_response_time_bound_edf.
unfold is_response_time_bound_of_task in *.
apply BOUND with (task_cost := task_cost) (task_period := task_period)
 (task_deadline := task_deadline) (job_deadline := job_deadline)
+ (arr_seq := arr_seq) (task_deadline := task_deadline) (job_deadline := job_deadline)
(job_task := job_task) (ts := ts) (tsk := tsk) (rt_bounds := rt_bounds); try (by ins).
by unfold edf_claimed_bounds in SOME; desf; rewrite edf_claimed_bounds_unzip1_iteration.
by ins; apply edf_claimed_bounds_finds_fixed_point_for_each_bound with (ts := ts).
@@ 952,19 +955,18 @@ Module ResponseTimeIterationEDF.
H_all_jobs_from_taskset into ALLJOBS,
H_test_succeeds into TEST.
 move => tsk INtsk j JOBtsk.
+ move => tsk INtsk j ARRj JOBtsk.
destruct (edf_claimed_bounds ts) as [rt_bounds ] eqn:SOME; last by ins.
exploit (HAS rt_bounds tsk); [by ins  by ins  clear HAS; intro HAS; des].
 have COMPLETED := RLIST tsk R HAS j JOBtsk.
 exploit (DL rt_bounds tsk R);
 [by ins  by ins  clear DL; intro DL].
+ have COMPLETED := RLIST tsk R HAS j ARRj JOBtsk.
+ exploit (DL rt_bounds tsk R); try (by done); clear DL; intro DL.
rewrite eqn_leq; apply/andP; split; first by apply cumulative_service_le_job_cost.
apply leq_trans with (n := service sched j (job_arrival j + R)); last first.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
apply extend_sum; rewrite // leq_add2l.
 specialize (JOBPARAMS j); des; rewrite JOBPARAMS1.
+ specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS1.
by rewrite JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
@@ 975,12 +977,12 @@ Module ResponseTimeIterationEDF.
are spawned by the task set, we conclude that no job misses
its deadline. *)
Theorem jobs_schedulable_by_edf_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j, arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_edf_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/global/basic/bertogna_edf_theory.v b/analysis/global/basic/bertogna_edf_theory.v
index e974ef8..4ae30ee 100644
 a/analysis/global/basic/bertogna_edf_theory.v
+++ b/analysis/global/basic/bertogna_edf_theory.v
@@ 26,18 +26,20 @@ Module ResponseTimeAnalysisEDF.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider a task set ts where all tasks have valid parameters
@@ 50,32 +52,34 @@ Module ResponseTimeAnalysisEDF.
(* ... and assume that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j > job_task j \in ts.
(* Next, consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs are sequential and do not execute before their
arrival times nor longer than their execution costs. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Assume that there exists at least one processor. *)
Hypothesis H_at_least_one_cpu: num_cpus > 0.
(* Assume that the schedule is a workconserving EDF schedule. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
 Hypothesis H_edf_policy: respects_JLFP_policy job_cost sched (EDF job_deadline).
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
+ Hypothesis H_edf_policy: respects_JLFP_policy job_arrival job_cost arr_seq sched
+ (EDF job_arrival job_deadline).
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Next we consider the responsetime recurrence.
Assume that a responsetime bound R is known... *)
@@ 107,7 +111,8 @@ Module ResponseTimeAnalysisEDF.
Hypothesis H_tsk_R_in_rt_bounds: (tsk, R) \in rt_bounds.
(* Consider any job j of tsk ... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* ... that did not complete on time, ... *)
@@ 115,7 +120,8 @@ Module ResponseTimeAnalysisEDF.
(* ... and that is the first job not to satisfy its responsetime bound. *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_other: JobIn arr_seq) tsk_other R_other,
+ forall j_other tsk_other R_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
(tsk_other, R_other) \in rt_bounds >
job_arrival j_other + R_other < job_arrival j + R >
@@ 123,11 +129,11 @@ Module ResponseTimeAnalysisEDF.
(* 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 sched j tsk_other
+ task_interference job_arrival job_cost job_task sched j tsk_other
(job_arrival j) (job_arrival j + R).
(* ...and X the total interference incurred by job j due to any task. *)
 Let X := total_interference job_cost sched j (job_arrival j) (job_arrival j + R).
+ Let X := total_interference job_arrival job_cost sched j (job_arrival j) (job_arrival j + R).
(* Recall Bertogna and Cirinei's workload bound ... *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
@@ 188,8 +194,9 @@ Module ResponseTimeAnalysisEDF.
apply leq_trans with (n := workload job_task sched tsk_other
(job_arrival j) (job_arrival j + R));
first by apply task_interference_le_workload.
 by apply workload_bounded_by_W with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline); try (by ins); last 2 first;
+ by apply workload_bounded_by_W with (task_deadline0 := task_deadline) (arr_seq0 := arr_seq)
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (job_deadline0 := job_deadline);
+ try (by ins); last 2 first;
[ by apply bertogna_edf_R_other_ge_cost
 by ins; apply NOMISS
 by ins; apply TASK_PARAMS
@@ 202,7 +209,7 @@ Module ResponseTimeAnalysisEDF.
x tsk_other <= edf_specific_bound tsk_other R_other.
Proof.
apply interference_bound_edf_bounds_interference with (job_deadline0 := job_deadline)
 (ts0 := ts); try (by done);
+ (arr_seq0 := arr_seq) (ts0 := ts); try (by done);
[ by apply bertogna_edf_tsk_other_in_ts
 by apply H_tasks_miss_no_deadlines
 by apply H_tasks_miss_no_deadlines  ].
@@ 234,12 +241,12 @@ Module ResponseTimeAnalysisEDF.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(job_arrival j <= t < job_arrival j + R)
 backlogged job_cost sched j t) +
+ backlogged job_arrival job_cost sched j t) +
service sched j (job_arrival j + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_j_arrives); des; rewrite JOBtsk.
}
unfold service; rewrite service_before_arrival_eq_service_during //.
rewrite big_split /=.
@@ 247,7 +254,7 @@ Module ResponseTimeAnalysisEDF.
first by rewrite big_const_nat iter_addn mul1n addn0 addKn.
rewrite big_nat_cond [\sum_(_ <= _ < _  true) _]big_nat_cond.
apply leq_sum; move => i /andP [/andP [GEi LTi] _].
 destruct (backlogged job_cost sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 266,7 +273,8 @@ Module ResponseTimeAnalysisEDF.
Lemma bertogna_edf_interference_by_different_tasks :
forall t j_other,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ arrives_in arr_seq j_other >
+ backlogged job_arrival job_cost sched j t >
scheduled sched j_other t >
job_task j_other != tsk.
Proof.
@@ 278,18 +286,19 @@ Module ResponseTimeAnalysisEDF.
H_all_previous_jobs_completed_on_time into BEFOREok,
H_tasks_miss_no_deadlines into NOMISS,
H_constrained_deadlines into CONSTR.
 move => t j_other /andP [LEt GEt] BACK SCHED.
+ move => t j_other /andP [LEt GEt] ARRother BACK SCHED.
apply/eqP; red; intro SAMEtsk.
move: SCHED => /existsP [cpu SCHED].
assert (SCHED': scheduled sched j_other t).
by apply/existsP; exists cpu.
clear SCHED; rename SCHED' into SCHED.
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_cost0 := job_cost) (job_arrival0 := job_arrival)
+ in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
move: (BEFOREother) => LT; rewrite (ltn_add2r R) in LT.
 specialize (BEFOREok j_other tsk R SAMEtsk INbounds LT).
+ specialize (BEFOREok j_other tsk R ARRother SAMEtsk INbounds LT).
move: PENDING => /andP [_ /negP NOTCOMP]; apply NOTCOMP.
apply completion_monotonic with (t0 := job_arrival j_other + R); try (by done).
apply leq_trans with (n := job_arrival j); last by done.
@@ 297,12 +306,12 @@ Module ResponseTimeAnalysisEDF.
first by rewrite leq_add2l; apply NOMISS.
apply leq_trans with (n := job_arrival j_other + task_period tsk);
first by rewrite leq_add2l; apply CONSTR; rewrite JOBtsk FROMTS.
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; try (by done); [  by rewrite JOBtsk  by apply ltnW].
by red; intro EQ; subst; rewrite ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge.
apply leq_ltn_trans with (n := t); first by done.
@@ 321,7 +330,8 @@ Module ResponseTimeAnalysisEDF.
With this lemma, we can conclude that during job j's scheduling
window there cannot be multiple pending jobs of each task.*)
Lemma bertogna_edf_all_previous_jobs_complete_by_their_period:
 forall t (j0: JobIn arr_seq),
+ forall t j0,
+ arrives_in arr_seq j0 >
t < job_arrival j + R >
job_arrival j0 + task_period (job_task j0) <= t >
completed job_cost sched j0
@@ 332,7 +342,7 @@ Module ResponseTimeAnalysisEDF.
H_tasks_miss_no_deadlines into NOMISS,
H_all_jobs_from_taskset into FROMTS,
H_all_previous_jobs_completed_on_time into BEFOREok.
 intros t j0 LEt LE.
+ intros t j0 ARR0 LEt LE.
cut ((job_task j0) \in unzip1 rt_bounds = true); last by rewrite UNZIP FROMTS.
move => /mapP [p IN EQ]; destruct p as [tsk' R0]; simpl in *; subst tsk'.
apply completion_monotonic with (t0 := job_arrival j0 + R0); first by done.
@@ 358,7 +368,7 @@ Module ResponseTimeAnalysisEDF.
Lemma bertogna_edf_all_cpus_are_busy:
forall t,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ backlogged job_arrival job_cost sched j t >
count (other_scheduled_task t) ts = num_cpus.
Proof.
rename H_all_jobs_from_taskset into FROMTS,
@@ 373,27 +383,25 @@ Module ResponseTimeAnalysisEDF.
H_work_conserving into WORK.
unfold x, X, total_interference, task_interference.
move => t /andP [LEt LTt] BACK.
 eapply platform_cpus_busy_with_interfering_tasks; try (by done);
 [ by apply WORK  by apply SPO
  apply PARAMS; rewrite JOBtsk; apply FROMTS
  by apply JOBtsk  by apply BACK  ].
+ have PLAT := platform_cpus_busy_with_interfering_tasks task_cost task_period task_deadline
+ job_arrival job_cost job_task arr_seq sched.
+ apply PLAT with (j := j); try (by done);
+ first by apply PARAMS; rewrite JOBtsk; apply FROMTS.
+ intros j0 tsk0 ARR0 TSK0 LE.
+ cut (tsk0 \in unzip1 rt_bounds = true); last by rewrite UNZIP TSK0 FROMTS.
+ move => /mapP [p IN EQ]; destruct p as [tsk' R0]; simpl in *; subst tsk'.
+ apply completion_monotonic with (t0 := job_arrival j0 + R0); try (by done).
{
 intros j0 tsk0 TSK0 LE.
 cut (tsk0 \in unzip1 rt_bounds = true); last by rewrite UNZIP TSK0 FROMTS.
 move => /mapP [p IN EQ]; destruct p as [tsk' R0]; simpl in *; subst tsk'.
 apply completion_monotonic with (t0 := job_arrival j0 + R0); try (by done).
 {
 rewrite leq_add2l TSK0.
 apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
 by apply RESTR; rewrite TSK0 FROMTS.
 }
 {
 apply BEFOREok with (tsk_other := tsk0); try (by done).
 apply leq_ltn_trans with (n := t); last by done.
 apply leq_trans with (n := job_arrival j0 + task_period tsk0); last by done.
 rewrite leq_add2l; apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
 by apply RESTR; rewrite TSK0 FROMTS.
 }
+ rewrite leq_add2l TSK0.
+ apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
+ by apply RESTR; rewrite TSK0 FROMTS.
+ }
+ {
+ apply BEFOREok with (tsk_other := tsk0); try (by done).
+ apply leq_ltn_trans with (n := t); last by done.
+ apply leq_trans with (n := job_arrival j0 + task_period tsk0); last by done.
+ rewrite leq_add2l; apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
+ by apply RESTR; rewrite TSK0 FROMTS.
}
Qed.
@@ 409,7 +417,7 @@ Module ResponseTimeAnalysisEDF.
rename H_all_jobs_from_taskset into FROMTS,
H_valid_task_parameters into PARAMS,
H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
 H_work_conserving into WORK,
+ H_work_conserving into WORK, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_tsk_R_in_rt_bounds into INbounds,
H_all_previous_jobs_completed_on_time into BEFOREok,
H_tasks_miss_no_deadlines into NOMISS,
@@ 418,9 +426,9 @@ Module ResponseTimeAnalysisEDF.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost sched j t) eqn:BACK; last first.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last first.
{
rewrite (eq_bigr (fun i => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
@@ 431,7 +439,9 @@ Module ResponseTimeAnalysisEDF.
rewrite exchange_big /=.
apply eq_trans with (y := \sum_(cpu < num_cpus) 1); last by simpl_sum_const.
apply eq_bigr; intros cpu _.
 move: (WORK j t BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ move: (WORK j t H_j_arrives BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (FROMSEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
rewrite (eq_bigr (fun i => 0));
@@ 440,7 +450,7 @@ Module ResponseTimeAnalysisEDF.
by unfold task_scheduled_on; rewrite SCHED.
}
rewrite mem_filter; apply/andP; split; last by apply FROMTS.
 apply DIFFTASK with (t := t); [by auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu; apply/eqP.
Qed.
@@ 465,7 +475,7 @@ Module ResponseTimeAnalysisEDF.
H_sporadic_tasks into SPO,
H_tsk_R_in_rt_bounds into INbounds,
H_all_previous_jobs_completed_on_time into BEFOREok,
 H_tasks_miss_no_deadlines into NOMISS,
+ H_tasks_miss_no_deadlines into NOMISS, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_constrained_deadlines into CONSTR,
H_sequential_jobs into SEQ.
unfold sporadic_task_model in *.
@@ 473,11 +483,11 @@ Module ResponseTimeAnalysisEDF.
rewrite has_count in HAS.
set some_interference_A := fun t =>
 has (fun tsk_k => backlogged job_cost sched j t &&
+ has (fun tsk_k => backlogged job_arrival job_cost sched j t &&
(x tsk_k >= delta) &&
task_is_scheduled job_task sched tsk_k t) other_tasks.
set total_interference_B := fun t =>
 backlogged job_cost sched j t *
+ backlogged job_arrival job_cost sched j t *
count (fun tsk_k => (x tsk_k < delta) &&
task_is_scheduled job_task sched tsk_k t) other_tasks.
@@ 489,7 +499,7 @@ Module ResponseTimeAnalysisEDF.
apply leq_trans with (n := x tsk_a); first by apply LEa.
unfold x, task_interference, some_interference_A.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
last by rewrite (eq_bigr (fun x => 0)); [by simpl_sum_const  by ins].
destruct ([exists cpu, task_scheduled_on job_task sched tsk_a cpu t]) eqn:SCHED;
last first.
@@ 515,12 +525,16 @@ Module ResponseTimeAnalysisEDF.
destruct (sched cpu' t) as [j2] eqn:SCHED2; last by done.
move: SCHED SCHED' => /eqP JOB /eqP JOB'.
subst tsk_a; symmetry in JOB'.
 assert (PENDING1: pending job_cost sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu'; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu; apply/eqP.
}
 assert (PENDING2: pending job_cost sched j2 t).
+ assert (PENDING2: pending job_arrival job_cost sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu'; apply/eqP.
@@ 529,9 +543,10 @@ Module ResponseTimeAnalysisEDF.
{
apply platform_at_most_one_pending_job_of_each_task with (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline) (tsk0 := tsk)
 (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t);
 rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
 intros j0 tsk0 TSK0 LE.
+ (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (j0 := j) (t0 := t)
+ (job_arrival0 := job_arrival) (arr_seq0 := arr_seq);
+ rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
+ intros j0 tsk0 ARR0 TSK0 LE.
by apply (COMP t); rewrite ?TSK0.
}
by subst j2; apply SEQ with (j := j1) (t := t).
@@ 543,7 +558,7 @@ Module ResponseTimeAnalysisEDF.
rewrite big_distrl /=.
apply leq_sum_nat; move => t LEt _.
unfold some_interference_A, total_interference_B.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
[rewrite mul1n /=  by rewrite has_pred0 //].
destruct (has (fun tsk_k : sporadic_task => (delta <= x tsk_k) &&
@@ 572,7 +587,7 @@ Module ResponseTimeAnalysisEDF.
{
unfold x at 2, total_interference_B.
rewrite exchange_big /=; apply leq_sum; intros t _.
 destruct (backlogged job_cost sched j t) eqn:BACK; last by ins.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last by ins.
rewrite mul1n sum1_count.
rewrite big_mkcond [\sum_(i < other_tasks  _ < _) _]big_mkcond /=.
apply leq_sum_seq; move => tsk_k IN _.
@@ 740,7 +755,7 @@ Module ResponseTimeAnalysisEDF.
Theorem bertogna_cirinei_response_time_bound_edf :
response_time_bounded_by tsk R.
Proof.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
remember (job_arrival j + R) as ctime.
@@ 751,14 +766,15 @@ Module ResponseTimeAnalysisEDF.
(* Now, we apply strong induction on the absolute responsetime bound. *)
induction ctime as [ctime IH] using strong_ind.
 intros j tsk' JOBtsk R' EQc INbounds; subst ctime.
+ intros j ARRj tsk' JOBtsk R' EQc INbounds; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq) tsk R0,
 job_task j0 = tsk >
 (tsk, R0) \in rt_bounds >
 job_arrival j0 + R0 < job_arrival j + R' >
 service sched j0 (job_arrival j0 + R0) == job_cost j0).
+ assert (BEFOREok: forall j0 tsk R0,
+ arrives_in arr_seq j0 >
+ job_task j0 = tsk >
+ (tsk, R0) \in rt_bounds >
+ job_arrival j0 + R0 < job_arrival j + R' >
+ service sched j0 (job_arrival j0 + R0) == job_cost j0).
{
by ins; apply IH with (tsk := tsk0) (R := R0).
}
@@ 772,7 +788,7 @@ Module ResponseTimeAnalysisEDF.
apply negbT in NOTCOMP; exfalso.
(* Next, we derive a contradiction using the previous lemmas. *)
 exploit (bertogna_edf_exists_task_that_exceeds_bound tsk' R' INbounds j JOBtsk NOTCOMP).
+ exploit (bertogna_edf_exists_task_that_exceeds_bound tsk' R' INbounds j ARRj JOBtsk NOTCOMP).
{
by ins; apply IH with (tsk := tsk_other) (R := R_other).
}
@@ 780,7 +796,8 @@ Module ResponseTimeAnalysisEDF.
unfold interference_bound_edf, interference_bound_generic in LTmin.
rewrite minnAC in LTmin; apply min_lt_same in LTmin.
have BASICBOUND := bertogna_edf_workload_bounds_interference R' j BEFOREok tsk_other R_other HP.
 have EDFBOUND := (bertogna_edf_specific_bound_holds tsk' R' INbounds j JOBtsk BEFOREok tsk_other R_other HP).
+ have EDFBOUND := (bertogna_edf_specific_bound_holds tsk' R' INbounds j ARRj
+ JOBtsk BEFOREok tsk_other R_other HP).
unfold minn in LTmin; clear LTmin HP BASICBOUND EDFBOUND tsk; desf.
{
by apply (leq_ltn_trans BASICBOUND) in LTmin; rewrite ltnn in LTmin.
diff git a/analysis/global/basic/bertogna_fp_comp.v b/analysis/global/basic/bertogna_fp_comp.v
index 164a8dc..920d9df 100644
 a/analysis/global/basic/bertogna_fp_comp.v
+++ b/analysis/global/basic/bertogna_fp_comp.v
@@ 20,6 +20,7 @@ Module ResponseTimeIterationFP.
Let task_with_response_time := (sporadic_task * time)%type.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 493,25 +494,28 @@ Module ResponseTimeIterationFP.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...jobs have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
 (* Then, consider any platform with at least one CPU such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ (* Then, consider any schedule of this arrival sequence such that... *)
+ Variable sched: schedule Job num_cpus.
Hypothesis H_at_least_one_cpu: num_cpus > 0.

+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
(* ...jobs only execute after they arrived and no longer
than their execution costs. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 519,16 +523,16 @@ Module ResponseTimeIterationFP.
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* Assume that the scheduler is workconserving and respects the FP policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_respects_FP_policy:
 respects_FP_policy job_cost job_task sched higher_priority.
+ respects_FP_policy job_arrival job_cost job_task arr_seq sched higher_priority.
Let no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in fp_claimed_bounds is safe. The proof follows by induction on the task set:
@@ 565,20 +569,13 @@ Module ResponseTimeIterationFP.
clear EQ.
assert (PAIR: forall idx, (TASK idx, RESP idx) = NTH idx).
 {
by intros i; unfold TASK, RESP; destruct (NTH i).
 }
assert (SUBST: forall i, i < size hp_bounds > TASK i = nth tsk ts i).
 {

by intros i LTi; rewrite /TASK /NTH UNZIP (nth_map elem) //.
 }
assert (SIZE: size hp_bounds = size ts).
 {
by rewrite UNZIP size_map.
 }
induction idx as [idx IH'] using strong_ind.
@@ 672,7 +669,7 @@ Module ResponseTimeIterationFP.
job_misses_no_deadline, completed,
fp_schedulable, valid_sporadic_job in *.
rename H_valid_job_parameters into JOBPARAMS.
 move => tsk INtsk j JOBtsk.
+ move => tsk INtsk j ARRj JOBtsk.
destruct (fp_claimed_bounds ts) as [rt_bounds ]; last by ins.
feed (UNZIP rt_bounds); first by done.
assert (EX: exists R, (tsk, R) \in rt_bounds).
@@ 680,14 +677,14 @@ Module ResponseTimeIterationFP.
rewrite set_mem UNZIP in INtsk; move: INtsk => /mapP EX.
by destruct EX as [p]; destruct p as [tsk' R]; simpl in *; subst tsk'; exists R.
} des.
 exploit (RLIST tsk R); [by ins  by apply JOBtsk  intro COMPLETED].
+ exploit (RLIST tsk R EX j ARRj); [by done  intro COMPLETED].
exploit (DL rt_bounds tsk R); [by ins  by ins  clear DL; intro DL].
rewrite eqn_leq; apply/andP; split; first by apply cumulative_service_le_job_cost.
apply leq_trans with (n := service sched j (job_arrival j + R)); last first.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
apply extend_sum; rewrite // leq_add2l.
 specialize (JOBPARAMS j); des; rewrite JOBPARAMS1.
+ specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS1.
by rewrite JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
@@ 698,12 +695,12 @@ Module ResponseTimeIterationFP.
are spawned by the task set, we also conclude that no job in
the schedule misses its deadline. *)
Theorem jobs_schedulable_by_fp_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j, arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_fp_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/global/basic/bertogna_fp_theory.v b/analysis/global/basic/bertogna_fp_theory.v
index 5c6e1c2..4091fe0 100644
 a/analysis/global/basic/bertogna_fp_theory.v
+++ b/analysis/global/basic/bertogna_fp_theory.v
@@ 26,18 +26,20 @@ Module ResponseTimeAnalysisFP.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Assume that we have a task set where all tasks have valid
@@ 50,19 +52,19 @@ Module ResponseTimeAnalysisFP.
(* ... and that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Next, consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs are sequential and do not execute before their
arrival times nor longer than their execution costs. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Assume that there exists at least one processor. *)
Hypothesis H_at_least_one_cpu: num_cpus > 0.
@@ 72,15 +74,15 @@ Module ResponseTimeAnalysisFP.
(* ... and assume that the schedule is a workconserving
schedule that respects this policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_respects_FP_policy:
 respects_FP_policy job_cost job_task sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_task arr_seq sched higher_eq_priority.
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Next, we consider the responsetime recurrence.
Let tsk be a task in ts that is to be analyzed. *)
@@ 132,24 +134,26 @@ Module ResponseTimeAnalysisFP.
Section Lemmas.
(* Consider any job j of tsk. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* 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 (job_arrival j + R).
Hypothesis H_previous_jobs_of_tsk_completed :
 forall (j0: JobIn arr_seq),
+ forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
completed job_cost sched j0 (job_arrival j0 + 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 sched j tsk_other
+ task_interference job_arrival job_cost job_task sched j tsk_other
(job_arrival j) (job_arrival j + R).
(* ...and X the total interference incurred by job j due to any task. *)
 Let X := total_interference job_cost sched j (job_arrival j) (job_arrival j + R).
+ Let X := total_interference job_arrival job_cost sched j (job_arrival j) (job_arrival j + R).
(* Recall Bertogna and Cirinei's workload bound. *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
@@ 200,14 +204,17 @@ Module ResponseTimeAnalysisFP.
}
move: SCHED => /existsP [t /existsP [cpu SCHED]].
unfold task_scheduled_on in SCHED.
 destruct (sched cpu t) as [j0 ]; last by done.
+ destruct (sched cpu t) as [j0 ] eqn:SCHED'; last by done.
assert (INts: tsk_other \in ts).
 by move: SCHED => /eqP <; rewrite FROMTS.
+ {
+ move: SCHED => /eqP <. apply FROMTS, (H_jobs_come_from_arrival_sequence j0 t).
+ by apply/existsP; exists cpu; apply/eqP.
+ }
apply leq_trans with (n := workload job_task sched tsk_other
(job_arrival j) (job_arrival j + R));
first by apply task_interference_le_workload.
 by apply workload_bounded_by_W with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline);
+ by apply workload_bounded_by_W with (task_deadline0 := task_deadline) (arr_seq0 := arr_seq)
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (job_deadline0 := job_deadline);
try (by ins); last 2 first;
[ by ins; apply GE_COST
 by ins; apply NOMISS
@@ 242,12 +249,12 @@ Module ResponseTimeAnalysisFP.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(job_arrival j <= t < job_arrival j + R)
 backlogged job_cost sched j t) +
+ backlogged job_arrival job_cost sched j t) +
service sched j (job_arrival j + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_j_arrives); des; rewrite JOBtsk.
}
unfold service; rewrite service_before_arrival_eq_service_during //.
rewrite big_split /=.
@@ 255,7 +262,7 @@ Module ResponseTimeAnalysisFP.
first by rewrite big_const_nat iter_addn mul1n addn0 addKn.
rewrite big_nat_cond [\sum_(_ <= _ < _  true) _]big_nat_cond.
apply leq_sum; move => i /andP [/andP [GEi LTi] _].
 destruct (backlogged job_cost sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 274,7 +281,8 @@ Module ResponseTimeAnalysisFP.
Lemma bertogna_fp_interference_by_different_tasks :
forall t j_other,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ arrives_in arr_seq j_other >
+ backlogged job_arrival job_cost sched j t >
scheduled sched j_other t >
job_task j_other != tsk.
Proof.
@@ 285,18 +293,19 @@ Module ResponseTimeAnalysisFP.
H_constrained_deadlines into CONSTR,
H_previous_jobs_of_tsk_completed into PREV,
H_response_time_no_larger_than_deadline into NOMISS.
 move => t j_other /andP [LEt GEt] BACK SCHED.
+ move => t j_other /andP [LEt GEt] ARRother BACK SCHED.
apply/eqP; red; intro SAMEtsk.
move: SCHED => /existsP [cpu SCHED].
assert (SCHED': scheduled sched j_other t).
by apply/existsP; exists cpu.
clear SCHED; rename SCHED' into SCHED.
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
move: (BEFOREother) => LT; rewrite (ltn_add2r R) in LT.
 specialize (PREV j_other SAMEtsk BEFOREother).
+ specialize (PREV j_other ARRother SAMEtsk BEFOREother).
move: PENDING => /andP [_ /negP NOTCOMP]; apply NOTCOMP.
apply completion_monotonic with (t0 := job_arrival j_other + R); try (by done).
apply leq_trans with (n := job_arrival j); last by done.
@@ 304,12 +313,12 @@ Module ResponseTimeAnalysisFP.
first by rewrite leq_add2l; apply NOMISS.
apply leq_trans with (n := job_arrival j_other + task_period tsk);
first by rewrite leq_add2l; apply CONSTR; rewrite JOBtsk FROMTS.
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; try (by done); [  by rewrite JOBtsk  by apply ltnW].
by intro EQ; subst j_other; rewrite ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge.
apply leq_ltn_trans with (n := t); first by done.
@@ 332,7 +341,7 @@ Module ResponseTimeAnalysisFP.
Lemma bertogna_fp_all_cpus_are_busy:
forall t,
job_arrival j <= t < job_arrival j + R >
 backlogged job_cost sched j t >
+ backlogged job_arrival job_cost sched j t >
count (other_scheduled_task t) ts = num_cpus.
Proof.
rename H_valid_task_parameters into PARAMS,
@@ 348,16 +357,15 @@ Module ResponseTimeAnalysisFP.
move => t /andP [LEt LTt] BACK.
apply platform_fp_cpus_busy_with_interfering_tasks with (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline) (job_task0 := job_task)
 (ts0 := ts) (tsk0 := tsk) (higher_eq_priority0 := higher_eq_priority) in BACK;
 try (by done); first by apply PARAMS.
+ (arr_seq0 := arr_seq) (ts0 := ts) (tsk0 := tsk) (higher_eq_priority0 := higher_eq_priority)
+ in BACK; try (by done); first by apply PARAMS.
{
apply leq_trans with (n := job_arrival j + R); first by done.
rewrite leq_add2l.
by apply leq_trans with (n := task_deadline tsk); last by apply RESTR.
}
{
 intros j_other tsk_other JOBother INTERF.
 move: HAS => HAS.
+ intros j_other tsk_other ARRother JOBother INTERF.
feed (HAS tsk_other); first by rewrite JOBother FROMTS.
move: (HAS INTERF) => [R' IN].
apply completion_monotonic with (t0 := job_arrival j_other + R'); try (by done);
@@ 384,19 +392,20 @@ Module ResponseTimeAnalysisFP.
Proof.
have DIFFTASK := bertogna_fp_interference_by_different_tasks.
rename H_work_conserving into WORK, H_respects_FP_policy into FP,
+ H_jobs_come_from_arrival_sequence into SEQ,
H_all_jobs_from_taskset into FROMTS, H_job_of_tsk into JOBtsk.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
last by rewrite big1 //; ins; rewrite big1.
rewrite big_mkcond /=.
rewrite exchange_big /=.
apply eq_trans with (y := \sum_(cpu < num_cpus) 1); last by simpl_sum_const.
apply eq_bigr; intros cpu _.
 move: (WORK j t BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ move: (WORK j t H_j_arrives BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
rewrite (eq_bigr (fun i => 0));
@@ 404,13 +413,15 @@ Module ResponseTimeAnalysisFP.
rewrite big_const_seq iter_addn mul0n 2!addn0; apply/eqP; rewrite eqb1.
by unfold task_scheduled_on; rewrite SCHED.
}
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (SEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite mem_filter; apply/andP; split; last by apply FROMTS.
apply/andP; split.
{
rewrite JOBtsk; apply FP with (t := t); try by done.
by apply/existsP; exists cpu; apply/eqP.
}
 apply DIFFTASK with (t := t); [by auto  by done ].
+ apply DIFFTASK with (t := t); try (by done); first by auto.
by apply/existsP; exists cpu; apply/eqP.
Qed.
@@ 428,27 +439,23 @@ Module ResponseTimeAnalysisFP.
\sum_(i < hp_tasks  x i < delta) x i >= delta * (num_cpus  num_tasks_exceeding delta).
Proof.
have INV := bertogna_fp_all_cpus_are_busy.
 rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
 H_job_of_tsk into JOBtsk,
 H_sporadic_tasks into SPO,
 H_previous_jobs_of_tsk_completed into BEFOREok,
+ rename H_all_jobs_from_taskset into FROMTS, H_jobs_come_from_arrival_sequence into FROMSEQ,
+ H_valid_task_parameters into PARAMS, H_job_of_tsk into JOBtsk,
+ H_sporadic_tasks into SPO, H_previous_jobs_of_tsk_completed into BEFOREok,
H_response_time_no_larger_than_deadline into NOMISS,
 H_constrained_deadlines into CONSTR,
 H_sequential_jobs into SEQ,
 H_respects_FP_policy into FP,
 H_hp_bounds_has_interfering_tasks into HASHP,
+ H_constrained_deadlines into CONSTR, H_sequential_jobs into SEQ,
+ H_respects_FP_policy into FP, H_hp_bounds_has_interfering_tasks into HASHP,
H_interfering_tasks_miss_no_deadlines into NOMISSHP.
unfold sporadic_task_model in *.
move => delta /andP [HAS LT].
rewrite has_count in HAS.
set some_interference_A := fun t =>
 has (fun tsk_k => backlogged job_cost sched j t &&
+ has (fun tsk_k => backlogged job_arrival job_cost sched j t &&
(x tsk_k >= delta) &&
task_is_scheduled job_task sched tsk_k t) hp_tasks.
set total_interference_B := fun t =>
 backlogged job_cost sched j t *
+ backlogged job_arrival job_cost sched j t *
count (fun tsk_k => (x tsk_k < delta) &&
task_is_scheduled job_task sched tsk_k t) hp_tasks.
@@ 460,7 +467,7 @@ Module ResponseTimeAnalysisFP.
apply leq_trans with (n := x tsk_a); first by apply LEa.
unfold x, task_interference, some_interference_A.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
last by rewrite (eq_bigr (fun x => 0)); [by simpl_sum_const  by ins].
destruct ([exists cpu, task_scheduled_on job_task sched tsk_a cpu t]) eqn:SCHED;
last first.
@@ 486,12 +493,16 @@ Module ResponseTimeAnalysisFP.
destruct (sched cpu' t) as [j2] eqn:SCHED2; last by done.
move: SCHED SCHED' => /eqP JOB /eqP JOB'.
subst tsk_a; symmetry in JOB'.
 assert (PENDING1: pending job_cost sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu'; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu; apply/eqP.
}
 assert (PENDING2: pending job_cost sched j2 t).
+ assert (PENDING2: pending job_arrival job_cost sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu'; apply/eqP.
@@ 503,7 +514,7 @@ Module ResponseTimeAnalysisFP.
move: SAMEtsk => /eqP SAMEtsk.
move: (PENDING1) => SAMEjob.
apply platform_fp_no_multiple_jobs_of_tsk with (task_cost0 := task_cost)
 (task_period0 := task_period) (task_deadline0 := task_deadline)
+ (arr_seq0 := arr_seq) (task_period0 := task_period) (task_deadline0 := task_deadline)
(job_task0 := job_task) (tsk0 := tsk) (j0 := j) in SAMEjob; try (by done);
[  by apply PARAMS  ]; last 2 first.
{
@@ 511,7 +522,7 @@ Module ResponseTimeAnalysisFP.
by apply leq_trans with (n := task_deadline tsk); last by apply CONSTR.
}
{
 intros j0 JOB0 LT0.
+ intros j0 ARR0 JOB0 LT0.
apply completion_monotonic with (t0 := job_arrival j0 + R); try (by done);
last by apply BEFOREok.
rewrite leq_add2l.
@@ 524,15 +535,16 @@ Module ResponseTimeAnalysisFP.
assert (INTERF: is_hp_task (job_task j1)).
{
apply/andP; split; last by rewrite SAMEtsk.
 rewrite JOBtsk; apply FP with (t := t); first by done.
+ rewrite JOBtsk; apply FP with (t := t); try (by done).
by apply/existsP; exists cpu; apply/eqP.
}
apply platform_fp_no_multiple_jobs_of_interfering_tasks with
 (task_period0 := task_period) (tsk0 := tsk) (higher_eq_priority0 := higher_eq_priority)
 (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (t0 := t);
+ (job_arrival0 := job_arrival) (arr_seq0 := arr_seq) (task_period0 := task_period)
+ (tsk0 := tsk) (higher_eq_priority0 := higher_eq_priority)
+ (job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (t0 := t);
rewrite ?JOBtsk ?SAMEtsk //.
{
 intros j0 tsk0 JOB0 INTERF0.
+ intros j0 tsk0 ARR0 JOB0 INTERF0.
feed (HASHP tsk0); first by rewrite JOB0 FROMTS.
move: (HASHP INTERF0) => [R0 IN0].
apply completion_monotonic with (t0 := job_arrival j0 + R0); try (by done);
@@ 552,7 +564,7 @@ Module ResponseTimeAnalysisFP.
rewrite big_distrl /=.
apply leq_sum_nat; move => t LEt _.
unfold some_interference_A, total_interference_B.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
[rewrite mul1n /=  by rewrite has_pred0 //].
destruct (has (fun tsk_k : sporadic_task => (delta <= x tsk_k) &&
@@ 581,7 +593,7 @@ Module ResponseTimeAnalysisFP.
{
unfold x at 2, total_interference_B.
rewrite exchange_big /=; apply leq_sum; intros t _.
 destruct (backlogged job_cost sched j t) eqn:BACK; last by ins.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last by ins.
rewrite mul1n sum1_count.
rewrite big_mkcond [\sum_(i < hp_tasks  _ < _) _]big_mkcond /=.
apply leq_sum_seq; move => tsk_k IN _.
@@ 733,7 +745,7 @@ Module ResponseTimeAnalysisFP.
H_response_time_of_interfering_tasks_is_known into RESP,
H_hp_bounds_has_interfering_tasks into HAS,
H_response_time_no_larger_than_deadline into LEdl.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
remember (job_arrival j + R) as ctime.
@@ 742,10 +754,11 @@ Module ResponseTimeAnalysisFP.
generalize dependent j.
induction ctime as [ctime IH] using strong_ind.
 intros j JOBtsk EQc; subst ctime.
+ intros j ARRj JOBtsk EQc; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq),
+ assert (BEFOREok: forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
service sched j0 (job_arrival j0 + R) == job_cost j0).
@@ 763,7 +776,7 @@ Module ResponseTimeAnalysisFP.
apply negbT in NOTCOMP; exfalso.
(* We derive a contradiction using the previous lemmas. *)
 specialize (EX j JOBtsk NOTCOMP BEFOREok).
+ specialize (EX j ARRj JOBtsk NOTCOMP BEFOREok).
destruct EX as [tsk_k [R_k [HPk LTmin]]].
unfold minn at 1 in LTmin.
specialize (WORKLOAD j tsk_k R_k HPk).
diff git a/analysis/global/basic/interference_bound_edf.v b/analysis/global/basic/interference_bound_edf.v
index 0106270..513cc0b 100644
 a/analysis/global/basic/interference_bound_edf.v
+++ b/analysis/global/basic/interference_bound_edf.v
@@ 113,30 +113,32 @@ Module InterferenceBoundEDF.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs do not execute before their arrival times nor longer
than their execution costs. *)
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival 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. *)
@@ 147,28 +149,29 @@ Module InterferenceBoundEDF.
and tasks have valid parameters and constrained deadlines. *)
Variable ts: taskset_of sporadic_task.
Hypothesis all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
Hypothesis H_constrained_deadlines:
forall tsk, tsk \in ts > task_deadline tsk <= task_period tsk.
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Assume that the scheduler is a workconserving EDF scheduler. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_edf_scheduler:
 respects_JLFP_policy job_cost sched (EDF job_deadline).
+ respects_JLFP_policy job_arrival job_cost arr_seq sched (EDF job_arrival job_deadline).
(* Let tsk_i be the task to be analyzed, ...*)
Variable tsk_i: sporadic_task.
Hypothesis H_tsk_i_in_task_set: tsk_i \in ts.
(* ... and j_i one of its jobs. *)
 Variable j_i: JobIn arr_seq.
+ Variable j_i: Job.
+ Hypothesis H_j_i_arrives: arrives_in arr_seq j_i.
Hypothesis H_job_of_tsk_i: job_task j_i = tsk_i.
(* Let tsk_k denote any interfering task, ... *)
@@ 185,7 +188,8 @@ Module InterferenceBoundEDF.
(* Assume that the jobs of tsk_k satisfy the responsetime bound before the end of the interval *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_k: JobIn arr_seq),
+ forall j_k,
+ arrives_in arr_seq j_k >
job_task j_k = tsk_k >
job_arrival j_k + R_k < job_arrival j_i + delta >
completed job_cost sched j_k (job_arrival j_k + R_k).
@@ 196,7 +200,7 @@ Module InterferenceBoundEDF.
(* Let's call x the task interference incurred by job j due to tsk_k. *)
Let x :=
 task_interference job_cost job_task sched j_i tsk_k
+ task_interference job_arrival job_cost job_task sched j_i tsk_k
(job_arrival j_i) (job_arrival j_i + delta).
(* Also, recall the EDFspecific interference bound for EDF. *)
@@ 213,17 +217,17 @@ Module InterferenceBoundEDF.
Let n_k := div_floor D_i p_k.
(* Let's give a simpler name to job interference. *)
 Let interference_caused_by := job_interference job_cost sched j_i.
+ Let interference_caused_by := job_interference job_arrival job_cost sched j_i.
(* Identify the subset of jobs that actually cause interference *)
Let interfering_jobs :=
 filter (fun (x: JobIn arr_seq) =>
 (job_task x == tsk_k) && (interference_caused_by x t1 t2 != 0))
+ filter (fun j' =>
+ (job_task j' == tsk_k) && (interference_caused_by j' t1 t2 != 0))
(jobs_scheduled_between sched t1 t2).
(* Now, consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
 Let sorted_jobs := (sort earlier_arrival interfering_jobs).
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
+ Let sorted_jobs := sort earlier_arrival interfering_jobs.
(* Now we proceed with the proof. The first step consists in simplifying the sum corresponding to the workload. *)
Section SimplifyJobSequence.
@@ 271,13 +275,20 @@ Module InterferenceBoundEDF.
Lemma interference_bound_edf_all_jobs_from_tsk_k :
forall j,
j \in sorted_jobs >
+ arrives_in arr_seq j /\
job_task j = tsk_k /\
interference_caused_by j t1 t2 != 0 /\
j \in jobs_scheduled_between sched t1 t2.
Proof.
 intros j LT.
 rewrite interference_bound_edf_job_in_same_sequence mem_filter in LT.
 by move: LT => /andP [/andP [/eqP JOBi SERVi] INi]; repeat split.
+ rename H_jobs_come_from_arrival_sequence into FROMarr.
+ intros j LTi.
+ rewrite interference_bound_edf_job_in_same_sequence mem_filter in LTi; des.
+ have IN := LTi0.
+ unfold jobs_scheduled_between in *; rewrite mem_undup in IN.
+ apply mem_bigcat_nat_exists in IN; des.
+ rewrite mem_scheduled_jobs_eq_scheduled in IN.
+ repeat split; try (by done).
+ by apply (FROMarr j i).
Qed.
(* ...and consecutive jobs are ordered by arrival. *)
@@ 299,13 +310,16 @@ Module InterferenceBoundEDF.
interference_caused_by j t1 t2 <= task_cost tsk_k.
Proof.
rename H_valid_job_parameters into PARAMS.
 intros j; rewrite mem_filter; move => /andP [/andP [/eqP JOBj _] _].
 specialize (PARAMS j); des.
+ intros j IN.
+ feed (interference_bound_edf_all_jobs_from_tsk_k j);
+ first by rewrite interference_bound_edf_job_in_same_sequence.
+ move => [ARRj [TSKj _]].
apply leq_trans with (n := service_during sched j t1 t2);
first by apply job_interference_le_service.
 by apply cumulative_service_le_task_cost with (job_task0 := job_task)
 (task_deadline0 := task_deadline) (job_cost0 := job_cost)
 (job_deadline0 := job_deadline).
+ apply cumulative_service_le_task_cost with (job_task0 := job_task)
+ (task_deadline0 := task_deadline) (job_cost0 := job_cost) (job_deadline0 := job_deadline);
+ try (by done).
+ by apply PARAMS.
Qed.
End SimplifyJobSequence.
@@ 346,7 +360,7 @@ Module InterferenceBoundEDF.
Qed.
(* Let j_fst be the first job, and a_fst its arrival time. *)
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let a_fst := job_arrival j_fst.
@@ 355,6 +369,7 @@ Module InterferenceBoundEDF.
(* The first job is an interfering job of task tsk_k. *)
Lemma interference_bound_edf_j_fst_is_job_of_tsk_k :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk_k /\
interference_caused_by j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 370,8 +385,8 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask _].
 by specialize (PARAMS j_fst); des; rewrite PARAMS1 FSTtask.
+ destruct FST as [FSTarr [FSTtask _]].
+ by specialize (PARAMS j_fst FSTarr); des; rewrite PARAMS1 FSTtask.
Qed.
(* The deadline of j_i is the deadline of tsk_i. *)
@@ 381,7 +396,7 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS,
H_job_of_tsk_i into JOBtsk.
 by specialize (PARAMS j_i); des; rewrite PARAMS1 JOBtsk.
+ by specialize (PARAMS j_i H_j_i_arrives); des; rewrite PARAMS1 JOBtsk.
Qed.
(* If j_fst completes by its responsetime bound, then t1 <= a_fst + R_k,
@@ 393,13 +408,13 @@ Module InterferenceBoundEDF.
intros RBOUND.
rewrite leqNgt; apply/negP; unfold not; intro BUG.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ FSTserv _]].
+ destruct FST as [FSTarr [_ [ FSTserv _]]].
move: FSTserv => /negP FSTserv; apply FSTserv.
rewrite leqn0; apply leq_trans with (n := service_during sched j_fst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k);
 try (by done); apply ltnW.
+ by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k)
+ (job_arrival0 := job_arrival); try (by done); apply ltnW.
Qed.
End FactsAboutFirstJob.
@@ 438,20 +453,20 @@ Module InterferenceBoundEDF.
completed job_cost sched j_fst (a_fst + R_k).
Lemma interference_bound_edf_holds_for_single_job_that_completes_on_time :
 job_interference job_cost sched j_i j_fst t1 t2 <= D_i  (D_k  R_k).
+ job_interference job_arrival job_cost sched j_i j_fst t1 t2 <= D_i  (D_k  R_k).
Proof.
rename H_j_fst_completed_by_rt_bound into RBOUND.
have AFTERt1 :=
interference_bound_edf_j_fst_completion_implies_rt_bound_inside_interval RBOUND.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ LEdl _]].
+ destruct FST as [FSTarr [_ [ LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
destruct (D_k  R_k <= D_i) eqn:LEdk; last first.
{
apply negbT in LEdk; rewrite ltnNge in LEdk.
apply leq_trans with (n := 0); last by done.
 apply leq_trans with (n := job_interference job_cost sched j_i j_fst
+ apply leq_trans with (n := job_interference job_arrival job_cost sched j_i j_fst
(a_fst + R_k) t2).
{
apply extend_sum; last by apply leqnn.
@@ 465,8 +480,8 @@ Module InterferenceBoundEDF.
apply leq_trans with (n := service_during sched j_fst (a_fst + R_k) t2);
first by apply job_interference_le_service.
unfold service_during; rewrite leqn0; apply/eqP.
 by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k);
 try (by done); apply leqnn.
+ by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k)
+ (job_arrival0 := job_arrival); try (by done); apply leqnn.
}
{
rewrite (leq_add2r (D_k  R_k)) subh1 // addnBA // subnn addn0.
@@ 476,7 +491,7 @@ Module InterferenceBoundEDF.
rewrite addnC subnBA; last by apply leq_addr.
by rewrite addnC addnBA // subnn addn0.
}
 apply leq_trans with (n := job_interference job_cost sched j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost sched j_i j_fst t1
(a_fst + D_k) + (D_k  R_k)).
{
rewrite leq_add2r.
@@ 491,7 +506,7 @@ Module InterferenceBoundEDF.
apply negbT in LEt2; rewrite ltnNge in LEt2.
rewrite > big_cat_nat with (n := a_fst + R_k);
[simpl  by apply AFTERt1  by apply ltnW].
 apply leq_trans with (n := job_interference job_cost sched j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost sched j_i j_fst t1
(a_fst + R_k) + service_during sched j_fst (a_fst + R_k) t2).
{
rewrite leq_add2l.
@@ 499,7 +514,7 @@ Module InterferenceBoundEDF.
}
unfold service_during.
rewrite > cumulative_service_after_job_rt_zero with
 (job_cost0 := job_cost) (R := R_k); try (by done).
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (R := R_k); try (by done).
rewrite addn0; apply extend_sum; first by apply leqnn.
by rewrite leq_add2l; apply H_R_k_le_deadline.
}
@@ 508,7 +523,7 @@ Module InterferenceBoundEDF.
unfold job_interference.
rewrite > big_cat_nat with (n := a_fst + R_k);
[simpl by apply AFTERt1  by rewrite leq_add2l; apply H_R_k_le_deadline].
 apply leq_trans with (n := job_interference job_cost sched j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost sched j_i j_fst t1
(a_fst+R_k) + service_during sched j_fst (a_fst+R_k) (a_fst+D_k) + (D_kR_k)).
{
rewrite leq_add2r leq_add2l.
@@ 516,7 +531,7 @@ Module InterferenceBoundEDF.
}
unfold service_during.
rewrite > cumulative_service_after_job_rt_zero with
 (job_cost0 := job_cost) (R:=R_k); try (by done).
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (R:=R_k); try (by done).
rewrite addn0.
apply leq_trans with (n := (\sum_(t1 <= t < a_fst + R_k) 1) +
\sum_(a_fst + R_k <= t < a_fst + D_k) 1).
@@ 549,7 +564,7 @@ Module InterferenceBoundEDF.
job_arrival j_fst + R_k >= job_arrival j_i + delta.
Proof.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask _].
+ destruct FST as [FSTarr [FSTtask _]].
rewrite leqNgt; apply/negP; intro LT.
move: H_j_fst_not_complete_by_rt_bound => /negP BUG; apply BUG.
by apply H_all_previous_jobs_completed_on_time.
@@ 570,8 +585,10 @@ Module InterferenceBoundEDF.
by apply interference_bound_edf_response_time_bound_of_j_fst_after_interval.
}
apply/eqP; rewrite [_ _ _ _ == 0]negbK; apply/negP; red; intro BUG.
+ have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
+ destruct FST as [FSTarr [_ [LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in BUG; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in BUG; try (by done).
rewrite interference_bound_edf_j_fst_deadline
interference_bound_edf_j_i_deadline in BUG.
by apply (leq_trans LTdk) in BUG; rewrite ltnn in BUG.
@@ 585,10 +602,10 @@ Module InterferenceBoundEDF.
Proof.
intro LEdk.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask [LEdl _]].
+ destruct FST as [FSTarr [FSTtask [LEdl _]]].
have LTr := interference_bound_edf_response_time_bound_of_j_fst_after_interval.
apply subh3; last by apply LEdk.
 apply leq_trans with (n := job_interference job_cost sched j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost sched j_i j_fst t1
(job_arrival j_fst + R_k) + (D_k  R_k));
first by rewrite leq_add2r; apply extend_sum; [by apply leqnn].
apply leq_trans with (n := \sum_(t1 <= t < a_fst + R_k) 1 +
@@ 615,7 +632,7 @@ Module InterferenceBoundEDF.
unfold D_i, D_k, t1, a_fst; rewrite interference_bound_edf_j_fst_deadline
interference_bound_edf_j_i_deadline.
by apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl.
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl.
Qed.
End ResponseTimeOfSingleJobNotBounded.
@@ 672,6 +689,7 @@ Module InterferenceBoundEDF.
(* The last job is an interfering job of task tsk_k. *)
Lemma interference_bound_edf_j_lst_is_job_of_tsk_k :
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk_k /\
interference_caused_by j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 687,8 +705,8 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [LSTtask _].
 by specialize (PARAMS j_lst); des; rewrite PARAMS1 LSTtask.
+ destruct LST as [LSTarr [LSTtask _]].
+ by specialize (PARAMS j_lst LSTarr); des; rewrite PARAMS1 LSTtask.
Qed.
(* The first job arrives before the last job. *)
@@ 711,12 +729,12 @@ Module InterferenceBoundEDF.
apply mem_nth; instantiate (1 := num_mid_jobs.+1).
by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
}
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
+ instantiate (1 := elem); move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
apply LSTserv; apply/eqP; rewrite leqn0.
apply leq_trans with (n := service_during sched j_lst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP; unfold service_during.
 by apply cumulative_service_before_job_arrival_zero.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
Qed.
(* Since there are multiple jobs, j_fst is far enough from the end of
@@ 731,7 +749,7 @@ Module InterferenceBoundEDF.
{
by apply mem_nth; instantiate (1 := 1); rewrite H_at_least_two_jobs.
}
 instantiate (1 := elem); move => [SNDtsk [/eqP SNDserv _]].
+ instantiate (1 := elem); move => [SNDarr [SNDtsk [/eqP SNDserv _]]].
apply H_all_previous_jobs_completed_on_time; try (by done).
apply leq_ltn_trans with (n := job_arrival j_snd); last first.
{
@@ 740,7 +758,7 @@ Module InterferenceBoundEDF.
sched j_snd t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 by apply cumulative_service_before_job_arrival_zero.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
}
apply leq_trans with (n := a_fst + p_k).
{
@@ 750,8 +768,8 @@ Module InterferenceBoundEDF.
(* Since jobs are sporadic, we know that the first job arrives
at least p_k units before the second. *)
 unfold p_k; rewrite FST.
 apply H_sporadic_tasks; [ by rewrite SNDtsk  ]; last first.
+ unfold p_k; rewrite FST0.
+ apply H_sporadic_tasks; try (by done); [ by rewrite SNDtsk  ]; last first.
{
apply interference_bound_edf_jobs_ordered_by_arrival.
by rewrite H_at_least_two_jobs.
@@ 787,14 +805,13 @@ Module InterferenceBoundEDF.
assert (ARRle: job_arrival cur <= job_arrival next).
by unfold cur, next; apply interference_bound_edf_jobs_ordered_by_arrival.
 (* Show that both cur and next are in the arrival sequence *)
 assert (INnth: cur \in interfering_jobs /\ next \in interfering_jobs).
 {
 rewrite 2!interference_bound_edf_job_in_same_sequence; split.
 by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs; ins.
 by apply mem_nth; destruct sorted_jobs; ins.
 }
 rewrite 2?mem_filter in INnth; des.
+ feed (interference_bound_edf_all_jobs_from_tsk_k cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (interference_bound_edf_all_jobs_from_tsk_k next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
(* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
@@ 802,15 +819,15 @@ Module InterferenceBoundEDF.
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /interfering_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk.
}
 by rewrite subh3 // addnC /p_k INnth.
+ by rewrite subh3 // addnC /p_k CURtsk.
Qed.
(* Using the lemma above, we prove that the ratio n_k is at least the number of
@@ 836,9 +853,9 @@ Module InterferenceBoundEDF.
by rewrite leq_add2l; apply H_R_k_le_deadline.
}
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LEdl _]].
+ destruct LST as [LSTarr [_ [ LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
unfold D_i, D_k in DIST; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline in LEdl.
by rewrite ltnNge LEdl in DIST.
@@ 919,11 +936,11 @@ Module InterferenceBoundEDF.
apply leq_trans with (n := t1 + D_i);
last by rewrite addnA [D_i + _]addnC addnA leq_add2r addnC AFTERt1.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LSTserv _]].
+ destruct LST as [LSTarr [_ [ LSTserv _]]].
unfold D_i, D_k, a_lst, t1; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline.
by apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LSTserv.
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LSTserv.
Qed.
(* To conclude that the interference bound holds, it suffices to show that
@@ 949,7 +966,7 @@ Module InterferenceBoundEDF.
}
destruct (leqP t2 (a_fst + R_k)) as [LEt2  GTt2].
{
 apply leq_trans with (n := job_interference job_cost sched j_i j_fst t1
+ apply leq_trans with (n := job_interference job_arrival job_cost sched j_i j_fst t1
(a_fst + R_k));
first by apply extend_sum; rewrite ?leqnn.
simpl_sum_const; rewrite {1}[_ + R_k](addKn t1) addnBA //.
@@ 967,8 +984,8 @@ Module InterferenceBoundEDF.
apply leq_trans with (n := service_during sched j_fst (a_fst + R_k) t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k);
 [ by done   by apply leqnn].
+ apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k)
+ (job_arrival0 := job_arrival); [ by done   by apply leqnn].
by apply interference_bound_edf_j_fst_completed_on_time.
}
Qed.
@@ 1041,11 +1058,11 @@ Module InterferenceBoundEDF.
apply (leq_trans interference_bound_edf_bounding_interference_with_interval_lengths).
rewrite interference_bound_edf_simpl_by_concatenation_of_intervals leq_subLR.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LSTserv _]].
+ destruct LST as [LSTarr [_ [ LSTserv _]]].
unfold D_i, D_k, a_lst, t1; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline.
by apply interference_under_edf_implies_shorter_deadlines
 with (job_deadline0 := job_deadline) in LSTserv.
+ with (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LSTserv.
Qed.
End InterferenceOfFirstJob.
@@ 1099,7 +1116,7 @@ Module InterferenceBoundEDF.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
+ assert (EX: exists elem: Job, True).
destruct sorted_jobs as [ j]; [by rewrite ltn0 in NUM  by exists j].
destruct EX as [elem _].
@@ 1111,7 +1128,7 @@ Module InterferenceBoundEDF.
first by rewrite big_geq.
(* Then, we show the same for a single job, or for multiple jobs. *)
 rewrite SIZE; destruct n as [ num_mid_jobs].
+ destruct n as [ num_mid_jobs].
{
rewrite big_nat_recr // big_geq //.
rewrite [nth]lock /= lock add0n.
diff git a/analysis/global/basic/workload_bound.v b/analysis/global/basic/workload_bound.v
index 39ecac1..4d26cef 100644
 a/analysis/global/basic/workload_bound.v
+++ b/analysis/global/basic/workload_bound.v
@@ 122,6 +122,7 @@ Module WorkloadBound.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
Variable job_deadline: Job > time.
@@ 130,17 +131,20 @@ Module WorkloadBound.
(* Assume that all jobs have valid parameters *)
Hypothesis H_jobs_have_valid_parameters :
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider any schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* Assumption: jobs only execute if they arrived.
This is used to eliminate jobs that arrive after end of the interval t1 + delta. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* Assumption: jobs do not execute after they completed.
This is used to eliminate jobs that complete before the start of the interval t1. *)
@@ 154,7 +158,7 @@ Module WorkloadBound.
(* Assumption: sporadic task model.
This is necessary to conclude that consecutive jobs ordered by arrival times
are separated by at least 'period' times units. *)
 Hypothesis H_sporadic_tasks: sporadic_task_model task_period arr_seq job_task.
+ Hypothesis H_sporadic_tasks: sporadic_task_model task_period job_arrival job_task arr_seq.
(* Before starting the proof, let's give simpler names to the definitions. *)
Let job_has_completed_by := completed job_cost sched.
@@ 190,10 +194,11 @@ Module WorkloadBound.
Variable R_tsk: time.
Hypothesis H_response_time_bound :
 forall (j: JobIn arr_seq),
 job_task j = tsk >
 job_arrival j + R_tsk < t1 + delta >
 job_has_completed_by j (job_arrival j + R_tsk).
+ forall j,
+ arrives_in arr_seq j >
+ job_task j = tsk >
+ job_arrival j + R_tsk < t1 + delta >
+ job_has_completed_by j (job_arrival j + R_tsk).
(* ... such that R_tsk >= task_cost tsk and R_tsk <= task_deadline tsk. *)
Hypothesis H_response_time_ge_cost: R_tsk >= task_cost tsk.
@@ 215,8 +220,8 @@ Module WorkloadBound.
jobs_of_task_scheduled_between job_task sched tsk t1 t2.
(* Now, let's consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
 Let sorted_jobs := (sort earlier_arrival scheduled_jobs).
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
+ Let sorted_jobs := sort earlier_arrival scheduled_jobs.
(* The first step consists in simplifying the sum corresponding
to the workload. *)
@@ 246,18 +251,23 @@ Module WorkloadBound.
Lemma workload_bound_all_jobs_from_tsk :
forall j_i,
j_i \in sorted_jobs >
+ arrives_in arr_seq j_i /\
job_task j_i = tsk /\
service_during sched j_i t1 t2 != 0 /\
j_i \in jobs_scheduled_between sched t1 t2.
Proof.
+ rename H_jobs_come_from_arrival_sequence into FROMarr.
intros j_i LTi.
rewrite workload_bound_job_in_same_sequence mem_filter in LTi; des.
 repeat split; [by done   by done].
+ have IN := LTi0.
+ unfold jobs_scheduled_between in *; rewrite mem_undup in IN.
+ apply mem_bigcat_nat_exists in IN; des.
+ rewrite mem_scheduled_jobs_eq_scheduled in IN.
+ repeat split; try (by done); first by apply (FROMarr j_i i).
unfold jobs_scheduled_between in *; rewrite mem_undup in LTi0.
apply mem_bigcat_nat_exists in LTi0; des.
rewrite mem_scheduled_jobs_eq_scheduled in LTi0.
 apply service_implies_cumulative_service with (t := i);
 first by apply/andP; split.
+ apply service_implies_cumulative_service with (t := i); first by apply/andP; split.
by rewrite not_scheduled_no_service negbK.
Qed.
@@ 294,7 +304,7 @@ Module WorkloadBound.
apply leq_sum; intros j_i; move/andP => [INi _].
apply workload_bound_all_jobs_from_tsk in INi; des.
eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute  by apply INi ].
+ [by apply H_completed_jobs_dont_execute  by apply INi0 ].
by apply H_jobs_have_valid_parameters.
}
Qed.
@@ 308,11 +318,12 @@ Module WorkloadBound.
(* Assume that there's at least one job in the sorted list. *)
Hypothesis H_at_least_one_job: size sorted_jobs > 0.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
(* The first job is an interfering job of task tsk. *)
Lemma workload_bound_j_fst_is_job_of_tsk :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk /\
service_during sched j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 334,14 +345,14 @@ Module WorkloadBound.
rewrite [service_during _ _ _ _]add0n [_* task_cost tsk]mulSnr.
apply leq_add; first by done.
by eapply cumulative_service_le_task_cost;
 [ by apply INfst
+ [ by apply INfst0
 by apply H_jobs_have_valid_parameters].
}
{
rewrite 2!mul0n addn0 subn0 leq_min; apply/andP; split.
{
by eapply cumulative_service_le_task_cost;
 [ by apply INfst
+ [ by apply INfst0
 by apply H_jobs_have_valid_parameters].
}
{
@@ 362,12 +373,13 @@ Module WorkloadBound.
Variable num_mid_jobs: nat.
Hypothesis H_at_least_two_jobs : size sorted_jobs = num_mid_jobs.+2.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let j_lst := nth elem sorted_jobs num_mid_jobs.+1.
(* The last job is an interfering job of task tsk. *)
Lemma workload_bound_j_lst_is_job_of_tsk :
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk /\
service_during sched j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 386,11 +398,11 @@ Module WorkloadBound.
apply mem_nth; instantiate (1 := 0).
apply ltn_trans with (n := 1); [by done  by rewrite H_at_least_two_jobs].
}
 instantiate (1 := elem); move => [FSTtsk [/eqP FSTserv FSTin]].
+ instantiate (1 := elem); move => [FSTarr [FSTtsk [/eqP FSTserv FSTin]]].
apply FSTserv.
 apply (cumulative_service_after_job_rt_zero job_cost) with (R := R_tsk);
+ apply (cumulative_service_after_job_rt_zero job_arrival job_cost) with (R := R_tsk);
try (by done); last by apply ltnW.
 apply H_response_time_bound; first by done.
+ apply H_response_time_bound; try (by done).
by apply leq_trans with (n := t1); last by apply leq_addr.
Qed.
@@ 404,8 +416,9 @@ Module WorkloadBound.
apply mem_nth; instantiate (1 := num_mid_jobs.+1).
by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
}
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
 by unfold service_during; apply LSTserv, cumulative_service_before_job_arrival_zero.
+ instantiate (1 := elem); move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
+ unfold service_during; apply LSTserv.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
Qed.
(* Next, we upperbound the service of the first and last jobs using their arrival times. *)
@@ 431,11 +444,12 @@ Module WorkloadBound.
[ by apply workload_bound_response_time_of_first_job_inside_interval
 by apply ltnW].
rewrite {2}[\sum_(_ <= _ < _) _]addn0 /= leq_add2l leqn0; apply/eqP.
 apply (cumulative_service_after_job_rt_zero job_cost) with (R := R_tsk); try (by done).
 apply H_response_time_bound; last by done.
 exploit workload_bound_all_jobs_from_tsk.
 by apply mem_nth; instantiate (1 := 0); rewrite H_at_least_two_jobs.
 by instantiate (1 := elem); move => [FSTtsk _].
+ apply (cumulative_service_after_job_rt_zero job_arrival job_cost) with
+ (R := R_tsk); try (by done).
+ feed (workload_bound_all_jobs_from_tsk j_fst).
+ by apply mem_nth; rewrite H_at_least_two_jobs.
+ move => [FSTarr [FSTtsk _]].
+ by apply H_response_time_bound.
}
}
{
@@ 454,7 +468,7 @@ Module WorkloadBound.
[ by apply ltnW
 by apply ltnW, workload_bound_last_job_arrives_before_end_of_interval].
rewrite /= [\sum_(_ <= _ < _) 1]add0n; apply leq_add.
 rewrite cumulative_service_before_job_arrival_zero;
+ rewrite (cumulative_service_before_job_arrival_zero job_arrival);
[by apply leqnn  by ins  by apply leqnn].
by apply leq_sum; ins; apply service_at_most_one.
}
@@ 490,15 +504,14 @@ Module WorkloadBound.
last by rewrite big_const_nat iter_addn addn0 mulnC subn0.
rewrite big_nat_cond [\sum_(0 <= i < num_mid_jobs) task_cost _]big_nat_cond.
apply leq_sum; intros i; rewrite andbT; move => /andP LT; des.
 eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute   by apply H_jobs_have_valid_parameters].
exploit workload_bound_all_jobs_from_tsk.
{
instantiate (1 := nth elem sorted_jobs i.+1).
apply mem_nth; rewrite H_at_least_two_jobs.
by rewrite ltnS; apply leq_trans with (n := num_mid_jobs).
}
 by ins; des.
+ move => [ARR [TSK _]].
+ by eapply cumulative_service_le_task_cost; eauto 2.
Qed.
(* Conclude that the distance between first and last is at least num_mid_jobs + 1 periods. *)
@@ 521,14 +534,13 @@ Module WorkloadBound.
assert (ARRle: job_arrival cur <= job_arrival next).
by unfold cur, next; apply workload_bound_jobs_ordered_by_arrival.
 (* Show that both cur and next are in the arrival sequence *)
 assert (INnth: cur \in scheduled_jobs /\ next \in scheduled_jobs).
 {
 rewrite 2!workload_bound_job_in_same_sequence; split.
 by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs; ins.
 by apply mem_nth; destruct sorted_jobs; ins.
 }
 rewrite 2?mem_filter in INnth; des.
+ feed (workload_bound_all_jobs_from_tsk cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (workload_bound_all_jobs_from_tsk next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
(* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
@@ 536,15 +548,15 @@ Module WorkloadBound.
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /scheduled_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk.
}
 by rewrite subh3 // addnC INnth.
+ by rewrite subh3 // addnC CURtsk.
Qed.
(* Prove that n_k is at least the number of the middle jobs *)
@@ 645,8 +657,9 @@ Module WorkloadBound.
by rewrite H_at_least_two_jobs.
have INfst := workload_bound_j_fst_is_job_of_tsk SIZE elem;
have INlst := workload_bound_j_lst_is_job_of_tsk; des.
 by apply leq_add; apply cumulative_service_le_task_cost with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline) (job_task0 := job_task).
+ by apply leq_add; apply cumulative_service_le_task_cost with
+ (task_deadline0 := task_deadline) (job_cost0 := job_cost)
+ (job_deadline0 := job_deadline) (job_task0 := job_task); eauto 2.
}
{
rewrite subnAC subnK; last first.
@@ 689,8 +702,8 @@ Module WorkloadBound.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
 destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists j].
+ assert (EX: exists elem: Job, True).
+ destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists s].
destruct EX as [elem _].
(* Now we index the sum to access the first and last elements. *)
diff git a/analysis/global/jitter/bertogna_edf_comp.v b/analysis/global/jitter/bertogna_edf_comp.v
index 2c4fabe..88aadea 100755
 a/analysis/global/jitter/bertogna_edf_comp.v
+++ b/analysis/global/jitter/bertogna_edf_comp.v
@@ 21,6 +21,7 @@ Module ResponseTimeIterationEDF.
Let task_with_response_time := (sporadic_task * time)%type.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 960,25 +961,28 @@ Module ResponseTimeIterationEDF.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...they have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost
job_deadline job_task job_jitter j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
 (* Then, consider any platform with at least one CPU such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ (* Then, consider any schedule of this arrival sequence such that... *)
+ Variable sched: schedule Job num_cpus.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs only execute after jitter and no longer than their execution costs. *)
Hypothesis H_jobs_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 986,15 +990,16 @@ Module ResponseTimeIterationEDF.
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* Assume that we have a workconserving EDF scheduler. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
 Hypothesis H_edf_policy: respects_JLFP_policy job_cost job_jitter sched (EDF job_deadline).
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
+ Hypothesis H_edf_policy: respects_JLFP_policy job_arrival job_cost job_jitter arr_seq sched
+ (EDF job_arrival job_deadline).
Let no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in edf_claimed_bounds is safe. The proof follows by direct application of
@@ 1015,7 +1020,7 @@ Module ResponseTimeIterationEDF.
unfold response_time_bounded_by, is_response_time_bound_of_task in *.
intros j JOBtsk.
apply BOUND with (task_cost := task_cost) (task_period := task_period)
 (task_deadline := task_deadline) (job_deadline := job_deadline) (job_jitter := job_jitter)
+ (arr_seq := arr_seq) (task_deadline := task_deadline) (job_deadline := job_deadline) (job_jitter := job_jitter)
(job_task := job_task) (ts := ts) (tsk := tsk) (rt_bounds := rt_bounds); try (by ins).
by unfold edf_claimed_bounds in SOME; desf; rewrite edf_claimed_bounds_unzip1_iteration.
by ins; apply edf_claimed_bounds_finds_fixed_point_for_each_bound with (ts := ts).
@@ 1043,19 +1048,19 @@ Module ResponseTimeIterationEDF.
H_jobs_execute_after_jitter into AFTER,
H_all_jobs_from_taskset into ALLJOBS,
H_test_succeeds into TEST.
 move => tsk INtsk j JOBtsk.
+ move => tsk INtsk j ARRj JOBtsk.
destruct (edf_claimed_bounds ts) as [rt_bounds ] eqn:SOME; last by ins.
exploit (HAS rt_bounds tsk); [by ins  by ins  clear HAS; intro HAS; des].
 have COMPLETED := RLIST tsk R HAS j JOBtsk.
+ have COMPLETED := RLIST tsk R HAS j ARRj JOBtsk.
exploit (DL rt_bounds tsk R);
[by ins  by ins  clear DL; intro DL].

+
rewrite eqn_leq; apply/andP; split; first by apply cumulative_service_le_job_cost.
apply leq_trans with (n := service sched j (job_arrival j + task_jitter tsk + R)); last first.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
rewrite extend_sum // addnA leq_add2l.
 specialize (JOBPARAMS j); des; rewrite JOBPARAMS2.
+ specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS2.
by rewrite JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
@@ 1066,12 +1071,12 @@ Module ResponseTimeIterationEDF.
are spawned by the task set, we conclude that no job misses
its deadline. *)
Theorem jobs_schedulable_by_edf_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j, arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_edf_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/global/jitter/bertogna_edf_theory.v b/analysis/global/jitter/bertogna_edf_theory.v
index 2373e1e..fa969ae 100644
 a/analysis/global/jitter/bertogna_edf_theory.v
+++ b/analysis/global/jitter/bertogna_edf_theory.v
@@ 29,6 +29,7 @@ Module ResponseTimeAnalysisEDFJitter.
Variable task_jitter: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 40,9 +41,10 @@ Module ResponseTimeAnalysisEDFJitter.
(* ... in which jobs arrive sporadically and have valid parameters.
Note: the jitter of a valid job is bounded by the jitter of its task. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost
job_deadline job_task job_jitter j.
@@ 56,17 +58,21 @@ Module ResponseTimeAnalysisEDFJitter.
(* ... and that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
(* Next, consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs are sequential, do not execute before the
jitter has passed and nor longer than their execution costs. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
Hypothesis H_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 74,14 +80,15 @@ Module ResponseTimeAnalysisEDFJitter.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
(* Assume that the schedule is a workconserving EDF schedule. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
 Hypothesis H_edf_policy: respects_JLFP_policy job_cost job_jitter sched (EDF job_deadline).
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
+ Hypothesis H_edf_policy: respects_JLFP_policy job_arrival job_cost job_jitter arr_seq sched
+ (EDF job_arrival job_deadline).
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Next we consider the responsetime recurrence.
Assume that a responsetime bound R is known... *)
@@ 114,7 +121,8 @@ Module ResponseTimeAnalysisEDFJitter.
Hypothesis H_tsk_R_in_rt_bounds: (tsk, R) \in rt_bounds.
(* Consider any job j of tsk. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* Let t1 be the first point in time where j can actually be scheduled. *)
@@ 125,7 +133,8 @@ Module ResponseTimeAnalysisEDFJitter.
(* ...and that it is the first job not to satisfy its responsetime bound. *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_other: JobIn arr_seq) tsk_other R_other,
+ forall j_other tsk_other R_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
(tsk_other, R_other) \in rt_bounds >
job_arrival j_other + task_jitter tsk_other + R_other < job_arrival j + task_jitter tsk + R >
@@ 133,10 +142,10 @@ Module ResponseTimeAnalysisEDFJitter.
(* 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).
+ task_interference job_arrival 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).
+ Let X := total_interference job_arrival 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) :=
@@ 195,19 +204,19 @@ Module ResponseTimeAnalysisEDFJitter.
have INts := bertogna_edf_tsk_other_in_ts.
apply leq_trans with (n := workload job_task sched tsk_other t1 (t1 + R));
first by apply task_interference_le_workload.
 apply workload_bounded_by_W with (task_deadline0 := task_deadline)
 (job_jitter0 := job_jitter) (job_cost0 := job_cost) (job_deadline0 := job_deadline);
 try (by ins); last 2 first;
+ have BOUND := workload_bounded_by_W task_cost task_period task_deadline task_jitter
+ job_arrival job_cost job_task job_deadline job_jitter arr_seq _ sched.
+ apply BOUND; try (by done); last 2 first;
[ by apply NOMISS 
 by ins; apply TASK_PARAMS
 by apply RESTR
 by apply bertogna_edf_R_other_ge_cost].
{
 intros j0 JOB0 LT0; apply BEFOREok; try (by done).
+ intros j0 ARR0 JOB0 LT0; apply BEFOREok; try (by done).
unfold t1 in *.
apply leq_trans with (n := job_arrival j + job_jitter j + R); first by done.
rewrite leq_add2r leq_add2l.
 specialize (PARAMS j); des.
+ specialize (PARAMS j H_j_arrives); des.
rewrite H_job_of_tsk; apply PARAMS0.
}
Qed.
@@ 217,7 +226,7 @@ Module ResponseTimeAnalysisEDFJitter.
x tsk_other <= edf_specific_bound tsk_other R_other.
Proof.
by apply interference_bound_edf_bounds_interference with (job_deadline0 := job_deadline)
 (ts0 := ts); try (by done);
+ (arr_seq0 := arr_seq) (ts0 := ts); try (by done);
[ by apply bertogna_edf_tsk_other_in_ts
 by apply H_tasks_miss_no_deadlines
 by apply leq_trans with (n := task_jitter tsk + R);
@@ 250,21 +259,21 @@ Module ResponseTimeAnalysisEDFJitter.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(t1 <= t < t1 + R)
 backlogged job_cost job_jitter sched j t) +
+ backlogged job_arrival job_cost job_jitter sched j t) +
service sched j (t1 + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_j_arrives); des; rewrite JOBtsk.
}
unfold service.
rewrite > big_cat_nat with (n := t1) (m := 0); rewrite ?leq_addr // /=.
 rewrite (cumulative_service_before_jitter_zero job_jitter) // add0n.
+ rewrite (cumulative_service_before_jitter_zero job_arrival job_jitter) // add0n.
rewrite big_split /=.
apply leq_trans with (n := \sum_(t1 <= i < t1 + R) 1);
first by simpl_sum_const; rewrite addKn.
apply leq_sum_nat; move => i /andP [GEi LTi] _.
 destruct (backlogged job_cost job_jitter sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 283,7 +292,7 @@ Module ResponseTimeAnalysisEDFJitter.
Lemma bertogna_edf_interference_by_different_tasks :
forall t j_other,
t1 <= t < t1 + R >
 backlogged job_cost job_jitter sched j t >
+ backlogged job_arrival job_cost job_jitter sched j t >
scheduled sched j_other t >
job_task j_other != tsk.
Proof.
@@ 300,16 +309,17 @@ Module ResponseTimeAnalysisEDFJitter.
move => t j_other /andP [LEt GEt] BACK SCHED.
apply/eqP; red; intro SAMEtsk.
move: SCHED => /existsP [cpu SCHED].
 assert (SCHED': scheduled sched j_other t).
 by apply/existsP; exists cpu.
+ have SCHED': scheduled sched j_other t by apply/existsP; exists cpu.
clear SCHED; rename SCHED' into SCHED.
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (H_jobs_come_from_arrival_sequence j_other t).
move: (SCHED) => PENDING.
apply scheduled_implies_pending with (job_cost0 := job_cost) (job_jitter0 := job_jitter)
 in PENDING; try (by done).
+ (job_arrival0 := job_arrival) in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
move: (BEFOREother) => LT; rewrite (ltn_add2r R) in LT.
 exploit (BEFOREok j_other tsk R SAMEtsk INbounds).
+ exploit (BEFOREok j_other tsk R ARRother SAMEtsk INbounds).
{
rewrite addnA [_ + R]addnC addnA [(_ + _) + R]addnA [_ tsk + R]addnC addnA.
by rewrite ltn_add2r.
@@ 326,12 +336,12 @@ Module ResponseTimeAnalysisEDFJitter.
by apply leq_trans with (n := task_deadline tsk);
[by apply NOMISS  by apply CONSTR; rewrite JOBtsk FROMTS].
}
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; [  by done  by done by rewrite JOBtsk  by apply ltnW].
by red; intro EQ; subst; rewrite ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge JOBtsk.
apply leq_trans with (n := job_arrival j + task_deadline tsk);
@@ 341,7 +351,7 @@ Module ResponseTimeAnalysisEDFJitter.
apply leq_trans with (n := t1 + R); last first.
{
rewrite leq_add2r leq_add2l JOBtsk.
 by specialize (JOBPARAMS j); des.
+ by specialize (JOBPARAMS j H_j_arrives); des.
}
apply leq_ltn_trans with (n := job_arrival j_other + job_jitter j_other);
first by apply leq_addr.
@@ 358,8 +368,9 @@ Module ResponseTimeAnalysisEDFJitter.
With this lemma, we can conclude that during job j's scheduling
window there cannot be multiple pending jobs of each task.*)
Lemma bertogna_edf_all_previous_jobs_complete_by_their_period:
 forall t (j0: JobIn arr_seq),
+ forall t j0,
t < t1 + R >
+ arrives_in arr_seq j0 >
job_arrival j0 + task_period (job_task j0) <= t >
completed job_cost sched j0
(job_arrival j0 + task_period (job_task j0)).
@@ 372,7 +383,7 @@ Module ResponseTimeAnalysisEDFJitter.
H_all_jobs_from_taskset into FROMTS,
H_all_previous_jobs_completed_on_time into BEFOREok.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 intros t j0 LEt LE.
+ intros t j0 LEt ARR0 LE.
cut ((job_task j0) \in unzip1 rt_bounds = true); last by rewrite UNZIP FROMTS.
move => /mapP [p IN EQ]; destruct p as [tsk' R0]; simpl in *; subst tsk'.
apply completion_monotonic with (t0 := job_arrival j0 +
@@ 387,7 +398,7 @@ Module ResponseTimeAnalysisEDFJitter.
{
apply leq_trans with (n := t1 + R); first by done.
rewrite leq_add2r leq_add2l JOBtsk.
 by specialize (JOBPARAMS j); des.
+ by specialize (JOBPARAMS j H_j_arrives); des.
}
apply leq_trans with (n := job_arrival j0 + task_period (job_task j0)); last by done.
by rewrite addnA leq_add2l; apply leq_trans with (n := task_deadline (job_task j0));
@@ 406,13 +417,13 @@ Module ResponseTimeAnalysisEDFJitter.
Lemma bertogna_edf_all_cpus_are_busy:
forall t,
t1 <= t < t1 + R >
 backlogged job_cost job_jitter sched j t >
+ backlogged job_arrival job_cost job_jitter sched j t >
count (other_scheduled_task t) ts = num_cpus.
Proof.
rename H_all_jobs_from_taskset into FROMTS,
H_valid_task_parameters into PARAMS,
H_valid_job_parameters into JOBPARAMS,
 H_job_of_tsk into JOBtsk,
+ H_job_of_tsk into JOBtsk, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_sporadic_tasks into SPO,
H_tsk_R_in_rt_bounds into INbounds,
H_all_previous_jobs_completed_on_time into BEFOREok,
@@ 423,37 +434,30 @@ Module ResponseTimeAnalysisEDFJitter.
unfold x, X, total_interference, task_interference,
valid_sporadic_job_with_jitter, valid_sporadic_job in *.
move => t /andP [LEt LTt] BACK.
 eapply platform_cpus_busy_with_interfering_tasks; try (by done);
 [ by apply WORK  by done  by apply SPO
  apply PARAMS; rewrite JOBtsk; apply FROMTS
  by apply JOBtsk  by apply BACK  ].
+ have PLAT := platform_cpus_busy_with_interfering_tasks task_cost task_period task_deadline
+ job_arrival job_cost job_task job_jitter arr_seq sched FROMSEQ WORK.
+ apply PLAT with (j := j); try (by done);
+ [by apply PARAMS; rewrite JOBtsk; apply FROMTS  clear PLAT].
+ intros j0 tsk0 ARR0 TSK0 LE.
+ cut (tsk0 \in unzip1 rt_bounds = true); last by rewrite UNZIP TSK0 FROMTS //.
+ move => /mapP [p IN EQ]; destruct p as [tsk' R0]; simpl in *; subst tsk'.
+ apply completion_monotonic with (t0 := job_arrival j0 + task_jitter tsk0 + R0); try (by done).
{
 intros j0 tsk0 TSK0 LE.
 cut (tsk0 \in unzip1 rt_bounds = true); last by rewrite UNZIP TSK0 FROMTS.
 move => /mapP [p IN EQ]; destruct p as [tsk' R0]; simpl in *; subst tsk'.
 apply completion_monotonic with (t0 := job_arrival j0 + task_jitter tsk0 + R0); try (by done).
 {
 rewrite addnA leq_add2l TSK0.
 apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
 by apply RESTR; rewrite TSK0 FROMTS.
 }
 {
 apply BEFOREok with (tsk_other := tsk0); try (by done).
 apply leq_trans with (n := t1 + R); last first.
 {
 rewrite leq_add2r leq_add2l JOBtsk.
 by specialize (JOBPARAMS j); des.
 }
 apply leq_ltn_trans with (n := t); last by done.
 apply leq_trans with (n := job_arrival j0 + task_period tsk0);
 last by done.
 rewrite addnA leq_add2l.
 apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
 by apply RESTR; rewrite TSK0; apply FROMTS.
 }
+ rewrite addnA leq_add2l TSK0.
+ apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
+ by apply RESTR; rewrite TSK0 FROMTS.
+ }
+ {
+ apply BEFOREok with (tsk_other := tsk0); try (by done).
+ apply leq_trans with (n := t1 + R);
+ last by rewrite leq_add2r leq_add2l JOBtsk; specialize (JOBPARAMS j H_j_arrives); des.
+ apply leq_ltn_trans with (n := t); last by done.
+ apply leq_trans with (n := job_arrival j0 + task_period tsk0); last by done.
+ rewrite addnA leq_add2l.
+ apply leq_trans with (n := task_deadline tsk0); first by apply NOMISS.
+ by apply RESTR; rewrite TSK0; apply FROMTS.
}
Qed.

(* 4) 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
@@ 464,27 +468,27 @@ Module ResponseTimeAnalysisEDFJitter.
\sum_(tsk_k < other_tasks) x tsk_k = X * num_cpus.
Proof.
have DIFFTASK := bertogna_edf_interference_by_different_tasks.
 rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
+ rename H_all_jobs_from_taskset into FROMTS, H_valid_task_parameters into PARAMS,
H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
 H_work_conserving into WORK,
+ H_work_conserving into WORK, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_tsk_R_in_rt_bounds into INbounds,
H_all_previous_jobs_completed_on_time into BEFOREok,
 H_tasks_miss_no_deadlines into NOMISS,
 H_rt_bounds_contains_all_tasks into UNZIP,
+ H_tasks_miss_no_deadlines into NOMISS, H_rt_bounds_contains_all_tasks into UNZIP,
H_constrained_deadlines into CONSTR.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK;
last by rewrite big1 //; ins; rewrite big1.
rewrite big_mkcond /=.
rewrite exchange_big /=.
apply eq_trans with (y := \sum_(cpu < num_cpus) 1); last by simpl_sum_const.
apply eq_bigr; intros cpu _.
 move: (WORK j t BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ move: (WORK j t H_j_arrives BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (FROMSEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
rewrite (eq_bigr (fun i => 0));
@@ 512,10 +516,9 @@ Module ResponseTimeAnalysisEDFJitter.
Proof.
have COMP := bertogna_edf_all_previous_jobs_complete_by_their_period.
have INV := bertogna_edf_all_cpus_are_busy.
 rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
+ rename H_all_jobs_from_taskset into FROMTS, H_valid_task_parameters into PARAMS,
H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
 H_tsk_R_in_rt_bounds into INbounds,
+ H_tsk_R_in_rt_bounds into INbounds, H_jobs_come_from_arrival_sequence into FROMSEQ,
H_all_previous_jobs_completed_on_time into BEFOREok,
H_tasks_miss_no_deadlines into NOMISS,
H_constrained_deadlines into CONSTR, H_sequential_jobs into SEQ.
@@ 524,11 +527,11 @@ Module ResponseTimeAnalysisEDFJitter.
rewrite has_count in HAS.
set some_interference_A := fun t =>
 has (fun tsk_k => backlogged job_cost job_jitter sched j t &&
+ has (fun tsk_k => backlogged job_arrival job_cost job_jitter sched j t &&
(x tsk_k >= delta) &&
task_is_scheduled job_task sched tsk_k t) other_tasks.
set total_interference_B := fun t =>
 backlogged job_cost job_jitter sched j t *
+ backlogged job_arrival job_cost job_jitter sched j t *
count (fun tsk_k => (x tsk_k < delta) &&
task_is_scheduled job_task sched tsk_k t) other_tasks.
@@ 540,7 +543,7 @@ Module ResponseTimeAnalysisEDFJitter.
apply leq_trans with (n := x tsk_a); first by apply LEa.
unfold x, task_interference, some_interference_A.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK;
last by rewrite (eq_bigr (fun x => 0)); [by simpl_sum_const  by ins].
destruct ([exists cpu, task_scheduled_on job_task sched tsk_a cpu t]) eqn:SCHED;
last first.
@@ 566,12 +569,16 @@ Module ResponseTimeAnalysisEDFJitter.
destruct (sched cpu' t) as [j2] eqn:SCHED2; last by done.
move: SCHED SCHED' => /eqP JOB /eqP JOB'.
subst tsk_a; symmetry in JOB'.
 assert (PENDING1: pending job_cost job_jitter sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu'; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost job_jitter sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu; apply/eqP.
}
 assert (PENDING2: pending job_cost job_jitter sched j2 t).
+ assert (PENDING2: pending job_arrival job_cost job_jitter sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu'; apply/eqP.
@@ 580,10 +587,11 @@ Module ResponseTimeAnalysisEDFJitter.
{
apply platform_at_most_one_pending_job_of_each_task with (task_cost0 := task_cost)
(job_jitter0 := job_jitter) (task_period0 := task_period) (job_cost0 := job_cost)
 (task_deadline0 := task_deadline) (tsk0 := tsk) (job_task0 := job_task) (sched0 := sched)
+ (task_deadline0 := task_deadline) (tsk0 := tsk) (job_task0 := job_task)
+ (sched0 := sched) (job_arrival0 := job_arrival) (arr_seq0 := arr_seq)
(j0 := j) (t0 := t);
rewrite ?JOBtsk ?SAMEtsk //; first by apply PARAMS; rewrite JOBtsk FROMTS.
 by intros j0 tsk0 TSK0 LE; apply (COMP t); rewrite ?TSK0.
+ by intros j0 tsk0 ARR0 TSK0 LE; apply (COMP t); rewrite ?TSK0.
}
by subst j2; apply SEQ with (j := j1) (t := t).
}
@@ 593,7 +601,7 @@ Module ResponseTimeAnalysisEDFJitter.
rewrite big_distrl /=.
apply leq_sum_nat; move => t LEt _.
unfold some_interference_A, total_interference_B.
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK;
[rewrite mul1n /=  by rewrite has_pred0 //].
destruct (has (fun tsk_k : sporadic_task => (delta <= x tsk_k) &&
@@ 622,7 +630,7 @@ Module ResponseTimeAnalysisEDFJitter.
{
unfold x at 2, total_interference_B.
rewrite exchange_big /=; apply leq_sum; intros t _.
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK; last by ins.
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK; last by ins.
rewrite mul1n sum1_count.
rewrite big_mkcond [\sum_(i < other_tasks  _ < _) _]big_mkcond /=.
apply leq_sum_seq; move => tsk_k IN _.
@@ 794,7 +802,7 @@ Module ResponseTimeAnalysisEDFJitter.
have EDFBOUND := bertogna_edf_specific_bound_holds.
rename H_valid_job_parameters into JOBPARAMS.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
rewrite addnA.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
@@ 806,10 +814,11 @@ Module ResponseTimeAnalysisEDFJitter.
(* Now, we apply strong induction on the absolute responsetime bound. *)
induction ctime as [ctime IH] using strong_ind.
 intros j tsk' JOBtsk R' EQc INbounds; subst ctime.
+ intros j ARRj tsk' JOBtsk R' EQc INbounds; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq) tsk R0,
+ assert (BEFOREok: forall j0 tsk R0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
(tsk, R0) \in rt_bounds >
job_arrival j0 + task_jitter tsk + R0 < job_arrival j + task_jitter tsk' + R' >
@@ 826,21 +835,21 @@ Module ResponseTimeAnalysisEDFJitter.
{
apply completion_monotonic with (t := job_arrival j + job_jitter j + R'); try (by done).
rewrite leq_add2r leq_add2l.
 specialize (JOBPARAMS j); des.
+ specialize (JOBPARAMS j ARRj); des.
by rewrite JOBtsk; apply JOBPARAMS0.
}
apply negbT in NOTCOMP; exfalso.
(* Next, we derive a contradiction using the previous lemmas. *)
 exploit (EXISTS tsk' R' INbounds j JOBtsk NOTCOMP).
+ exploit (EXISTS tsk' R' INbounds j ARRj JOBtsk NOTCOMP).
{
by ins; apply IH with (tsk := tsk_other) (R := R_other).
}
intro EX; destruct EX as [tsk_other [R_other [HP LTmin]]].
unfold interference_bound_edf, interference_bound_generic in LTmin.
rewrite minnAC in LTmin; apply min_lt_same in LTmin.
 specialize (BASICBOUND tsk' R' j JOBtsk BEFOREok tsk_other R_other HP).
 specialize (EDFBOUND tsk' R' INbounds j JOBtsk BEFOREok tsk_other R_other HP).
+ specialize (BASICBOUND tsk' R' j ARRj JOBtsk BEFOREok tsk_other R_other HP).
+ specialize (EDFBOUND tsk' R' INbounds j ARRj JOBtsk BEFOREok tsk_other R_other HP).
unfold minn in LTmin; clear LTmin HP BASICBOUND EDFBOUND tsk; desf.
{
by apply (leq_ltn_trans BASICBOUND) in LTmin; rewrite ltnn in LTmin.
diff git a/analysis/global/jitter/bertogna_fp_comp.v b/analysis/global/jitter/bertogna_fp_comp.v
index 12c0ff8..05dad2c 100644
 a/analysis/global/jitter/bertogna_fp_comp.v
+++ b/analysis/global/jitter/bertogna_fp_comp.v
@@ 21,6 +21,7 @@ Module ResponseTimeIterationFP.
Let task_with_response_time := (sporadic_task * time)%type.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 494,25 +495,28 @@ Module ResponseTimeIterationFP.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...they have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost
job_deadline job_task job_jitter j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
 (* Then, consider any platform with at least one CPU such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ (* Then, consider any schedule of this arrival sequence such that... *)
+ Variable sched: schedule Job num_cpus.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs only execute after jitter and no longer than their execution costs. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 520,16 +524,16 @@ Module ResponseTimeIterationFP.
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* Assume that the scheduler is workconserving and respects the FP policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_respects_FP_policy:
 respects_FP_policy job_cost job_task job_jitter sched higher_priority.
+ respects_FP_policy job_arrival job_cost job_task job_jitter arr_seq sched higher_priority.
Let no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in fp_claimed_bounds is safe. The proof follows by induction on the task set:
@@ 681,7 +685,7 @@ Module ResponseTimeIterationFP.
fp_schedulable,
valid_sporadic_job_with_jitter, valid_sporadic_job in *.
rename H_valid_job_parameters into JOBPARAMS.
 move => tsk INtsk j JOBtsk.
+ move => tsk INtsk j ARRj JOBtsk.
destruct (fp_claimed_bounds ts) as [rt_bounds ]; last by ins.
feed (UNZIP rt_bounds); first by done.
assert (EX: exists R, (tsk, R) \in rt_bounds).
@@ 689,15 +693,16 @@ Module ResponseTimeIterationFP.
rewrite set_mem UNZIP in INtsk; move: INtsk => /mapP EX.
by destruct EX as [p]; destruct p as [tsk' R]; simpl in *; subst tsk'; exists R.
} des.
 exploit (RLIST tsk R); [by ins  by apply JOBtsk  intro COMPLETED].
+ exploit (RLIST tsk R); [by done  by apply ARRj  by done  intro COMPLETED].
exploit (DL rt_bounds tsk R); [by ins  by ins  clear DL; intro DL].
rewrite eqn_leq; apply/andP; split; first by apply cumulative_service_le_job_cost.
 apply leq_trans with (n := service sched j (job_arrival j + (task_jitter tsk + R))); last first.
+ apply leq_trans with (n := service sched j (job_arrival j + (task_jitter tsk + R)));
+ last first.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
apply extend_sum; rewrite // leq_add2l.
 by specialize (JOBPARAMS j); des; rewrite JOBPARAMS2 JOBtsk.
+ by specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS2 JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
by apply COMPLETED.
@@ 707,12 +712,13 @@ Module ResponseTimeIterationFP.
are spawned by the task set, we also conclude that no job in
the schedule misses its deadline. *)
Theorem jobs_schedulable_by_fp_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j,
+ arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_fp_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/global/jitter/bertogna_fp_theory.v b/analysis/global/jitter/bertogna_fp_theory.v
index 8b37726..34c1a9f 100644
 a/analysis/global/jitter/bertogna_fp_theory.v
+++ b/analysis/global/jitter/bertogna_fp_theory.v
@@ 30,6 +30,7 @@ Module ResponseTimeAnalysisFP.
Variable task_jitter: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 40,9 +41,10 @@ Module ResponseTimeAnalysisFP.
(* ... in which jobs arrive sporadically and have valid parameters. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost
job_deadline job_task job_jitter j.
@@ 56,17 +58,19 @@ Module ResponseTimeAnalysisFP.
(* ... and that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j > job_task j \in ts.
 (* Next, consider any schedule such that...*)
+ (* Next, consider any schedule of this arrival sequence such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence: jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs are sequential, do not execute before the jitter
has passed and nor longer than their execution costs. *)
Hypothesis H_sequential_jobs: sequential_jobs sched.
Hypothesis H_jobs_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 77,15 +81,15 @@ Module ResponseTimeAnalysisFP.
Variable higher_eq_priority: FP_policy sporadic_task.
(* ...and assume that the schedule is workconserving and respects this policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_respects_priority:
 respects_FP_policy job_cost job_task job_jitter sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_task job_jitter arr_seq sched higher_eq_priority.
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Next, we consider the responsetime recurrence.
Let tsk be a task in ts that is to be analyzed. *)
@@ 140,7 +144,8 @@ Module ResponseTimeAnalysisFP.
Section Lemmas.
(* Consider any job j of tsk. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_job_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* Let t1 be the first point in time where j can actually be scheduled. *)
@@ 149,17 +154,18 @@ Module ResponseTimeAnalysisFP.
(* 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 :
 forall (j0: JobIn arr_seq),
+ forall j0,
+ arrives_in arr_seq j0 >
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).
+ task_interference job_arrival 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).
+ Let X := total_interference job_arrival 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) :=
@@ 211,12 +217,16 @@ Module ResponseTimeAnalysisFP.
}
move: SCHED => /existsP [t /existsP [cpu SCHED]].
unfold task_scheduled_on in SCHED.
 destruct (sched cpu t) as [j0 ]; last by done.
+ destruct (sched cpu t) as [j0 ] eqn:SCHED0; last by done.
assert (INts: tsk_other \in ts).
 by move: SCHED => /eqP <; rewrite FROMTS.
+ {
+ move: SCHED => /eqP <. apply FROMTS, (H_jobs_come_from_arrival_sequence j0 t).
+ by apply/existsP; exists cpu; apply/eqP.
+ }
apply leq_trans with (n := workload job_task sched tsk_other t1 (t1 + R));
 first by apply task_interference_le_workload.
 by apply workload_bounded_by_W with (task_deadline0 := task_deadline)
+ first by apply task_interference_le_workload.
+ apply workload_bounded_by_W with (task_deadline0 := task_deadline)
+ (job_arrival0 := job_arrival) (arr_seq0 := arr_seq)
(job_jitter0 := job_jitter) (job_cost0 := job_cost) (job_deadline0 := job_deadline);
try (by ins); last 2 first;
[ by apply NOMISS
@@ 252,21 +262,21 @@ Module ResponseTimeAnalysisFP.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(t1 <= t < t1 + R)
 backlogged job_cost job_jitter sched j t) +
+ backlogged job_arrival job_cost job_jitter sched j t) +
service sched j (t1 + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_job_arrives); des; rewrite JOBtsk.
}
unfold service.
rewrite > big_cat_nat with (n := t1) (m := 0); rewrite ?leq_addr // /=.
 rewrite (cumulative_service_before_jitter_zero job_jitter) // add0n.
+ rewrite (cumulative_service_before_jitter_zero job_arrival job_jitter) // add0n.
rewrite big_split /=.
apply leq_trans with (n := \sum_(t1 <= i < t1 + R) 1);
first by simpl_sum_const; rewrite addKn.
apply leq_sum_nat; move => i /andP [GEi LTi] _.
 destruct (backlogged job_cost job_jitter sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 285,7 +295,8 @@ Module ResponseTimeAnalysisFP.
Lemma bertogna_fp_interference_by_different_tasks :
forall t j_other,
t1 <= t < t1 + R >
 backlogged job_cost job_jitter sched j t >
+ arrives_in arr_seq j_other >
+ backlogged job_arrival job_cost job_jitter sched j t >
scheduled sched j_other t >
job_task j_other != tsk.
Proof.
@@ 297,19 +308,18 @@ Module ResponseTimeAnalysisFP.
H_previous_jobs_of_tsk_completed into PREV,
H_response_time_no_larger_than_deadline into NOMISS.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 move => t j_other /andP [LEt GEt] BACK SCHED.
+ move => t j_other /andP [LEt GEt] ARRother BACK SCHED.
apply/eqP; red; intro SAMEtsk.
move: SCHED => /existsP [cpu SCHED].
 assert (SCHED': scheduled sched j_other t).
 by apply/existsP; exists cpu.
+ have SCHED': scheduled sched j_other t by apply/existsP; exists cpu.
clear SCHED; rename SCHED' into SCHED.
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost) (job_jitter0 := job_jitter)
 in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) (job_jitter0 := job_jitter) in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
move: (BEFOREother) => LT; rewrite (ltn_add2r R) in LT.
 specialize (PREV j_other SAMEtsk BEFOREother).
+ specialize (PREV j_other ARRother SAMEtsk BEFOREother).
move: PENDING => /andP [_ /negP NOTCOMP]; apply NOTCOMP.
apply completion_monotonic with (t0 := job_arrival j_other + task_jitter tsk + R);
try by done.
@@ 321,12 +331,12 @@ Module ResponseTimeAnalysisFP.
by apply leq_trans with (n := task_deadline tsk);
[by apply NOMISS  by apply CONSTR; rewrite JOBtsk FROMTS].
}
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; [  by done  by done  by rewrite JOBtsk  by apply ltnW].
by red; intro EQ; subst j_other; rewrite ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge JOBtsk.
apply leq_trans with (n := job_arrival j + task_deadline tsk);
@@ 336,7 +346,7 @@ Module ResponseTimeAnalysisFP.
apply leq_trans with (n := t1 + R); last first.
{
rewrite leq_add2r leq_add2l JOBtsk.
 by specialize (JOBPARAMS j); des.
+ by specialize (JOBPARAMS j H_job_arrives); des.
}
apply leq_ltn_trans with (n := job_arrival j_other + job_jitter j_other);
first by apply leq_addr.
@@ 357,7 +367,7 @@ Module ResponseTimeAnalysisFP.
Lemma bertogna_fp_all_cpus_are_busy:
forall t,
t1 <= t < t1 + R >
 backlogged job_cost job_jitter sched j t >
+ backlogged job_arrival job_cost job_jitter sched j t >
count (other_scheduled_task t) ts = num_cpus.
Proof.
rename H_valid_task_parameters into PARAMS,
@@ 376,23 +386,23 @@ Module ResponseTimeAnalysisFP.
apply platform_fp_cpus_busy_with_interfering_tasks with (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline) (job_task0 := job_task)
 (ts0 := ts) (tsk0 := tsk) (higher_eq_priority0 := higher_eq_priority) in BACK;
 try (by done); first by apply PARAMS; rewrite JOBtsk FROMTS.
+ (ts0 := ts) (tsk0 := tsk) (higher_eq_priority0 := higher_eq_priority) (arr_seq0 := arr_seq)
+ in BACK; try (by done); first by apply PARAMS; rewrite JOBtsk FROMTS.
{
apply leq_trans with (n := job_arrival j + job_jitter j + R); first by done.
rewrite addnA leq_add2l.
apply leq_trans with (n := task_deadline tsk); last by apply RESTR.
apply leq_trans with (n := task_jitter tsk + R); last by done.
 by rewrite leq_add2r JOBtsk; specialize (JOBPARAMS j); des.
+ by rewrite leq_add2r JOBtsk; specialize (JOBPARAMS j H_job_arrives); des.
}
{
 intros j_other tsk_other JOBother INTERF.
+ intros j_other tsk_other ARRother JOBother INTERF.
feed (HAS tsk_other); first by rewrite JOBother FROMTS.
move: (HAS INTERF) => [R' IN].
apply completion_monotonic with (t0 := job_arrival j_other + task_jitter tsk_other + R');
try (by done); last by rewrite addnA; apply PREV.
 by rewrite addnA leq_add2l; apply leq_trans with (n := task_deadline tsk_other);
 [by apply NOMISS  by apply RESTR; rewrite JOBother].
+ rewrite addnA leq_add2l; apply leq_trans with (n := task_deadline tsk_other);
+ [by apply NOMISS  by apply RESTR; rewrite JOBother; apply FROMTS].
}
{
ins; apply completion_monotonic with (t0 := job_arrival j0 + task_jitter tsk + R);
@@ 402,7 +412,6 @@ Module ResponseTimeAnalysisFP.
}
Qed.

(* 3) Now we prove that, at all times that j is backlogged, the number
of tasks other than tsk that are scheduled is exactly the number
of processors in the system. This is required to prove lemma (4). *)
@@ 411,25 +420,23 @@ Module ResponseTimeAnalysisFP.
Proof.
have DIFFTASK := bertogna_fp_interference_by_different_tasks.
rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
+ H_valid_task_parameters into PARAMS, H_jobs_come_from_arrival_sequence into SEQ,
H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
 H_work_conserving into WORK,
 H_constrained_deadlines into CONSTR,
+ H_work_conserving into WORK, H_constrained_deadlines into CONSTR,
H_previous_jobs_of_tsk_completed into PREV,
 H_respects_priority into FP,
 H_response_time_no_larger_than_deadline into NOMISS.
+ H_respects_priority into FP, H_response_time_no_larger_than_deadline into NOMISS.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /= mul1n.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK;
last by rewrite big1 //; ins; rewrite big1.
rewrite big_mkcond /=.
rewrite exchange_big /=.
apply eq_trans with (y := \sum_(cpu < num_cpus) 1); last by simpl_sum_const.
apply eq_bigr; intros cpu _.
 move: (WORK j t BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
+ move: (WORK j t H_job_arrives BACK cpu) => [j_other /eqP SCHED]; unfold scheduled_on in *.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
rewrite (eq_bigr (fun i => 0));
@@ 437,13 +444,15 @@ Module ResponseTimeAnalysisFP.
simpl_sum_const; apply/eqP; rewrite eqb1.
by unfold task_scheduled_on; rewrite SCHED.
}
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (SEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite mem_filter; apply/andP; split; last by apply FROMTS.
unfold is_hp_task, higher_priority_task; apply/andP; split.
{
rewrite JOBtsk; apply FP with (t := t); try by done.
by apply/existsP; exists cpu; apply/eqP.
}
 apply DIFFTASK with (t := t); [by auto  by done ].
+ apply DIFFTASK with (t := t); [by auto  by done  by done ].
by apply/existsP; exists cpu; apply/eqP.
Qed.
@@ 462,27 +471,24 @@ Module ResponseTimeAnalysisFP.
Proof.
have INV := bertogna_fp_all_cpus_are_busy.
rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
 H_valid_job_parameters into JOBPARAMS,
 H_job_of_tsk into JOBtsk,
 H_sporadic_tasks into SPO,
+ H_valid_task_parameters into PARAMS, H_valid_job_parameters into JOBPARAMS,
+ H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
H_previous_jobs_of_tsk_completed into BEFOREok,
H_response_time_no_larger_than_deadline into NOMISS,
H_constrained_deadlines into CONSTR,
 H_sequential_jobs into SEQ,
 H_respects_priority into FP,
 H_hp_bounds_has_interfering_tasks into HASHP,
+ H_sequential_jobs into SEQ, H_jobs_come_from_arrival_sequence into FROMSEQ,
+ H_respects_priority into FP, H_hp_bounds_has_interfering_tasks into HASHP,
H_interfering_tasks_miss_no_deadlines into NOMISSHP.
unfold sporadic_task_model, valid_sporadic_job_with_jitter, valid_sporadic_job in *.
move => delta /andP [HAS LT].
rewrite has_count in HAS.
set some_interference_A := fun t =>
 has (fun tsk_k => backlogged job_cost job_jitter sched j t &&
+ has (fun tsk_k => backlogged job_arrival job_cost job_jitter sched j t &&
(x tsk_k >= delta) &&
task_is_scheduled job_task sched tsk_k t) hp_tasks.
set total_interference_B := fun t =>
 backlogged job_cost job_jitter sched j t *
+ backlogged job_arrival job_cost job_jitter sched j t *
count (fun tsk_k => (x tsk_k < delta) &&
task_is_scheduled job_task sched tsk_k t) hp_tasks.
@@ 494,7 +500,7 @@ Module ResponseTimeAnalysisFP.
apply leq_trans with (n := x tsk_a); first by apply LEa.
unfold x, task_interference, some_interference_A.
apply leq_sum_nat; move => t /andP [GEt LTt] _.
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK;
last by rewrite (eq_bigr (fun x => 0)); [by simpl_sum_const  by ins].
destruct ([exists cpu, task_scheduled_on job_task sched tsk_a cpu t]) eqn:SCHED;
last first.
@@ 520,12 +526,16 @@ Module ResponseTimeAnalysisFP.
destruct (sched cpu' t) as [j2] eqn:SCHED2; last by done.
move: SCHED SCHED' => /eqP JOB /eqP JOB'.
subst tsk_a; symmetry in JOB'.
 assert (PENDING1: pending job_cost job_jitter sched j1 t).
+ have ARR1: arrives_in arr_seq j1.
+ by apply (FROMSEQ j1 t); apply/existsP; exists cpu; apply/eqP.
+ have ARR2: arrives_in arr_seq j2.
+ by apply (FROMSEQ j2 t); apply/existsP; exists cpu'; apply/eqP.
+ assert (PENDING1: pending job_arrival job_cost job_jitter sched j1 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu; apply/eqP.
}
 assert (PENDING2: pending job_cost job_jitter sched j2 t).
+ assert (PENDING2: pending job_arrival job_cost job_jitter sched j2 t).
{
apply scheduled_implies_pending; try by done.
by apply/existsP; exists cpu'; apply/eqP.
@@ 537,19 +547,19 @@ Module ResponseTimeAnalysisFP.
move: SAMEtsk => /eqP SAMEtsk.
move: (PENDING1) => SAMEjob.
apply platform_fp_no_multiple_jobs_of_tsk with (task_cost0 := task_cost)
 (task_period0 := task_period) (task_deadline0 := task_deadline)
+ (task_period0 := task_period) (task_deadline0 := task_deadline) (arr_seq0 := arr_seq)
(job_task0 := job_task) (tsk0 := tsk) (j0 := j) in SAMEjob; try (by done);
[  by apply PARAMS  ]; last 2 first.
{
apply (leq_trans LTt); rewrite addnA leq_add2l.
apply leq_trans with (n := task_deadline tsk); last by apply CONSTR.
apply leq_trans with (n := task_jitter tsk + R); last by apply NOMISS.
 by rewrite leq_add2r JOBtsk; specialize (JOBPARAMS j); des.
+ by rewrite leq_add2r JOBtsk; specialize (JOBPARAMS j H_job_arrives); des.
}
{
 intros j0 JOB0 LT0.
 apply completion_monotonic with (t0 := job_arrival j0 + task_jitter tsk + R); try (by done);
 last by apply BEFOREok.
+ intros j0 ARR0 JOB0 LT0.
+ apply completion_monotonic with (t0 := job_arrival j0 + task_jitter tsk + R);
+ try (by done); last by apply BEFOREok.
rewrite addnA leq_add2l.
by apply leq_trans with (n := task_deadline tsk); last by apply CONSTR.
}
@@ 560,16 +570,17 @@ Module ResponseTimeAnalysisFP.
assert (INTERF: is_hp_task (job_task j1)).
{
apply/andP; split; last by rewrite SAMEtsk.
 rewrite JOBtsk; apply FP with (t := t); first by done.
+ rewrite JOBtsk; apply FP with (t := t); try (by done).
by apply/existsP; exists cpu; apply/eqP.
}
apply platform_fp_no_multiple_jobs_of_interfering_tasks with
 (task_period0 := task_period) (tsk0 := tsk)
+ (task_period0 := task_period) (tsk0 := tsk) (job_arrival0 := job_arrival)
(higher_eq_priority0 := higher_eq_priority) (job_jitter0 := job_jitter)
+ (arr_seq0 := arr_seq)
(job_cost0 := job_cost) (job_task0 := job_task) (sched0 := sched) (t0 := t);
rewrite ?JOBtsk ?SAMEtsk //.
{
 intros j0 tsk0 JOB0 INTERF0.
+ intros j0 tsk0 ARR0 JOB0 INTERF0.
feed (HASHP tsk0); first by rewrite JOB0 FROMTS.
move: (HASHP INTERF0) => [R0 IN0].
apply completion_monotonic with (t0 := job_arrival j0 + task_jitter tsk0 + R0);
@@ 593,7 +604,7 @@ Module ResponseTimeAnalysisFP.
rewrite big_distrl /=.
apply leq_sum_nat; move => t LEt _.
unfold some_interference_A, total_interference_B.
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK;
[rewrite mul1n /=  by rewrite has_pred0 //].
destruct (has (fun tsk_k : sporadic_task => (delta <= x tsk_k) &&
@@ 622,7 +633,7 @@ Module ResponseTimeAnalysisFP.
{
unfold x at 2, total_interference_B.
rewrite exchange_big /=; apply leq_sum; intros t _.
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK; last by ins.
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK; last by ins.
rewrite mul1n sum1_count.
rewrite big_mkcond [\sum_(i < hp_tasks  _ < _) _]big_mkcond /=.
apply leq_sum_seq; move => tsk_k IN _.
@@ 771,7 +782,7 @@ Module ResponseTimeAnalysisFP.
have WORKLOAD := bertogna_fp_workload_bounds_interference.
rename H_valid_job_parameters into PARAMS.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
remember (job_arrival j + (task_jitter tsk + R)) as ctime.
@@ 780,10 +791,11 @@ Module ResponseTimeAnalysisFP.
generalize dependent j.
induction ctime as [ctime IH] using strong_ind.
 intros j JOBtsk EQc; subst ctime.
+ intros j ARRj JOBtsk EQc; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq),
+ assert (BEFOREok: forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
completed job_cost sched j0 (job_arrival j0 + task_jitter tsk + R)).
@@ 797,7 +809,7 @@ Module ResponseTimeAnalysisFP.
apply completion_monotonic with (t := job_arrival j + job_jitter j + R); first by done.
{
rewrite leq_add2r leq_add2l.
 specialize (PARAMS j); des.
+ specialize (PARAMS j ARRj); des.
by rewrite JOBtsk; apply PARAMS0.
}
destruct (completed job_cost sched j (job_arrival j + job_jitter j + R)) eqn:NOTCOMP;
@@ 805,7 +817,7 @@ Module ResponseTimeAnalysisFP.
apply negbT in NOTCOMP; exfalso.
(* We derive a contradiction using the previous lemmas. *)
 specialize (EX j JOBtsk NOTCOMP BEFOREok).
+ specialize (EX j ARRj JOBtsk NOTCOMP BEFOREok).
destruct EX as [tsk_k [R_k [HPk LTmin]]].
unfold minn at 1 in LTmin.
specialize (WORKLOAD j tsk_k R_k HPk).
diff git a/analysis/global/jitter/interference_bound_edf.v b/analysis/global/jitter/interference_bound_edf.v
index df36d60..88d4f55 100644
 a/analysis/global/jitter/interference_bound_edf.v
+++ b/analysis/global/jitter/interference_bound_edf.v
@@ 116,6 +116,7 @@ Module InterferenceBoundEDFJitter.
Variable task_jitter: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 126,18 +127,21 @@ Module InterferenceBoundEDFJitter.
(* ... in which jobs arrive sporadically and have valid parameters. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
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.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs do not execute before jitter nor longer than their execution costs. *)
Hypothesis H_jobs_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 150,27 +154,30 @@ Module InterferenceBoundEDFJitter.
parameters and constrained deadlines. *)
Variable ts: taskset_of sporadic_task.
Hypothesis all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j > job_task j \in ts.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
Hypothesis H_constrained_deadlines:
forall tsk, tsk \in ts > task_deadline tsk <= task_period tsk.
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Assume that we have a workconserving EDF scheduler. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
 Hypothesis H_edf_policy: respects_JLFP_policy job_cost job_jitter sched (EDF job_deadline).
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
+ Hypothesis H_edf_policy: respects_JLFP_policy job_arrival job_cost job_jitter arr_seq
+ sched (EDF job_arrival job_deadline).
(* Let tsk_i be the task to be analyzed, ...*)
Variable tsk_i: sporadic_task.
Hypothesis H_tsk_i_in_task_set: tsk_i \in ts.
(* and j_i one of its jobs. *)
 Variable j_i: JobIn arr_seq.
+ Variable j_i: Job.
+ Hypothesis H_j_i_arrives: arrives_in arr_seq j_i.
Hypothesis H_job_of_tsk_i: job_task j_i = tsk_i.
(* Let tsk_k denote any interfering task, ... *)
@@ 187,7 +194,8 @@ Module InterferenceBoundEDFJitter.
(* Assume that the jobs of tsk_k satisfy the responsetime bound before the end of the interval *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_k: JobIn arr_seq),
+ forall j_k,
+ arrives_in arr_seq j_k >
job_task j_k = tsk_k >
job_arrival j_k + task_jitter tsk_k + R_k < job_arrival j_i + task_jitter tsk_i + delta >
completed job_cost sched j_k (job_arrival j_k + task_jitter tsk_k + R_k).
@@ 202,7 +210,7 @@ Module InterferenceBoundEDFJitter.
(* Let's call x the task interference incurred by job j due to tsk_k. *)
Let x :=
 task_interference job_cost job_task job_jitter sched j_i tsk_k t1 t2.
+ task_interference job_arrival job_cost job_task job_jitter sched j_i tsk_k t1 t2.
(* Also, recall the EDFspecific interference bound for EDF. *)
Let interference_bound :=
@@ 219,16 +227,16 @@ Module InterferenceBoundEDFJitter.
Let n_k := div_floor D_i p_k.
(* Let's give a simpler name to job interference. *)
 Let interference_caused_by := job_interference job_cost job_jitter sched j_i.
+ Let interference_caused_by := job_interference job_arrival job_cost job_jitter sched j_i.
(* Identify the subset of jobs that actually cause interference *)
Let interfering_jobs :=
 filter (fun (x: JobIn arr_seq) =>
 (job_task x == tsk_k) && (interference_caused_by x t1 t2 != 0))
+ filter (fun j' =>
+ (job_task j' == tsk_k) && (interference_caused_by j' t1 t2 != 0))
(jobs_scheduled_between sched t1 t2).
(* Now, consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
Let sorted_jobs := (sort earlier_arrival interfering_jobs).
(* Now we proceed with the proof.
@@ 278,13 +286,18 @@ Module InterferenceBoundEDFJitter.
Lemma interference_bound_edf_all_jobs_from_tsk_k :
forall j,
j \in sorted_jobs >
+ arrives_in arr_seq j /\
job_task j = tsk_k /\
interference_caused_by j t1 t2 != 0 /\
j \in jobs_scheduled_between sched t1 t2.
Proof.
intros j LT.
rewrite interference_bound_edf_job_in_same_sequence mem_filter in LT.
 by move: LT => /andP [/andP [/eqP JOBi SERVi] INi]; repeat split.
+ move: LT => /andP [/andP [/eqP JOBi SERVi] INi]; repeat split; try (by done).
+ unfold jobs_scheduled_between in *; rewrite mem_undup in INi.
+ apply mem_bigcat_nat_exists in INi; des.
+ rewrite mem_scheduled_jobs_eq_scheduled in INi.
+ by apply (H_jobs_come_from_arrival_sequence j i).
Qed.
(* ...and consecutive jobs are ordered by arrival. *)
@@ 307,13 +320,16 @@ Module InterferenceBoundEDFJitter.
Proof.
rename H_valid_job_parameters into PARAMS.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 intros j; rewrite mem_filter; move => /andP [/andP [/eqP JOBj _] _].
 specialize (PARAMS j); des.
+ intros j IN.
+ feed (interference_bound_edf_all_jobs_from_tsk_k j);
+ first by rewrite interference_bound_edf_job_in_same_sequence.
+ move => [ARRj [TSKj [_ SCHEDj]]].
+ specialize (PARAMS j ARRj); des.
apply leq_trans with (n := service_during sched j t1 t2);
first by apply job_interference_le_service.
by apply cumulative_service_le_task_cost with (job_task0 := job_task)
(task_deadline0 := task_deadline) (job_cost0 := job_cost)
 (job_deadline0 := job_deadline).
+ (job_deadline0 := job_deadline); try (by done).
Qed.
End SimplifyJobSequence.
@@ 354,7 +370,7 @@ Module InterferenceBoundEDFJitter.
Qed.
(* Let j_fst be the first job, and a_fst its arrival time. *)
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let a_fst := job_arrival j_fst.
@@ 363,6 +379,7 @@ Module InterferenceBoundEDFJitter.
(* The first job is an interfering job of task tsk_k. *)
Lemma interference_bound_edf_j_fst_is_job_of_tsk_k :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk_k /\
interference_caused_by j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 376,10 +393,10 @@ Module InterferenceBoundEDFJitter.
job_deadline j_fst = task_deadline tsk_k.
Proof.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 rename H_valid_job_parameters into PARAMS.
+ rename H_valid_job_parameters into PARAMS.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask _].
 by specialize (PARAMS j_fst); des; rewrite PARAMS2 FSTtask.
+ destruct FST as [FSTarr [FSTtask _]].
+ by specialize (PARAMS j_fst FSTarr); des; rewrite PARAMS2 FSTtask.
Qed.
(* The deadline of j_i is the deadline of tsk_i. *)
@@ 389,7 +406,7 @@ Module InterferenceBoundEDFJitter.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS,
H_job_of_tsk_i into JOBtsk.
 by specialize (PARAMS j_i); des; rewrite PARAMS2 JOBtsk.
+ by specialize (PARAMS j_i H_j_i_arrives); des; rewrite PARAMS2 JOBtsk.
Qed.
(* If j_fst completes by its responsetime bound, then t1 <= a_fst + R_k,
@@ 401,18 +418,18 @@ Module InterferenceBoundEDFJitter.
intros RBOUND.
rewrite leqNgt; apply/negP; unfold not; intro BUG.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ FSTserv _]].
+ destruct FST as [_ [_ [FSTserv _]]].
move: FSTserv => /negP FSTserv; apply FSTserv.
rewrite leqn0; apply leq_trans with (n := service_during sched j_fst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
unfold service_during.
 by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := J_k + R_k);
 try (by done); rewrite addnA; last by apply ltnW.
+ by apply cumulative_service_after_job_rt_zero with
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (R := J_k + R_k);
+ try (by done); rewrite addnA; last by apply ltnW.
Qed.
End FactsAboutFirstJob.

(* Now, let's prove the interference bound for the particular case of a single job.
This case must be solved separately because the single job can simultaneously
@@ 449,25 +466,28 @@ Module InterferenceBoundEDFJitter.
completed job_cost sched j_fst (a_fst + J_k + R_k).
Lemma interference_bound_edf_holds_for_single_job_that_completes_on_time :
 job_interference job_cost job_jitter sched j_i j_fst t1 t2 <= D_i  (D_k  R_k  J_k).
+ job_interference job_arrival job_cost job_jitter sched j_i j_fst t1 t2
+ <= D_i  (D_k  R_k  J_k).
Proof.
rename H_j_fst_completed_by_rt_bound into RBOUND.
have AFTERt1 :=
interference_bound_edf_j_fst_completion_implies_rt_bound_inside_interval RBOUND.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ LEdl _]].
+ destruct FST as [ARRfst [_ [LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
destruct (D_k  R_k  J_k <= D_i) eqn:LEdk; last first.
{
apply negbT in LEdk; rewrite ltnNge in LEdk.
apply leq_trans with (n := 0); last by done.
 apply leq_trans with (n := job_interference job_cost job_jitter sched j_i j_fst (a_fst + J_k + R_k) t2); last first.
+ apply leq_trans with (n := job_interference job_arrival job_cost
+ job_jitter sched j_i j_fst (a_fst + J_k + R_k) t2); last first.
{
apply leq_trans with (n := service_during sched j_fst (a_fst + J_k + R_k) t2);
first by apply job_interference_le_service.
unfold service_during; rewrite leqn0; apply/eqP.
 by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := J_k + R_k);
+ by apply cumulative_service_after_job_rt_zero with
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (R := J_k + R_k);
try (by done); rewrite addnA // leqnn.
}
{
@@ 485,7 +505,7 @@ Module InterferenceBoundEDFJitter.
by apply ltnW; rewrite ltn_subRL addnC subnDA.
}
}
 apply leq_trans with (n := job_interference job_cost job_jitter sched j_i j_fst a_i t2);
+ apply leq_trans with (n := job_interference job_arrival job_cost job_jitter sched j_i j_fst a_i t2);
first by apply extend_sum; [by apply leq_addr  by apply leqnn].
rewrite (leq_add2r (D_k  R_k  J_k)) subh1 // addnBA // subnn addn0.
@@ 500,8 +520,8 @@ Module InterferenceBoundEDFJitter.
by rewrite [_ + R_k]addnC subnDA.
}
 apply leq_trans with (n := job_interference job_cost job_jitter sched j_i j_fst a_i
 (a_fst + D_k) + (D_k  R_k  J_k)).
+ apply leq_trans with (n := job_interference job_arrival job_cost job_jitter sched j_i
+ j_fst a_i (a_fst + D_k) + (D_k  R_k  J_k)).
{
rewrite leq_add2r.
destruct (t2 <= a_fst + J_k + R_k) eqn:LEt2.
@@ 519,7 +539,7 @@ Module InterferenceBoundEDFJitter.
{
by apply leq_trans with (n := t1); first by apply leq_addr.
}
 apply leq_trans with (n := job_interference job_cost job_jitter sched j_i j_fst a_i
+ apply leq_trans with (n := job_interference job_arrival job_cost job_jitter sched j_i j_fst a_i
(a_fst + J_k + R_k) + service_during sched j_fst (a_fst + J_k + R_k) t2).
{
rewrite leq_add2l.
@@ 527,7 +547,7 @@ Module InterferenceBoundEDFJitter.
}
unfold service_during.
rewrite > cumulative_service_after_job_rt_zero with (job_cost0 := job_cost)
 (R := J_k + R_k);
+ (job_arrival0 := job_arrival) (R := J_k + R_k);
rewrite ?addnA //.
rewrite addn0; apply extend_sum; first by done.
rewrite addnA leq_add2l.
@@ 545,14 +565,15 @@ Module InterferenceBoundEDFJitter.
{
by apply leq_trans with (n := t1); first by apply leq_addr.
}
 apply leq_trans with (n := job_interference job_cost job_jitter sched j_i j_fst a_i
+ apply leq_trans with (n := job_interference job_arrival job_cost job_jitter sched j_i j_fst a_i
(a_fst + J_k + R_k) + service_during sched j_fst (a_fst + J_k + R_k) (a_fst + D_k) + (D_k  R_k  J_k)).
{
rewrite leq_add2r leq_add2l.
by apply job_interference_le_service.
}
unfold service_during.
 rewrite > cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R:=J_k + R_k);
+ rewrite > cumulative_service_after_job_rt_zero with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) (R:=J_k + R_k);
rewrite ?addnA //.
rewrite addn0.
apply leq_trans with (n := (\sum_(a_i <= t < a_fst + J_k + R_k) 1) +
@@ 588,7 +609,7 @@ Module InterferenceBoundEDFJitter.
job_arrival j_fst + J_k + R_k >= job_arrival j_i + J_i + delta.
Proof.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask _].
+ destruct FST as [FSTarr [FSTtask _]].
rewrite leqNgt; apply/negP; intro LT.
move: H_j_fst_not_complete_by_rt_bound => /negP BUG; apply BUG.
by apply H_all_previous_jobs_completed_on_time.
@@ 600,8 +621,10 @@ Module InterferenceBoundEDFJitter.
interference_caused_by j_fst t1 t2 = 0.
Proof.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 have PARAMS := H_valid_job_parameters j_i; des.
+ have PARAMS := H_valid_job_parameters j_i H_j_i_arrives; des.
intro LTdk.
+ have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
+ destruct FST as [FSTarr [FSTtask _]].
rewrite 2!ltn_subRL addnA [R_k + _]addnC in LTdk.
rewrite (ltn_add2l a_fst) 2!addnA in LTdk.
apply leq_ltn_trans with (m := t1 + D_i) in LTdk; last first.
@@ 617,7 +640,7 @@ Module InterferenceBoundEDFJitter.
}
apply/eqP; rewrite [_ _ _ _ == 0]negbK; apply/negP; red; intro BUG.
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in BUG; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in BUG; try (by done).
rewrite interference_bound_edf_j_fst_deadline
interference_bound_edf_j_i_deadline in BUG.
apply leq_ltn_trans with (m := job_arrival j_i + D_i) in LTdk;
@@ 632,14 +655,14 @@ Module InterferenceBoundEDFJitter.
interference_caused_by j_fst t1 t2 <= D_i  (D_k  R_k  J_k).
Proof.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
 have PARAMS := H_valid_job_parameters j_i; des.
+ have PARAMS := H_valid_job_parameters j_i H_j_i_arrives; des.
intro LEdk.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask [LEdl _]].
+ destruct FST as [FSTtask [_ [LEdl _]]].
have LTr := interference_bound_edf_response_time_bound_of_j_fst_after_interval.
apply subh3; last by apply LEdk.
 apply leq_trans with (n := job_interference job_cost job_jitter sched j_i j_fst t1
 (job_arrival j_fst + J_k + R_k) + (D_k  R_k  J_k)).
+ apply leq_trans with (n := job_interference job_arrival job_cost job_jitter sched j_i
+ j_fst t1 (job_arrival j_fst + J_k + R_k) + (D_k  R_k  J_k)).
{
rewrite leq_add2r; apply extend_sum; first by apply leqnn.
apply leq_trans with (n := job_arrival j_i + J_i + delta);
@@ 684,8 +707,8 @@ Module InterferenceBoundEDFJitter.
interference_bound_edf_j_i_deadline.
apply leq_trans with (n := a_i + job_deadline j_i);
last by rewrite leq_add2r leq_addr.
 by apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl.
+ by apply interference_under_edf_implies_shorter_deadlines with (arr_seq0 := arr_seq)
+ (job_arrival0 := job_arrival) (job_deadline0 := job_deadline) in LEdl.
Qed.
End ResponseTimeOfSingleJobNotBounded.
@@ 742,6 +765,7 @@ Module InterferenceBoundEDFJitter.
(* The last job is an interfering job of task tsk_k. *)
Lemma interference_bound_edf_j_lst_is_job_of_tsk_k :
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk_k /\
interference_caused_by j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 757,8 +781,8 @@ Module InterferenceBoundEDFJitter.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [LSTtask _].
 by specialize (PARAMS j_lst); des; rewrite PARAMS2 LSTtask.
+ destruct LST as [LSTarr [LSTtask _]].
+ by specialize (PARAMS j_lst LSTarr); des; rewrite PARAMS2 LSTtask.
Qed.
(* The first job arrives before the last job. *)
@@ 776,17 +800,14 @@ Module InterferenceBoundEDFJitter.
job_arrival j_lst < t2.
Proof.
rewrite leqNgt; apply/negP; unfold not; intro LT2.
 exploit interference_bound_edf_all_jobs_from_tsk_k.
 {
 apply mem_nth; instantiate (1 := num_mid_jobs.+1).
 by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
 }
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
+ feed (interference_bound_edf_all_jobs_from_tsk_k j_lst).
+ by apply mem_nth; rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
+ move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
apply LSTserv; apply/eqP; rewrite leqn0.
apply leq_trans with (n := service_during sched j_lst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP; unfold service_during.
 apply cumulative_service_before_job_arrival_zero; last by done.
+ rewrite (cumulative_service_before_job_arrival_zero job_arrival) //.
by apply arrival_before_jitter with (job_jitter0 := job_jitter).
Qed.
@@ 796,7 +817,7 @@ Module InterferenceBoundEDFJitter.
Lemma interference_bound_edf_j_fst_completed_on_time :
completed job_cost sched j_fst (a_fst + J_k + R_k).
Proof.
 have PARAMS := H_valid_job_parameters j_i.
+ have PARAMS := H_valid_job_parameters j_i H_j_i_arrives.
unfold valid_sporadic_job_with_jitter, valid_sporadic_job in *; des.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k; des.
set j_snd := nth elem sorted_jobs 1.
@@ 804,7 +825,7 @@ Module InterferenceBoundEDFJitter.
{
by apply mem_nth; instantiate (1 := 1); rewrite H_at_least_two_jobs.
}
 instantiate (1 := elem); move => [SNDtsk [/eqP SNDserv _]].
+ instantiate (1 := elem); move => [SNDarr [SNDtsk [/eqP SNDserv _]]].
apply H_all_previous_jobs_completed_on_time; try (by done).
apply leq_ltn_trans with (n := job_arrival j_snd); last first.
{
@@ 818,7 +839,8 @@ Module InterferenceBoundEDFJitter.
sched j_snd t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 apply cumulative_service_before_job_arrival_zero; last by done.
+ apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival);
+ try (by done).
by apply arrival_before_jitter with (job_jitter0 := job_jitter).
}
apply leq_trans with (n := a_fst + p_k).
@@ 830,8 +852,8 @@ Module InterferenceBoundEDFJitter.
(* Since jobs are sporadic, we know that the first job arrives
at least p_k units before the second. *)
 unfold p_k; rewrite FST.
 apply H_sporadic_tasks; [ by rewrite SNDtsk  ]; last first.
+ unfold p_k; rewrite FST0.
+ apply H_sporadic_tasks; [ by done  by done  by rewrite SNDtsk  ]; last first.
{
apply interference_bound_edf_jobs_ordered_by_arrival.
by rewrite H_at_least_two_jobs.
@@ 876,19 +898,27 @@ Module InterferenceBoundEDFJitter.
}
rewrite 2?mem_filter in INnth; des.
 (* Use the sporadic task model to conclude that cur and next are separated
+ feed (interference_bound_edf_all_jobs_from_tsk_k cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (interference_bound_edf_all_jobs_from_tsk_k next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
+
+ (* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
Since we don't know much about the list (except that it's sorted), we must
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /interfering_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk.
}
by rewrite subh3 // addnC /p_k INnth.
Qed.
@@ 920,9 +950,9 @@ Module InterferenceBoundEDFJitter.
apply leq_trans with (p := a_lst + D_k) in DIST;
last by rewrite leq_add2l.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LEdl _]].
+ destruct LST as [LSTarr [_ [LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
unfold D_i, D_k in DIST; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline in LEdl.
by apply (leq_trans DIST) in LEdl; rewrite ltnn in LEdl.
@@ 1007,11 +1037,11 @@ Module InterferenceBoundEDFJitter.
by apply leq_trans with (n := t1); first by apply leq_addr.
}
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LSTserv _]].
+ destruct LST as [LSTarr [_ [ LSTserv _]]].
unfold D_i, D_k, a_lst, t1; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline.
by apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LSTserv.
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LSTserv.
Qed.
(* To conclude that the interference bound holds, it suffices to show that
@@ 1037,8 +1067,8 @@ Module InterferenceBoundEDFJitter.
}
destruct (leqP t2 (a_fst + J_k + R_k)) as [LEt2  GTt2].
{
 apply leq_trans with (n := job_interference job_cost job_jitter sched j_i j_fst t1
 (a_fst + J_k + R_k));
+ apply leq_trans with (n := job_interference job_arrival job_cost job_jitter sched j_i
+ j_fst t1 (a_fst + J_k + R_k));
first by apply extend_sum; rewrite ?leqnn.
simpl_sum_const; rewrite {1}[_ + _ + R_k](addKn t1) addnBA //.
by apply job_interference_le_delta.
@@ 1055,7 +1085,8 @@ Module InterferenceBoundEDFJitter.
apply leq_trans with (n := service_during sched j_fst (a_fst + J_k + R_k) t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := J_k + R_k);
+ apply cumulative_service_after_job_rt_zero with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) (R := J_k + R_k);
[ by done  rewrite addnA  by rewrite addnA leqnn].
by apply interference_bound_edf_j_fst_completed_on_time.
}
@@ 1129,13 +1160,13 @@ Module InterferenceBoundEDFJitter.
apply (leq_trans interference_bound_edf_bounding_interference_with_interval_lengths).
rewrite interference_bound_edf_simpl_by_concatenation_of_intervals leq_subLR.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LSTserv _]].
+ destruct LST as [LSTarr [_ [LSTserv _]]].
unfold D_i, D_k, a_lst, t1; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline.
apply leq_trans with (n := a_i + job_deadline j_i);
last by rewrite addnA leq_add2l leq_addl.
by apply interference_under_edf_implies_shorter_deadlines
 with (job_deadline0 := job_deadline) in LSTserv.
+ with (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LSTserv.
Qed.
End InterferenceOfFirstJob.
@@ 1189,7 +1220,7 @@ Module InterferenceBoundEDFJitter.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
+ assert (EX: exists elem: Job, True).
destruct sorted_jobs as [ j]; [by rewrite ltn0 in NUM  by exists j].
destruct EX as [elem _].
@@ 1201,7 +1232,7 @@ Module InterferenceBoundEDFJitter.
first by rewrite big_geq.
(* Then, we show the same for a single job, or for multiple jobs. *)
 rewrite SIZE; destruct n as [ num_mid_jobs].
+ destruct n as [ num_mid_jobs].
{
rewrite big_nat_recr // big_geq //.
rewrite [nth]lock /= lock add0n.
diff git a/analysis/global/jitter/workload_bound.v b/analysis/global/jitter/workload_bound.v
index 5482fcb..95ba570 100644
 a/analysis/global/jitter/workload_bound.v
+++ b/analysis/global/jitter/workload_bound.v
@@ 124,27 +124,33 @@ Module WorkloadBoundJitter.
Variable task_jitter: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
Variable job_deadline: Job > time.
Variable job_jitter: Job > time.
+ (* Consider any job arrival sequence... *)
Variable arr_seq: arrival_sequence Job.
 (* Assume that all jobs have valid parameters *)
 Hypothesis H_jobs_have_valid_parameters :
 forall (j: JobIn arr_seq),
 valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost job_deadline job_task job_jitter j.
+ (* ...where jobs have valid parameters. *)
+ Hypothesis H_jobs_have_valid_parameters:
+ forall j,
+ arrives_in arr_seq j >
+ valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost
+ job_deadline job_task job_jitter j.
 (* Consider any schedule. *)
+ (* Consider any schedule of this arrival sequence. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* Assumption: jobs only execute after the jitter.
This is used to discard the workload of jobs that arrive after
the end of the interval t1 + delta. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
(* Assumption: jobs do not execute after they completed.
This is used to eliminate jobs that complete before the start of the interval t1. *)
@@ 158,7 +164,8 @@ Module WorkloadBoundJitter.
(* Assumption: sporadic task model.
This is necessary to conclude that consecutive jobs ordered by arrival times
are separated by at least 'period' times units. *)
 Hypothesis H_sporadic_tasks: sporadic_task_model task_period arr_seq job_task.
+ Hypothesis H_sporadic_tasks:
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Before starting the proof, let's give simpler names to the definitions. *)
Let job_has_completed_by := completed job_cost sched.
@@ 198,10 +205,11 @@ Module WorkloadBoundJitter.
Hypothesis H_no_deadline_miss: task_jitter tsk + R_tsk <= task_deadline tsk.
Hypothesis H_response_time_bound :
 forall (j: JobIn arr_seq),
 job_task j = tsk >
 job_arrival j + task_jitter tsk + R_tsk < t1 + delta >
 job_has_completed_by j (job_arrival j + task_jitter tsk + R_tsk).
+ forall j,
+ arrives_in arr_seq j >
+ job_task j = tsk >
+ job_arrival j + task_jitter tsk + R_tsk < t1 + delta >
+ job_has_completed_by j (job_arrival j + task_jitter tsk + R_tsk).
Section MainProof.
@@ 219,7 +227,7 @@ Module WorkloadBoundJitter.
jobs_of_task_scheduled_between job_task sched tsk t1 t2.
(* Now, let's consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
Let sorted_jobs := (sort earlier_arrival scheduled_jobs).
(* The first step consists in simplifying the sum corresponding
@@ 250,16 +258,19 @@ Module WorkloadBoundJitter.
Lemma workload_bound_all_jobs_from_tsk :
forall j_i,
j_i \in sorted_jobs >
+ arrives_in arr_seq j_i /\
job_task j_i = tsk /\
service_during sched j_i t1 t2 != 0 /\
j_i \in jobs_scheduled_between sched t1 t2.
Proof.
+ rename H_jobs_come_from_arrival_sequence into FROMarr.
intros j_i LTi.
rewrite workload_bound_job_in_same_sequence mem_filter in LTi; des.
 repeat split; [by done   by done].
 unfold jobs_scheduled_between in *; rewrite mem_undup in LTi0.
 apply mem_bigcat_nat_exists in LTi0; des.
 rewrite mem_scheduled_jobs_eq_scheduled in LTi0.
+ have IN := LTi0.
+ unfold jobs_scheduled_between in *; rewrite mem_undup in IN.
+ apply mem_bigcat_nat_exists in IN; des.
+ rewrite mem_scheduled_jobs_eq_scheduled in IN.
+ repeat split; try (by done); first by apply (FROMarr j_i i).
apply service_implies_cumulative_service with (t := i);
first by apply/andP; split.
by rewrite not_scheduled_no_service negbK.
@@ 292,15 +303,13 @@ Module WorkloadBoundJitter.
rewrite [\sum_(_ < _  _) _]add0n leq_add //.
apply leq_trans with (n := \sum_(x < sorted_jobs) task_cost tsk);
last by rewrite big_const_seq iter_addn addn0 mulnC leq_mul2r; apply/orP; right.
 {
 rewrite [\sum_(_ < _) service_during _ _ _ _]big_seq_cond.
 rewrite [\sum_(_ < _) task_cost _]big_seq_cond.
 apply leq_sum; intros j_i; move/andP => [INi _].
 apply workload_bound_all_jobs_from_tsk in INi; des.
 eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute  by apply INi ].
 by apply H_jobs_have_valid_parameters.
 }
+ rewrite [\sum_(_ < _) service_during _ _ _ _]big_seq_cond.
+ rewrite [\sum_(_ < _) task_cost _]big_seq_cond.
+ apply leq_sum; intros j_i; move/andP => [INi _].
+ apply workload_bound_all_jobs_from_tsk in INi; des.
+ eapply cumulative_service_le_task_cost;
+ [by apply H_completed_jobs_dont_execute  by apply INi0 ].
+ by apply H_jobs_have_valid_parameters.
Qed.
End WorkloadNotManyJobs.
@@ 312,11 +321,12 @@ Module WorkloadBoundJitter.
(* Assume that there's at least one job in the sorted list. *)
Hypothesis H_at_least_one_job: size sorted_jobs > 0.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
(* The first job is an interfering job of task tsk. *)
Lemma workload_bound_j_fst_is_job_of_tsk :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk /\
service_during sched j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 338,21 +348,15 @@ Module WorkloadBoundJitter.
rewrite [service_during _ _ _ _]add0n [_* task_cost tsk]mulSnr.
apply leq_add; first by done.
by eapply cumulative_service_le_task_cost;
 [ by apply INfst
  by apply H_jobs_have_valid_parameters].
+ [ by apply INfst0  by apply H_jobs_have_valid_parameters].
}
{
 rewrite 2!mul0n addn0 subn0 leq_min; apply/andP; split.
 {
 by eapply cumulative_service_le_task_cost;
 [ by apply INfst
  by apply H_jobs_have_valid_parameters].
 }
 {
 rewrite addnBA // [service_during _ _ _ _]addn0.
 rewrite addnA; apply leq_add; last by done.
 by apply cumulative_service_le_delta.
 }
+ rewrite 2!mul0n addn0 subn0 leq_min; apply/andP; split;
+ first by eapply cumulative_service_le_task_cost;
+ [ by apply INfst0  by apply H_jobs_have_valid_parameters].
+ rewrite addnBA // [service_during _ _ _ _]addn0.
+ rewrite addnA; apply leq_add; last by done.
+ by apply cumulative_service_le_delta.
}
Qed.
@@ 366,12 +370,13 @@ Module WorkloadBoundJitter.
Variable num_mid_jobs: nat.
Hypothesis H_at_least_two_jobs : size sorted_jobs = num_mid_jobs.+2.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let j_lst := nth elem sorted_jobs num_mid_jobs.+1.
(* The last job is an interfering job of task tsk. *)
Lemma workload_bound_j_lst_is_job_of_tsk :
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk /\
service_during sched j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 392,11 +397,12 @@ Module WorkloadBoundJitter.
apply mem_nth; instantiate (1 := 0).
apply ltn_trans with (n := 1); [by done  by rewrite H_at_least_two_jobs].
}
 instantiate (1 := elem); move => [FSTtsk [/eqP FSTserv FSTin]].
+ instantiate (1 := elem); move => [FSTARR [FSTtsk [/eqP FSTserv FSTin]]].
apply FSTserv.
 apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := task_jitter tsk + R_tsk);
+ apply cumulative_service_after_job_rt_zero with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) (R := task_jitter tsk + R_tsk);
[by done   by rewrite addnA ltnW].
 rewrite addnA; apply H_response_time_bound; first by done.
+ rewrite addnA; apply H_response_time_bound; try (by done).
by apply leq_trans with (n := t1); last by apply leq_addr.
Qed.
@@ 410,9 +416,9 @@ Module WorkloadBoundJitter.
apply mem_nth; instantiate (1 := num_mid_jobs.+1).
by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
}
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
+ instantiate (1 := elem); move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
apply LSTserv.
 apply cumulative_service_before_job_arrival_zero; last by done.
+ apply (cumulative_service_before_job_arrival_zero job_arrival); last by done.
by apply arrival_before_jitter with (job_jitter0 := job_jitter).
Qed.
@@ 440,12 +446,14 @@ Module WorkloadBoundJitter.
by apply workload_bound_response_time_of_first_job_inside_interval
 by apply ltnW].
rewrite addnA.
 rewrite [\sum_(_ <= _ < t2)_](cumulative_service_after_job_rt_zero job_cost _ _ _ (task_jitter tsk + R_tsk)); rewrite ?leqnn //; first by rewrite addn0 leqnn.
+ rewrite [\sum_(_ <= _ < t2)_]
+ (cumulative_service_after_job_rt_zero job_arrival job_cost _ _ _
+ (task_jitter tsk + R_tsk)); rewrite ?leqnn //; first by rewrite addn0 leqnn.
rewrite addnA.
 apply H_response_time_bound; last by done.
 exploit workload_bound_all_jobs_from_tsk.
 by apply mem_nth; instantiate (1 := 0); rewrite H_at_least_two_jobs.
 by instantiate (1 := elem); move => [FSTtsk _].
+ have ALL := workload_bound_all_jobs_from_tsk j_fst.
+ feed ALL; first by apply mem_nth; rewrite H_at_least_two_jobs.
+ move: ALL => [FSTarr [FSTtsk _]].
+ by apply H_response_time_bound.
}
}
{
@@ 465,7 +473,7 @@ Module WorkloadBoundJitter.
 by apply ltnW, workload_bound_last_job_arrives_before_end_of_interval].
rewrite /= [\sum_(_ <= _ < _) 1]add0n; apply leq_add;
last by apply leq_sum; ins; apply service_at_most_one.
 rewrite cumulative_service_before_job_arrival_zero;
+ rewrite (cumulative_service_before_job_arrival_zero job_arrival);
[by apply leqnn   by apply leqnn].
by apply arrival_before_jitter with (job_jitter0 := job_jitter).
}
@@ 481,7 +489,6 @@ Module WorkloadBoundJitter.
have lemma2 := workload_bound_response_time_of_first_job_inside_interval.
rewrite addnBA; last by apply ltnW.
rewrite subh1; last by done.
 (*rewrite [_ + R_tsk]addnC.*)
rewrite addnBA; last by apply leq_addr.
rewrite addnC; unfold t2.
@@ 509,15 +516,15 @@ Module WorkloadBoundJitter.
last by rewrite big_const_nat iter_addn addn0 mulnC subn0.
rewrite big_nat_cond [\sum_(0 <= i < num_mid_jobs) task_cost _]big_nat_cond.
apply leq_sum; intros i; rewrite andbT; move => /andP LT; des.
 eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute   by apply H_jobs_have_valid_parameters].
exploit workload_bound_all_jobs_from_tsk.
{
instantiate (1 := nth elem sorted_jobs i.+1).
apply mem_nth; rewrite H_at_least_two_jobs.
by rewrite ltnS; apply leq_trans with (n := num_mid_jobs).
}
 by ins; des.
+ move => [ARRin [JOBtsk _]].
+ by eapply cumulative_service_le_task_cost;
+ [by apply H_completed_jobs_dont_execute   by apply H_jobs_have_valid_parameters].
Qed.
(* Conclude that the distance between first and last is at least num_mid_jobs + 1 periods. *)
@@ 536,18 +543,19 @@ Module WorkloadBoundJitter.
set cur := nth elem sorted_jobs i.
set next := nth elem sorted_jobs i.+1.
+ have ALL := workload_bound_all_jobs_from_tsk.
+
(* Show that cur arrives earlier than next *)
assert (ARRle: job_arrival cur <= job_arrival next).
by unfold cur, next; apply workload_bound_jobs_ordered_by_arrival.
 (* Show that both cur and next are in the arrival sequence *)
 assert (INnth: cur \in scheduled_jobs /\ next \in scheduled_jobs).
 {
 rewrite 2!workload_bound_job_in_same_sequence; split.
 by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs; ins.
 by apply mem_nth; destruct sorted_jobs; ins.
 }
 rewrite 2?mem_filter in INnth; des.
+ feed (workload_bound_all_jobs_from_tsk cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (workload_bound_all_jobs_from_tsk next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
(* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
@@ 555,15 +563,15 @@ Module WorkloadBoundJitter.
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /scheduled_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk NEXTtsk.
}
 by rewrite subh3 // addnC INnth.
+ by rewrite subh3 // addnC CURtsk.
Qed.
(* Prove that n_k is at least the number of the middle jobs *)
@@ 627,7 +635,8 @@ Module WorkloadBoundJitter.
move => NK; rewrite NK.
apply leq_add;
last by apply workload_bound_service_of_middle_jobs.
 apply leq_trans with (n := delta + task_jitter tsk + R_tsk  (job_arrival j_lst  (job_arrival j_fst))).
+ apply leq_trans with (n := delta + task_jitter tsk + R_tsk 
+ (job_arrival j_lst  (job_arrival j_fst))).
{
rewrite addnC workload_bound_simpl_expression_with_first_and_last.
by apply workload_bound_service_of_first_and_last_jobs.
@@ 673,10 +682,11 @@ Module WorkloadBoundJitter.
by rewrite H_at_least_two_jobs.
have INfst := workload_bound_j_fst_is_job_of_tsk SIZE elem;
have INlst := workload_bound_j_lst_is_job_of_tsk; des.
 have PARAMSfst := JOBPARAMS j_fst; des.
 have PARAMSlst := JOBPARAMS j_lst; des.
 by apply leq_add; apply cumulative_service_le_task_cost with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline) (job_task0 := job_task).
+ have PARAMSfst := JOBPARAMS j_fst INfst; des.
+ have PARAMSlst := JOBPARAMS j_lst INlst; des.
+ by apply leq_add; apply cumulative_service_le_task_cost with
+ (task_deadline0 := task_deadline) (job_cost0 := job_cost)
+ (job_deadline0 := job_deadline) (job_task0 := job_task).
}
{
rewrite subnAC subnK; last first.
@@ 721,8 +731,8 @@ Module WorkloadBoundJitter.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
 destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists j].
+ assert (EX: exists elem: Job, True).
+ destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists s].
destruct EX as [elem _].
(* Now we index the sum to access the first and last elements. *)
diff git a/analysis/global/parallel/bertogna_edf_comp.v b/analysis/global/parallel/bertogna_edf_comp.v
index b1a4a2d..1bec09f 100755
 a/analysis/global/parallel/bertogna_edf_comp.v
+++ b/analysis/global/parallel/bertogna_edf_comp.v
@@ 20,6 +20,7 @@ Module ResponseTimeIterationEDF.
Let task_with_response_time := (sporadic_task * time)%type.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 868,39 +869,42 @@ Module ResponseTimeIterationEDF.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...they have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Then, consider any platform with at least one CPU such that...*)
 Variable sched: schedule num_cpus arr_seq.
 Hypothesis H_at_least_one_cpu :
 num_cpus > 0.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_at_least_one_cpu: num_cpus > 0.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs only execute after they arrived and no longer
than their execution costs,... *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
(* Assume a workconserving scheduler with EDF policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
 Hypothesis H_edf_policy: respects_JLFP_policy job_cost sched (EDF job_deadline).
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
+ Hypothesis H_edf_policy: respects_JLFP_policy job_arrival job_cost arr_seq sched
+ (EDF job_arrival job_deadline).
Definition no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Definition no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in edf_claimed_bounds is safe. The proof follows by direct application of
@@ 916,7 +920,7 @@ Module ResponseTimeIterationEDF.
have BOUND := bertogna_cirinei_response_time_bound_edf.
unfold is_response_time_bound_of_task in *.
apply BOUND with (task_cost := task_cost) (task_period := task_period)
 (task_deadline := task_deadline) (job_deadline := job_deadline)
+ (arr_seq := arr_seq) (task_deadline := task_deadline) (job_deadline := job_deadline)
(job_task := job_task) (ts := ts) (tsk := tsk) (rt_bounds := rt_bounds); try (by ins).
by unfold edf_claimed_bounds in SOME; desf; rewrite edf_claimed_bounds_unzip1_iteration.
by ins; apply edf_claimed_bounds_finds_fixed_point_for_each_bound with (ts := ts).
@@ 945,10 +949,10 @@ Module ResponseTimeIterationEDF.
H_all_jobs_from_taskset into ALLJOBS,
H_test_succeeds into TEST.
 move => tsk INtsk j JOBtsk.
+ move => tsk INtsk j ARRj JOBtsk.
destruct (edf_claimed_bounds ts) as [rt_bounds ] eqn:SOME; last by ins.
exploit (HAS rt_bounds tsk); [by ins  by ins  clear HAS; intro HAS; des].
 have COMPLETED := RLIST tsk R HAS j JOBtsk.
+ have COMPLETED := RLIST tsk R HAS j ARRj JOBtsk.
exploit (DL rt_bounds tsk R);
[by ins  by ins  clear DL; intro DL].
@@ 957,7 +961,7 @@ Module ResponseTimeIterationEDF.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
apply extend_sum; rewrite // leq_add2l.
 specialize (JOBPARAMS j); des; rewrite JOBPARAMS1.
+ specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS1.
by rewrite JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
@@ 968,12 +972,12 @@ Module ResponseTimeIterationEDF.
are spawned by the task set, we conclude that no job misses
its deadline. *)
Theorem jobs_schedulable_by_edf_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j, arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_edf_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/global/parallel/bertogna_edf_theory.v b/analysis/global/parallel/bertogna_edf_theory.v
index f68bf99..a36dc8a 100644
 a/analysis/global/parallel/bertogna_edf_theory.v
+++ b/analysis/global/parallel/bertogna_edf_theory.v
@@ 27,18 +27,20 @@ Module ResponseTimeAnalysisEDF.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Assume that we have a task set where all tasks have valid
@@ 51,16 +53,18 @@ Module ResponseTimeAnalysisEDF.
(* ... and that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Next, consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...jobs do not execute before their arrival times nor longer
than their execution costs. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 68,14 +72,15 @@ Module ResponseTimeAnalysisEDF.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
(* Assume that the schedule is a workconserving EDF schedule. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
 Hypothesis H_edf_policy: respects_JLFP_policy job_cost sched (EDF job_deadline).
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
+ Hypothesis H_edf_policy: respects_JLFP_policy job_arrival job_cost arr_seq sched
+ (EDF job_arrival job_deadline).
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Next we consider the responsetime recurrence.
Assume that a responsetime bound R is known... *)
@@ 107,7 +112,8 @@ Module ResponseTimeAnalysisEDF.
Hypothesis H_tsk_R_in_rt_bounds: (tsk, R) \in rt_bounds.
(* Consider any job j of tsk. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* Assume that job j did not complete on time, ... *)
@@ 115,7 +121,8 @@ Module ResponseTimeAnalysisEDF.
(* ...and that it is the first job not to satisfy its responsetime bound. *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_other: JobIn arr_seq) tsk_other R_other,
+ forall j_other tsk_other R_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
(tsk_other, R_other) \in rt_bounds >
job_arrival j_other + R_other < job_arrival j + R >
@@ 123,11 +130,11 @@ Module ResponseTimeAnalysisEDF.
(* 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 sched j
+ task_interference job_arrival job_cost job_task sched j
tsk_other (job_arrival j) (job_arrival j + R).
(* ...and X the total interference incurred by job j due to any task. *)
 Let X := total_interference job_cost sched j (job_arrival j) (job_arrival j + R).
+ Let X := total_interference job_arrival job_cost sched j (job_arrival j) (job_arrival j + R).
(* Recall Bertogna and Cirinei's workload bound ... *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
@@ 187,9 +194,9 @@ Module ResponseTimeAnalysisEDF.
apply leq_trans with (n := workload job_task sched tsk_other
(job_arrival j) (job_arrival j + R));
first apply task_interference_le_workload.

 apply workload_bounded_by_W with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline); try (by ins).
+ have BOUND := workload_bounded_by_W task_cost task_period task_deadline
+ job_arrival job_cost job_task job_deadline arr_seq _ sched.
+ apply BOUND; try (by done); last 2 first.
 by ins; apply TASK_PARAMS.
 by ins; apply BEFOREok with (tsk_other := tsk_other).
Qed.
@@ 200,7 +207,7 @@ Module ResponseTimeAnalysisEDF.
Proof.
rename H_job_of_tsk into JOBtsk, H_all_jobs_from_taskset into FROMTS.
apply interference_bound_edf_bounds_interference with (job_deadline0 := job_deadline)
 (ts0 := ts); try (by done);
+ (arr_seq0 := arr_seq) (ts0 := ts); try (by done);
[ by rewrite JOBtsk FROMTS
 by apply bertogna_edf_tsk_other_in_ts
 by apply H_tasks_miss_no_deadlines
@@ 234,12 +241,12 @@ Module ResponseTimeAnalysisEDF.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(job_arrival j <= t < job_arrival j + R)
 backlogged job_cost sched j t) +
+ backlogged job_arrival job_cost sched j t) +
service sched j (job_arrival j + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_j_arrives); des; rewrite JOBtsk.
}
unfold service; rewrite service_before_arrival_eq_service_during //.
rewrite big_split /=.
@@ 247,7 +254,7 @@ Module ResponseTimeAnalysisEDF.
first by rewrite big_const_nat iter_addn mul1n addn0 addKn.
rewrite big_nat_cond [\sum_(_ <= _ < _  true) _]big_nat_cond.
apply leq_sum; move => i /andP [/andP [GEi LTi] _].
 destruct (backlogged job_cost sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 268,9 +275,8 @@ Module ResponseTimeAnalysisEDF.
Proof.
rename H_all_jobs_from_taskset into FROMTS,
H_valid_task_parameters into PARAMS,
 H_job_of_tsk into JOBtsk,
 H_sporadic_tasks into SPO,
 H_work_conserving into WORK,
+ H_job_of_tsk into JOBtsk, H_jobs_come_from_arrival_sequence into FROMSEQ,
+ H_sporadic_tasks into SPO, H_work_conserving into WORK,
H_tsk_R_in_rt_bounds into INbounds,
H_all_previous_jobs_completed_on_time into BEFOREok,
H_tasks_miss_no_deadlines into NOMISS,
@@ 279,9 +285,9 @@ Module ResponseTimeAnalysisEDF.
unfold sporadic_task_model in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /=.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost sched j t) eqn:BACK; last first.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last first.
{
rewrite (eq_bigr (fun i => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
@@ 293,8 +299,10 @@ Module ResponseTimeAnalysisEDF.
apply eq_trans with (y := \sum_(cpu < num_cpus) 1);
last by rewrite big_const_ord iter_addn mul1n addn0.
apply eq_bigr; intros cpu _.
 specialize (WORK j t BACK cpu); des.
+ specialize (WORK j t H_j_arrives BACK cpu); des.
move: WORK => /eqP SCHED.
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (FROMSEQ j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
rewrite (eq_bigr (fun i => 0));
@@ 312,11 +320,12 @@ Module ResponseTimeAnalysisEDF.
}
clear SCHED; rename SCHED' into SCHED.
move: (SCHED) => PENDING.
apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_cost0 := job_cost) (job_arrival0 := job_arrival)
+ in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
move: (BEFOREother) => LT; rewrite (ltn_add2r R) in LT.
 specialize (BEFOREok j_other tsk R SAMEtsk INbounds LT).
+ specialize (BEFOREok j_other tsk R ARRother SAMEtsk INbounds LT).
move: PENDING => /andP [_ /negP NOTCOMP]; apply NOTCOMP.
apply completion_monotonic with (t0 := job_arrival j_other + R); try (by done).
apply leq_trans with (n := job_arrival j); last by done.
@@ 324,12 +333,12 @@ apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by
first by rewrite leq_add2l; apply NOMISS.
apply leq_trans with (n := job_arrival j_other + task_period tsk);
first by rewrite leq_add2l; apply RESTR; rewrite JOBtsk FROMTS.
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; try (by done); [  by rewrite JOBtsk  by apply ltnW].
by red; intro EQ; subst; rewrite ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge.
apply leq_ltn_trans with (n := t); first by done.
@@ 433,7 +442,7 @@ apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by
Theorem bertogna_cirinei_response_time_bound_edf :
response_time_bounded_by tsk R.
Proof.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
remember (job_arrival j + R) as ctime.
@@ 444,11 +453,12 @@ apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by
(* Now, we apply strong induction on the absolute responsetime bound. *)
induction ctime as [ctime IH] using strong_ind.
 intros j tsk' JOBtsk R' EQc INbounds; subst ctime.
+ intros j ARRj tsk' JOBtsk R' EQc INbounds; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq) tsk R0,
 job_task j0 = tsk >
+ assert (BEFOREok: forall j0 tsk R0,
+ arrives_in arr_seq j0 >
+ job_task j0 = tsk >
(tsk, R0) \in rt_bounds >
job_arrival j0 + R0 < job_arrival j + R' >
service sched j0 (job_arrival j0 + R0) == job_cost j0).
@@ 465,14 +475,15 @@ apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by
apply negbT in NOTCOMP; exfalso.
(* Next, we derive a contradiction using the previous lemmas. *)
 exploit (bertogna_edf_exists_task_that_exceeds_bound tsk' R' INbounds j JOBtsk NOTCOMP).
+ exploit (bertogna_edf_exists_task_that_exceeds_bound tsk' R' INbounds j ARRj JOBtsk NOTCOMP).
{
by ins; apply IH with (tsk := tsk_other) (R := R_other).
}
intro EX; destruct EX as [tsk_other [R_other [HP LTmin]]].
unfold interference_bound_edf, interference_bound_generic in LTmin.
have BASICBOUND := bertogna_edf_workload_bounds_interference R' j BEFOREok tsk_other R_other HP.
 have EDFBOUND := (bertogna_edf_specific_bound_holds tsk' R' j JOBtsk BEFOREok tsk_other R_other HP).
+ have EDFBOUND := bertogna_edf_specific_bound_holds tsk' R' j ARRj JOBtsk
+ BEFOREok tsk_other R_other HP.
unfold minn in LTmin; clear LTmin HP BASICBOUND EDFBOUND tsk; desf.
{
by apply (leq_ltn_trans BASICBOUND) in LTmin; rewrite ltnn in LTmin.
diff git a/analysis/global/parallel/bertogna_fp_comp.v b/analysis/global/parallel/bertogna_fp_comp.v
index ca8584b..28cbef9 100644
 a/analysis/global/parallel/bertogna_fp_comp.v
+++ b/analysis/global/parallel/bertogna_fp_comp.v
@@ 20,6 +20,7 @@ Module ResponseTimeIterationFP.
Let task_with_response_time := (sporadic_task * time)%type.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 349,7 +350,7 @@ Module ResponseTimeIterationFP.
destruct i as [i R].
have GE_COST := fp_claimed_bounds_ge_cost ts_hp rt_bounds i R SOME IN.
have UNZIP := fp_claimed_bounds_unzip ts_hp rt_bounds SOME.
unfold interference_bound_generic; simpl.
+ unfold interference_bound_generic; simpl.
apply W_monotonic; try (by done).
have INts: i \in ts_hp by rewrite UNZIP; apply/mapP; exists (i, R).
by exploit (VALID i);
@@ 479,43 +480,46 @@ unfold interference_bound_generic; simpl.
Hypothesis H_priority_transitive: FP_is_transitive higher_priority.
(* Next, consider any arrival sequence such that...*)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ...all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...they have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
 (* Then, consider any platform with at least one CPU such that...*)
 Variable sched: schedule num_cpus arr_seq.
+ (* Then, consider any schedule of this arrival sequence such that... *)
+ Variable sched: schedule Job num_cpus.
Hypothesis H_at_least_one_cpu: num_cpus > 0.

+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
(* ...jobs only execute after they arrived and no longer
than their execution costs,... *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
(* Assume that the scheduler is workconserving and respects the FP policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_respects_FP_policy:
 respects_FP_policy job_cost job_task sched higher_priority.
+ respects_FP_policy job_arrival job_cost job_task arr_seq sched higher_priority.
Let no_deadline_missed_by_task (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* In the following theorem, we prove that any responsetime bound contained
in fp_claimed_bounds is safe. The proof follows by induction on the task set:
@@ 552,20 +556,13 @@ unfold interference_bound_generic; simpl.
clear EQ.
assert (PAIR: forall idx, (TASK idx, RESP idx) = NTH idx).
 {
by intros i; unfold TASK, RESP; destruct (NTH i).
 }
assert (SUBST: forall i, i < size hp_bounds > TASK i = nth tsk ts i).
 {

by intros i LTi; rewrite /TASK /NTH UNZIP (nth_map elem) //.
 }
assert (SIZE: size hp_bounds = size ts).
 {
by rewrite UNZIP size_map.
 }
induction idx as [idx IH'] using strong_ind.
@@ 651,7 +648,7 @@ unfold interference_bound_generic; simpl.
job_misses_no_deadline, completed,
fp_schedulable, valid_sporadic_job in *.
rename H_valid_job_parameters into JOBPARAMS.
 move => tsk INtsk j JOBtsk.
+ move => tsk INtsk j ARRj JOBtsk.
destruct (fp_claimed_bounds ts) as [rt_bounds ]; last by ins.
feed (UNZIP rt_bounds); first by done.
@@ 660,14 +657,14 @@ unfold interference_bound_generic; simpl.
rewrite set_mem UNZIP in INtsk; move: INtsk => /mapP EX.
by destruct EX as [p]; destruct p as [tsk' R]; simpl in *; subst tsk'; exists R.
} des.
 exploit (RLIST tsk R); [by ins  by apply JOBtsk  intro COMPLETED].
+ exploit (RLIST tsk R); eauto 1; intro COMPLETED.
exploit (DL rt_bounds tsk R); [by ins  by ins  clear DL; intro DL].
rewrite eqn_leq; apply/andP; split; first by apply cumulative_service_le_job_cost.
apply leq_trans with (n := service sched j (job_arrival j + R)); last first.
{
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
apply extend_sum; rewrite // leq_add2l.
 specialize (JOBPARAMS j); des; rewrite JOBPARAMS1.
+ specialize (JOBPARAMS j ARRj); des; rewrite JOBPARAMS1.
by rewrite JOBtsk.
}
rewrite leq_eqVlt; apply/orP; left; rewrite eq_sym.
@@ 678,12 +675,12 @@ unfold interference_bound_generic; simpl.
are spawned by the task set, we also conclude that no job in
the schedule misses its deadline. *)
Theorem jobs_schedulable_by_fp_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j, arrives_in arr_seq j > no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_fp_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/global/parallel/bertogna_fp_theory.v b/analysis/global/parallel/bertogna_fp_theory.v
index bad3ef0..23d9953 100644
 a/analysis/global/parallel/bertogna_fp_theory.v
+++ b/analysis/global/parallel/bertogna_fp_theory.v
@@ 27,18 +27,20 @@ Module ResponseTimeAnalysisFP.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable 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.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Assume that we have a task set where all tasks have valid
@@ 51,16 +53,18 @@ Module ResponseTimeAnalysisFP.
(* ... and that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Next, consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.

+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
(* ...jobs do not execute before their arrival times nor longer
than their execution costs. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 69,18 +73,18 @@ Module ResponseTimeAnalysisFP.
(* ... and assume that the schedule is an APA workconserving
schedule that respects this policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_respects_FP_policy:
 respects_FP_policy job_cost job_task sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_task arr_seq sched higher_eq_priority.
(* Assume that there exists at least one processor. *)
Hypothesis H_at_least_one_cpu: num_cpus > 0.
(* Let's define some local names to avoid passing many parameters. *)
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Next, we consider the responsetime recurrence.
Let tsk be a task in ts that is to be analyzed. *)
@@ 122,24 +126,26 @@ Module ResponseTimeAnalysisFP.
Section Lemmas.
(* Consider any job j of tsk. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_tsk: job_task j = tsk.
(* 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 (job_arrival j + R).
Hypothesis H_previous_jobs_of_tsk_completed :
 forall (j0: JobIn arr_seq),
+ forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
completed job_cost sched j0 (job_arrival j0 + 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 sched j
+ task_interference job_arrival job_cost job_task sched j
tsk_other (job_arrival j) (job_arrival j + R).
(* ...and X the total interference incurred by job j due to any task. *)
 Let X := total_interference job_cost sched j (job_arrival j) (job_arrival j + R).
+ Let X := total_interference job_arrival job_cost sched j (job_arrival j) (job_arrival j + R).
(* Recall Bertogna and Cirinei's workload bound. *)
Let workload_bound (tsk_other: sporadic_task) (R_other: time) :=
@@ 186,14 +192,17 @@ Module ResponseTimeAnalysisFP.
}
move: SCHED => /existsP [t /existsP [cpu SCHED]].
unfold task_scheduled_on in SCHED.
 destruct (sched cpu t) as [j0 ]; last by done.
+ destruct (sched cpu t) as [j0 ] eqn:SCHED0; last by done.
assert (INts: tsk_other \in ts).
 by move: SCHED => /eqP <; rewrite FROMTS.
+ {
+ move: SCHED => /eqP <; apply FROMTS, (H_jobs_come_from_arrival_sequence j0 t).
+ by apply/existsP; exists cpu; apply/eqP.
+ }
apply leq_trans with (n := workload job_task sched tsk_other
(job_arrival j) (job_arrival j + R));
first by apply task_interference_le_workload.
 by apply workload_bounded_by_W with (task_deadline0 := task_deadline)
 (job_cost0 := job_cost) (job_deadline0 := job_deadline);
+ by apply workload_bounded_by_W with (task_deadline0 := task_deadline) (arr_seq0 := arr_seq)
+ (job_arrival0 := job_arrival) (job_cost0 := job_cost) (job_deadline0 := job_deadline);
try (by ins);
[ by ins; apply TASK_PARAMS
 by ins; apply RESP with (hp_tsk := tsk_other)].
@@ 226,12 +235,12 @@ Module ResponseTimeAnalysisFP.
by apply cumulative_service_le_job_cost.
}
apply leq_ltn_trans with (n := (\sum_(job_arrival j <= t < job_arrival j + R)
 backlogged job_cost sched j t) +
+ backlogged job_arrival job_cost sched j t) +
service sched j (job_arrival j + R)); last first.
{
rewrite addn1 addnA leq_add2l addn1.
apply leq_trans with (n := job_cost j); first by done.
 by specialize (PARAMS j); des; rewrite JOBtsk.
+ by specialize (PARAMS j H_j_arrives); des; rewrite JOBtsk.
}
unfold service; rewrite service_before_arrival_eq_service_during //.
rewrite big_split /=.
@@ 239,7 +248,7 @@ Module ResponseTimeAnalysisFP.
first by rewrite big_const_nat iter_addn mul1n addn0 addKn.
rewrite big_nat_cond [\sum_(_ <= _ < _  true) _]big_nat_cond.
apply leq_sum; move => i /andP [/andP [GEi LTi] _].
 destruct (backlogged job_cost sched j i) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j i) eqn:BACK;
first by rewrite addn1 addnC; apply leq_add.
apply negbT in BACK.
rewrite add0n lt0n not_scheduled_no_service negbK.
@@ 261,11 +270,9 @@ Module ResponseTimeAnalysisFP.
Lemma bertogna_fp_all_cpus_are_busy:
\sum_(tsk_k < hp_tasks) x tsk_k = X * num_cpus.
Proof.
 rename H_all_jobs_from_taskset into FROMTS,
 H_valid_task_parameters into PARAMS,
 H_job_of_tsk into JOBtsk,
 H_sporadic_tasks into SPO,
 H_work_conserving into WORK,
+ rename H_all_jobs_from_taskset into FROMTS, H_valid_task_parameters into PARAMS,
+ H_job_of_tsk into JOBtsk, H_sporadic_tasks into SPO,
+ H_work_conserving into WORK, H_jobs_come_from_arrival_sequence into FROMarr,
H_constrained_deadlines into RESTR,
H_respects_FP_policy into FP,
H_previous_jobs_of_tsk_completed into BEFOREok,
@@ 274,9 +281,9 @@ Module ResponseTimeAnalysisFP.
respects_JLDP_policy, FP_to_JLDP in *.
unfold x, X, total_interference, task_interference.
rewrite big_mkcond exchange_big big_distrl /=.
 rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _) _]big_mkcond.
+ rewrite [\sum_(_ <= _ < _  backlogged _ _ _ _ _) _]big_mkcond.
apply eq_big_nat; move => t /andP [GEt LTt].
 destruct (backlogged job_cost sched j t) eqn:BACK; last first.
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK; last first.
{
rewrite (eq_bigr (fun i => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
@@ 288,7 +295,7 @@ Module ResponseTimeAnalysisFP.
apply eq_trans with (y := \sum_(cpu < num_cpus) 1);
last by rewrite big_const_ord iter_addn mul1n addn0.
apply eq_bigr; intros cpu _.
 specialize (WORK j t BACK cpu); des.
+ specialize (WORK j t H_j_arrives BACK cpu); des.
move: WORK => /eqP SCHED.
rewrite (bigD1_seq (job_task j_other)) /=; last by rewrite filter_uniq; destruct ts.
{
@@ 297,10 +304,12 @@ Module ResponseTimeAnalysisFP.
rewrite big_const_seq iter_addn mul0n 2!addn0; apply/eqP; rewrite eqb1.
by unfold task_scheduled_on; rewrite SCHED.
}
+ have ARRother: arrives_in arr_seq j_other.
+ by apply (FROMarr j_other t); apply/existsP; exists cpu; apply/eqP.
rewrite mem_filter; apply/andP; split; last by apply FROMTS.
apply/andP; split.
{
 rewrite JOBtsk; apply FP with (t := t); first by done.
+ rewrite JOBtsk; apply FP with (t := t); try (by done).
by apply/existsP; exists cpu; apply/eqP.
}
{
@@ 311,10 +320,11 @@ Module ResponseTimeAnalysisFP.
by apply/existsP; exists cpu; rewrite SCHED.
} clear SCHED; rename SCHED' into SCHED.
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) in PENDING; try (by done).
destruct (ltnP (job_arrival j_other) (job_arrival j)) as [BEFOREother  BEFOREj].
{
 specialize (BEFOREok j_other SAMEtsk BEFOREother).
+ specialize (BEFOREok j_other ARRother SAMEtsk BEFOREother).
move: PENDING => /andP [_ /negP NOTCOMP]; apply NOTCOMP.
apply completion_monotonic with (t0 := job_arrival j_other + R); try (by done).
apply leq_trans with (n := job_arrival j); last by done.
@@ 322,12 +332,12 @@ Module ResponseTimeAnalysisFP.
first by rewrite leq_add2l; apply NOMISS.
apply leq_trans with (n := job_arrival j_other + task_period tsk);
first by rewrite leq_add2l; apply RESTR; rewrite JOBtsk FROMTS.
 rewrite SAMEtsk; apply SPO; [  by rewrite JOBtsk  by apply ltnW].
+ rewrite SAMEtsk; apply SPO; try (by done); [  by rewrite JOBtsk  by apply ltnW].
by red; intro EQ; rewrite EQ ltnn in BEFOREother.
}
{
move: PENDING => /andP [ARRIVED _].
 exploit (SPO j j_other); [  by rewrite SAMEtsk  by done  ]; last first.
+ exploit (SPO j j_other); try (by done); [  by rewrite SAMEtsk  ]; last first.
{
apply/negP; rewrite ltnNge.
apply leq_ltn_trans with (n := t); first by done.
@@ 422,7 +432,7 @@ Module ResponseTimeAnalysisFP.
H_response_time_of_interfering_tasks_is_known into RESP,
H_hp_bounds_has_interfering_tasks into HAS,
H_response_time_no_larger_than_deadline into LEdl.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
(* First, rewrite the claim in terms of the *absolute* responsetime bound (arrival + R) *)
remember (job_arrival j + R) as ctime.
@@ 431,10 +441,11 @@ Module ResponseTimeAnalysisFP.
generalize dependent j.
induction ctime as [ctime IH] using strong_ind.
 intros j JOBtsk EQc; subst ctime.
+ intros j ARRj JOBtsk EQc; subst ctime.
(* First, let's simplify the induction hypothesis. *)
 assert (BEFOREok: forall (j0: JobIn arr_seq),
+ assert (BEFOREok: forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
service sched j0 (job_arrival j0 + R) == job_cost j0).
@@ 452,7 +463,7 @@ Module ResponseTimeAnalysisFP.
apply negbT in NOTCOMP; exfalso.
(* We derive a contradiction using the previous lemmas. *)
 specialize (EX j JOBtsk NOTCOMP BEFOREok).
+ specialize (EX j ARRj JOBtsk NOTCOMP BEFOREok).
destruct EX as [tsk_k [R_k [HPk LTmin]]].
specialize (BOUND j tsk_k R_k HPk).
by apply (leq_ltn_trans BOUND) in LTmin; rewrite ltnn in LTmin.
diff git a/analysis/global/parallel/interference_bound_edf.v b/analysis/global/parallel/interference_bound_edf.v
index 7741a5e..638d24a 100644
 a/analysis/global/parallel/interference_bound_edf.v
+++ b/analysis/global/parallel/interference_bound_edf.v
@@ 112,6 +112,7 @@ Module InterferenceBoundEDF.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
@@ 121,19 +122,22 @@ Module InterferenceBoundEDF.
(* ... in which jobs arrive sporadically and have valid parameters. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider any schedule such that...*)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.

+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
(* ...jobs do not execute before their arrival times nor longer
than their execution costs. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 144,28 +148,29 @@ Module InterferenceBoundEDF.
parameters and constrained deadlines. *)
Variable ts: taskset_of sporadic_task.
Hypothesis all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
Hypothesis H_constrained_deadlines:
forall tsk, tsk \in ts > task_deadline tsk <= task_period tsk.
Let no_deadline_is_missed_by_tsk (tsk: sporadic_task) :=
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
Let response_time_bounded_by (tsk: sporadic_task) :=
 is_response_time_bound_of_task job_cost job_task tsk sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk.
(* Assume that the scheduler is a workconserving EDF scheduler. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_edf_scheduler:
 respects_JLFP_policy job_cost sched (EDF job_deadline).
+ respects_JLFP_policy job_arrival job_cost arr_seq sched (EDF job_arrival job_deadline).
(* Let tsk_i be the task to be analyzed, ...*)
Variable tsk_i: sporadic_task.
Hypothesis H_tsk_i_in_task_set: tsk_i \in ts.
(* and j_i one of its jobs. *)
 Variable j_i: JobIn arr_seq.
+ Variable j_i: Job.
+ Hypothesis H_j_i_arrives: arrives_in arr_seq j_i.
Hypothesis H_job_of_tsk_i: job_task j_i = tsk_i.
(* Let tsk_k denote any interfering task, ... *)
@@ 182,7 +187,8 @@ Module InterferenceBoundEDF.
(* Assume that the jobs of tsk_k satisfy the responsetime bound before the end of the interval *)
Hypothesis H_all_previous_jobs_completed_on_time :
 forall (j_k: JobIn arr_seq),
+ forall j_k,
+ arrives_in arr_seq j_k >
job_task j_k = tsk_k >
job_arrival j_k + R_k < job_arrival j_i + delta >
completed job_cost sched j_k (job_arrival j_k + R_k).
@@ 193,7 +199,7 @@ Module InterferenceBoundEDF.
(* Let's call x the task interference incurred by job j due to tsk_k. *)
Let x :=
 task_interference job_cost job_task sched j_i
+ task_interference job_arrival job_cost job_task sched j_i
tsk_k (job_arrival j_i) (job_arrival j_i + delta).
(* Also, recall the EDFspecific interference bound for EDF. *)
@@ 210,17 +216,17 @@ Module InterferenceBoundEDF.
Let n_k := div_ceil (D_i + R_k  D_k + 1) p_k.
(* Let's give a simpler name to job interference. *)
 Let interference_caused_by := job_interference job_cost sched j_i.
+ Let interference_caused_by := job_interference job_arrival job_cost sched j_i.
(* Identify the subset of jobs that actually cause interference *)
Let interfering_jobs :=
 filter (fun (x: JobIn arr_seq) =>
 (job_task x == tsk_k) && (interference_caused_by x t1 t2 != 0))
+ filter (fun j' =>
+ (job_task j' == tsk_k) && (interference_caused_by j' t1 t2 != 0))
(jobs_scheduled_between sched t1 t2).
(* Now, consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
 Let sorted_jobs := (sort earlier_arrival interfering_jobs).
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
+ Let sorted_jobs := sort earlier_arrival interfering_jobs.
(* Now we proceed with the proof.
The first step consists in simplifying the sum corresponding to the workload. *)
@@ 238,7 +244,7 @@ Module InterferenceBoundEDF.
apply leq_sum. move => t /andP [LEt _].
rewrite exchange_big /=.
apply leq_sum; intros cpu _.
 destruct (backlogged job_cost sched j_i t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j_i t) eqn:BACK;
last by rewrite andFb (eq_bigr (fun x => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
rewrite andTb.
@@ 246,7 +252,7 @@ Module InterferenceBoundEDF.
last by done.
unfold task_scheduled_on in *.
destruct (sched cpu t) eqn:SOME; last by done.
 rewrite big_mkcond /= (bigD1_seq j) /=; last by apply undup_uniq.
+ rewrite big_mkcond /= (bigD1_seq s) /=; last by apply undup_uniq.
{
rewrite SCHED addn1 addnC; apply leq_add; last by done.
apply eq_leq; symmetry; apply/eqP; rewrite eqb1.
@@ 295,13 +301,19 @@ Module InterferenceBoundEDF.
Lemma interference_bound_edf_all_jobs_from_tsk_k :
forall j,
j \in sorted_jobs >
+ arrives_in arr_seq j /\
job_task j = tsk_k /\
interference_caused_by j t1 t2 != 0 /\
j \in jobs_scheduled_between sched t1 t2.
Proof.
intros j LT.
rewrite interference_bound_edf_job_in_same_sequence mem_filter in LT.
 by move: LT => /andP [/andP [/eqP JOBi SERVi] INi]; repeat split.
+ move: LT => /andP [/andP [/eqP JOBi SERVi] INi].
+ repeat split; try (by done).
+ unfold jobs_scheduled_between in *; rewrite mem_undup in INi.
+ apply mem_bigcat_nat_exists in INi; des.
+ rewrite mem_scheduled_jobs_eq_scheduled in INi.
+ by apply (H_jobs_come_from_arrival_sequence j i).
Qed.
(* ...and consecutive jobs are ordered by arrival. *)
@@ 323,13 +335,15 @@ Module InterferenceBoundEDF.
interference_caused_by j t1 t2 <= task_cost tsk_k.
Proof.
rename H_valid_job_parameters into PARAMS.
 intros j; rewrite mem_filter; move => /andP [/andP [/eqP JOBj _] _].
 specialize (PARAMS j); des.
+ intros j INj.
+ feed (interference_bound_edf_all_jobs_from_tsk_k j);
+ first by rewrite interference_bound_edf_job_in_same_sequence.
+ move => [ARRj [TSKj _]].
+ specialize (PARAMS j ARRj); des.
apply leq_trans with (n := service_during sched j t1 t2);
first by apply job_interference_le_service.
by apply cumulative_service_le_task_cost with (job_task0 := job_task)
 (task_deadline0 := task_deadline) (job_cost0 := job_cost)
 (job_deadline0 := job_deadline).
+ (task_deadline0 := task_deadline) (job_cost0 := job_cost) (job_deadline0 := job_deadline).
Qed.
End SimplifyJobSequence.
@@ 373,7 +387,7 @@ Module InterferenceBoundEDF.
Qed.
(* Let j_fst be the first job, and a_fst its arrival time. *)
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let a_fst := job_arrival j_fst.
@@ 382,6 +396,7 @@ Module InterferenceBoundEDF.
(* The first job is an interfering job of task tsk_k. *)
Lemma interference_bound_edf_j_fst_is_job_of_tsk_k :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk_k /\
interference_caused_by j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 397,8 +412,8 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [FSTtask _].
 by specialize (PARAMS j_fst); des; rewrite PARAMS1 FSTtask.
+ destruct FST as [FSTarr [FSTtask _]].
+ by specialize (PARAMS j_fst FSTarr); des; rewrite PARAMS1 FSTtask.
Qed.
(* The deadline of j_i is the deadline of tsk_i. *)
@@ 408,7 +423,7 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS,
H_job_of_tsk_i into JOBtsk.
 by specialize (PARAMS j_i); des; rewrite PARAMS1 JOBtsk.
+ by specialize (PARAMS j_i H_j_i_arrives); des; rewrite PARAMS1 JOBtsk.
Qed.
(* If j_fst completes by its responsetime bound, then t1 <= a_fst + R_k,
@@ 420,12 +435,13 @@ Module InterferenceBoundEDF.
intros RBOUND.
rewrite leqNgt; apply/negP; unfold not; intro BUG.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ FSTserv _]].
+ destruct FST as [_ [_ [ FSTserv _]]].
move: FSTserv => /negP FSTserv; apply FSTserv.
rewrite leqn0; apply leq_trans with (n := service_during sched j_fst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost) (R := R_k);
+ by apply cumulative_service_after_job_rt_zero with (job_cost0 := job_cost)
+ (job_arrival0 := job_arrival) (R := R_k);
try (by done); apply ltnW.
Qed.
@@ 484,6 +500,7 @@ Module InterferenceBoundEDF.
(* The last job is an interfering job of task tsk_k. *)
Lemma interference_bound_edf_j_lst_is_job_of_tsk_k :
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk_k /\
interference_caused_by j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 499,8 +516,8 @@ Module InterferenceBoundEDF.
unfold valid_sporadic_job in *.
rename H_valid_job_parameters into PARAMS.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [LSTtask _].
 by specialize (PARAMS j_lst); des; rewrite PARAMS1 LSTtask.
+ destruct LST as [LSTarr [LSTtask _]].
+ by specialize (PARAMS j_lst LSTarr); des; rewrite PARAMS1 LSTtask.
Qed.
(* The first job arrives before the last job. *)
@@ 523,12 +540,12 @@ Module InterferenceBoundEDF.
apply mem_nth; instantiate (1 := num_mid_jobs.+1).
by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
}
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
+ instantiate (1 := elem); move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
apply LSTserv; apply/eqP; rewrite leqn0.
apply leq_trans with (n := service_during sched j_lst t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP; unfold service_during.
 by apply cumulative_service_before_job_arrival_zero.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
Qed.
(* Since there are multiple jobs, j_fst is far enough from the end of
@@ 543,7 +560,7 @@ Module InterferenceBoundEDF.
{
by apply mem_nth; instantiate (1 := 1); rewrite H_at_least_two_jobs.
}
 instantiate (1 := elem); move => [SNDtsk [/eqP SNDserv _]].
+ instantiate (1 := elem); move => [SNDarr [SNDtsk [/eqP SNDserv _]]].
apply H_all_previous_jobs_completed_on_time; try (by done).
apply leq_ltn_trans with (n := job_arrival j_snd); last first.
{
@@ 552,7 +569,7 @@ Module InterferenceBoundEDF.
sched j_snd t1 t2);
first by apply job_interference_le_service.
rewrite leqn0; apply/eqP.
 by apply cumulative_service_before_job_arrival_zero.
+ by apply cumulative_service_before_job_arrival_zero with (job_arrival0 := job_arrival).
}
apply leq_trans with (n := a_fst + p_k).
{
@@ 562,8 +579,8 @@ Module InterferenceBoundEDF.
(* Since jobs are sporadic, we know that the first job arrives
at least p_k units before the second. *)
 unfold p_k; rewrite FST.
 apply H_sporadic_tasks; [ by rewrite SNDtsk  ]; last first.
+ unfold p_k; rewrite FST0.
+ apply H_sporadic_tasks; try (by done); [ by rewrite SNDtsk  ]; last first.
{
apply interference_bound_edf_jobs_ordered_by_arrival.
by rewrite H_at_least_two_jobs.
@@ 599,14 +616,13 @@ Module InterferenceBoundEDF.
assert (ARRle: job_arrival cur <= job_arrival next).
by unfold cur, next; apply interference_bound_edf_jobs_ordered_by_arrival.
 (* Show that both cur and next are in the arrival sequence *)
 assert (INnth: cur \in interfering_jobs /\ next \in interfering_jobs).
 {
 rewrite 2!interference_bound_edf_job_in_same_sequence; split.
 by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs; ins.
 by apply mem_nth; destruct sorted_jobs; ins.
 }
 rewrite 2?mem_filter in INnth; des.
+ feed (interference_bound_edf_all_jobs_from_tsk_k cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (interference_bound_edf_all_jobs_from_tsk_k next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
(* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
@@ 614,15 +630,15 @@ Module InterferenceBoundEDF.
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /interfering_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk.
}
 by rewrite subh3 // addnC /p_k INnth.
+ by rewrite subh3 // addnC /p_k CURtsk.
Qed.
Lemma interference_bound_edf_slack_le_delta:
@@ 636,9 +652,9 @@ Module InterferenceBoundEDF.
apply leq_trans with (n := D_i + t1);
last by rewrite leq_add2l.
have FST := interference_bound_edf_j_fst_is_job_of_tsk_k.
 destruct FST as [_ [ LEdl _]].
+ destruct FST as [ARRfst [_ [ LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
rewrite addnC [D_i + _]addnC.
unfold D_k, D_i.
by rewrite interference_bound_edf_j_fst_deadline
@@ 689,9 +705,9 @@ Module InterferenceBoundEDF.
apply leq_ltn_trans with (m := t1 + D_i) in BUG;
last by rewrite leq_add2r.
have LST := interference_bound_edf_j_lst_is_job_of_tsk_k.
 destruct LST as [_ [ LEdl _]].
+ destruct LST as [ARRlst [_ [ LEdl _]]].
apply interference_under_edf_implies_shorter_deadlines with
 (job_deadline0 := job_deadline) in LEdl; try (by done).
+ (arr_seq0 := arr_seq) (job_deadline0 := job_deadline) in LEdl; try (by done).
unfold D_i, D_k in DIST; rewrite interference_bound_edf_j_lst_deadline
interference_bound_edf_j_i_deadline in LEdl.
by rewrite ltnNge LEdl in BUG.
@@ 743,7 +759,7 @@ Module InterferenceBoundEDF.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
+ assert (EX: exists elem: Job, True).
destruct sorted_jobs as [ j]; [by rewrite ltn0 in NUM  by exists j].
destruct EX as [elem _].
@@ 755,7 +771,7 @@ Module InterferenceBoundEDF.
first by rewrite big_geq.
(* Then, we show the same for a single job, or for multiple jobs. *)
 rewrite SIZE; destruct n as [ num_mid_jobs].
+ destruct n as [ num_mid_jobs].
{
rewrite big_nat_recr // big_geq //.
rewrite [nth]lock /= lock add0n.
diff git a/analysis/global/parallel/workload_bound.v b/analysis/global/parallel/workload_bound.v
index 2446a80..7634843 100644
 a/analysis/global/parallel/workload_bound.v
+++ b/analysis/global/parallel/workload_bound.v
@@ 70,6 +70,7 @@ Module WorkloadBound.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
Variable job_deadline: Job > time.
@@ 78,17 +79,20 @@ Module WorkloadBound.
(* Assume that all jobs have valid parameters *)
Hypothesis H_jobs_have_valid_parameters :
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider any schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.

+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
(* Assumption: jobs only execute if they arrived.
This is used to eliminate jobs that arrive after end of the interval t1 + delta. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* Assumption: jobs do not execute after they completed.
This is used to eliminate jobs that complete before the start of the interval t1. *)
@@ 98,7 +102,8 @@ Module WorkloadBound.
(* Assumption: sporadic task model.
This is necessary to conclude that consecutive jobs ordered by arrival times
are separated by at least 'period' times units. *)
 Hypothesis H_sporadic_tasks: sporadic_task_model task_period arr_seq job_task.
+ Hypothesis H_sporadic_tasks:
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Before starting the proof, let's give simpler names to the definitions. *)
Let job_has_completed_by := completed job_cost sched.
@@ 128,10 +133,11 @@ Module WorkloadBound.
Variable R_tsk: time.
Hypothesis H_response_time_bound :
 forall (j: JobIn arr_seq),
 job_task j = tsk >
 job_arrival j + R_tsk < t1 + delta >
 job_has_completed_by j (job_arrival j + R_tsk).
+ forall j,
+ arrives_in arr_seq j >
+ job_task j = tsk >
+ job_arrival j + R_tsk < t1 + delta >
+ job_has_completed_by j (job_arrival j + R_tsk).
Section MainProof.
@@ 149,7 +155,7 @@ Module WorkloadBound.
jobs_of_task_scheduled_between job_task sched tsk t1 t2.
(* Now, let's consider the list of interfering jobs sorted by arrival time. *)
 Let earlier_arrival := fun (x y: JobIn arr_seq) => job_arrival x <= job_arrival y.
+ Let earlier_arrival := fun x y => job_arrival x <= job_arrival y.
Let sorted_jobs := (sort earlier_arrival scheduled_jobs).
(* The first step consists in simplifying the sum corresponding
@@ 180,19 +186,28 @@ Module WorkloadBound.
Lemma workload_bound_all_jobs_from_tsk :
forall j_i,
j_i \in sorted_jobs >
+ arrives_in arr_seq j_i /\
job_task j_i = tsk /\
service_during sched j_i t1 t2 != 0 /\
j_i \in jobs_scheduled_between sched t1 t2.
Proof.
+ rename H_jobs_come_from_arrival_sequence into FROMarr.
intros j_i LTi.
rewrite workload_bound_job_in_same_sequence mem_filter in LTi; des.
 repeat split; [by done   by done].
unfold jobs_scheduled_between in *; rewrite mem_undup in LTi0.
apply mem_bigcat_nat_exists in LTi0; des.
rewrite mem_scheduled_jobs_eq_scheduled in LTi0.
 apply service_implies_cumulative_service with (t := i);
 first by apply/andP; split.
 by rewrite not_scheduled_no_service negbK.
+ repeat split; try (by done); first by apply (FROMarr j_i i).
+ {
+ apply service_implies_cumulative_service with (t := i);
+ first by apply/andP; split.
+ by rewrite not_scheduled_no_service negbK.
+ }
+ {
+ rewrite mem_undup.
+ apply mem_bigcat_nat with (j := i); first by auto.
+ by rewrite mem_scheduled_jobs_eq_scheduled.
+ }
Qed.
(* Remember that consecutive jobs are ordered by arrival. *)
@@ 226,7 +241,7 @@ Module WorkloadBound.
apply leq_sum; intros j_i; move/andP => [INi _].
apply workload_bound_all_jobs_from_tsk in INi; des.
eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute  by apply INi ].
+ [by apply H_completed_jobs_dont_execute  by apply INi0 ].
by apply H_jobs_have_valid_parameters.
Qed.
@@ 239,11 +254,12 @@ Module WorkloadBound.
(* Assume that there's at least one job in the sorted list. *)
Hypothesis H_at_least_one_job: size sorted_jobs > 0.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
(* The first job is an interfering job of task tsk. *)
Lemma workload_bound_j_fst_is_job_of_tsk :
+ arrives_in arr_seq j_fst /\
job_task j_fst = tsk /\
service_during sched j_fst t1 t2 != 0 /\
j_fst \in jobs_scheduled_between sched t1 t2.
@@ 261,16 +277,17 @@ Module WorkloadBound.
unfold workload_bound, W; fold n_k.
have INfst := workload_bound_j_fst_is_job_of_tsk; des.
rewrite big_nat_recr // big_geq // [nth]lock /= lock add0n.
 apply leq_trans with (n := task_cost tsk);
 first by eapply cumulative_service_le_task_cost;
 [ by apply INfst
  by apply H_jobs_have_valid_parameters].
+ apply leq_trans with (n := task_cost tsk).
+ {
+ eapply cumulative_service_le_task_cost; [by eauto 1  by apply INfst0 ].
+ by apply H_jobs_have_valid_parameters.
+ }
rewrite {1}[task_cost tsk]mul1n leq_mul2r; apply/orP; right.
apply ceil_neq0; last by apply PARAMS0.
{
apply leq_trans with (n := delta); last by apply leq_addr.
rewrite lt0n; apply/eqP; intro EQ0.
 move: INfst0 => /eqP BUG; apply BUG.
+ move: INfst1 => /eqP BUG; apply BUG.
unfold t2; rewrite EQ0 addn0.
by unfold service_during; rewrite big_geq.
}
@@ 286,12 +303,13 @@ Module WorkloadBound.
Variable num_mid_jobs: nat.
Hypothesis H_at_least_two_jobs : size sorted_jobs = num_mid_jobs.+2.
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let j_fst := nth elem sorted_jobs 0.
Let j_lst := nth elem sorted_jobs num_mid_jobs.+1.
(* The last job is an interfering job of task tsk. *)
Lemma workload_bound_j_lst_is_job_of_tsk :
+ arrives_in arr_seq j_lst /\
job_task j_lst = tsk /\
service_during sched j_lst t1 t2 != 0 /\
j_lst \in jobs_scheduled_between sched t1 t2.
@@ 310,11 +328,11 @@ Module WorkloadBound.
apply mem_nth; instantiate (1 := 0).
apply ltn_trans with (n := 1); [by done  by rewrite H_at_least_two_jobs].
}
 instantiate (1 := elem); move => [FSTtsk [/eqP FSTserv FSTin]].
+ instantiate (1 := elem); move => [FSTarr [FSTtsk [/eqP FSTserv FSTin]]].
apply FSTserv.
 apply (cumulative_service_after_job_rt_zero job_cost) with (R := R_tsk);
+ apply (cumulative_service_after_job_rt_zero job_arrival job_cost) with (R := R_tsk);
try (by done); last by apply ltnW.
 apply H_response_time_bound; first by done.
+ apply H_response_time_bound; try (by done).
by apply leq_trans with (n := t1); last by apply leq_addr.
Qed.
@@ 328,8 +346,9 @@ Module WorkloadBound.
apply mem_nth; instantiate (1 := num_mid_jobs.+1).
by rewrite (ltn_add2r 1) addn1 H_at_least_two_jobs addn1.
}
 instantiate (1 := elem); move => [LSTtsk [/eqP LSTserv LSTin]].
 by unfold service_during; apply LSTserv, cumulative_service_before_job_arrival_zero.
+ instantiate (1 := elem); move => [LSTarr [LSTtsk [/eqP LSTserv LSTin]]].
+ unfold service_during; apply LSTserv.
+ by eapply cumulative_service_before_job_arrival_zero; eauto 1.
Qed.
(* Bound the service of the middle jobs. *)
@@ 344,15 +363,15 @@ Module WorkloadBound.
last by rewrite big_const_nat iter_addn addn0 mulnC subn0.
rewrite big_nat_cond [\sum_(0 <= i < num_mid_jobs) task_cost _]big_nat_cond.
apply leq_sum; intros i; rewrite andbT; move => /andP LT; des.
 eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute   by apply H_jobs_have_valid_parameters].
exploit workload_bound_all_jobs_from_tsk.
{
instantiate (1 := nth elem sorted_jobs i.+1).
apply mem_nth; rewrite H_at_least_two_jobs.
by rewrite ltnS; apply leq_trans with (n := num_mid_jobs).
}
 by ins; des.
+ move => [ARR [TSK _]].
+ eapply cumulative_service_le_task_cost; eauto 1.
+ by apply H_jobs_have_valid_parameters.
Qed.
(* Conclude that the distance between first and last is at least num_mid_jobs + 1 periods. *)
@@ 375,14 +394,13 @@ Module WorkloadBound.
assert (ARRle: job_arrival cur <= job_arrival next).
by unfold cur, next; apply workload_bound_jobs_ordered_by_arrival.
 (* Show that both cur and next are in the arrival sequence *)
 assert (INnth: cur \in scheduled_jobs /\ next \in scheduled_jobs).
 {
 rewrite 2!workload_bound_job_in_same_sequence; split.
 by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs; ins.
 by apply mem_nth; destruct sorted_jobs; ins.
 }
 rewrite 2?mem_filter in INnth; des.
+ feed (workload_bound_all_jobs_from_tsk cur).
+ by apply mem_nth, (ltn_trans LT0); destruct sorted_jobs.
+ intros [CURarr [CURtsk [_ CURin]]].
+
+ feed (workload_bound_all_jobs_from_tsk next).
+ by apply mem_nth; destruct sorted_jobs.
+ intros [NEXTarr [NEXTtsk [_ NEXTin]]].
(* Use the sporadic task model to conclude that cur and next are separated
by at least (task_period tsk) units. Of course this only holds if cur != next.
@@ 390,15 +408,15 @@ Module WorkloadBound.
also prove that it doesn't contain duplicates. *)
assert (CUR_LE_NEXT: job_arrival cur + task_period (job_task cur) <= job_arrival next).
{
 apply H_sporadic_tasks; last by ins.
+ apply H_sporadic_tasks; try (by done).
unfold cur, next, not; intro EQ; move: EQ => /eqP EQ.
rewrite nth_uniq in EQ; first by move: EQ => /eqP EQ; intuition.
by apply ltn_trans with (n := (size sorted_jobs).1); destruct sorted_jobs; ins.
by destruct sorted_jobs; ins.
by rewrite sort_uniq /scheduled_jobs filter_uniq // undup_uniq.
 by rewrite INnth INnth0.
+ by rewrite CURtsk.
}
 by rewrite subh3 // addnC INnth.
+ by rewrite subh3 // addnC CURtsk.
Qed.
(* Next, we prove that n_k covers every scheduled job, ... *)
@@ 454,14 +472,14 @@ Module WorkloadBound.
last by rewrite big_const_nat iter_addn addn0 subn0 mulnC.
rewrite big_nat_cond [\sum_(_ <= _ < _  true)_]big_nat_cond.
apply leq_sum; intro i; move => /andP [/andP [_ LEi] _].
 eapply cumulative_service_le_task_cost;
 [by apply H_completed_jobs_dont_execute   by apply H_jobs_have_valid_parameters].
exploit workload_bound_all_jobs_from_tsk.
{
instantiate (1 := nth elem sorted_jobs i).
by apply mem_nth; rewrite H_at_least_two_jobs.
}
 by ins; des.
+ move => [ARR [TSK _]].
+ eapply cumulative_service_le_task_cost; eauto 1.
+ by apply H_jobs_have_valid_parameters.
Qed.
End WorkloadTwoOrMoreJobs.
@@ 486,8 +504,8 @@ Module WorkloadBound.
apply negbT in NUM; rewrite ltnNge in NUM.
(* Find some dummy element to use in the nth function *)
 assert (EX: exists elem: JobIn arr_seq, True).
 destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists j].
+ assert (EX: exists elem: Job, True).
+ destruct sorted_jobs; [ by rewrite ltn0 in NUM  by exists s].
destruct EX as [elem _].
(* Now we index the sum to access the first and last elements. *)
diff git a/analysis/uni/basic/fp_rta_comp.v b/analysis/uni/basic/fp_rta_comp.v
index eae958b..f374094 100644
 a/analysis/uni/basic/fp_rta_comp.v
+++ b/analysis/uni/basic/fp_rta_comp.v
@@ 243,6 +243,7 @@ Module ResponseTimeIterationFP.
Variable task_deadline: SporadicTask > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > SporadicTask.
@@ 254,22 +255,24 @@ Module ResponseTimeIterationFP.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
 (* Next, consider any arrival sequence such that...*)
 Context {arr_seq: arrival_sequence Job}.
+ (* Assume any job arrival sequence with consistent, nonduplicate arrivals... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
 (* ...all jobs come from task set ts, ...*)
+ (* ...such that all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...jobs have valid parameters...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
 (* ... and satisfy the sporadic task model.*)
+ (* ... and jobs satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Assume any fixedpriority policy... *)
Variable higher_eq_priority: FP_policy SporadicTask.
@@ 278,28 +281,28 @@ Module ResponseTimeIterationFP.
Hypothesis H_priority_reflexive: FP_is_reflexive higher_eq_priority.
Hypothesis H_priority_transitive: FP_is_transitive higher_eq_priority.
 (* Next, consider any uniprocessor schedule... *)
 Variable sched: schedule arr_seq.
+ (* Next, consider any uniprocessor schedule of this arrival sequence...*)
+ Variable sched: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence: jobs_come_from_arrival_sequence sched arr_seq.
 (* ...where jobs only execute after they arrived and no longer
 than their execution costs. *)
+ (* ...where jobs do not execute before their arrival times nor after completion. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
(* Also assume that the scheduler is workconserving and respects the FP policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_respects_FP_policy:
 respects_FP_policy job_cost job_task sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_task arr_seq sched higher_eq_priority.
(* For simplicity, let's define some local names. *)
Let no_deadline_missed_by_task :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
Let no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
 Let response_time_bounded_by:=
 is_response_time_bound_of_task job_cost job_task sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
+ Let response_time_bounded_by :=
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched.
(* Recall the iteration for the responsetime analysis and the corresponding
schedulability test. *)
@@ 353,7 +356,8 @@ Module ResponseTimeIterationFP.
Theorem taskset_schedulable_by_fp_rta :
forall tsk, tsk \in ts > no_deadline_missed_by_task tsk.
Proof.
 rename H_test_succeeds into TEST.
+ have RTA := fp_analysis_yields_response_time_bounds.
+ rename H_test_succeeds into TEST, H_valid_job_parameters into JOBPARAMS.
unfold claimed_to_be_schedulable, fp_schedulable in *.
have RESP := fp_claimed_bounds_for_every_task task_cost task_period task_deadline
higher_eq_priority ts.
@@ 363,26 +367,28 @@ Module ResponseTimeIterationFP.
intros tsk IN.
move: (RESP rt_bounds TEST tsk IN) => [R INbounds].
specialize (DL rt_bounds TEST tsk R INbounds).
 apply task_completes_before_deadline with (task_cost0 := task_cost)
 (task_deadline0 := task_deadline) (R0 := R); try (by done).
 apply fp_analysis_yields_response_time_bounds.
 by rewrite /RTA_claimed_bounds TEST.
+ apply task_completes_before_deadline with
+ (task_deadline0 := task_deadline) (R0 := R); try (by done);
+ first by intros j ARRj; specialize (JOBPARAMS j ARRj); move: JOBPARAMS => [_ [_ EQ]].
+ by apply RTA; rewrite /RTA_claimed_bounds TEST.
Qed.
(* Since all jobs of the arrival sequence are spawned by the task set,
we also conclude that no job in the schedule misses its deadline. *)
Theorem jobs_schedulable_by_fp_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j,
+ arrives_in arr_seq j >
+ no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_fp_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
End AnalysisIsSufficient.
End ProvingCorrectness.

+
End ResponseTimeIterationFP.
\ No newline at end of file
diff git a/analysis/uni/basic/fp_rta_theory.v b/analysis/uni/basic/fp_rta_theory.v
index d9aaf2e..7f4e041 100644
 a/analysis/uni/basic/fp_rta_theory.v
+++ b/analysis/uni/basic/fp_rta_theory.v
@@ 24,19 +24,22 @@ Module ResponseTimeAnalysisFP.
Variable task_deadline: SporadicTask > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > SporadicTask.
 (* Assume any job arrival sequence without duplicates... *)
 Context {arr_seq: arrival_sequence Job}.
+ (* Assume any job arrival sequence with consistent, nonduplicate arrivals... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
(* ... in which jobs arrive sporadically and have valid parameters. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Consider a task set ts where all tasks have valid parameters... *)
@@ 46,15 +49,15 @@ Module ResponseTimeAnalysisFP.
(* ... and assume that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
 (* Next, consider any uniprocessor schedule such that...*)
 Variable sched: schedule arr_seq.
+ (* Next, consider any uniprocessor schedule of this arrival sequence...*)
+ Variable sched: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence: jobs_come_from_arrival_sequence sched arr_seq.
 (* ...jobs do not execute before their arrival times nor longer than their
 execution costs. *)
+ (* ... where jobs do not execute before their arrival times nor after completion. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 65,8 +68,9 @@ Module ResponseTimeAnalysisFP.
Hypothesis H_priority_is_transitive: FP_is_transitive higher_eq_priority.
(* Next, assume that the schedule is a workconserving FP schedule. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
 Hypothesis H_respects_fp_policy: respects_FP_policy job_cost job_task sched higher_eq_priority.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
+ Hypothesis H_respects_fp_policy:
+ respects_FP_policy job_arrival job_cost job_task arr_seq sched higher_eq_priority.
(* Now we proceed with the analysis.
Let tsk be any task in ts that is to be analyzed. *)
@@ 76,7 +80,7 @@ Module ResponseTimeAnalysisFP.
(* Recall the definition of responsetime bound and the total workload bound W
for tasks with higherorequal priority (with respect to tsk). *)
Let response_time_bounded_by :=
 is_response_time_bound_of_task job_cost job_task sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched.
Let W := total_workload_bound_fp task_cost task_period higher_eq_priority ts tsk.
(* Let R be any positive fixed point of the responsetime recurrence. *)
@@ 93,13 +97,13 @@ Module ResponseTimeAnalysisFP.
response_time_bounded_by tsk R.
Proof.
rename H_response_time_is_fixed_point into FIX.
 intros j JOBtsk.
 have bla := busy_interval_bounds_response_time.
 set prio := FP_to_JLFP job_task arr_seq higher_eq_priority.
 apply busy_interval_bounds_response_time with (higher_eq_priority0 := prio); try (by done).
+ intros j ARRj JOBtsk.
+ set prio := FP_to_JLFP job_task higher_eq_priority.
+ apply busy_interval_bounds_response_time with (arr_seq0 := arr_seq)
+ (higher_eq_priority0 := prio); try (by done).
 by intros x; apply H_priority_is_reflexive.
 by intros x z y; apply H_priority_is_transitive.
 apply fp_workload_bound_holds with (task_cost0 := task_cost)
+ apply fp_workload_bound_holds with (job_arrival0 := job_arrival) (task_cost0 := task_cost)
(task_period0 := task_period) (task_deadline0 := task_deadline)
(job_deadline0 := job_deadline) (ts0 := ts); try (by done).
by rewrite JOBtsk.
diff git a/analysis/uni/basic/workload_bound_fp.v b/analysis/uni/basic/workload_bound_fp.v
index 23f95dd..26bede2 100644
 a/analysis/uni/basic/workload_bound_fp.v
+++ b/analysis/uni/basic/workload_bound_fp.v
@@ 17,10 +17,8 @@ Module WorkloadBoundFP.
Variable task_cost: Task > time.
Variable task_period: Task > time.
 (* Consider any task tsk with responsetime bound R_tsk, that is
 scheduled in an interval of length delta. *)
+ (* Consider any task tsk that is to be scheduled in an interval of length delta. *)
Variable tsk: Task.
 Variable R_tsk: time.
Variable delta: time.
(* Based on the maximum number of jobs of tsk that can execute in the interval, ... *)
@@ 152,6 +150,7 @@ Module WorkloadBoundFP.
Variable task_deadline: Task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > Task.
@@ 161,22 +160,24 @@ Module WorkloadBoundFP.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
 (* Consider any arrival sequence with no duplicate arrivals. *)
+ (* Consider any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_arr_seq_is_a_set: arrival_sequence_is_a_set arr_seq.
(* Assume that all jobs come from the task set ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...and have valid parameters. *)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* Assume that jobs arrived sporadically. *)
Hypothesis H_sporadic_arrivals:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Let tsk be any task in ts. *)
Variable tsk: Task.
@@ 186,8 +187,10 @@ Module WorkloadBoundFP.
Variable higher_eq_priority: FP_policy Task.
(* First, let's define some local names for clarity. *)
 Let hp_workload :=
 workload_of_higher_or_equal_priority_tasks job_cost job_task arr_seq higher_eq_priority tsk.
+ Let arrivals_between := jobs_arrived_between arr_seq.
+ Let hp_workload t1 t2:=
+ workload_of_higher_or_equal_priority_tasks job_cost job_task (arrivals_between t1 t2)
+ higher_eq_priority tsk.
Let workload_bound :=
total_workload_bound_fp task_cost task_period higher_eq_priority ts tsk.
@@ 201,8 +204,8 @@ Module WorkloadBoundFP.
forall t,
hp_workload t (t + R) <= R.
Proof.
 have BOUND := sporadic_task_arrival_bound task_period job_task arr_seq.
 feed_n 2 BOUND; try (by done).
+ have BOUND := sporadic_task_arrival_bound task_period job_arrival job_task arr_seq.
+ feed_n 3 BOUND; try (by done).
rename H_fixed_point into FIX, H_all_jobs_from_taskset into FROMTS,
H_valid_job_parameters into JOBPARAMS,
H_valid_task_parameters into PARAMS.
@@ 216,18 +219,23 @@ Module WorkloadBoundFP.
apply leq_trans with (n := \sum_(tsk' < ts  hep tsk' tsk)
(\sum_(j0 < l  job_task j0 == tsk') job_cost j0)).
{
 have EXCHANGE := exchange_big_dep (fun (x: JobIn arr_seq) => hep (job_task x) tsk).
+ have EXCHANGE := exchange_big_dep (fun x => hep (job_task x) tsk).
rewrite EXCHANGE /=; last by move => tsk0 j0 HEP /eqP JOB0; rewrite JOB0.
 apply leq_sum; intros j0 HP0.
 rewrite big_mkcond (big_rem (job_task j0)) /=; last by rewrite FROMTS.
 by rewrite HP0 andTb eq_refl; apply leq_addr.
+ rewrite /workload_of_jobs /l big_seq_cond [X in _ <= X]big_seq_cond.
+ apply leq_sum; move => j0 /andP [IN0 HP0].
+ rewrite big_mkcond (big_rem (job_task j0)) /=;
+ first by rewrite HP0 andTb eq_refl; apply leq_addr.
+ by apply in_arrivals_implies_arrived in IN0; apply FROMTS.
}
 apply leq_sum_seq; intros tsk0 IN0 HP0.
 apply leq_trans with (n := num_arrivals_of_task job_task arr_seq tsk0 t (t + R) * task_cost tsk0).
+ apply leq_sum_seq; intros tsk0 INtsk0 HP0.
+ apply leq_trans with (n := num_arrivals_of_task job_task arr_seq
+ tsk0 t (t + R) * task_cost tsk0).
{
 rewrite /num_arrivals_of_task sum1_size big_distrl /=.
 rewrite big_filter; apply leq_sum; move => j0 /eqP EQ; rewrite EQ mul1n.
 by specialize (JOBPARAMS j0); des.
+ rewrite /num_arrivals_of_task sum1_size big_distrl /= big_filter.
+ apply leq_sum_seq; move => j0 IN0 /eqP EQ.
+ rewrite EQ mul1n.
+ feed (JOBPARAMS j0); first by eapply in_arrivals_implies_arrived; eauto 1.
+ by move: JOBPARAMS => [_ [LE _]].
}
rewrite /task_workload_bound_FP leq_mul2r; apply/orP; right.
feed (BOUND t (t + R) tsk0); first by feed (PARAMS tsk0); last by des.
diff git a/analysis/uni/jitter/fp_rta_comp.v b/analysis/uni/jitter/fp_rta_comp.v
index 3dab068..7b54d24 100644
 a/analysis/uni/jitter/fp_rta_comp.v
+++ b/analysis/uni/jitter/fp_rta_comp.v
@@ 253,6 +253,7 @@ Module ResponseTimeIterationFP.
Variable task_jitter: SporadicTask > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_jitter: Job > time.
@@ 265,23 +266,27 @@ Module ResponseTimeIterationFP.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
 (* Next, consider any arrival sequence such that...*)
 Context {arr_seq: arrival_sequence Job}.
 Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
+ (* Next, consider any job arrival sequence with consistent, nonduplicate arrivals, ... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_arr_seq_is_a_set: arrival_sequence_is_a_set arr_seq.
(* ...where all jobs come from task set ts, ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
 (* ...jobs have valid parameters...*)
+ (* ...have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter
job_cost job_deadline job_jitter job_task j.
(* ... and satisfy the sporadic task model.*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Assume any fixedpriority policy... *)
Variable higher_eq_priority: FP_policy SporadicTask.
@@ 290,26 +295,27 @@ Module ResponseTimeIterationFP.
Hypothesis H_priority_reflexive: FP_is_reflexive higher_eq_priority.
Hypothesis H_priority_transitive: FP_is_transitive higher_eq_priority.
 (* Next, consider any jitteraware uniprocessor schedule... *)
 Variable sched: schedule arr_seq.
+ (* Next, consider any jitteraware uniprocessor schedule of these jobs... *)
+ Variable sched: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
 (* ...where jobs only execute after the jitter has passed and no longer
 than their execution costs. *)
 Hypothesis H_jobs_execute_after_jitter: jobs_execute_after_jitter job_jitter sched.
+ (* ...where jobs do not execute before the jitter has passed nor after completion. *)
+ Hypothesis H_jobs_execute_after_jitter: jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Also assume that the scheduler is jitteraware workconserving and respects the FP policy. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_respects_FP_policy:
 respects_FP_policy job_cost job_jitter job_task sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_jitter job_task arr_seq sched higher_eq_priority.
(* For simplicity, let's define some local names. *)
Let no_deadline_missed_by_task :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
Let no_deadline_missed_by_job :=
 job_misses_no_deadline job_cost job_deadline sched.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched.
Let response_time_bounded_by:=
 is_response_time_bound_of_task job_cost job_task sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched.
(* Recall the responsetime analysis and the corresponding schedulability test. *)
Let RTA_claimed_bounds :=
@@ 369,11 +375,11 @@ Module ResponseTimeIterationFP.
intros tsk IN.
move: (RESP rt_bounds TEST tsk IN) => [R INbounds].
specialize (DL rt_bounds TEST tsk R INbounds).
 apply task_completes_before_deadline with (task_cost0 := task_cost)
+ apply task_completes_before_deadline with
(task_deadline0 := task_deadline) (R0 := task_jitter tsk + R); try (by done).
{
 intros j; unfold valid_sporadic_job_with_jitter in *.
 by specialize (JOBPARAMS j); move: JOBPARAMS => [JOBPARAMS _].
+ intros j ARRj; unfold valid_sporadic_job_with_jitter in *.
+ by specialize (JOBPARAMS j ARRj); move: JOBPARAMS => [[_ [_ EQ]] _].
}
by apply BOUND; rewrite /RTA_claimed_bounds TEST.
Qed.
@@ 381,12 +387,14 @@ Module ResponseTimeIterationFP.
(* Since all jobs of the arrival sequence are spawned by the task set,
we also conclude that no job in the schedule misses its deadline. *)
Theorem jobs_schedulable_by_fp_rta :
 forall (j: JobIn arr_seq), no_deadline_missed_by_job j.
+ forall j,
+ arrives_in arr_seq j >
+ no_deadline_missed_by_job j.
Proof.
 intros j.
+ intros j ARRj.
have SCHED := taskset_schedulable_by_fp_rta.
unfold no_deadline_missed_by_task, task_misses_no_deadline in *.
 apply SCHED with (tsk := job_task j); last by done.
+ apply SCHED with (tsk := job_task j); try (by done).
by apply H_all_jobs_from_taskset.
Qed.
diff git a/analysis/uni/jitter/fp_rta_theory.v b/analysis/uni/jitter/fp_rta_theory.v
index b9faff5..645ad7c 100644
 a/analysis/uni/jitter/fp_rta_theory.v
+++ b/analysis/uni/jitter/fp_rta_theory.v
@@ 6,7 +6,6 @@ Require Import rt.model.arrival.jitter.job rt.model.arrival.jitter.task_arrival
Require Import rt.model.schedule.uni.schedule_of_task rt.model.schedule.uni.service
rt.model.schedule.uni.schedulability rt.model.schedule.uni.response_time.
Require Import rt.model.schedule.uni.jitter.schedule
 rt.model.schedule.uni.jitter.workload
rt.model.schedule.uni.jitter.busy_interval
rt.model.schedule.uni.jitter.platform.
Require Import rt.analysis.uni.jitter.workload_bound_fp.
@@ 16,7 +15,7 @@ Module ResponseTimeAnalysisFP.
Import ArrivalSequenceWithJitter JobWithJitter TaskArrivalWithJitter ArrivalBounds
UniprocessorScheduleWithJitter ScheduleOfTask SporadicTaskset Priority
 ResponseTime WorkloadBoundFP Platform Schedulability BusyInterval Workload Service.
+ ResponseTime WorkloadBoundFP Platform Schedulability BusyInterval.
(* In this section, we prove that any fixed point in the RTA for jitteraware
uniprocessor FP scheduling is a responsetime bound. *)
@@ 29,20 +28,23 @@ Module ResponseTimeAnalysisFP.
Variable task_jitter: SporadicTask > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_jitter: Job > time.
Variable job_task: Job > SporadicTask.
 (* Assume any job arrival sequence without duplicates... *)
 Context {arr_seq: arrival_sequence Job}.
 Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
+ (* Consider any job arrival sequence with consistent, nonduplicate arrivals... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_arr_seq_is_a_set: arrival_sequence_is_a_set arr_seq.
(* ... in which jobs arrive sporadically and have valid parameters. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter
job_cost job_deadline job_jitter job_task j.
@@ 53,13 +55,17 @@ Module ResponseTimeAnalysisFP.
(* ... and assume that all jobs in the arrival sequence come from the task set. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
 (* Next, consider any uniprocessor schedule such that...*)
 Variable sched: schedule arr_seq.

 (* ...jobs do not execute before the jitter has passed nor after completion. *)
 Hypothesis H_jobs_execute_after_jitter: jobs_execute_after_jitter job_jitter sched.
+ (* Next, consider any uniprocessor schedule of this arrival sequence... *)
+ Variable sched: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
+ (* ...such that jobs do not execute before the jitter has passed nor after completion. *)
+ Hypothesis H_jobs_execute_after_jitter: jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Consider any FP policy that indicates a higherorequal priority relation,
@@ 69,9 +75,9 @@ Module ResponseTimeAnalysisFP.
Hypothesis H_priority_is_transitive: FP_is_transitive higher_eq_priority.
(* Next, assume that the schedule is a jitteraware, workconserving FP schedule. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_respects_fp_policy:
 respects_FP_policy job_cost job_jitter job_task sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_jitter job_task arr_seq sched higher_eq_priority.
(* Now we proceed with the analysis.
Let tsk be any task in ts that is to be analyzed. *)
@@ 81,7 +87,7 @@ Module ResponseTimeAnalysisFP.
(* Recall the definition of responsetime bound and the total workload bound W
for higherorequalpriority tasks (with respect to tsk). *)
Let response_time_bounded_by :=
 is_response_time_bound_of_task job_cost job_task sched.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched.
Let W := total_workload_bound_fp task_cost task_period task_jitter higher_eq_priority ts tsk.
(* Let R be any positive fixed point of the responsetime recurrence. *)
@@ 102,14 +108,16 @@ Module ResponseTimeAnalysisFP.
rename H_response_time_is_fixed_point into FIX,
H_valid_task_parameters into PARAMS,
H_valid_job_parameters into JOBPARAMS.
 intros j JOBtsk.
 apply completion_monotonic with (t := actual_arrival job_jitter j + R); try (by done).
+ intros j IN JOBtsk.
+ set arr := actual_arrival job_arrival job_jitter.
+ apply completion_monotonic with (t := arr j + R); try (by done).
{
 rewrite /actual_arrival addnA leq_add2l leq_add2r.
 by rewrite JOBtsk; specialize (JOBPARAMS j); des.
+ rewrite addnA leq_add2l leq_add2r.
+ by rewrite JOBtsk; specialize (JOBPARAMS j IN); des.
}
 set prio := FP_to_JLFP job_task arr_seq higher_eq_priority.
 apply busy_interval_bounds_response_time with (higher_eq_priority0 := prio); try (by done).
+ set prio := FP_to_JLFP job_task higher_eq_priority.
+ apply busy_interval_bounds_response_time with (arr_seq0 := arr_seq)
+ (higher_eq_priority0 := prio); try (by done).
 by intros x; apply H_priority_is_reflexive.
 by intros x z y; apply H_priority_is_transitive.
intros t.
diff git a/analysis/uni/jitter/workload_bound_fp.v b/analysis/uni/jitter/workload_bound_fp.v
index eaec3d9..f7379e3 100644
 a/analysis/uni/jitter/workload_bound_fp.v
+++ b/analysis/uni/jitter/workload_bound_fp.v
@@ 3,7 +3,8 @@ Require Import rt.model.arrival.basic.task rt.model.priority.
Require Import rt.model.arrival.jitter.job
rt.model.arrival.jitter.task_arrival
rt.model.arrival.jitter.arrival_bounds.
Require Import rt.model.schedule.uni.jitter.schedule rt.model.schedule.uni.jitter.workload.
+Require Import rt.model.schedule.uni.workload.
+Require Import rt.model.schedule.uni.jitter.schedule.
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop div.
(* In this file, we define the workload bound for jitteraware FP scheduling. *)
@@ 158,6 +159,7 @@ Module WorkloadBoundFP.
Variable task_jitter: Task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_jitter: Job > time.
@@ 168,23 +170,30 @@ Module WorkloadBoundFP.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
 (* Consider any arrival sequence with no duplicate arrivals. *)
+ (* Consider any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
 Hypothesis H_arr_seq_is_a_set: arrival_sequence_is_a_set arr_seq.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
 (* Assume that all jobs come from the task set ...*)
+ (* First, let's define some local names for clarity. *)
+ Let actual_arrivals := actual_arrivals_between job_arrival job_jitter arr_seq.
+
+ (* Next, assume that all jobs come from the task set ...*)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
(* ...and have valid parameters. *)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter
job_cost job_deadline job_jitter job_task j.
(* Assume that jobs arrived sporadically. *)
Hypothesis H_sporadic_arrivals:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Then, let tsk be any task in ts. *)
Variable tsk: Task.
@@ 194,9 +203,9 @@ Module WorkloadBoundFP.
Variable higher_eq_priority: FP_policy Task.
(* ...we recall the definitions of higherorequalpriority workload and the workload bound. *)
 Let actual_hp_workload :=
 workload_of_higher_or_equal_priority_tasks job_cost job_jitter
 job_task arr_seq higher_eq_priority tsk.
+ Let actual_hp_workload t1 t2 :=
+ workload_of_higher_or_equal_priority_tasks job_cost job_task (actual_arrivals t1 t2)
+ higher_eq_priority tsk.
Let workload_bound :=
total_workload_bound_fp task_cost task_period task_jitter higher_eq_priority ts tsk.
@@ 213,36 +222,44 @@ Module WorkloadBoundFP.
Proof.
rename H_fixed_point into FIX, H_all_jobs_from_taskset into FROMTS,
H_valid_job_parameters into JOBPARAMS,
 H_valid_task_parameters into PARAMS.
+ H_valid_task_parameters into PARAMS,
+ H_arrival_times_are_consistent into CONS, H_arrival_sequence_is_a_set into SET.
unfold actual_hp_workload, workload_of_higher_or_equal_priority_tasks,
valid_sporadic_job_with_jitter, valid_sporadic_job, valid_realtime_job,
valid_sporadic_taskset, is_valid_sporadic_task in *.
 have BOUND := sporadic_task_with_jitter_arrival_bound task_period task_jitter job_jitter
 job_task arr_seq H_arr_seq_is_a_set.
 feed_n 2 BOUND; try (by done).
 {
 by intros j; specialize (JOBPARAMS j); des.
 }
+ have BOUND := sporadic_task_with_jitter_arrival_bound task_period task_jitter job_arrival
+ job_jitter job_task arr_seq CONS SET.
+ feed_n 2 BOUND; (try by done);
+ first by intros j ARRj; specialize (JOBPARAMS j ARRj); des.
intro t.
rewrite {2}FIX /workload_bound /total_workload_bound_fp.
 set l := actual_arrivals_between job_jitter arr_seq t (t + R).
+ set l := actual_arrivals_between job_arrival job_jitter arr_seq t (t + R).
set hep := higher_eq_priority.
apply leq_trans with (n := \sum_(tsk' < ts  hep tsk' tsk)
(\sum_(j0 < l  job_task j0 == tsk') job_cost j0)).
{
 have EXCHANGE := exchange_big_dep (fun (x: JobIn arr_seq) => hep (job_task x) tsk).
+ have EXCHANGE := exchange_big_dep (fun x => hep (job_task x) tsk).
rewrite EXCHANGE /=; last by move => tsk0 j0 HEP /eqP JOB0; rewrite JOB0.
 apply leq_sum; intros j0 HP0.
 rewrite big_mkcond (big_rem (job_task j0)) /=; last by rewrite FROMTS.
 by rewrite HP0 andTb eq_refl; apply leq_addr.
+ rewrite /workload_of_jobs /l big_seq_cond [X in _ <= X]big_seq_cond.
+ apply leq_sum; move => j0 /andP [IN0 HP0].
+ rewrite big_mkcond (big_rem (job_task j0)) /=;
+ first by rewrite HP0 andTb eq_refl; apply leq_addr.
+ rewrite mem_filter in IN0; move: IN0 => /andP [_ ARR0].
+ by apply in_arrivals_implies_arrived in ARR0; apply FROMTS.
}
apply leq_sum_seq; intros tsk0 IN0 HP0.
 apply leq_trans with (n := num_actual_arrivals_of_task job_jitter job_task arr_seq
+ apply leq_trans with (n := num_actual_arrivals_of_task job_arrival job_jitter job_task arr_seq
tsk0 t (t + R) * task_cost tsk0).
{
 rewrite /num_actual_arrivals_of_task sum1_size big_distrl /=.
 rewrite big_filter; apply leq_sum; move => j0 /eqP EQ; rewrite EQ mul1n.
 by specialize (JOBPARAMS j0); des.
+ rewrite /num_actual_arrivals_of_task sum1_size big_distrl /= big_filter.
+ apply leq_sum_seq; move => j1 IN1 /eqP EQ.
+ rewrite EQ mul1n.
+ feed (JOBPARAMS j1).
+ {
+ rewrite mem_filter in IN1; move: IN1 => /andP [_ ARR1].
+ by apply in_arrivals_implies_arrived in ARR1.
+ }
+ by move: JOBPARAMS => [[_ [LE _]] _].
}
rewrite /task_workload_bound_FP leq_mul2r; apply/orP; right.
feed (BOUND t (t + R) tsk0); first by feed (PARAMS tsk0); last by des.
diff git a/analysis/uni/susp/dynamic/oblivious/fp_rta.v b/analysis/uni/susp/dynamic/oblivious/fp_rta.v
index ab5811e..6aba2b6 100644
 a/analysis/uni/susp/dynamic/oblivious/fp_rta.v
+++ b/analysis/uni/susp/dynamic/oblivious/fp_rta.v
@@ 27,6 +27,7 @@ Module SuspensionObliviousFP.
Variable task_deadline: SporadicTask > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > SporadicTask.
@@ 38,20 +39,24 @@ Module SuspensionObliviousFP.
Hypothesis H_valid_task_parameters:
valid_sporadic_taskset task_cost task_period task_deadline ts.
 (* Next, consider any job arrival sequence with no duplicate arrivals,... *)
 Context {arr_seq: arrival_sequence Job}.
+ (* Next, consider any job arrival sequence with consistent, nonduplicate arrivals,... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
(* ...in which all jobs come from task set ts, ... *)
 Hypothesis H_jobs_from_taskset: forall (j: JobIn arr_seq), job_task j \in ts.
+ Hypothesis H_jobs_from_taskset:
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* ...have valid parameters,...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
 (* ... and satisfy the sporadic task model.*)
 Hypothesis H_sporadic_tasks: sporadic_task_model task_period arr_seq job_task.
+ (* ... and satisfy the sporadic task model. *)
+ Hypothesis H_sporadic_tasks:
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider any FP policy that is reflexive, transitive and total, indicating
"higher or equal task priority". *)
@@ 80,28 +85,32 @@ Module SuspensionObliviousFP.
(* Now we proceed with the schedulability analysis. *)
Section MainProof.
 (* Consider any suspensionaware schedule... *)
 Variable sched: schedule arr_seq.
+ (* Consider any suspensionaware schedule of the arrival sequence... *)
+ Variable sched: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* ...where jobs only execute after they arrive... *)
 Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
(* ...and no longer than their execution costs. *)
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Also assume that the schedule is workconserving when there are nonsuspended jobs, ... *)
 Hypothesis H_work_conserving: work_conserving job_cost next_suspension sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost next_suspension arr_seq sched.
(* ...that the schedule respects job priority... *)
Hypothesis H_respects_priority:
 respects_FP_policy job_cost job_task next_suspension sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_task next_suspension arr_seq
+ sched higher_eq_priority.
(* ...and that suspended jobs are not allowed to be scheduled. *)
Hypothesis H_respects_self_suspensions:
 respects_self_suspensions job_cost next_suspension sched.
+ respects_self_suspensions job_arrival job_cost next_suspension sched.
(* For simplicity, let's also define some local names. *)
 Let task_is_schedulable := task_misses_no_deadline job_cost job_deadline job_task sched.
+ Let task_is_schedulable :=
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, recall the responsetime analysis for FP scheduling instantiated with
the inflated task costs. *)
@@ 122,27 +131,26 @@ Module SuspensionObliviousFP.
Proof.
rename H_claimed_schedulable_by_suspension_oblivious_RTA into SCHED,
H_jobs_from_taskset into FROMTS, H_inflated_cost_le_deadline_and_period into LEdl.
 intros tsk INts j JOBtsk.
+ intros tsk INts j ARRj JOBtsk.
apply suspension_oblivious_preserves_schedulability with
 (higher_eq_priority0 := (FP_to_JLDP job_task arr_seq higher_eq_priority))
 (next_suspension0 := next_suspension); try (by done).
  by intros t x; apply H_priority_is_reflexive.
+ (higher_eq_priority0 := (FP_to_JLDP job_task higher_eq_priority))
+ (arr_seq0 := arr_seq) (next_suspension0 := next_suspension); try (by done).
 by intros t y x z; apply H_priority_is_transitive.
  by intros t j1 j2; apply/orP; apply H_priority_is_total.
+  by intros j1 j2 t ARR1 ARR2; apply/orP; apply H_priority_is_total; apply FROMTS.
apply jobs_schedulable_by_fp_rta with (task_cost0 := inflated_cost) (ts0 := ts)
(task_period0 := task_period) (task_deadline0 := task_deadline) (job_task0 := job_task)
(higher_eq_priority0 := higher_eq_priority); try (by done).
 by apply suspension_oblivious_task_parameters_remain_valid.
 by apply suspension_oblivious_job_parameters_remain_valid with (ts0 := ts)
(task_period0 := task_period).
+  by apply sched_newjobs_come_from_arrival_sequence.
 by apply sched_new_jobs_must_arrive_to_execute.
 by apply sched_new_completed_jobs_dont_execute.
 by apply sched_new_work_conserving.
{
 intros j_low j_hp t; apply sched_new_respects_policy.
  by intros t' x; apply H_priority_is_reflexive.
+ intros j_low j_hp t; apply sched_new_respects_policy; try (by done).
 by intros t' j1 j2 j3; apply H_priority_is_transitive.
  by intros t' j1 j2; apply/orP; apply H_priority_is_total.
+  by intros j1 j2 t' ARR1 ARR2; apply/orP; apply H_priority_is_total; apply FROMTS.
}
Qed.
diff git a/analysis/uni/susp/dynamic/oblivious/reduction.v b/analysis/uni/susp/dynamic/oblivious/reduction.v
index ef9e8b9..fef1c01 100644
 a/analysis/uni/susp/dynamic/oblivious/reduction.v
+++ b/analysis/uni/susp/dynamic/oblivious/reduction.v
@@ 28,25 +28,27 @@ Module ReductionToBasicSchedule.
Variable task_deadline: Task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > Task.
(* Let ts be any task set to be analyzed. *)
Variable ts: seq Task.
 (* Next, consider any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ (* Next, consider any consistent job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
(* ...whose jobs come from task set ts. *)
Hypothesis H_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Consider any JLDP policy that is reflexive, transitive and total, i.e., that
indicates "higher or equal priority". *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
Hypothesis H_priority_is_reflexive: JLDP_is_reflexive higher_eq_priority.
Hypothesis H_priority_is_transitive: JLDP_is_transitive higher_eq_priority.
 Hypothesis H_priority_is_total: JLDP_is_total higher_eq_priority.
+ Hypothesis H_priority_is_total: JLDP_is_total arr_seq higher_eq_priority.
(* Consider the original job and task costs. *)
Variable original_job_cost: Job > time.
@@ 59,12 +61,14 @@ Module ReductionToBasicSchedule.
Hypothesis H_dynamic_suspensions:
dynamic_suspension_model original_job_cost job_task next_suspension task_suspension_bound.
 (* Next, consider any suspensionaware schedule where jobs have their original costs. *)
 Variable sched_susp: schedule arr_seq.
+ (* Next, consider any suspensionaware schedule of this arrival sequence. *)
+ Variable sched_susp: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched_susp arr_seq.
(* Assume that jobs only execute after they arrive... *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched_susp.
+ jobs_must_arrive_to_execute job_arrival sched_susp.
(* ...and no longer than their execution costs. *)
Hypothesis H_completed_jobs_dont_execute:
@@ 72,16 +76,16 @@ Module ReductionToBasicSchedule.
(* Also assume that the schedule is workconserving if there are nonsuspended jobs, ... *)
Hypothesis H_work_conserving:
 susp_aware.work_conserving original_job_cost next_suspension sched_susp.
+ susp_aware.work_conserving job_arrival original_job_cost next_suspension arr_seq sched_susp.
(* ...that the schedule respects job priority... *)
Hypothesis H_respects_priority:
 susp_aware.respects_JLDP_policy original_job_cost next_suspension
 sched_susp higher_eq_priority.
+ susp_aware.respects_JLDP_policy job_arrival original_job_cost next_suspension
+ arr_seq sched_susp higher_eq_priority.
(* ...and that suspended jobs are not allowed to be scheduled. *)
Hypothesis H_respects_self_suspensions:
 respects_self_suspensions original_job_cost next_suspension sched_susp.
+ respects_self_suspensions job_arrival original_job_cost next_suspension sched_susp.
(* Now we proceed with the reduction. First, we formalize the inflation of job and task costs. *)
Section CostInflation.
@@ 103,7 +107,8 @@ Module ReductionToBasicSchedule.
(* Recall the definition of valid sporadic jobs and tasks. *)
Let jobs_are_valid job_cost task_cost :=
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
Let tasks_are_valid task_cost :=
valid_sporadic_taskset task_cost task_period task_deadline ts.
@@ 123,7 +128,7 @@ Module ReductionToBasicSchedule.
rename H_inflated_cost_le_deadline_and_period into LEdl,
H_dynamic_suspensions into DYN, H_jobs_from_taskset into FROMTS.
unfold jobs_are_valid, valid_sporadic_job, valid_realtime_job.
 intros VALIDjob j; specialize (VALIDjob j); des.
+ intros VALIDjob j ARRj; specialize (VALIDjob j ARRj); des.
split.
{
split;
@@ 131,7 +136,7 @@ Module ReductionToBasicSchedule.
last by apply leq_addr.
split; last by done.
rewrite /job_cost_le_deadline /inflated_job_cost.
 feed (LEdl (job_task j)); [by done  move: LEdl => [LEdl _]].
+ feed (LEdl (job_task j)); [by apply FROMTS  move: LEdl => [LEdl _]].
apply leq_trans with (n := inflated_task_cost (job_task j));
last by rewrite VALIDjob1 LEdl.
by apply leq_add; last by apply DYN.
@@ 168,27 +173,24 @@ Module ReductionToBasicSchedule.
(* For any time t, suppose that we have generated the schedule prefix in the
interval [0, t). Then, we must define what should be scheduled at time t. *)
 Variable sched_prefix: schedule arr_seq.
+ Variable sched_prefix: schedule Job.
Variable t: time.
 (* First, consider the list of pending jobs at time t in the generated schedule, ... *)
 Let job_is_pending := pending inflated_job_cost sched_prefix.
+ (* First, consider the list of pending jobs at time t in the generated schedule. *)
+ Let job_is_pending := pending job_arrival inflated_job_cost sched_prefix.
Definition pending_jobs :=
[seq j < jobs_arrived_up_to arr_seq t  job_is_pending j t].
 (* ...which we sort by (decreasing) higherorequal priority. *)
 Definition sorted_jobs := sort (higher_eq_priority t) pending_jobs.

 (* From the sorted list, let's call j_hp one of the (possibly many) highestpriority jobs,
 or None, in case there are no pending jobs. *)
 Definition highest_priority_job := ohead sorted_jobs.
+ (* From the list of pending jobs, we take one of the (possibly many) highestpriority
+ jobs, or None, in case there are no pending jobs. *)
+ Definition highest_priority_job := seq_min (higher_eq_priority t) pending_jobs.
(* Then, we construct the schedule at time t as follows.
a) If there's a job scheduled in the original schedule at time t that is also a
highestpriority pending job in the generated schedule, copy this job.
b) Else, pick one of the highest priority pending jobs in the generated schedule. *)
 Definition build_schedule : option (JobIn arr_seq) :=
+ Definition build_schedule : option Job :=
(* If there is a highestpriority job j_hp in the generated schedule, ...*)
if highest_priority_job is Some j_hp then
(* ...and there is some job scheduled in the original schedule... *)
@@ 204,10 +206,10 @@ Module ReductionToBasicSchedule.
End ConstructionStep.
(* Next, starting from the empty schedule, ...*)
 Let empty_schedule : schedule arr_seq := fun t => None.
+ Let empty_schedule : schedule Job := fun t => None.
(* ...we use the recursive definition above to construct the suspensionoblivious schedule. *)
 Definition sched_new := build_schedule_from_prefixes arr_seq build_schedule empty_schedule.
+ Definition sched_new := build_schedule_from_prefixes build_schedule empty_schedule.
(* Then, by showing that the construction function depends only on the previous service, ... *)
Lemma sched_new_depends_only_on_service:
@@ 216,20 +218,21 @@ Module ReductionToBasicSchedule.
build_schedule sched1 t = build_schedule sched2 t.
Proof.
intros sched1 sched2 t ALL.
 rewrite /build_schedule /highest_priority_job /sorted_jobs.
+ rewrite /build_schedule /highest_priority_job.
have SAME: pending_jobs sched1 t = pending_jobs sched2 t.
{
apply eq_in_filter.
 intros j IN; apply JobIn_arrived in IN.
+ intros j IN.
+ eapply in_arrivals_implies_arrived_before in IN; last by eauto.
rewrite /arrived_before ltnS in IN.
rewrite /pending /has_arrived IN 2!andTb.
by rewrite /completed_by ALL.
}
 have SAME': forall j,
 pending inflated_job_cost sched1 j t = pending inflated_job_cost sched2 j t.
+ have SAME': forall j, pending job_arrival inflated_job_cost sched1 j t =
+ pending job_arrival inflated_job_cost sched2 j t.
{
intros j; rewrite /pending.
 case: (has_arrived j t); [rewrite 2!andTb  by done].
+ case: (has_arrived _ j t); [rewrite 2!andTb  by done].
by rewrite /completed_by ALL.
}
rewrite SAME.
@@ 252,26 +255,44 @@ Module ReductionToBasicSchedule.
(* Next, we prove that the generated schedule is wellformed. *)
Section GeneratedScheduleIsValid.
 (* First, we show that jobs do not execute before their arrival times... *)
+ (* First, we show that scheduled jobs come from the arrival sequence. *)
+ Lemma sched_newjobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched_new arr_seq.
+ Proof.
+ rename H_jobs_come_from_arrival_sequence into FROM.
+ move => j t /eqP SCHED.
+ rewrite sched_new_uses_construction_function in SCHED.
+ rewrite /build_schedule in SCHED.
+ destruct (highest_priority_job sched_new t) as [j_hp] eqn:HP; last by done.
+ have ARRhp: arrives_in arr_seq j_hp.
+ {
+ rewrite /highest_priority_job in HP.
+ apply seq_min_in_seq in HP.
+ rewrite mem_filter in HP; move: HP => /andP [_ ARR].
+ by eapply in_arrivals_implies_arrived, ARR.
+ }
+ destruct (sched_susp t) eqn:SUSP; last by case: SCHED => SAME; subst.
+ by move: SCHED; case PEND: (_ && _); case => EQ; subst;
+ first by apply (FROM j t); apply/eqP.
+ Qed.
+
+ (* Next, we show that jobs do not execute before their arrival times... *)
Lemma sched_new_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched_new.
+ jobs_must_arrive_to_execute job_arrival sched_new.
Proof.
move => j t /eqP SCHED.
rewrite sched_new_uses_construction_function in SCHED.
rewrite /build_schedule in SCHED.
destruct (highest_priority_job sched_new t) as [j_hp] eqn:HP; last by done.
 have IN: has_arrived j_hp t.
+ have IN: has_arrived job_arrival j_hp t.
{
suff IN: j_hp \in pending_jobs sched_new t.
by rewrite mem_filter in IN; move: IN => /andP [/andP [ARR _] _].
 suff: j_hp \in sorted_jobs sched_new t by rewrite mem_sort.
 rewrite /highest_priority_job in HP.
 by destruct (sorted_jobs sched_new t);
 last by move: HP; case => EQ; subst; rewrite in_cons eq_refl.
+ by apply: (seq_min_in_seq (higher_eq_priority t)).
}
destruct (sched_susp t) eqn:SUSP; last by move: SCHED; case => EQ; subst.
move: SCHED; case: ifP; last by move => _; case => SAME; subst.
 by move => /andP [/andP [ARR _] _]; case => SAME; subst.
+ by move => /andP [/andP [ARR _] _]; case => SAME; subst.
Qed.
(* ...nor longer than their execution costs. *)
@@ 303,78 +324,77 @@ Module ReductionToBasicSchedule.
}
{
apply/eqP; case => SAME; subst.
 suff IN: j \in sorted_jobs sched_new t.
+ suff IN: j \in pending_jobs sched_new t.
{
 rewrite mem_sort mem_filter in IN; move: IN => /andP [/andP [_ NOTCOMP] _].
 by rewrite /completed_by EQ eq_refl in NOTCOMP.
+ rewrite mem_filter in IN; move: IN => /andP [/andP [_ NOTCOMP] _].
+ by rewrite /completed_by EQ eq_refl in NOTCOMP.
}
 destruct (sorted_jobs sched_new t); first by done.
 by case: HP => SAME; subst; rewrite in_cons; apply/orP; left.
+ by apply: (seq_min_in_seq (higher_eq_priority t)).
}
}
{
apply/eqP; case => SAME; subst.
 suff IN: j \in sorted_jobs sched_new t.
+ suff IN: j \in pending_jobs sched_new t.
{
 rewrite mem_sort mem_filter in IN; move: IN => /andP [/andP [_ NOTCOMP] _].
 by rewrite /completed_by EQ eq_refl in NOTCOMP.
+ rewrite mem_filter in IN; move: IN => /andP [/andP [_ NOTCOMP] _].
+ by rewrite /completed_by EQ eq_refl in NOTCOMP.
}
 destruct (sorted_jobs sched_new t); first by done.
 by case: HP => SAME; subst; rewrite in_cons; apply/orP; left.
+ by apply: (seq_min_in_seq (higher_eq_priority t)).
}
Qed.
(* In addition, we prove that the schedule is (suspensionoblivious) workconserving... *)
Lemma sched_new_work_conserving:
 susp_oblivious.work_conserving inflated_job_cost sched_new.
+ susp_oblivious.work_conserving job_arrival inflated_job_cost arr_seq sched_new.
Proof.
 intros j t BACK.
+ intros j t ARRj BACK.
move: BACK => /andP [/andP [ARR NOTCOMP] NOTSCHED].
rewrite /scheduled_at sched_new_uses_construction_function /build_schedule in NOTSCHED.
rewrite /scheduled_at sched_new_uses_construction_function /build_schedule.
destruct (highest_priority_job sched_new t) as [j_hp] eqn:HP.
{
 destruct (sched_susp t) eqn:SUSP; last by exists j_hp.
+ destruct (sched_susp t) as [j0 ] eqn:SUSP; last by exists j_hp.
by case: ifP => [_  _]; [exists j0  exists j_hp].
}
{
rewrite /highest_priority_job in HP.
 have IN: j \in sorted_jobs sched_new t.
 by rewrite mem_sort mem_filter /pending ARR NOTCOMP 2!andTb; apply JobIn_arrived.
 by destruct (sorted_jobs sched_new t).
+ have IN: j \in pending_jobs sched_new t.
+ {
+ rewrite mem_filter /pending ARR NOTCOMP 2!andTb.
+ by eapply arrived_between_implies_in_arrivals, ARR.
+ }
+ by apply seq_min_exists with (rel := higher_eq_priority t) in IN; rewrite HP eq_refl in IN.
}
Qed.
(* ...and respects job priorities. *)
Lemma sched_new_respects_policy:
 susp_oblivious.respects_JLDP_policy inflated_job_cost
 sched_new higher_eq_priority.
+ susp_oblivious.respects_JLDP_policy job_arrival inflated_job_cost
+ arr_seq sched_new higher_eq_priority.
Proof.
rename H_priority_is_transitive into TRANS, H_priority_is_total into TOTAL,
H_priority_is_reflexive into REFL.
 move => j1 j2 t BACK /eqP SCHED.
+ move => j1 j2 t ARRj1 BACK /eqP SCHED.
move: BACK => /andP [/andP [ARR NOTCOMP] NOTSCHED].
rewrite /scheduled_at sched_new_uses_construction_function /build_schedule in NOTSCHED.
rewrite /scheduled_at sched_new_uses_construction_function /build_schedule in SCHED.
destruct (highest_priority_job sched_new t) as [j_hp] eqn:HP; last by done.
 have ALL: forall j, j \in sorted_jobs sched_new t > higher_eq_priority t j_hp j.
+ rewrite /highest_priority_job in HP.
+ have ALL: forall j, j \in pending_jobs sched_new t > higher_eq_priority t j_hp j.
{
 intros j IN.
 have SORT: sorted (higher_eq_priority t) (sorted_jobs sched_new t) by apply sort_sorted.
 rewrite /highest_priority_job in HP.
 destruct (sorted_jobs sched_new t) as [j0 l]; first by done.
 simpl in *; case: HP => SAME; subst.
 rewrite in_cons in IN; move: IN => /orP [/eqP SAME  IN]; subst; first by apply REFL.
 apply order_path_min in SORT; last by done.
 by move: SORT => /allP ALL; apply ALL.
+ intros j IN; apply seq_min_computes_min with (y := j) in HP; try (by done).
+ intros x y; rewrite 2!mem_filter; move => /andP [_ INx] /andP [_ INy].
+ by apply TOTAL; eapply in_arrivals_implies_arrived; eauto 1.
}
 have IN: j1 \in sorted_jobs sched_new t.
 by rewrite mem_sort mem_filter /pending ARR NOTCOMP 2!andTb; apply JobIn_arrived.
 rewrite /highest_priority_job in HP.
 destruct (sched_susp t) eqn:SUSP;
+ have IN: j1 \in pending_jobs sched_new t.
+ {
+ rewrite mem_filter /pending ARR NOTCOMP 2!andTb.
+ by eapply arrived_between_implies_in_arrivals, ARR.
+ }
+ destruct (sched_susp t) as [j0] eqn:SUSP;
last by case: SCHED => SAME; subst; apply ALL; last by done.
 destruct (pending inflated_job_cost sched_new j t
 && higher_eq_priority t j j_hp) eqn:PEND;
+ destruct (pending job_arrival inflated_job_cost sched_new j0 t
+ && higher_eq_priority t j0 j_hp) eqn:PEND;
last by case: SCHED => SAME; subst; apply ALL.
move: PEND => /andP [PEND HPj]; case: SCHED => SAME; subst.
by apply: (TRANS _ j_hp); last by apply ALL.
@@ 388,7 +408,7 @@ Module ReductionToBasicSchedule.
higher_eq_priority t j1 j2 >
higher_eq_priority t j2 j1 >
scheduled_at sched_susp j1 t >
 pending inflated_job_cost sched_new j1 t >
+ pending job_arrival inflated_job_cost sched_new j1 t >
scheduled_at sched_new j2 t >
j1 = j2.
Proof.
@@ 400,7 +420,7 @@ Module ReductionToBasicSchedule.
rewrite PEND andTb in SCHEDn.
move: SCHEDn; case: ifP => HP'; case => SAME; subst; first by done.
by rewrite HP1 in HP'.
 Qed.
+ Qed.
(* To reason about schedulability, we now prove that the generated schedule
preserves the service received by each job. *)
@@ 408,10 +428,10 @@ Module ReductionToBasicSchedule.
(* Recall the definitions of suspended job, cumulative service and
cumulative suspension time in the suspensionaware schedule. *)
 Let job_suspended_at (sched: schedule arr_seq) :=
 suspended_at original_job_cost next_suspension sched.
+ Let job_suspended_at (sched: schedule Job) :=
+ suspended_at job_arrival original_job_cost next_suspension sched.
Let job_cumulative_suspension :=
 cumulative_suspension original_job_cost next_suspension sched_susp.
+ cumulative_suspension job_arrival original_job_cost next_suspension sched_susp.
Let job_service_with_suspensions := service sched_susp.
(* Also recall the definition of cumulative service in the generated schedule. *)
@@ 427,29 +447,31 @@ Module ReductionToBasicSchedule.
(* Assume that the claim we want to prove holds for the interval [0, t). *)
Variable t: time.
Hypothesis H_induction_hypothesis:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
job_service_without_suspensions j t <=
job_service_with_suspensions j t + job_cumulative_suspension j t.
(* Now, let j be any job in arrival sequence. We are going to prove that the claim
continues to hold for job j in the interval [0, t + 1). *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_comes_from_arrival_sequence: arrives_in arr_seq j.
(* If j has not arrived by time t, then the proof is trivial, ... *)
Lemma reduction_inductive_step_not_arrived:
 ~~ has_arrived j t >
+ ~~ has_arrived job_arrival j t >
job_service_without_suspensions j t.+1 <=
job_service_with_suspensions j t.+1 + job_cumulative_suspension j t.+1.
Proof.
rewrite ltnNge; intro NOTARR.
rewrite /job_service_without_suspensions /job_service_with_suspensions
/service /service_during.
 rewrite cumulative_service_before_job_arrival_zero //.
 by apply sched_new_jobs_must_arrive_to_execute.
+ rewrite (cumulative_service_before_job_arrival_zero job_arrival) //.
+ by apply sched_new_jobs_must_arrive_to_execute.
Qed.
(* ...so let's assume instead that j has arrived by time t. *)
 Hypothesis H_j_has_arrived: has_arrived j t.
+ Hypothesis H_j_has_arrived: has_arrived job_arrival j t.
(* We begin by performing a case analysis on whether j has completed in the
suspensionaware schedule. *)
@@ 537,24 +559,30 @@ Module ReductionToBasicSchedule.
(* ...which implies that j is backlogged at time t in the suspensionaware schedule. *)
Lemma reduction_inductive_step_j_is_backlogged:
 susp.backlogged original_job_cost next_suspension sched_susp j t.
+ susp.backlogged job_arrival original_job_cost next_suspension sched_susp j t.
Proof.
 by repeat (apply/andP; split).
+ by repeat (apply/andP; split).
Qed.
(* By work conservation, there must be a scheduled job with higher or equal
priority in the suspensionaware schedule. *)
Lemma reduction_inductive_step_exists_hep_job:
 exists j_hp, scheduled_at sched_susp j_hp t /\ higher_eq_priority t j_hp j.
+ exists j_hp, arrives_in arr_seq j_hp /\
+ scheduled_at sched_susp j_hp t /\
+ higher_eq_priority t j_hp j.
Proof.
 rename H_work_conserving into WORKs, H_respects_priority into PRIOs.
+ rename H_work_conserving into WORKs, H_respects_priority into PRIOs,
+ H_jobs_come_from_arrival_sequence into FROM.
have BACKs := reduction_inductive_step_j_is_backlogged.
 move: (BACKs) => BACKs'; apply WORKs in BACKs.
 by move: BACKs => [j_hp SCHEDhp]; exists j_hp; split; last by apply PRIOs.
+ move: (BACKs) => BACKs'; apply WORKs in BACKs; last by done.
+ move: BACKs => [j_hp SCHEDhp]; exists j_hp.
+ split; first by apply (FROM j_hp t).
+ by split; last by apply PRIOs.
Qed.
(* Let j_hp be this job with higherorequal priority. *)
 Variable j_hp: JobIn arr_seq.
+ Variable j_hp: Job.
+ Hypothesis H_j_hp_comes_from_sequence: arrives_in arr_seq j_hp.
Hypothesis H_j_hp_is_scheduled: scheduled_at sched_susp j_hp t.
Hypothesis H_higher_or_equal_priority: higher_eq_priority t j_hp j.
@@ 568,20 +596,21 @@ Module ReductionToBasicSchedule.
Proof.
rename H_j_not_scheduled_in_susp into NOTSCHEDs, H_j_scheduled_in_new into SCHEDn.
move: H_j_hp_is_scheduled (H_j_hp_is_scheduled) => SCHEDhp PENDhp.
 apply scheduled_implies_pending with (job_cost := original_job_cost) in PENDhp;
 try (by done).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost := original_job_cost) in PENDhp; try (by done).
move: PENDhp => /andP [ARRhp _].
apply contraT; intro NOTCOMPhp.
 have PENDhp: pending inflated_job_cost sched_new j_hp t by apply/andP; split.
+ have PENDhp: pending job_arrival inflated_job_cost sched_new j_hp t
+ by apply/andP; split.
destruct (boolP (scheduled_at sched_new j_hp t)) as [SCHEDhp'  NOTSCHEDhp'].
{
have SAME: j = j_hp by apply only_one_job_scheduled with (j1 := j) in SCHEDhp'.
 by subst; rewrite SCHEDhp in NOTSCHEDs.
+ by subst; rewrite SCHEDhp in NOTSCHEDs.
}
 have BACKhp: backlogged inflated_job_cost sched_new j_hp t by apply/andP.
+ have BACKhp: backlogged job_arrival inflated_job_cost sched_new j_hp t by apply/andP.
have HP': higher_eq_priority t j j_hp by apply sched_new_respects_policy.
apply sched_new_breaks_ties in HP'; try (by done).
 by subst; rewrite SCHEDn in NOTSCHEDhp'.
+ by subst; rewrite SCHEDn in NOTSCHEDhp'.
Qed.
(* However, recall from the induction hypothesis how the service in the two schedules
@@ 598,8 +627,9 @@ Module ReductionToBasicSchedule.
rewrite /(inflated_job_cost _).
apply leq_trans with (n := job_service_without_suspensions j_hp t);
first by apply eq_leq; symmetry; apply/eqP; apply COMPNEW.
 apply: (leq_trans (IHt j_hp)).
 by rewrite leq_add2l; apply cumulative_suspension_le_total_suspension.
+ feed (IHt j_hp); first by done.
+ apply: (leq_trans IHt).
+ by rewrite leq_add2l; apply cumulative_suspension_le_total_suspension.
Qed.
(* ...which of course is a contradiction, since we assumed that j_hp was scheduled
@@ 609,7 +639,7 @@ Module ReductionToBasicSchedule.
have COMPhp' := reduction_inductive_step_j_hp_completed_in_susp.
rename H_j_hp_is_scheduled into SCHEDhp.
apply completed_implies_not_scheduled in COMPhp'; try (by done).
 by rewrite SCHEDhp in COMPhp'.
+ by rewrite SCHEDhp in COMPhp'.
Qed.
End ProofByContradiction.
@@ 637,8 +667,8 @@ Module ReductionToBasicSchedule.
apply eq_leq; symmetry; apply/eqP; rewrite eqb1.
apply contraT; intro NOTSUSP.
specialize (HP NOTSCHEDs NOTSUSP); specialize (CONTRA SCHEDn NOTSCHEDs NOTSUSP).
 move: HP => [j_hp [SCHEDhp HP]].
 by exfalso; apply CONTRA with (j_hp := j_hp).
+ move: HP => [j_hp [INhp [SCHEDhp HP]]].
+ by exfalso; apply CONTRA with (j_hp := j_hp).
Qed.
End PendingInSuspensionAwareSchedule.
@@ 649,6 +679,7 @@ Module ReductionToBasicSchedule.
job j at any time t is preserved in the suspensionaware schedule. *)
Theorem suspension_oblivious_preserves_service:
forall j t,
+ arrives_in arr_seq j >
job_service_without_suspensions j t <= job_service_with_suspensions j t
+ job_cumulative_suspension j t.
Proof.
@@ 657,54 +688,58 @@ Module ReductionToBasicSchedule.
move => j t; move: t j.
induction t;
first by ins; rewrite /job_service_without_suspensions/service/service_during big_geq.
 intros j.
 destruct (boolP (has_arrived j t)) as [ARR  NOTARR];
+ intros j ARRj.
+ destruct (boolP (has_arrived job_arrival j t)) as [ARR  NOTARR];
last by apply reduction_inductive_step_not_arrived.
destruct (boolP (completed_by original_job_cost sched_susp j t)) as [COMP  NOTCOMP];
first by apply CASE1.
 by apply CASE2.
+ by apply CASE2.
Qed.
(* As a corollary, we show that if a job has completed in the suspensionoblivious
schedule, it must have completed in the suspensionaware schedule as well. *)
Corollary suspension_oblivious_preserves_completion:
forall j t,
+ arrives_in arr_seq j >
completed_by inflated_job_cost sched_new j t >
completed_by original_job_cost sched_susp j t.
Proof.
have COMP := sched_new_completed_jobs_dont_execute.
have SERV := suspension_oblivious_preserves_service.
 intros j t COMPLETED.
+ intros j t ARRj COMPLETED.
rewrite /completed_by eqn_leq; apply/andP; split;
first by apply cumulative_service_le_job_cost.
rewrite (leq_add2r (total_suspension original_job_cost next_suspension j)).
rewrite /(inflated_job_cost j).
move: COMPLETED => /eqP EQ; rewrite EQ.
 apply: (leq_trans (SERV _ _)); rewrite leq_add2l.
 by apply cumulative_suspension_le_total_suspension.
+ apply: (leq_trans (SERV j t ARRj)); rewrite leq_add2l.
+ by apply cumulative_suspension_le_total_suspension.
Qed.
End Service.
End GeneratedScheduleIsValid.

(* To conclude, based on the definition of schedulability, ...*)
Let schedulable_without_suspensions :=
 job_misses_no_deadline inflated_job_cost job_deadline sched_new.
+ job_misses_no_deadline job_arrival inflated_job_cost job_deadline sched_new.
Let schedulable_with_suspensions :=
 job_misses_no_deadline original_job_cost job_deadline sched_susp.
+ job_misses_no_deadline job_arrival original_job_cost job_deadline sched_susp.
(* ...we prove that if no job misses a deadline in the suspensionoblivious schedule, ... *)
Hypothesis H_schedulable_without_suspensions:
 forall j, schedulable_without_suspensions j.
+ forall j,
+ arrives_in arr_seq j >
+ schedulable_without_suspensions j.
(* ...then no job misses a deadline in the suspensionaware schedule. *)
Corollary suspension_oblivious_preserves_schedulability:
 forall j, schedulable_with_suspensions j.
+ forall j,
+ arrives_in arr_seq j >
+ schedulable_with_suspensions j.
Proof.
rename H_schedulable_without_suspensions into SCHED.
 by intros j; apply suspension_oblivious_preserves_completion, SCHED.
+ by intros j ARRj; apply suspension_oblivious_preserves_completion, SCHED.
Qed.
End Reduction.
diff git a/implementation/apa/arrival_sequence.v b/implementation/apa/arrival_sequence.v
index 4fcc118..6c68acb 100644
 a/implementation/apa/arrival_sequence.v
+++ b/implementation/apa/arrival_sequence.v
@@ 15,9 +15,9 @@ Module ConcreteArrivalSequence.
(* At any time t, we release Some job of tsk if t is a multiple of the period,
otherwise we release None. *)
 Definition add_job (t: time) (tsk: @concrete_task num_cpus) : option (@concrete_job _) :=
 if task_period tsk % t then
 Some (Build_concrete_job (t %/ task_period tsk) (task_cost tsk) (task_deadline tsk) tsk)
+ Definition add_job (arr: time) (tsk: @concrete_task num_cpus) : option (@concrete_job _) :=
+ if task_period tsk % arr then
+ Some (Build_concrete_job (arr %/ task_period tsk) arr (task_cost tsk) (task_deadline tsk) tsk)
else
None.
@@ 38,14 +38,23 @@ Module ConcreteArrivalSequence.
(* Regarding the periodic arrival sequence built from ts, we prove that...*)
Let arr_seq := periodic_arrival_sequence ts.
+ (* ... arrival times are consistent, ... *)
+ Theorem periodic_arrivals_are_consistent:
+ arrival_times_are_consistent job_arrival arr_seq.
+ Proof.
+ move => j t ARRj.
+ rewrite /arrives_at mem_pmap in ARRj.
+ move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
+ by unfold add_job in *; desf.
+ Qed.
+
(* ... every job comes from the task set, ... *)
Theorem periodic_arrivals_all_jobs_from_taskset:
 forall (j: JobIn arr_seq),
 job_task (job_of_job_in j) \in ts. (* TODO: fix coercion. *)
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
Proof.
 intros j.
 destruct j as [j arr ARRj]; simpl.
 unfold arr_seq, arrives_at, periodic_arrival_sequence in *.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj.
move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
by unfold add_job in *; desf.
@@ 53,13 +62,13 @@ Module ConcreteArrivalSequence.
(* ..., jobs have valid parameters, ... *)
Theorem periodic_arrivals_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
Proof.
rename H_valid_task_parameters into PARAMS.
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
 intros j; destruct j as [j arr ARRj]; simpl.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in ARRj.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj; move: ARRj => /mapP [tsk IN SOME].
unfold add_job in SOME; desf.
specialize (PARAMS tsk IN); des.
@@ 69,12 +78,10 @@ Module ConcreteArrivalSequence.
(* ... job arrivals satisfy the sporadic task model, ... *)
Theorem periodic_arrivals_are_sporadic:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Proof.
 unfold sporadic_task_model; move => j j' /eqP DIFF SAMEtsk LE.
 destruct j as [j arr ARR], j' as [j' arr' ARR']; simpl in *.
 rewrite eqE /= /jobin_eqdef negb_and /= in DIFF.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in *.
+ move => j j' /eqP DIFF [arr ARR] [arr' ARR'] SAMEtsk LE.
+ rewrite eqE /= /job_eqdef negb_and /= SAMEtsk eq_refl orbF in DIFF.
rewrite 2!mem_pmap in ARR ARR'.
move: ARR ARR' => /mapP [tsk_j INj SOMEj] /mapP [tsk_j' INj' SOMEj'].
unfold add_job in SOMEj, SOMEj'; desf; simpl in *;
@@ 84,18 +91,11 @@ Module ConcreteArrivalSequence.
rewrite leq_eqVlt in LE; move: LE => /orP [/eqP EQ  LESS].
{
exfalso; move: DIFF => /negP DIFF; apply DIFF.
 by subst; rewrite EQ.
+ by subst; rewrite EQ !eq_refl.
}
subst; rewrite leq_mul2r; apply/orP; right.
by rewrite ltn_mul2r in LESS; move: LESS => /andP [_ LT].
}
 {
 assert (LT: arr < arr'). by rewrite ltn_neqAle; apply/andP.
 clear LE DIFF; subst tsk_j' arr arr'.
 rewrite ltn_mul2r in LT; move: LT => /andP [_ LT].
 by apply leq_trans with (n := k.+1 * task_period tsk_j);
 [by rewrite mulSnr  by rewrite leq_mul2r; apply/orP; right].
 }
Qed.
(* ... and the arrival sequence has no duplicate jobs. *)
diff git a/implementation/apa/bertogna_edf_example.v b/implementation/apa/bertogna_edf_example.v
index 8310c62..ebf1a1a 100644
 a/implementation/apa/bertogna_edf_example.v
+++ b/implementation/apa/bertogna_edf_example.v
@@ 133,12 +133,12 @@ Module ResponseTimeAnalysisEDF.
Let arr_seq := periodic_arrival_sequence ts.
(* Let sched be the weak APA EDF scheduler. *)
 Let sched := scheduler job_cost job_task num_cpus arr_seq task_affinity
 (JLFP_to_JLDP arr_seq (EDF job_deadline)).
+ Let sched := scheduler job_arrival job_cost job_task num_cpus arr_seq task_affinity
+ (JLFP_to_JLDP (EDF job_arrival job_deadline)).
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* To show that the RTA works, we infer the schedulability of the task
set from the result of the RTA procedure. *)
@@ 151,30 +151,34 @@ Module ResponseTimeAnalysisEDF.
have VALID := periodic_arrivals_valid_job_parameters ts ts_has_valid_parameters.
have VALIDTS := ts_has_valid_parameters.
unfold valid_sporadic_job, valid_realtime_job in *; des.
 apply taskset_schedulable_by_edf_rta with (task_cost := task_cost) (task_period := task_period) (task_deadline := task_deadline) (alpha := task_affinity) (alpha' := task_affinity) (ts0 := ts).
  by apply ts_has_valid_parameters.
+ apply taskset_schedulable_by_edf_rta with (task_cost := task_cost) (task_period := task_period)
+ (task_deadline := task_deadline) (alpha := task_affinity) (alpha' := task_affinity)
+ (ts0 := ts); try (by done).
 by apply ts_has_constrained_deadlines.
 by apply ts_non_empty_affinities.
 by ins.
 by apply periodic_arrivals_all_jobs_from_taskset.
  by apply periodic_arrivals_valid_job_parameters, ts_has_valid_parameters.
 by apply periodic_arrivals_are_sporadic.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_must_arrive_to_execute.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_sequential_jobs, periodic_arrivals_is_a_set.
+  apply scheduler_sequential_jobs.
+  by apply periodic_arrivals_are_consistent.
+  by apply periodic_arrivals_is_a_set.
 by apply scheduler_respects_affinity.
  apply scheduler_apa_work_conserving; try (by done).
+  apply scheduler_apa_work_conserving.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by intro t; apply EDF_is_transitive.
  by intro t; apply EDF_is_total.
+  by intros t; apply RM_is_transitive.
+  by intros t x y; apply leq_total.
 apply scheduler_respects_policy.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by intro t; apply EDF_is_transitive.
  by intro t; apply EDF_is_total.
+  by intros t; apply RM_is_transitive.
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
  by apply IN.
Qed.
End ExampleRTA.
diff git a/implementation/apa/bertogna_fp_example.v b/implementation/apa/bertogna_fp_example.v
index 5046647..3797a35 100644
 a/implementation/apa/bertogna_fp_example.v
+++ b/implementation/apa/bertogna_fp_example.v
@@ 87,9 +87,9 @@ Module ResponseTimeAnalysisFP.
(* Then, let arr_seq be the periodic arrival sequence from ts. *)
Let arr_seq := periodic_arrival_sequence ts.
 (* Assume ratemonotonic priorities. *)
 Let higher_priority : JLDP_policy arr_seq :=
 (FP_to_JLDP job_task arr_seq (RM task_period)).
+ (* Assume ratemonotonic priorities. *)
+ Let higher_priority : JLDP_policy (@concrete_job_eqType num_cpus) :=
+ FP_to_JLDP job_task (RM task_period).
Section FactsAboutPriorityOrder.
@@ 216,11 +216,12 @@ Module ResponseTimeAnalysisFP.
Qed.
(* Let sched be the workconserving RM APA scheduler. *)
 Let sched := scheduler job_cost job_task num_cpus arr_seq task_affinity higher_priority.
+ Let sched :=
+ scheduler job_arrival job_cost job_task num_cpus arr_seq task_affinity higher_priority.
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, we prove that ts is schedulable with the result of the test. *)
Corollary ts_is_schedulable:
@@ 244,26 +245,25 @@ Module ResponseTimeAnalysisFP.
 by apply RM_is_transitive.
 by apply periodic_arrivals_all_jobs_from_taskset.
 by apply periodic_arrivals_are_sporadic.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_must_arrive_to_execute.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_sequential_jobs, periodic_arrivals_is_a_set.
+  apply scheduler_sequential_jobs.
+  by apply periodic_arrivals_are_consistent.
+  by apply periodic_arrivals_is_a_set.
 by apply scheduler_respects_affinity.
 apply scheduler_apa_work_conserving.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by ins; apply RM_is_transitive.
 {
 unfold FP_to_JLDP; intros t x y; apply/orP.
 by apply priority_is_total; rewrite periodic_arrivals_all_jobs_from_taskset.
 }
+  by intros t; apply RM_is_transitive.
+  by intros t x y; apply leq_total.
 apply scheduler_respects_policy.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by ins; apply RM_is_transitive.
 {
 unfold FP_to_JLDP; intros t x y; apply/orP.
 by apply priority_is_total; rewrite periodic_arrivals_all_jobs_from_taskset.
 }
+  by intros t; apply RM_is_transitive.
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
Qed.
diff git a/implementation/apa/job.v b/implementation/apa/job.v
index 1bb3394..7dbdca0 100644
 a/implementation/apa/job.v
+++ b/implementation/apa/job.v
@@ 15,6 +15,7 @@ Module ConcreteJob.
Record concrete_job :=
{
job_id: nat;
+ job_arrival: nat;
job_cost: time;
job_deadline: time;
job_task: @concrete_task num_cpus
@@ 24,6 +25,7 @@ Module ConcreteJob.
equality for concrete jobs. *)
Definition job_eqdef (j1 j2: concrete_job) :=
(job_id j1 == job_id j2) &&
+ (job_arrival j1 == job_arrival j2) &&
(job_cost j1 == job_cost j2) &&
(job_deadline j1 == job_deadline j2) &&
(job_task j1 == job_task j2).
@@ 35,7 +37,7 @@ Module ConcreteJob.
destruct (job_eqdef x y) eqn:EQ.
{
apply ReflectT; unfold job_eqdef in *.
 move: EQ => /andP [/andP [/andP [/eqP ID /eqP COST] /eqP DL] /eqP TASK].
+ move: EQ => /andP [/andP [/andP [/andP [/eqP ID /eqP ARRIVAL] /eqP COST] /eqP DL] /eqP TASK].
by destruct x, y; simpl in *; subst.
}
{
@@ 45,12 +47,12 @@ Module ConcreteJob.
destruct x, y.
rewrite negb_and in EQ.
move: EQ => /orP [EQ  /eqP TASK]; last by apply TASK; inversion BUG.
 move: EQ => /orP [EQ  /eqP DL].
+ move: EQ => /orP [EQ  /eqP DL]; last by apply DL; inversion BUG.
rewrite negb_and in EQ.
 move: EQ => /orP [/eqP ID  /eqP COST].
+ move: EQ => /orP [EQ  /eqP COST]; last by apply COST; inversion BUG.
+ rewrite negb_and in EQ.
+ move: EQ => /orP [/eqP ID  /eqP ARRIVAL]; last by apply ARRIVAL; inversion BUG.
by apply ID; inversion BUG.
 by apply COST; inversion BUG.
 by apply DL; inversion BUG.
}
Qed.
diff git a/implementation/apa/schedule.v b/implementation/apa/schedule.v
index a18117a..263da8f 100644
 a/implementation/apa/schedule.v
+++ b/implementation/apa/schedule.v
@@ 1,21 +1,22 @@
Require Import rt.util.all.
Require Import rt.model.arrival.basic.arrival_sequence rt.model.arrival.basic.job rt.model.arrival.basic.task rt.model.priority
 rt.model.arrival.basic.task_arrival.
+Require Import rt.model.priority.
+Require Import rt.model.arrival.basic.arrival_sequence rt.model.arrival.basic.task.
Require Import rt.model.schedule.global.basic.schedule.
Require Import rt.model.schedule.apa.affinity rt.model.schedule.apa.platform.
+Require Import rt.model.schedule.global.transformation.construction.
From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat fintype bigop seq path.
Module ConcreteScheduler.
 Import Job SporadicTaskset ArrivalSequence Schedule Platform
 Priority Affinity.
+ Import SporadicTaskset ArrivalSequence Schedule Platform Priority Affinity ScheduleConstruction.
(* In this section, we implement a concrete weak APA scheduler. *)
Section Implementation.
Context {Job: eqType}.
Context {sporadic_task: eqType}.

+
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
@@ 29,79 +30,102 @@ Module ConcreteScheduler.
Variable alpha: task_affinity sporadic_task num_cpus.
(* Assume a JLDP policy is given. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.

 (* Consider the list of pending jobs at time t, ... *)
 Definition jobs_pending_at (sched: schedule num_cpus arr_seq) (t: time) :=
 [seq j < jobs_arrived_up_to arr_seq t  pending job_cost sched j t].

 (* ... which we sort by decreasing priority. *)
 Definition sorted_pending_jobs (sched: schedule num_cpus arr_seq) (t: time) :=
 sort (higher_eq_priority t) (jobs_pending_at sched t).

 (* Now we implement the algorithm that generates the APA schedule. *)

 (* Given a job j at time t, we first define a predicate that states
 whether j should preempt a mapping (cpu, x), where x is either Some j'
 that is currently mapped to cpu or None. *)
 Definition should_be_scheduled (j: JobIn arr_seq) (t: time) p :=
 let '(cpu, mapped_job) := p in
 if mapped_job is Some j' then (* If there is a job j', check the priority and affinity. *)
 (can_execute_on alpha (job_task j) cpu) &&
 ~~ (higher_eq_priority t j' j)
 else (* Else, if cpu is idle, check only the affinity. *)
 (can_execute_on alpha (job_task j) cpu).

 (* Next, using the "should_be_scheduled" predicate, we define a function
 that tries to schedule job j by updating a list of mappings.
 It does so by replacing the first pair (cpu, x) where j can be
 scheduled (if it exists). *)
 Definition update_available_cpu t allocation j :=
 replace_first (should_be_scheduled j t) (* search for processors that j can preempt *)
 (set_pair_2nd (Some j)) (* replace the mapping in that processor with j *)
 allocation. (* list of mappings *)

 (* Using the fuction "update_available_cpu", we now define an iteration
 that tries to successively schedule each job in a list job_list.
 Starting with an empty mapping,
 <(cpu0, None), (cpu1, None), (cpu2, None), ...>,
 it tries to schedule each job in job_list and yields some updated list:
 <(cpu0, None), (cpu1, Some j5), (cpu2, j9), ...>. *)
 Definition try_to_schedule_every_job job_list t :=
 foldl (update_available_cpu t)
 (zip (enum (processor num_cpus)) (nseq num_cpus None)) (* empty mapping*)
 job_list.

 (* The iteration we just defined is then applied to the list of pending jobs
 at any time t. *)
 Definition schedule_every_pending_job prev_sched t :=
 try_to_schedule_every_job (sorted_pending_jobs prev_sched t) t.

 (* The schedule can now be constructed iteratively. Starting from the empty schedule, ... *)
 Definition empty_schedule : schedule num_cpus arr_seq :=
 fun cpu t => None.

 (* ..., we update the schedule at time t by calling schedule_every_pending_job with
 the list of pending jobs at time t, and then converting the result to a function. *)
 Definition update_schedule (prev_sched: schedule num_cpus arr_seq)
 (t_next: time) : schedule num_cpus arr_seq :=
 fun cpu t =>
 if t == t_next then
 pairs_to_function None (schedule_every_pending_job prev_sched t) cpu
 else prev_sched cpu t.
+ Variable higher_eq_priority: JLDP_policy Job.
+
+ (* Next, we show how to recursively construct the schedule. *)
+ Section ScheduleConstruction.
+
+ (* For any time t, suppose that we have generated the schedule prefix in the
+ interval [0, t). Then, we must define what should be scheduled at time t. *)
+ Variable sched_prefix: schedule Job num_cpus.
+ Variable cpu: processor num_cpus.
+ Variable t: time.
+
+ (* For simplicity, let's use some local names. *)
+ Let is_pending := pending job_arrival job_cost sched_prefix.
+ Let actual_arrivals := jobs_arrived_up_to arr_seq.
+
+ (* Consider the list of pending jobs at time t, ... *)
+ Definition pending_jobs := [seq j < actual_arrivals t  is_pending j t].
+
+ (* ...which we sort by priority. *)
+ Definition sorted_pending_jobs := sort (higher_eq_priority t) pending_jobs.
+
+ (* Now we implement the algorithm that generates the APA schedule. *)
+
+ (* Given a job j at time t, we first define a predicate that states
+ whether j should preempt a mapping (cpu, x), where x is either Some j'
+ that is currently mapped to cpu or None. *)
+ Definition should_be_scheduled (j: Job) p :=
+ let '(cpu, mapped_job) := p in
+ if mapped_job is Some j' then (* If there is a job j', check the priority and affinity. *)
+ (can_execute_on alpha (job_task j) cpu) &&
+ ~~ (higher_eq_priority t j' j)
+ else (* Else, if cpu is idle, check only the affinity. *)
+ (can_execute_on alpha (job_task j) cpu).
+
+ (* Next, using the "should_be_scheduled" predicate, we define a function
+ that tries to schedule job j by updating a list of mappings.
+ It does so by replacing the first pair (cpu, x) where j can be
+ scheduled (if it exists). *)
+ Definition update_available_cpu allocation j :=
+ replace_first (should_be_scheduled j) (* search for processors that j can preempt *)
+ (set_pair_2nd (Some j)) (* replace the mapping in that processor with j *)
+ allocation. (* list of mappings *)
+
+ (* Consider the empty mapping. *)
+ Let empty_mapping : seq (processor num_cpus * option Job) :=
+ (zip (enum (processor num_cpus)) (nseq num_cpus None)).
+
+ (* Using the fuction "update_available_cpu", we now define an iteration
+ that iteratively maps each pending job to a processor.
+
+ Starting with an empty mapping,
+ <(cpu0, None), (cpu1, None), (cpu2, None), ...>,
+ it tries to schedule each job on some processor and yields an updated list:
+ <(cpu0, None), (cpu1, Some j5), (cpu2, Some j9), ...>. *)
+ Definition schedule_jobs_from_list l :=
+ foldl update_available_cpu empty_mapping l.
+
+ (* To conclude, we take the list of pairs and convert to a function denoting
+ the actual schedule. *)
+ Definition apa_schedule :=
+ pairs_to_function None (schedule_jobs_from_list sorted_pending_jobs) cpu.
+
+ End ScheduleConstruction.
+
+ (* Starting from the empty schedule, the final schedule is obtained by iteratively
+ picking the highestpriority job. *)
+ Let empty_schedule : schedule Job num_cpus := fun cpu t => None.
+ Definition scheduler :=
+ build_schedule_from_prefixes num_cpus apa_schedule empty_schedule.
+
+ (* Then, by showing that the construction function depends only on the prefix, ... *)
+ Lemma scheduler_depends_only_on_prefix:
+ forall sched1 sched2 cpu t,
+ (forall t0 cpu0, t0 < t > sched1 cpu0 t0 = sched2 cpu0 t0) >
+ apa_schedule sched1 cpu t = apa_schedule sched2 cpu t.
+ Proof.
+ intros sched1 sched2 cpu t ALL.
+ rewrite /apa_schedule /schedule_jobs_from_list; do 2 f_equal.
+ rewrite /sorted_pending_jobs; f_equal.
+ apply eq_in_filter.
+ intros j ARR.
+ rewrite /pending; do 2 f_equal.
+ rewrite /completed; f_equal.
+ apply eq_big_nat; move => i /= LTi.
+ rewrite /service_at /scheduled_on; apply eq_bigl; move => cpu'.
+ by rewrite ALL.
+ Qed.
+
+ (* ...we infer that the generated schedule is indeed based on the construction function. *)
+ Corollary scheduler_uses_construction_function:
+ forall t cpu, scheduler cpu t = apa_schedule scheduler cpu t.
+ Proof.
+ by ins; apply prefix_dependent_schedule_construction,
+ scheduler_depends_only_on_prefix.
+ Qed.
 (* This allows us to iteratively construct the schedule up to some time t_max. *)
 Fixpoint schedule_prefix (t_max: time) : schedule num_cpus arr_seq :=
 if t_max is t_prev.+1 then
 (* At time t_prev + 1, schedule jobs that have not completed by time t_prev. *)
 update_schedule (schedule_prefix t_prev) t_prev.+1
 else
 (* At time 0, schedule any jobs that arrive. *)
 update_schedule empty_schedule 0.

 (* Finally, the prefixes are used to build the complete schedule. *)
 Definition scheduler (cpu: processor num_cpus) (t: time) := (schedule_prefix t) cpu t.

End Implementation.
(* In this section, we prove several properties about the scheduling algorithm we
@@ 110,7 +134,8 @@ Module ConcreteScheduler.
Context {Job: eqType}.
Context {sporadic_task: eqType}.

+
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
@@ 121,62 +146,34 @@ Module ConcreteScheduler.
(* Let alpha be an affinity associated with each task. *)
Variable alpha: task_affinity sporadic_task num_cpus.
 (* Let arr_seq be any arrival sequence of jobs where ...*)
+ (* Let arr_seq be any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
 (* ...jobs have positive cost and...*)
 Hypothesis H_job_cost_positive:
 forall (j: JobIn arr_seq), job_cost_positive job_cost j.
 (* ... at any time, there are no duplicates of the same job. *)
 Hypothesis H_arrival_sequence_is_a_set :
 arrival_sequence_is_a_set arr_seq.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
(* Consider any JLDP policy higher_eq_priority that is transitive and total. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
 Hypothesis H_priority_transitive: forall t, transitive (higher_eq_priority t).
+ Variable higher_eq_priority: JLDP_policy Job.
+ Hypothesis H_priority_transitive: JLDP_is_transitive higher_eq_priority.
Hypothesis H_priority_total: forall t, total (higher_eq_priority t).
(* Let sched denote our concrete scheduler implementation. *)
 Let sched := scheduler job_cost job_task num_cpus arr_seq alpha higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost job_task num_cpus arr_seq alpha higher_eq_priority.
(* Next, we provide some helper lemmas about the scheduler construction. *)
Section HelperLemmas.
 (* Let sched_prefix denote the prefix construction of our scheduler. *)
 Let sched_prefix := schedule_prefix job_cost job_task num_cpus arr_seq alpha higher_eq_priority.

 (* We begin by showing that the scheduler preserves its prefixes. *)
 Lemma scheduler_same_prefix :
 forall t t_max cpu,
 t <= t_max >
 sched_prefix t_max cpu t = sched cpu t.
 Proof.
 intros t t_max cpu LEt.
 induction t_max; first by rewrite leqn0 in LEt; move: LEt => /eqP EQ; subst.
 {
 rewrite leq_eqVlt in LEt.
 move: LEt => /orP [/eqP EQ  LESS]; first by subst.
 {
 feed IHt_max; first by done.
 unfold sched_prefix, schedule_prefix, update_schedule at 1.
 assert (FALSE: t == t_max.+1 = false).
 {
 by apply negbTE; rewrite neq_ltn LESS orTb.
 } rewrite FALSE.
 by rewrite IHt_max.
 }
 }
 Qed.

(* To avoid many parameters, let's also rename the scheduling function.
We make a generic version (for any list of jobs l), ... *)
 Let schedule_jobs t l := try_to_schedule_every_job job_task num_cpus arr_seq alpha higher_eq_priority t l.
+ Let schedule_jobs t l := schedule_jobs_from_list job_task num_cpus alpha higher_eq_priority t l.
(* ... and a specific version (for the pending jobs in sched). *)
 Let schedule_pending_jobs t := schedule_jobs (sorted_pending_jobs job_cost num_cpus arr_seq higher_eq_priority sched t) t.
+ Let schedule_pending_jobs t :=
+ schedule_jobs t (sorted_pending_jobs job_arrival job_cost num_cpus arr_seq
+ higher_eq_priority sched t).
(* Next, we show that there are no duplicate cpus in the mapping. *)
Lemma scheduler_uniq_cpus :
forall t l,
 uniq (unzip1 (schedule_jobs l t)).
+ uniq (unzip1 (schedule_jobs t l)).
Proof.
intros t l.
induction l as [ l' j_last] using last_ind.
@@ 184,13 +181,13 @@ Module ConcreteScheduler.
by rewrite unzip1_zip; [rewrite enum_uniq  rewrite size_enum_ord size_nseq].
}
{
 rewrite /schedule_jobs /try_to_schedule_every_job cats1 foldl_cat /=.
 assert (EQ: forall l j, unzip1 (update_available_cpu job_task num_cpus arr_seq
 alpha higher_eq_priority t l j) = unzip1 l).
+ rewrite /schedule_jobs /schedule_jobs_from_list cats1 foldl_cat /=.
+ set up := update_available_cpu _ _ _ _ _.
+ assert (EQ: forall l j, unzip1 (up l j) = unzip1 l).
{
intros l j; clear l j.
induction l; first by done.
 unfold update_available_cpu; simpl.
+ rewrite /up /update_available_cpu /=.
by case SHOULD: should_be_scheduled; simpl; f_equal.
}
by rewrite EQ.
@@ 201,17 +198,16 @@ Module ConcreteScheduler.
of jobs l used in the construction. *)
Lemma scheduler_job_in_mapping :
forall l j t cpu,
 (cpu, Some j) \in schedule_jobs l t > j \in l.
+ (cpu, Some j) \in schedule_jobs t l > j \in l.
Proof.
intros l j t cpu SOME; clear SOME.
 unfold schedule_every_pending_job in *.
induction l as [ l' j'] using last_ind; simpl in *.
{
apply mem_zip in SOME; last by rewrite size_enum_ord size_nseq.
by move: SOME => [_ /nseqP [SOME _]].
}
{
 rewrite /schedule_jobs /try_to_schedule_every_job cats1 foldl_cat /= in SOME.
+ rewrite /schedule_jobs /schedule_jobs_from_list cats1 foldl_cat /= in SOME.
unfold update_available_cpu in SOME.
elim (replace_first_cases SOME) => [IN  [y [NEW IN]]].
{
@@ 232,15 +228,15 @@ Module ConcreteScheduler.
can_execute_on alpha (job_task j) cpu.
Proof.
intros j t cpu SOME.
 unfold schedule_pending_jobs, schedule_every_pending_job in SOME.
 set l := sorted_pending_jobs _ _ _ _ _ _ in SOME.
+ unfold schedule_pending_jobs in SOME.
+ set l := sorted_pending_jobs _ _ _ _ _ _ _ in SOME.
induction l as [ l' j'] using last_ind; simpl in *.
{
apply mem_zip in SOME; last by rewrite size_enum_ord size_nseq.
by move: SOME => [_ /nseqP [BUG _]].
}
{
 unfold schedule_jobs, try_to_schedule_every_job in SOME.
+ unfold schedule_jobs, schedule_jobs_from_list in SOME.
rewrite cats1 foldl_cat /= in SOME.
elim (replace_first_cases SOME) => [IN  [y [NEW [SHOULD _]]]];
first by apply IHl.
@@ 258,10 +254,10 @@ Module ConcreteScheduler.
cpu1 = cpu2.
Proof.
intros j t cpu1 cpu2 SOME1 SOME2.
 unfold schedule_pending_jobs, schedule_every_pending_job in *.
 set l := sorted_pending_jobs _ _ _ _ _ _ in SOME1 SOME2.
+ unfold schedule_pending_jobs in *.
+ set l := sorted_pending_jobs _ _ _ _ _ _ _ in SOME1 SOME2.
assert (UNIQ: uniq l).
 by rewrite sort_uniq; apply filter_uniq, JobIn_uniq.
+ by rewrite sort_uniq; eapply filter_uniq, arrivals_uniq; eauto 1.
induction l as [ l' j'] using last_ind; simpl in *.
{
@@ 270,7 +266,7 @@ Module ConcreteScheduler.
}
{
rewrite rcons_uniq in UNIQ; move: UNIQ => /andP [NOTIN UNIQ].
 rewrite /schedule_jobs /try_to_schedule_every_job cats1 foldl_cat /= in SOME1 SOME2.
+ rewrite /schedule_jobs /schedule_jobs_from_list cats1 foldl_cat /= in SOME1 SOME2.
destruct (replace_first_cases SOME1) as [SAME1  [[cpu1' p1] [EQ1 [SHOULD1 PREV1]]]];
destruct (replace_first_cases SOME2) as [SAME2  [[cpu2' p2] [EQ2 [SHOULD2 PREV2]]]].
{
@@ 322,87 +318,18 @@ Module ConcreteScheduler.
Proof.
unfold schedule_pending_jobs, schedule_jobs in *.
intros j cpu t.
 induction t.
+ apply/idP/idP.
{
 apply/idP/idP.
 {
 intros SCHED.
 unfold scheduled_on, sched, scheduler, schedule_prefix in SCHED.
 rewrite /update_schedule eq_refl in SCHED; move: SCHED => /eqP SCHED.
 apply pairs_to_function_neq_default in SCHED; last by done.
 unfold schedule_every_pending_job in SCHED.
 set l := sorted_pending_jobs _ _ _ _ _ _ in SCHED.
 set l' := sorted_pending_jobs _ _ _ _ _ _.
 assert (EQ: l' = l).
 {
 unfold l, l', sorted_pending_jobs; f_equal.
 unfold jobs_pending_at; apply eq_filter.
 unfold pending; red; intro j0; do 2 f_equal.
 unfold completed; f_equal.
 by unfold service; rewrite big_geq // big_geq //.
 }
 by rewrite EQ.
 }
 {
 intros SCHED.
 have MEM := pairs_to_function_mem None.
 apply MEM in SCHED; clear MEM; last by apply (scheduler_uniq_cpus 0).
 unfold scheduled_on, sched, scheduler, schedule_prefix.
 rewrite /update_schedule eq_refl.
 rewrite SCHED; apply/eqP; f_equal.
 unfold schedule_pending_jobs, schedule_jobs, schedule_every_pending_job; f_equal.
 unfold sorted_pending_jobs, jobs_pending_at; f_equal.
 apply eq_filter; intros j0.
 unfold pending; do 2 f_equal.
 unfold completed; f_equal.
 by unfold service; rewrite big_geq // big_geq //.
 }
+ move => /eqP SCHED.
+ rewrite /sched scheduler_uses_construction_function /apa_schedule in SCHED.
+ by apply pairs_to_function_neq_default in SCHED; last by done.
}
{
 apply/idP/idP.
 {
 intros SCHED.
 unfold scheduled_on, sched, scheduler, schedule_prefix in SCHED.
 rewrite /update_schedule eq_refl in SCHED; move: SCHED => /eqP SCHED.
 apply pairs_to_function_neq_default in SCHED; last by done.
 unfold schedule_every_pending_job in SCHED.
 set l := try_to_schedule_every_job _ _ _ _ _ _ _ in SCHED.
 set l' := try_to_schedule_every_job _ _ _ _ _ _ _.
 assert (EQ: l' = l).
 {
 unfold l', l, schedule_every_pending_job; f_equal.
 unfold sorted_pending_jobs, jobs_pending_at; f_equal.
 apply eq_filter; intros j0.
 unfold pending; do 2 f_equal.
 unfold completed; f_equal.
 unfold service. rewrite big_nat_recr // big_nat_recr //=.
 f_equal; apply eq_big_nat; intros t0 LE.
 unfold service_at; apply eq_bigl; intros cpu0.
 unfold scheduled_on; f_equal.
 unfold sched; move: LE => /andP [_ LE].
 by rewrite < scheduler_same_prefix with (t_max := t); last by apply ltnW.
 }
 by rewrite EQ.
 }
 {
 intros SCHED.
 have MEM := pairs_to_function_mem None.
 apply MEM in SCHED; clear MEM; last by apply (scheduler_uniq_cpus t.+1).
 unfold scheduled_on, sched, scheduler, schedule_prefix.
 rewrite /update_schedule eq_refl.
 rewrite SCHED; apply/eqP; f_equal.
 unfold schedule_every_pending_job; f_equal.
 unfold sorted_pending_jobs, jobs_pending_at; f_equal.
 apply eq_filter; intros j0.
 unfold pending; do 2 f_equal.
 unfold completed; f_equal.
 unfold service. rewrite big_nat_recr // big_nat_recr //=.
 f_equal; apply eq_big_nat; intros t0 LE.
 unfold service_at; apply eq_bigl; intros cpu0.
 unfold scheduled_on; f_equal.
 unfold sched; move: LE => /andP [_ LE].
 by rewrite < scheduler_same_prefix with (t_max := t); last by apply ltnW.
 }
+ intros SCHED.
+ have MEM := pairs_to_function_mem None.
+ apply MEM in SCHED; clear MEM; last by apply scheduler_uniq_cpus.
+ apply/eqP.
+ by rewrite /sched scheduler_uses_construction_function.
}
Qed.
@@ 410,7 +337,7 @@ Module ConcreteScheduler.
Lemma scheduler_has_cpus :
forall cpu t l,
exists x,
 (cpu, x) \in schedule_jobs l t.
+ (cpu, x) \in schedule_jobs t l.
Proof.
intros cpu t l.
induction l as [ l' j_last] using last_ind; simpl in *.
@@ 419,7 +346,7 @@ Module ConcreteScheduler.
[by rewrite mem_enum  by rewrite size_enum_ord].
}
{
 rewrite /schedule_jobs /try_to_schedule_every_job cats1 foldl_cat /=.
+ rewrite /schedule_jobs /schedule_jobs_from_list cats1 foldl_cat /=.
move: IHl => [x IN].
eapply replace_first_previous in IN; des;
first by exists x; apply IN.
@@ 437,27 +364,26 @@ Module ConcreteScheduler.
j \in l >
sorted (higher_eq_priority t) l >
uniq l >
 (forall cpu, (cpu, Some j) \notin schedule_jobs l t) >
+ (forall cpu, (cpu, Some j) \notin schedule_jobs t l) >
can_execute_on alpha (job_task j) cpu >
exists j_other,
 (cpu, Some j_other) \in schedule_jobs l t.
+ (cpu, Some j_other) \in schedule_jobs t l.
Proof.
 intros j cpu t l IN SORT UNIQ NOTSCHED CAN.

+ intros j cpu t l IN SORT UNIQ NOTSCHED CAN.
generalize dependent cpu.
induction l as [ l' j_last] using last_ind; simpl in *;
first by rewrite in_nil in IN.
{
intros cpu CAN.
rewrite rcons_uniq in UNIQ; move: UNIQ => /andP [NOTIN UNIQ].
 rewrite /schedule_jobs /try_to_schedule_every_job cats1 foldl_cat /= in NOTSCHED *.
 set prev := foldl (update_available_cpu _ _ _ _ _ _) (zip _ _) l' in NOTSCHED *.
+ rewrite /schedule_jobs /schedule_jobs_from_list cats1 foldl_cat /= in NOTSCHED *.
+ set prev := foldl _ _ _ in NOTSCHED *.
rewrite mem_rcons in_cons in IN.
move: IN => /orP [/eqP IN  LAST]; subst.
{
clear IHl.
 assert (ALL: forall x, x \in prev > ~~ (should_be_scheduled job_task num_cpus arr_seq
 alpha higher_eq_priority j_last t) x).
+ assert (ALL: forall x, x \in prev >
+ ~~ (should_be_scheduled job_task num_cpus alpha higher_eq_priority t j_last) x).
{
apply replace_first_failed with (f := set_pair_2nd (Some j_last)).
by intros [cpu' j'] IN; apply NOTSCHED.
@@ 466,8 +392,7 @@ Module ConcreteScheduler.
specialize (ALL (cpu, x) IN).
simpl in ALL.
destruct x as [j' ]; last by rewrite CAN in ALL.
 eapply replace_first_previous in IN; des;
 first by exists j'; apply IN.
+ eapply replace_first_previous in IN; des; first by exists j'; apply IN.
by exists j_last; apply IN0.
}
{
@@ 479,7 +404,7 @@ Module ConcreteScheduler.
clear IHl; intros cpu'; specialize (NOTSCHED cpu').
apply/negP; intro BUG.
apply replace_first_previous with (f := set_pair_2nd (Some j_last))
 (P := should_be_scheduled job_task num_cpus arr_seq alpha higher_eq_priority j_last t)
+ (P := should_be_scheduled job_task num_cpus alpha higher_eq_priority t j_last)
in BUG; des;
first by rewrite BUG in NOTSCHED.
move: BUG => /andP [_ /negP HP].
@@ 495,13 +420,14 @@ Module ConcreteScheduler.
(* Next, we prove that the mapping respects priority. *)
Lemma scheduler_priority :
forall j j_hp cpu t,
 backlogged job_cost sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
can_execute_on alpha (job_task j) cpu >
scheduled_on sched j_hp cpu t >
higher_eq_priority t j_hp j.
Proof.
have SCHED_ON := scheduler_scheduled_on.
 intros j j_hp cpu t BACK CAN SCHED.
+ intros j j_hp cpu t ARRj BACK CAN SCHED.
move: BACK => /andP [PENDING NOTSCHED'].
assert (NOTSCHED: forall cpu, (cpu, Some j) \notin schedule_pending_jobs t).
{
@@ 511,24 +437,26 @@ Module ConcreteScheduler.
rewrite SCHED_ON in SCHED.
clear NOTSCHED' SCHED_ON.
 unfold schedule_pending_jobs, schedule_jobs, schedule_every_pending_job in *.
 set l := sorted_pending_jobs _ _ _ _ _ _ in SCHED NOTSCHED.
+ unfold schedule_pending_jobs, schedule_jobs, schedule_jobs_from_list in *.
+ set l := sorted_pending_jobs _ _ _ _ _ _ _ in SCHED NOTSCHED.
have IN: j \in l.
{
 rewrite mem_sort mem_filter PENDING andTb JobIn_arrived.
 by move: PENDING => /andP [H _].
+ rewrite mem_sort mem_filter PENDING andTb.
+ move: PENDING => /andP [ARR IN]; rewrite /has_arrived in ARR.
+ by apply arrived_between_implies_in_arrivals with (job_arrival0 := job_arrival).
}
have INhp: j_hp \in l by apply scheduler_job_in_mapping in SCHED.
 have SORT : sorted (higher_eq_priority t) l by apply sort_sorted.
 have UNIQ: uniq l by rewrite sort_uniq filter_uniq // JobIn_uniq //.
+ have SORT : sorted (higher_eq_priority t) l by apply sort_sorted, H_priority_total.
+ have UNIQ: uniq l.
+ by rewrite sort_uniq filter_uniq // (arrivals_uniq job_arrival) //.
induction l as [ l' j_last] using last_ind;
first by rewrite in_nil in IN.
{
 rewrite /try_to_schedule_every_job cats1 foldl_cat /= in SCHED.
 rewrite /try_to_schedule_every_job cats1 foldl_cat /= in NOTSCHED.
 set prev := foldl (update_available_cpu job_task num_cpus arr_seq alpha higher_eq_priority t) (zip (enum (processor num_cpus)) (nseq num_cpus None)) l' in SCHED NOTSCHED.
+ rewrite /schedule_jobs_from_list cats1 foldl_cat /= in SCHED.
+ rewrite /schedule_jobs_from_list cats1 foldl_cat /= in NOTSCHED.
+ set prev := foldl _ _ _ in SCHED NOTSCHED.
rewrite rcons_uniq in UNIQ; move: UNIQ => /andP [NOTIN UNIQ].
rewrite 2!mem_rcons 2!in_cons in IN INhp.
move: IN => /orP [/eqP EQ  IN];
@@ 564,7 +492,9 @@ Module ConcreteScheduler.
{
move: EX => /existsP [cpu' IN''].
unfold prev in IN''.
 apply replace_first_previous with (f := set_pair_2nd (Some j_hp)) (P := should_be_scheduled job_task num_cpus arr_seq alpha higher_eq_priority j_hp t) in IN''; des;
+ apply replace_first_previous with (f := set_pair_2nd (Some j_hp))
+ (P := should_be_scheduled job_task num_cpus alpha higher_eq_priority t j_hp)
+ in IN''; des;
first by specialize (NOTSCHED cpu'); rewrite IN'' in NOTSCHED.
move: IN'' => /andP [_ /negP HP].
by exfalso; apply HP, order_sorted_rcons with (s := l').
@@ 591,7 +521,9 @@ Module ConcreteScheduler.
{
intros cpu0; apply/negP; intro BUG.
unfold update_available_cpu in NOTSCHED.
 apply replace_first_previous with (f := set_pair_2nd (Some j_last)) (P := should_be_scheduled job_task num_cpus arr_seq alpha higher_eq_priority j_last t) in BUG; des.
+ apply replace_first_previous with (f := set_pair_2nd (Some j_last))
+ (P := should_be_scheduled job_task num_cpus alpha higher_eq_priority t j_last)
+ in BUG; des.
{
by specialize (NOTSCHED cpu0); rewrite BUG in NOTSCHED.
}
@@ 613,33 +545,27 @@ Module ConcreteScheduler.
(* Now, we prove the important properties about the implementation. *)
+ (* First, we show that scheduled jobs come from the arrival sequence. *)
+ Lemma scheduler_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+ Proof.
+ move => j t /existsP [cpu SCHED].
+ rewrite scheduler_scheduled_on in SCHED.
+ apply scheduler_job_in_mapping in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ move: SCHED => /andP [_ ARR].
+ by apply in_arrivals_implies_arrived in ARR.
+ Qed.
+
(* Jobs do not execute before they arrive, ...*)
Theorem scheduler_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Proof.
 unfold jobs_must_arrive_to_execute.
 intros j t SCHED.
 move: SCHED => /existsP [cpu /eqP SCHED].
 unfold sched, scheduler, schedule_prefix in SCHED.
 destruct t.
 {
 rewrite /update_schedule eq_refl in SCHED.
 apply pairs_to_function_neq_default in SCHED; last by done.
 unfold schedule_every_pending_job in SCHED.
 apply scheduler_job_in_mapping in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 move: SCHED => /andP [_ ARR].
 by apply JobIn_arrived in ARR.
 }
 {
 unfold update_schedule at 1 in SCHED; rewrite eq_refl /= in SCHED.
 apply pairs_to_function_neq_default in SCHED; last by done.
 unfold schedule_every_pending_job in SCHED.
 apply scheduler_job_in_mapping in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 move: SCHED => /andP [_ ARR].
 by apply JobIn_arrived in ARR.
 }
+ move => j t /existsP [cpu SCHED].
+ rewrite scheduler_scheduled_on in SCHED.
+ apply scheduler_job_in_mapping in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ by move: SCHED => /andP [/andP [ARR _] _].
Qed.
(* ..., jobs are sequential, ... *)
@@ 647,7 +573,7 @@ Module ConcreteScheduler.
Proof.
intros j t cpu1 cpu2 SCHED1 SCHED2.
by apply scheduler_has_no_duplicate_jobs with (j := j) (t := t);
 rewrite scheduler_scheduled_on; apply/eqP.
+ rewrite scheduler_scheduled_on; apply/eqP.
Qed.
(* ... and jobs do not execute after completion. *)
@@ 655,65 +581,54 @@ Module ConcreteScheduler.
completed_jobs_dont_execute job_cost sched.
Proof.
have SEQ := scheduler_sequential_jobs.
 rename H_job_cost_positive into GT0.
 unfold completed_jobs_dont_execute, service.
intros j t.
 induction t; first by rewrite big_geq.
+ induction t;
+ first by rewrite /service /service_during big_geq //.
+ rewrite /service /service_during big_nat_recr //=.
+ rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LT]; last first.
{
 rewrite big_nat_recr // /=.
 rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LESS]; last first.
 {
 destruct (job_cost j); first by rewrite ltn0 in LESS.
 rewrite addn1; rewrite ltnS in LESS.
 by apply leq_add; last by apply service_at_most_one, SEQ.
 }
 rewrite EQ {2}[job_cost j]addn0; apply leq_add; first by done.
 destruct t.
+ apply: leq_trans LT; rewrite addn1.
+ apply leq_add; first by done.
+ rewrite /service_at.
+ case (boolP ([exists cpu, scheduled_on sched j cpu t])) => [EX  ALL]; last first.
{
 rewrite big_geq // in EQ.
 specialize (GT0 j); unfold job_cost_positive in *.
 by rewrite EQ ltn0 in GT0.
 }
 {
 unfold service_at; rewrite big_mkcond.
 apply leq_trans with (n := \sum_(cpu < num_cpus) 0);
 last by rewrite big_const_ord iter_addn mul0n addn0.
 apply leq_sum; intros cpu _; desf.
 move: Heq => /eqP SCHED.
 unfold scheduler, schedule_prefix in SCHED.
 unfold sched, scheduler, schedule_prefix, update_schedule at 1 in SCHED.
 rewrite eq_refl in SCHED.
 apply pairs_to_function_neq_default in SCHED; last by done.
 unfold schedule_every_pending_job in SCHED.
 apply scheduler_job_in_mapping in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 move: SCHED => /andP [/andP [_ /negP NOTCOMP] _].
 exfalso; apply NOTCOMP; clear NOTCOMP.
 unfold completed; apply/eqP.
 unfold service; rewrite EQ.
 rewrite big_nat_cond [\sum_(_ <= _ < _  true)_]big_nat_cond.
 apply eq_bigr; move => i /andP [/andP [_ LT] _].
 apply eq_bigl; red; ins.
 unfold scheduled_on; f_equal.
 fold (schedule_prefix job_cost job_task num_cpus arr_seq alpha higher_eq_priority).
 by rewrite scheduler_same_prefix.
+ rewrite negb_exists in ALL; move: ALL => /forallP ALL.
+ rewrite big1 //; intros cpu SCHED.
+ by specialize (ALL cpu); rewrite SCHED in ALL.
}
+ move: EX => /existsP [cpu SCHED].
+ rewrite (bigD1 cpu) /=; last by done.
+ rewrite big1; first by rewrite addn0.
+ move => cpu' /andP [SCHED' NEQ].
+ move: SCHED SCHED' => /eqP SCHED /eqP SCHED'.
+ move: NEQ => /eqP NEQ; exfalso; apply: NEQ.
+ by apply SEQ with (j := j) (t := t).
}
+ rewrite [job_cost _]addn0; apply leq_add; first by rewrite EQ.
+ rewrite leqn0 /service_at big1 //.
+ move => cpu SCHED.
+ rewrite scheduler_scheduled_on in SCHED.
+ apply scheduler_job_in_mapping in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ move: SCHED => /andP [/andP [_ NOTCOMP] _].
+ by rewrite /completed EQ eq_refl in NOTCOMP.
Qed.
(* In addition, the scheduler is APA work conserving, ... *)
Theorem scheduler_apa_work_conserving:
 apa_work_conserving job_cost job_task sched alpha.
+ apa_work_conserving job_arrival job_cost job_task arr_seq sched alpha.
Proof.
 intros j t BACK cpu CAN.
 set l := (sorted_pending_jobs job_cost num_cpus arr_seq higher_eq_priority sched t).
 have SORT : sorted (higher_eq_priority t) l by apply sort_sorted.
 have UNIQ: uniq l by rewrite sort_uniq filter_uniq // JobIn_uniq //.
+ intros j t ARRj BACK cpu CAN.
+ set l := (sorted_pending_jobs job_arrival job_cost num_cpus arr_seq higher_eq_priority sched t).
+ have SORT : sorted (higher_eq_priority t) l by apply sort_sorted, H_priority_total.
+ have UNIQ: uniq l.
+ by rewrite sort_uniq filter_uniq // (arrivals_uniq job_arrival) //.
move: BACK => /andP [PENDING NOTSCHED].
have IN: j \in l.
{
 rewrite mem_sort mem_filter PENDING andTb JobIn_arrived.
 by move: PENDING => /andP [H _].
+ rewrite mem_sort mem_filter PENDING andTb.
+ move: PENDING => /andP [ARR _].
+ by apply arrived_between_implies_in_arrivals with (job_arrival0 := job_arrival).
}
have WORK := scheduler_mapping_is_work_conserving j cpu t l IN SORT UNIQ.
exploit WORK; try by done.
@@ 735,10 +650,11 @@ Module ConcreteScheduler.
(* ... and respects the JLDP policy under weak APA scheduling. *)
Theorem scheduler_respects_policy :
 respects_JLDP_policy_under_weak_APA job_cost job_task sched alpha higher_eq_priority.
+ respects_JLDP_policy_under_weak_APA job_arrival job_cost job_task arr_seq
+ sched alpha higher_eq_priority.
Proof.
unfold respects_JLDP_policy_under_weak_APA.
 intros j j_hp cpu t BACK SCHED ALPHA.
+ intros j j_hp cpu t ARRj BACK SCHED ALPHA.
rewrite scheduler_scheduled_on in SCHED.
apply scheduler_priority with (cpu := cpu); try by done.
by rewrite scheduler_scheduled_on.
diff git a/implementation/arrival_sequence.v b/implementation/arrival_sequence.v
index 0d5ca15..f82b7dd 100644
 a/implementation/arrival_sequence.v
+++ b/implementation/arrival_sequence.v
@@ 14,9 +14,10 @@ Module ConcreteArrivalSequence.
(* At any time t, we release Some job of tsk if t is a multiple of the period,
otherwise we release None. *)
 Definition add_job (t: time) (tsk: concrete_task) :=
 if task_period tsk % t then
 Some (Build_concrete_job (t %/ task_period tsk) (task_cost tsk) (task_deadline tsk) tsk)
+ Definition add_job (arr_time: time) (tsk: concrete_task) :=
+ if task_period tsk % arr_time then
+ Some (Build_concrete_job (arr_time %/ task_period tsk) arr_time
+ (task_cost tsk) (task_deadline tsk) tsk)
else
None.
@@ 35,14 +36,23 @@ Module ConcreteArrivalSequence.
(* Regarding the periodic arrival sequence built from ts, we prove that...*)
Let arr_seq := periodic_arrival_sequence ts.
+ (* ... arrival times are consistent, ... *)
+ Theorem periodic_arrivals_are_consistent:
+ arrival_times_are_consistent job_arrival arr_seq.
+ Proof.
+ move => j t ARRj.
+ rewrite /arrives_at mem_pmap in ARRj.
+ move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
+ by unfold add_job in *; desf.
+ Qed.
+
(* ... every job comes from the task set, ... *)
Theorem periodic_arrivals_all_jobs_from_taskset:
 forall (j: JobIn arr_seq),
 job_task (job_of_job_in j) \in ts. (* TODO: fix coercion. *)
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
Proof.
 intros j.
 destruct j as [j arr ARRj]; simpl.
 unfold arr_seq, arrives_at, periodic_arrival_sequence in *.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj.
move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
by unfold add_job in *; desf.
@@ 50,13 +60,13 @@ Module ConcreteArrivalSequence.
(* ..., jobs have valid parameters, ... *)
Theorem periodic_arrivals_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
Proof.
rename H_valid_task_parameters into PARAMS.
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
 intros j; destruct j as [j arr ARRj]; simpl.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in ARRj.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj; move: ARRj => /mapP [tsk IN SOME].
unfold add_job in SOME; desf.
specialize (PARAMS tsk IN); des.
@@ 66,12 +76,10 @@ Module ConcreteArrivalSequence.
(* ... job arrivals satisfy the sporadic task model, ... *)
Theorem periodic_arrivals_are_sporadic:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Proof.
 unfold sporadic_task_model; move => j j' /eqP DIFF SAMEtsk LE.
 destruct j as [j arr ARR], j' as [j' arr' ARR']; simpl in *.
 rewrite eqE /= /jobin_eqdef negb_and /= in DIFF.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in *.
+ move => j j' /eqP DIFF [arr ARR] [arr' ARR'] SAMEtsk LE.
+ rewrite eqE /= /job_eqdef negb_and /= SAMEtsk eq_refl orbF in DIFF.
rewrite 2!mem_pmap in ARR ARR'.
move: ARR ARR' => /mapP [tsk_j INj SOMEj] /mapP [tsk_j' INj' SOMEj'].
unfold add_job in SOMEj, SOMEj'; desf; simpl in *;
@@ 81,18 +89,11 @@ Module ConcreteArrivalSequence.
rewrite leq_eqVlt in LE; move: LE => /orP [/eqP EQ  LESS].
{
exfalso; move: DIFF => /negP DIFF; apply DIFF.
 by subst; rewrite EQ.
+ by subst; rewrite EQ !eq_refl.
}
subst; rewrite leq_mul2r; apply/orP; right.
by rewrite ltn_mul2r in LESS; move: LESS => /andP [_ LT].
}
 {
 assert (LT: arr < arr'). by rewrite ltn_neqAle; apply/andP.
 clear LE DIFF; subst tsk_j' arr arr'.
 rewrite ltn_mul2r in LT; move: LT => /andP [_ LT].
 by apply leq_trans with (n := k.+1 * task_period tsk_j);
 [by rewrite mulSnr  by rewrite leq_mul2r; apply/orP; right].
 }
Qed.
(* ... and the arrival sequence has no duplicate jobs. *)
diff git a/implementation/global/basic/bertogna_edf_example.v b/implementation/global/basic/bertogna_edf_example.v
index b51f7a0..429dba9 100644
 a/implementation/global/basic/bertogna_edf_example.v
+++ b/implementation/global/basic/bertogna_edf_example.v
@@ 89,12 +89,12 @@ Module ResponseTimeAnalysisEDF.
Let arr_seq := periodic_arrival_sequence ts.
(* Let sched be the workconserving EDF scheduler. *)
 Let sched := scheduler job_cost num_cpus arr_seq
 (JLFP_to_JLDP arr_seq (EDF job_deadline)).
+ Let sched := scheduler job_arrival job_cost num_cpus arr_seq
+ (JLFP_to_JLDP (EDF job_arrival job_deadline)).
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, we prove that ts is schedulable with the result of the test. *)
Corollary ts_is_schedulable:
@@ 106,24 +106,25 @@ Module ResponseTimeAnalysisEDF.
have VALID := periodic_arrivals_valid_job_parameters ts ts_has_valid_parameters.
have TSVALID := ts_has_valid_parameters.
unfold valid_sporadic_job, valid_realtime_job in *; des.
 apply taskset_schedulable_by_edf_rta with (task_cost := task_cost) (task_period := task_period) (task_deadline := task_deadline) (ts0 := ts).
  by apply ts_has_valid_parameters.
+ apply taskset_schedulable_by_edf_rta with (task_cost := task_cost) (task_period := task_period)
+ (task_deadline := task_deadline) (ts0 := ts); try (by done).
 by apply ts_has_constrained_deadlines.
 by apply periodic_arrivals_all_jobs_from_taskset.
  by apply periodic_arrivals_valid_job_parameters, ts_has_valid_parameters.
 by apply periodic_arrivals_are_sporadic.
  by compute.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_must_arrive_to_execute.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_sequential_jobs, periodic_arrivals_is_a_set.
  by apply scheduler_work_conserving.
+  apply scheduler_sequential_jobs.
+  by apply periodic_arrivals_are_consistent.
+  by apply periodic_arrivals_is_a_set.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
 apply scheduler_respects_policy.
  by intro t; apply EDF_is_transitive.
  by intro t; apply EDF_is_total.
+  by apply periodic_arrivals_are_consistent.
+  by intros t; apply RM_is_transitive.
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
  by apply IN.
Qed.
End ExampleRTA.
diff git a/implementation/global/basic/bertogna_fp_example.v b/implementation/global/basic/bertogna_fp_example.v
index cab27b9..9f8378d 100644
 a/implementation/global/basic/bertogna_fp_example.v
+++ b/implementation/global/basic/bertogna_fp_example.v
@@ 103,8 +103,7 @@ Module ResponseTimeAnalysisFP.
Let arr_seq := periodic_arrival_sequence ts.
(* Assume ratemonotonic priorities. *)
 Let higher_priority : JLDP_policy arr_seq :=
 (FP_to_JLDP job_task arr_seq (RM task_period)).
+ Let higher_priority := FP_to_JLDP job_task (RM task_period).
Section FactsAboutPriorityOrder.
@@ 129,11 +128,11 @@ Module ResponseTimeAnalysisFP.
End FactsAboutPriorityOrder.
(* Let sched be the workconserving RM scheduler. *)
 Let sched := scheduler job_cost num_cpus arr_seq higher_priority.
+ Let sched := scheduler job_arrival job_cost num_cpus arr_seq higher_priority.
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, we prove that ts is schedulable with the result of the test. *)
Corollary ts_is_schedulable:
@@ 154,18 +153,19 @@ Module ResponseTimeAnalysisFP.
 by apply RM_is_transitive.
 by apply periodic_arrivals_all_jobs_from_taskset.
 by apply periodic_arrivals_are_sporadic.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_must_arrive_to_execute.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_sequential_jobs, periodic_arrivals_is_a_set.
  by apply scheduler_work_conserving.
+  apply scheduler_sequential_jobs.
+  by apply periodic_arrivals_are_consistent.
+  by apply periodic_arrivals_is_a_set.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
 apply scheduler_respects_policy.
+  by apply periodic_arrivals_are_consistent.
 by intros t; apply RM_is_transitive.
 {
 unfold FP_to_JLDP; intros t x y; apply/orP.
 by apply priority_is_total; rewrite periodic_arrivals_all_jobs_from_taskset.
 }
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
Qed.
diff git a/implementation/global/basic/schedule.v b/implementation/global/basic/schedule.v
index 4a0eecf..ab07158 100644
 a/implementation/global/basic/schedule.v
+++ b/implementation/global/basic/schedule.v
@@ 1,345 +1,264 @@
Require Import rt.util.all.
Require Import rt.model.arrival.basic.job rt.model.arrival.basic.arrival_sequence rt.model.priority.
+Require Import rt.model.priority.
+Require Import rt.model.arrival.basic.job rt.model.arrival.basic.arrival_sequence.
Require Import rt.model.schedule.global.basic.schedule rt.model.schedule.global.basic.platform.
+Require Import rt.model.schedule.global.transformation.construction.
From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat fintype bigop seq path.
Module ConcreteScheduler.
 Import Job ArrivalSequence Schedule Platform Priority.
+ Import ArrivalSequence Schedule Platform Priority ScheduleConstruction.
Section Implementation.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Let num_cpus denote the number of processors, ...*)
Variable num_cpus: nat.
 (* ... and let arr_seq be any arrival sequence.*)
+ (* ... and let arr_seq be any arrival sequence. *)
Variable arr_seq: arrival_sequence Job.
(* Assume a JLDP policy is given. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
 (* Consider the list of pending jobs at time t. *)
 Definition jobs_pending_at (sched: schedule num_cpus arr_seq) (t: time) :=
 [seq j < jobs_arrived_up_to arr_seq t  pending job_cost sched j t].
+ (* Next, we show how to recursively construct the schedule. *)
+ Section ScheduleConstruction.
 (* Next, we sort this list by priority. *)
 Definition sorted_pending_jobs (sched: schedule num_cpus arr_seq) (t: time) :=
 sort (higher_eq_priority t) (jobs_pending_at sched t).
+ (* For any time t, suppose that we have generated the schedule prefix in the
+ interval [0, t). Then, we must define what should be scheduled at time t. *)
+ Variable sched_prefix: schedule Job num_cpus.
+ Variable cpu: processor num_cpus.
+ Variable t: time.
 (* Starting from the empty schedule as a base, ... *)
 Definition empty_schedule : schedule num_cpus arr_seq :=
 fun t cpu => None.
+ (* For simplicity, let's use some local names. *)
+ Let is_pending := pending job_arrival job_cost sched_prefix.
+ Let arrivals := jobs_arrived_up_to arr_seq.
+
+ (* Consider the list of pending jobs at time t, ... *)
+ Definition pending_jobs := [seq j < arrivals t  is_pending j t].
 (* ..., we redefine the mapping of jobs to processors at any time t as follows.
 The ith job in the sorted list is assigned to the ith cpu, or to None
 if the list is short. *)
 Definition update_schedule (prev_sched: schedule num_cpus arr_seq)
 (t_next: time) : schedule num_cpus arr_seq :=
 fun cpu t =>
 if t == t_next then
 nth_or_none (sorted_pending_jobs prev_sched t) cpu
 else prev_sched cpu t.

 (* The schedule is iteratively constructed by applying assign_jobs at every time t, ... *)
 Fixpoint schedule_prefix (t_max: time) : schedule num_cpus arr_seq :=
 if t_max is t_prev.+1 then
 (* At time t_prev + 1, schedule jobs that have not completed by time t_prev. *)
 update_schedule (schedule_prefix t_prev) t_prev.+1
 else
 (* At time 0, schedule any jobs that arrive. *)
 update_schedule empty_schedule 0.
+ (* ...which we sort by priority. *)
+ Definition sorted_pending_jobs :=
+ sort (higher_eq_priority t) pending_jobs.
+
+ (* Then, we take the nth highestpriority job from the list. *)
+ Definition nth_highest_priority_job :=
+ nth_or_none sorted_pending_jobs cpu.
+
+ End ScheduleConstruction.
 Definition scheduler (cpu: processor num_cpus) (t: time) := (schedule_prefix t) cpu t.
+ (* Starting from the empty schedule, the final schedule is obtained by iteratively
+ picking the highestpriority job. *)
+ Let empty_schedule : schedule Job num_cpus := fun cpu t => None.
+ Definition scheduler :=
+ build_schedule_from_prefixes num_cpus nth_highest_priority_job empty_schedule.
+ (* Then, by showing that the construction function depends only on the prefix, ... *)
+ Lemma scheduler_depends_only_on_prefix:
+ forall sched1 sched2 cpu t,
+ (forall t0 cpu0, t0 < t > sched1 cpu0 t0 = sched2 cpu0 t0) >
+ nth_highest_priority_job sched1 cpu t = nth_highest_priority_job sched2 cpu t.
+ Proof.
+ intros sched1 sched2 cpu t ALL.
+ rewrite /nth_highest_priority_job.
+ suff SAME: sorted_pending_jobs sched1 t = sorted_pending_jobs sched2 t by rewrite SAME.
+ rewrite /sorted_pending_jobs; f_equal.
+ apply eq_in_filter.
+ intros j ARR.
+ rewrite /pending; do 2 f_equal.
+ rewrite /completed; f_equal.
+ apply eq_big_nat; move => i /= LTi.
+ rewrite /service_at /scheduled_on; apply eq_bigl; move => cpu'.
+ by rewrite ALL.
+ Qed.
+
+ (* ...we infer that the generated schedule is indeed based on the construction function. *)
+ Corollary scheduler_uses_construction_function:
+ forall t cpu, scheduler cpu t = nth_highest_priority_job scheduler cpu t.
+ Proof.
+ by ins; apply prefix_dependent_schedule_construction,
+ scheduler_depends_only_on_prefix.
+ Qed.
+
End Implementation.
Section Proofs.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Assume a positive number of processors. *)
Variable num_cpus: nat.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
 (* Let arr_seq be any arrival sequence of jobs where ...*)
+ (* Let arr_seq be any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
 (* ...jobs have positive cost and...*)
 Hypothesis H_job_cost_positive:
 forall (j: JobIn arr_seq), job_cost_positive job_cost j.
 (* ... at any time, there are no duplicates of the same job. *)
 Hypothesis H_arrival_sequence_is_a_set :
 arrival_sequence_is_a_set arr_seq.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
(* Consider any JLDP policy higher_eq_priority that is transitive and total. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
 Hypothesis H_priority_transitive: forall t, transitive (higher_eq_priority t).
+ Variable higher_eq_priority: JLDP_policy Job.
+ Hypothesis H_priority_transitive: JLDP_is_transitive higher_eq_priority.
Hypothesis H_priority_total: forall t, total (higher_eq_priority t).
(* Let sched denote our concrete scheduler implementation. *)
 Let sched := scheduler job_cost num_cpus arr_seq higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost num_cpus arr_seq higher_eq_priority.
(* Next, we provide some helper lemmas about the scheduler construction. *)
Section HelperLemmas.
 (* Let's use a shorter name for the schedule prefix function. *)
 Let sched_prefix := schedule_prefix job_cost num_cpus arr_seq higher_eq_priority.

 (* First, we show that the scheduler preserves its prefixes. *)
 Lemma scheduler_same_prefix :
 forall t t_max cpu,
 t <= t_max >
 sched_prefix t_max cpu t = sched cpu t.
 Proof.
 intros t t_max cpu LEt.
 induction t_max.
 {
 by rewrite leqn0 in LEt; move: LEt => /eqP EQ; subst.
 }
 {
 rewrite leq_eqVlt in LEt.
 move: LEt => /orP [/eqP EQ  LESS]; first by subst.
 {
 feed IHt_max; first by done.
 unfold sched_prefix, schedule_prefix, update_schedule at 1.
 assert (FALSE: t == t_max.+1 = false).
 {
 by apply negbTE; rewrite neq_ltn LESS orTb.
 } rewrite FALSE.
 by rewrite IHt_max.
 }
 }
 Qed.

 (* With respect to the sorted list of pending jobs, ...*)
 Let sorted_jobs (t: time) :=
 sorted_pending_jobs job_cost num_cpus arr_seq higher_eq_priority sched t.
+ Let sorted_jobs :=
+ sorted_pending_jobs job_arrival job_cost num_cpus arr_seq higher_eq_priority sched.
 (* ..., we show that a job is mapped to a processor based on that list, ... *)
 Lemma scheduler_nth_or_none_mapping :
 forall t cpu x,
 sched cpu t = x >
 nth_or_none (sorted_jobs t) cpu = x.
+ (* First, we recall that the schedule picks the nth highestpriority job. *)
+ Corollary scheduler_nth_or_none_mapping :
+ forall t cpu,
+ sched cpu t = nth_or_none (sorted_jobs t) cpu.
Proof.
 intros t cpu x SCHED.
 unfold sched, scheduler, schedule_prefix in *.
 destruct t.
 {
 unfold update_schedule in SCHED; rewrite eq_refl in SCHED.
 rewrite SCHED; f_equal.
 unfold sorted_jobs, sorted_pending_jobs; f_equal.
 unfold jobs_pending_at; apply eq_filter; red; intro j'.
 unfold pending; f_equal; f_equal.
 unfold completed, service.
 by rewrite big_geq // big_geq //.
 }
 {
 unfold update_schedule at 1 in SCHED; rewrite eq_refl in SCHED.
 rewrite SCHED; f_equal.
 unfold sorted_jobs, sorted_pending_jobs; f_equal.
 unfold jobs_pending_at; apply eq_filter; red; intro j'.
 unfold pending; f_equal; f_equal.
 unfold completed, service; f_equal.
 apply eq_big_nat; move => t0 /andP [_ LT].
 unfold service_at; apply eq_bigl; red; intros cpu'.
 fold (schedule_prefix job_cost num_cpus arr_seq higher_eq_priority).
 have SAME := scheduler_same_prefix; unfold sched_prefix, sched in *.
 rewrite /scheduled_on; f_equal; unfold schedule_prefix.
 by rewrite SAME // ?leqnn.
 }
+ intros t cpu.
+ by rewrite /sched scheduler_uses_construction_function.
Qed.
 (* ..., a scheduled job is mapped to a cpu corresponding to its position, ... *)
 Lemma scheduler_nth_or_none_scheduled :
 forall j t,
 scheduled sched j t >
 exists (cpu: processor num_cpus),
 nth_or_none (sorted_jobs t) cpu = Some j.
 Proof.
 intros j t SCHED.
 move: SCHED => /existsP [cpu /eqP SCHED]; exists cpu.
 by apply scheduler_nth_or_none_mapping.
 Qed.

 (* ..., and that a backlogged job has a position larger than or equal to the number
+ (* We also prove that a backlogged job has priority larger than or equal to the number
of processors. *)
Lemma scheduler_nth_or_none_backlogged :
forall j t,
 backlogged job_cost sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
exists i,
nth_or_none (sorted_jobs t) i = Some j /\ i >= num_cpus.
Proof.
 have SAME := scheduler_same_prefix.
 intros j t BACK.
+ intros j t ARRj BACK.
move: BACK => /andP [PENDING /negP NOTCOMP].
assert (IN: j \in sorted_jobs t).
{
rewrite mem_sort mem_filter PENDING andTb.
move: PENDING => /andP [ARRIVED _].
 by rewrite JobIn_arrived.
+ by apply arrived_between_implies_in_arrivals with (job_arrival0 := job_arrival).
}
apply nth_or_none_mem_exists in IN; des.
exists n; split; first by done.
rewrite leqNgt; apply/negP; red; intro LT.
apply NOTCOMP; clear NOTCOMP PENDING.
apply/existsP; exists (Ordinal LT); apply/eqP.
 unfold sorted_jobs in *; clear sorted_jobs.
 unfold sched, scheduler, schedule_prefix in *; clear sched.
 destruct t.
 {
 unfold update_schedule; rewrite eq_refl.
 rewrite IN; f_equal.
 fold (schedule_prefix job_cost num_cpus arr_seq higher_eq_priority).
 unfold sorted_pending_jobs; f_equal.
 apply eq_filter; red; intros x.
 unfold pending; f_equal; f_equal.
 unfold completed; f_equal.
 by unfold service; rewrite 2?big_geq //.
 }
 {
 unfold update_schedule at 1; rewrite eq_refl.
 rewrite IN; f_equal.
 unfold sorted_pending_jobs; f_equal.
 apply eq_filter; red; intros x.
 unfold pending; f_equal; f_equal.
 unfold completed; f_equal.
 unfold service; apply eq_big_nat; move => i /andP [_ LTi].
 unfold service_at; apply eq_bigl; red; intro cpu.
 unfold scheduled_on; f_equal.
 fold (schedule_prefix job_cost num_cpus arr_seq higher_eq_priority).
 unfold sched_prefix in *.
 by rewrite /schedule_prefix SAME.
 }
+ by rewrite scheduler_nth_or_none_mapping.
Qed.
End HelperLemmas.
 (* Now, we prove the important properties about the implementation. *)

 (* Jobs do not execute before they arrive, ...*)
 Theorem scheduler_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
 Proof.
 unfold jobs_must_arrive_to_execute.
 intros j t SCHED.
 move: SCHED => /existsP [cpu /eqP SCHED].
 unfold sched, scheduler, schedule_prefix in SCHED.
 destruct t.
 {
 rewrite /update_schedule eq_refl in SCHED.
 apply (nth_or_none_mem _ cpu j) in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 move: SCHED => /andP [_ ARR].
 by apply JobIn_arrived in ARR.
 }
 {
 unfold update_schedule at 1 in SCHED; rewrite eq_refl /= in SCHED.
 apply (nth_or_none_mem _ cpu j) in SCHED.
+ (* First, we show that scheduled jobs come from the arrival sequence. *)
+ Lemma scheduler_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+ Proof.
+ move => j t /existsP [cpu /eqP SCHED].
+ rewrite scheduler_nth_or_none_mapping in SCHED.
+ apply nth_or_none_mem in SCHED.
rewrite mem_sort mem_filter in SCHED.
move: SCHED => /andP [_ ARR].
 by apply JobIn_arrived in ARR.
 }
+ rewrite /jobs_arrived_up_to in ARR.
+ by eapply in_arrivals_implies_arrived; eauto 1.
+ Qed.
+
+ (* Next, we show that jobs do not execute before their arrival times... *)
+ Theorem scheduler_jobs_must_arrive_to_execute:
+ jobs_must_arrive_to_execute job_arrival sched.
+ Proof.
+ move => j t /existsP [cpu /eqP SCHED].
+ rewrite scheduler_nth_or_none_mapping in SCHED.
+ apply nth_or_none_mem in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ by move: SCHED => /andP [/andP [ARR _] _].
Qed.
 (* ..., jobs are sequential, ... *)
+ (* ...jobs are sequential, ... *)
Theorem scheduler_sequential_jobs: sequential_jobs sched.
Proof.
 unfold sequential_jobs, sched, scheduler, schedule_prefix.
intros j t cpu1 cpu2 SCHED1 SCHED2.
 destruct t; rewrite /update_schedule eq_refl in SCHED1 SCHED2;
 have UNIQ := nth_or_none_uniq _ cpu1 cpu2 j _ SCHED1 SCHED2; (apply ord_inj, UNIQ);
 rewrite sort_uniq filter_uniq //;
 by apply JobIn_uniq.
+ rewrite 2!scheduler_nth_or_none_mapping in SCHED1 SCHED2.
+ set l := sorted_pending_jobs _ _ _ _ _ _ _ in SCHED1 SCHED2.
+ apply ord_inj, nth_or_none_uniq with (l0 := l) (x := j); try (by done).
+ by rewrite sort_uniq filter_uniq //; eapply arrivals_uniq; eauto 1.
Qed.

+
(* ... and jobs do not execute after completion. *)
Theorem scheduler_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
Proof.
 rename H_job_cost_positive into GT0.
 unfold completed_jobs_dont_execute, service.
intros j t.
 induction t; first by rewrite big_geq.
+ induction t;
+ first by rewrite /service /service_during big_geq //.
+ rewrite /service /service_during big_nat_recr //=.
+ rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LT]; last first.
{
 rewrite big_nat_recr // /=.
 rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LESS]; last first.
 {
 destruct (job_cost j); first by rewrite ltn0 in LESS.
 rewrite addn1; rewrite ltnS in LESS.
 apply leq_add; first by done.
 by apply service_at_most_one, scheduler_sequential_jobs.
 }
 rewrite EQ {2}[job_cost j]addn0; apply leq_add; first by done.
 destruct t.
+ apply: leq_trans LT; rewrite addn1.
+ apply leq_add; first by done.
+ rewrite /service_at.
+ case (boolP ([exists cpu, scheduled_on sched j cpu t])) => [EX  ALL]; last first.
{
 rewrite big_geq // in EQ.
 specialize (GT0 j); unfold job_cost_positive in *.
 by rewrite EQ ltn0 in GT0.
 }
 {
 unfold service_at; rewrite big_mkcond.
 apply leq_trans with (n := \sum_(cpu < num_cpus) 0);
 last by rewrite big_const_ord iter_addn mul0n addn0.
 apply leq_sum; intros cpu _; desf.
 move: Heq => /eqP SCHED.
 unfold scheduler, schedule_prefix in SCHED.
 unfold sched, scheduler, schedule_prefix, update_schedule at 1 in SCHED.
 rewrite eq_refl in SCHED.
 apply (nth_or_none_mem _ cpu j) in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 fold (update_schedule job_cost num_cpus arr_seq higher_eq_priority) in SCHED.
 move: SCHED => /andP [/andP [_ /negP NOTCOMP] _].
 exfalso; apply NOTCOMP; clear NOTCOMP.
 unfold completed; apply/eqP.
 unfold service; rewrite EQ.
 rewrite big_nat_cond [\sum_(_ <= _ < _  true)_]big_nat_cond.
 apply eq_bigr; move => i /andP [/andP [_ LT] _].
 apply eq_bigl; red; ins.
 unfold scheduled_on; f_equal.
 fold (schedule_prefix job_cost num_cpus arr_seq higher_eq_priority).
 by rewrite scheduler_same_prefix.
+ rewrite negb_exists in ALL; move: ALL => /forallP ALL.
+ rewrite big1 //; intros cpu SCHED.
+ by specialize (ALL cpu); rewrite SCHED in ALL.
}
+ move: EX => /existsP [cpu SCHED].
+ rewrite (bigD1 cpu) /=; last by done.
+ rewrite big1; first by rewrite addn0.
+ move => cpu' /andP [SCHED' NEQ].
+ move: NEQ => /eqP NEQ; exfalso; apply NEQ, ord_inj.
+ move: SCHED SCHED' => /eqP SCHED /eqP SCHED'.
+ rewrite 2!scheduler_nth_or_none_mapping in SCHED SCHED'.
+ set l := sorted_pending_jobs _ _ _ _ _ _ _ in SCHED SCHED'.
+ apply nth_or_none_uniq with (l0 := l) (x := j); try (by done).
+ by rewrite sort_uniq filter_uniq //; eapply arrivals_uniq; eauto 1.
}
+ rewrite [job_cost _]addn0; apply leq_add; first by rewrite EQ.
+ rewrite leqn0 /service_at big1 // /scheduled_on.
+ move => cpu /eqP SCHED.
+ rewrite scheduler_nth_or_none_mapping in SCHED.
+ apply nth_or_none_mem in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ move: SCHED => /andP [/andP [_ NOTCOMP] _].
+ by rewrite /completed EQ eq_refl in NOTCOMP.
Qed.

 (* In addition, the scheduler is work conserving ... *)
+
+ (* In addition, the scheduler is work conserving, ... *)
Theorem scheduler_work_conserving:
 work_conserving job_cost sched.
+ work_conserving job_arrival job_cost arr_seq sched.
Proof.
 unfold work_conserving; intros j t BACK cpu.
 set jobs := sorted_pending_jobs job_cost num_cpus arr_seq higher_eq_priority sched t.
 destruct (sched cpu t) eqn:SCHED; first by exists j0; apply/eqP.
 apply scheduler_nth_or_none_backlogged in BACK.
+ intros j t ARRj BACK cpu.
+ set jobs := sorted_pending_jobs job_arrival job_cost num_cpus arr_seq higher_eq_priority sched t.
+ destruct (sched cpu t) as [j0 ] eqn:SCHED; first by exists j0; apply/eqP.
+ apply scheduler_nth_or_none_backlogged in BACK; last by done.
destruct BACK as [cpu_out [NTH GE]].
exfalso; rewrite leqNgt in GE; move: GE => /negP GE; apply GE.
apply leq_ltn_trans with (n := cpu); last by done.
 apply scheduler_nth_or_none_mapping in SCHED.
+ rewrite scheduler_nth_or_none_mapping in SCHED.
apply nth_or_none_size_none in SCHED.
apply leq_trans with (n := size jobs); last by done.
by apply nth_or_none_size_some in NTH; apply ltnW.
Qed.
 (* ... and respects the JLDP policy. *)
+ (* ...and respects the JLDP policy. *)
Theorem scheduler_respects_policy :
 respects_JLDP_policy job_cost sched higher_eq_priority.
+ respects_JLDP_policy job_arrival job_cost arr_seq sched higher_eq_priority.
Proof.
 unfold respects_JLDP_policy; intros j j_hp t BACK SCHED.
 set jobs := sorted_pending_jobs job_cost num_cpus arr_seq higher_eq_priority sched t.
 apply scheduler_nth_or_none_backlogged in BACK.
+ move => j j_hp t ARRj BACK /existsP [cpu /eqP SCHED].
+ apply scheduler_nth_or_none_backlogged in BACK; last by done.
+ set jobs := sorted_pending_jobs _ _ _ _ _ _ _ in BACK.
destruct BACK as [cpu_out [SOME GE]].
 apply scheduler_nth_or_none_scheduled in SCHED.
 destruct SCHED as [cpu SCHED].
+ rewrite scheduler_nth_or_none_mapping in SCHED.
have EQ1 := nth_or_none_nth jobs cpu j_hp j SCHED.
have EQ2 := nth_or_none_nth jobs cpu_out j j SOME.
rewrite EQ1 {2}EQ2.
 apply sorted_lt_idx_implies_rel; [by done  by apply sort_sorted  ].
+ apply sorted_lt_idx_implies_rel; try (by done); last 2 first.
 by apply leq_trans with (n := num_cpus).
 by apply nth_or_none_size_some in SOME.
+  by apply sort_sorted, H_priority_total.
Qed.
End Proofs.

+
End ConcreteScheduler.
\ No newline at end of file
diff git a/implementation/global/jitter/arrival_sequence.v b/implementation/global/jitter/arrival_sequence.v
index 045cc97..dd34d7a 100644
 a/implementation/global/jitter/arrival_sequence.v
+++ b/implementation/global/jitter/arrival_sequence.v
@@ 14,9 +14,9 @@ Module ConcreteArrivalSequence.
(* At any time t, we release Some job of tsk if t is a multiple of the period,
otherwise we release None. *)
 Definition add_job (t: time) (tsk: concrete_task) :=
 if task_period tsk % t then
 Some (Build_concrete_job (t %/ task_period tsk) (task_cost tsk) (task_deadline tsk) (task_jitter tsk) tsk)
+ Definition add_job (arr: time) (tsk: concrete_task) :=
+ if task_period tsk % arr then
+ Some (Build_concrete_job (arr %/ task_period tsk) arr (task_cost tsk) (task_deadline tsk) (task_jitter tsk) tsk)
else
None.
@@ 35,14 +35,23 @@ Module ConcreteArrivalSequence.
(* Regarding the periodic arrival sequence built from ts, we prove that...*)
Let arr_seq := periodic_arrival_sequence ts.
+ (* ... arrival times are consistent, ... *)
+ Theorem periodic_arrivals_are_consistent:
+ arrival_times_are_consistent job_arrival arr_seq.
+ Proof.
+ move => j t ARRj.
+ rewrite /arrives_at mem_pmap in ARRj.
+ move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
+ by unfold add_job in *; desf.
+ Qed.
+
(* ... every job comes from the task set, ... *)
Theorem periodic_arrivals_all_jobs_from_taskset:
 forall (j: JobIn arr_seq),
 job_task (job_of_job_in j) \in ts. (* TODO: fix coercion *)
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
Proof.
 intros j.
 destruct j as [j arr ARRj]; simpl.
 unfold arr_seq, arrives_at, periodic_arrival_sequence in *.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj.
move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
by unfold add_job in *; desf.
@@ 50,13 +59,13 @@ Module ConcreteArrivalSequence.
(* ..., jobs have valid parameters, ... *)
Theorem periodic_arrivals_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job_with_jitter task_cost task_deadline task_jitter job_cost job_deadline job_task job_jitter j.
Proof.
rename H_valid_task_parameters into PARAMS.
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
 intros j; destruct j as [j arr ARRj]; simpl.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in ARRj.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj; move: ARRj => /mapP [tsk IN SOME].
unfold add_job in SOME; desf.
specialize (PARAMS tsk IN); des.
@@ 66,12 +75,10 @@ Module ConcreteArrivalSequence.
(* ... job arrivals satisfy the sporadic task model, ... *)
Theorem periodic_arrivals_are_sporadic:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Proof.
 unfold sporadic_task_model; move => j j' /eqP DIFF SAMEtsk LE.
 destruct j as [j arr ARR], j' as [j' arr' ARR']; simpl in *.
 rewrite eqE /= /jobin_eqdef negb_and /= in DIFF.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in *.
+ move => j j' /eqP DIFF [arr ARR] [arr' ARR'] SAMEtsk LE.
+ rewrite eqE /= /job_eqdef negb_and /= SAMEtsk eq_refl orbF in DIFF.
rewrite 2!mem_pmap in ARR ARR'.
move: ARR ARR' => /mapP [tsk_j INj SOMEj] /mapP [tsk_j' INj' SOMEj'].
unfold add_job in SOMEj, SOMEj'; desf; simpl in *;
@@ 81,18 +88,11 @@ Module ConcreteArrivalSequence.
rewrite leq_eqVlt in LE; move: LE => /orP [/eqP EQ  LESS].
{
exfalso; move: DIFF => /negP DIFF; apply DIFF.
 by subst; rewrite EQ.
+ by subst; rewrite EQ !eq_refl.
}
subst; rewrite leq_mul2r; apply/orP; right.
by rewrite ltn_mul2r in LESS; move: LESS => /andP [_ LT].
}
 {
 assert (LT: arr < arr'). by rewrite ltn_neqAle; apply/andP.
 clear LE DIFF; subst tsk_j' arr arr'.
 rewrite ltn_mul2r in LT; move: LT => /andP [_ LT].
 by apply leq_trans with (n := k.+1 * task_period tsk_j);
 [by rewrite mulSnr  by rewrite leq_mul2r; apply/orP; right].
 }
Qed.
(* ... and the arrival sequence has no duplicate jobs. *)
diff git a/implementation/global/jitter/bertogna_edf_example.v b/implementation/global/jitter/bertogna_edf_example.v
index 57bace7..05eb722 100644
 a/implementation/global/jitter/bertogna_edf_example.v
+++ b/implementation/global/jitter/bertogna_edf_example.v
@@ 92,12 +92,12 @@ Module ResponseTimeAnalysisEDF.
Let arr_seq := periodic_arrival_sequence ts.
(* Let sched be the workconserving EDF scheduler. *)
 Let sched := scheduler job_cost job_jitter num_cpus arr_seq
 (JLFP_to_JLDP arr_seq (EDF job_deadline)).
+ Let sched := scheduler job_arrival job_cost job_jitter num_cpus arr_seq
+ (JLFP_to_JLDP (EDF job_arrival job_deadline)).
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, we prove that ts is schedulable with the result of the test. *)
Corollary ts_is_schedulable:
@@ 110,24 +110,26 @@ Module ResponseTimeAnalysisEDF.
have VALIDTS := ts_has_valid_parameters.
unfold valid_sporadic_job_with_jitter,
valid_sporadic_job, valid_realtime_job in *; des.
 apply taskset_schedulable_by_edf_rta with (task_cost := task_cost) (task_period := task_period) (task_deadline := task_deadline) (ts0 := ts) (task_jitter := task_jitter) (job_jitter := job_jitter).
  by apply ts_has_valid_parameters.
+ apply taskset_schedulable_by_edf_rta with (task_cost := task_cost) (task_period := task_period)
+ (task_deadline := task_deadline) (ts0 := ts) (task_jitter := task_jitter)
+ (job_jitter := job_jitter); try (by done).
 by apply ts_has_constrained_deadlines.
  by apply periodic_arrivals_all_jobs_from_taskset.
  by apply periodic_arrivals_valid_job_parameters, ts_has_valid_parameters.
+  by apply periodic_arrivals_all_jobs_from_taskset.
 by apply periodic_arrivals_are_sporadic.
  by compute.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_execute_after_jitter.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_sequential_jobs, periodic_arrivals_is_a_set.
  by apply scheduler_work_conserving.
+  apply scheduler_sequential_jobs.
+  by apply periodic_arrivals_are_consistent.
+  by apply periodic_arrivals_is_a_set.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
 apply scheduler_respects_policy.
  by intros t; apply EDF_is_transitive.
  by intros t; apply EDF_is_total.
+  by apply periodic_arrivals_are_consistent.
+  by intros t; apply RM_is_transitive.
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
  by apply IN.
Qed.
End ExampleRTA.
diff git a/implementation/global/jitter/bertogna_fp_example.v b/implementation/global/jitter/bertogna_fp_example.v
index 9672000..eca5d05 100644
 a/implementation/global/jitter/bertogna_fp_example.v
+++ b/implementation/global/jitter/bertogna_fp_example.v
@@ 106,8 +106,7 @@ Module ResponseTimeAnalysisFP.
Let arr_seq := periodic_arrival_sequence ts.
(* Assume ratemonotonic priorities. *)
 Let higher_priority : JLDP_policy arr_seq :=
 (FP_to_JLDP job_task arr_seq (RM task_period)).
+ Let higher_priority := FP_to_JLDP job_task (RM task_period).
Section FactsAboutPriorityOrder.
@@ 132,11 +131,11 @@ Module ResponseTimeAnalysisFP.
End FactsAboutPriorityOrder.
(* Let sched be the workconserving RM scheduler. *)
 Let sched := scheduler job_cost job_jitter num_cpus arr_seq higher_priority.
+ Let sched := scheduler job_arrival job_cost job_jitter num_cpus arr_seq higher_priority.
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, we prove that ts is schedulable with the result of the test. *)
Corollary ts_is_schedulable:
@@ 158,18 +157,19 @@ Module ResponseTimeAnalysisFP.
 by apply RM_is_transitive.
 by apply periodic_arrivals_all_jobs_from_taskset.
 by apply periodic_arrivals_are_sporadic.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_execute_after_jitter.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_sequential_jobs, periodic_arrivals_is_a_set.
  by apply scheduler_work_conserving.
+  apply scheduler_sequential_jobs.
+  by apply periodic_arrivals_are_consistent.
+  by apply periodic_arrivals_is_a_set.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
 apply scheduler_respects_policy.
+  by apply periodic_arrivals_are_consistent.
 by intros t; apply RM_is_transitive.
 {
 unfold FP_to_JLDP; intros t x y; apply/orP.
 by apply priority_is_total; rewrite periodic_arrivals_all_jobs_from_taskset.
 }
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
Qed.
diff git a/implementation/global/jitter/job.v b/implementation/global/jitter/job.v
index abe5e30..e60a33c 100644
 a/implementation/global/jitter/job.v
+++ b/implementation/global/jitter/job.v
@@ 12,6 +12,7 @@ Module ConcreteJob.
Record concrete_job :=
{
job_id: nat;
+ job_arrival: nat;
job_cost: nat;
job_deadline: nat;
job_jitter: nat;
@@ 22,6 +23,7 @@ Module ConcreteJob.
equality for concrete jobs. *)
Definition job_eqdef (j1 j2: concrete_job) :=
(job_id j1 == job_id j2) &&
+ (job_arrival j1 == job_arrival j2) &&
(job_cost j1 == job_cost j2) &&
(job_deadline j1 == job_deadline j2) &&
(job_jitter j1 == job_jitter j2) &&
@@ 34,7 +36,7 @@ Module ConcreteJob.
destruct (job_eqdef x y) eqn:EQ.
{
apply ReflectT; unfold job_eqdef in *.
 move: EQ => /andP [/andP [/andP [/andP [/eqP ID /eqP COST] /eqP DL] /eqP JITTER] /eqP TASK].
+ move: EQ => /andP [/andP [/andP [/andP [/andP [/eqP ID /eqP ARRIVAL] /eqP COST] /eqP DL] /eqP JITTER] /eqP TASK].
by destruct x, y; simpl in *; subst.
}
{
@@ 48,7 +50,9 @@ Module ConcreteJob.
rewrite negb_and in EQ.
move: EQ => /orP [EQ  /eqP DL]; last by apply DL; inversion BUG.
rewrite negb_and in EQ.
 move: EQ => /orP [/eqP ID  /eqP COST]; last by apply COST; inversion BUG.
+ move: EQ => /orP [EQ  /eqP ID]; last by apply ID; inversion BUG.
+ rewrite negb_and in EQ.
+ move: EQ => /orP [/eqP ID  /eqP ARRIVAL]; last by apply ARRIVAL; inversion BUG.
by apply ID; inversion BUG.
}
Qed.
diff git a/implementation/global/jitter/schedule.v b/implementation/global/jitter/schedule.v
index 66daf7b..eb8c0cc 100644
 a/implementation/global/jitter/schedule.v
+++ b/implementation/global/jitter/schedule.v
@@ 1,66 +1,96 @@
Require Import rt.util.all.
Require Import rt.model.arrival.basic.arrival_sequence rt.model.priority.
Require Import rt.model.schedule.global.jitter.job rt.model.schedule.global.jitter.schedule
+Require Import rt.model.arrival.jitter.arrival_sequence rt.model.priority.
+Require Import rt.model.schedule.global.jitter.schedule
rt.model.schedule.global.jitter.platform.
+Require Import rt.model.schedule.global.transformation.construction.
From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat fintype bigop seq path.
Module ConcreteScheduler.
 Import Job ArrivalSequence ScheduleWithJitter Platform Priority.
+ Import ArrivalSequenceWithJitter ScheduleWithJitter Platform Priority ScheduleConstruction.
Section Implementation.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
(* Let num_cpus denote the number of processors, ...*)
Variable num_cpus: nat.
 (* ... and let arr_seq be any arrival sequence.*)
+ (* ...and let arr_seq be any job arrival sequence.*)
Variable arr_seq: arrival_sequence Job.
(* Assume a JLDP policy is given. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
 (* Consider the list of pending jobs at time t. *)
 Definition jobs_pending_at (sched: schedule num_cpus arr_seq) (t: time) :=
 [seq j < jobs_arrived_up_to arr_seq t  pending job_cost job_jitter sched j t].
+ (* Next, we show how to recursively construct the schedule. *)
+ Section ScheduleConstruction.
 (* Next, we sort this list by priority. *)
 Definition sorted_pending_jobs (sched: schedule num_cpus arr_seq) (t: time) :=
 sort (higher_eq_priority t) (jobs_pending_at sched t).
+ (* For any time t, suppose that we have generated the schedule prefix in the
+ interval [0, t). Then, we must define what should be scheduled at time t. *)
+ Variable sched_prefix: schedule Job num_cpus.
+ Variable cpu: processor num_cpus.
+ Variable t: time.
 (* Starting from the empty schedule as a base, ... *)
 Definition empty_schedule : schedule num_cpus arr_seq :=
 fun t cpu => None.
+ (* For simplicity, let's use some local names. *)
+ Let is_pending := pending job_arrival job_cost job_jitter sched_prefix.
+ Let actual_arrivals := actual_arrivals_up_to job_arrival job_jitter arr_seq.
+
+ (* Consider the list of pending jobs at time t, ... *)
+ Definition pending_jobs :=
+ [seq j < actual_arrivals t  is_pending j t].
 (* ..., we redefine the mapping of jobs to processors at any time t as follows.
 The ith job in the sorted list is assigned to the ith cpu, or to None
 if the list is short. *)
 Definition update_schedule (prev_sched: schedule num_cpus arr_seq)
 (t_next: time) : schedule num_cpus arr_seq :=
 fun cpu t =>
 if t == t_next then
 nth_or_none (sorted_pending_jobs prev_sched t) cpu
 else prev_sched cpu t.

 (* The schedule is iteratively constructed by applying assign_jobs at every time t, ... *)
 Fixpoint schedule_prefix (t_max: time) : schedule num_cpus arr_seq :=
 if t_max is t_prev.+1 then
 (* At time t_prev + 1, schedule jobs that have not completed by time t_prev. *)
 update_schedule (schedule_prefix t_prev) t_prev.+1
 else
 (* At time 0, schedule any jobs that arrive. *)
 update_schedule empty_schedule 0.
+ (* ...which we sort by priority. *)
+ Definition sorted_pending_jobs :=
+ sort (higher_eq_priority t) pending_jobs.
+
+ (* Then, we take the nth highestpriority job from the list. *)
+ Definition nth_highest_priority_job :=
+ nth_or_none sorted_pending_jobs cpu.
+
+ End ScheduleConstruction.
 Definition scheduler (cpu: processor num_cpus) (t: time) := (schedule_prefix t) cpu t.
+ (* Starting from the empty schedule, the final schedule is obtained by iteratively
+ picking the highestpriority job. *)
+ Let empty_schedule : schedule Job num_cpus := fun cpu t => None.
+ Definition scheduler :=
+ build_schedule_from_prefixes num_cpus nth_highest_priority_job empty_schedule.
+ (* Then, by showing that the construction function depends only on the prefix, ... *)
+ Lemma scheduler_depends_only_on_prefix:
+ forall sched1 sched2 cpu t,
+ (forall t0 cpu0, t0 < t > sched1 cpu0 t0 = sched2 cpu0 t0) >
+ nth_highest_priority_job sched1 cpu t = nth_highest_priority_job sched2 cpu t.
+ Proof.
+ intros sched1 sched2 cpu t ALL.
+ rewrite /nth_highest_priority_job.
+ suff SAME: sorted_pending_jobs sched1 t = sorted_pending_jobs sched2 t by rewrite SAME.
+ rewrite /sorted_pending_jobs; f_equal.
+ apply eq_in_filter.
+ intros j ARR.
+ rewrite /pending; do 2 f_equal.
+ rewrite /completed; f_equal.
+ apply eq_big_nat; move => i /= LTi.
+ rewrite /service_at /scheduled_on; apply eq_bigl; move => cpu'.
+ by rewrite ALL.
+ Qed.
+
+ (* ...we infer that the generated schedule is indeed based on the construction function. *)
+ Corollary scheduler_uses_construction_function:
+ forall t cpu, scheduler cpu t = nth_highest_priority_job scheduler cpu t.
+ Proof.
+ by ins; apply prefix_dependent_schedule_construction,
+ scheduler_depends_only_on_prefix.
+ Qed.
+
End Implementation.
Section Proofs.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
@@ 68,278 +98,171 @@ Module ConcreteScheduler.
Variable num_cpus: nat.
Hypothesis H_at_least_one_cpu: num_cpus > 0.
 (* Let arr_seq be any arrival sequence of jobs where ...*)
+ (* Let arr_seq be any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
 (* ...jobs have positive cost and...*)
 Hypothesis H_job_cost_positive:
 forall (j: JobIn arr_seq), job_cost_positive job_cost j.
 (* ... at any time, there are no duplicates of the same job. *)
 Hypothesis H_arrival_sequence_is_a_set :
 arrival_sequence_is_a_set arr_seq.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
(* Consider any JLDP policy higher_eq_priority that is transitive and total. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
 Hypothesis H_priority_transitive: forall t, transitive (higher_eq_priority t).
+ Variable higher_eq_priority: JLDP_policy Job.
+ Hypothesis H_priority_transitive: JLDP_is_transitive higher_eq_priority.
Hypothesis H_priority_total: forall t, total (higher_eq_priority t).
(* Let sched denote our concrete scheduler implementation. *)
 Let sched := scheduler job_cost job_jitter num_cpus arr_seq higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost job_jitter num_cpus arr_seq higher_eq_priority.
(* Next, we provide some helper lemmas about the scheduler construction. *)
Section HelperLemmas.
 (* Let's use a shorter name for the schedule prefix function. *)
 Let sched_prefix := schedule_prefix job_cost job_jitter num_cpus arr_seq higher_eq_priority.

 (* First, we show that the scheduler preserves its prefixes. *)
 Lemma scheduler_same_prefix :
 forall t t_max cpu,
 t <= t_max >
 sched_prefix t_max cpu t = sched cpu t.
 Proof.
 intros t t_max cpu LEt.
 induction t_max.
 {
 by rewrite leqn0 in LEt; move: LEt => /eqP EQ; subst.
 }
 {
 rewrite leq_eqVlt in LEt.
 move: LEt => /orP [/eqP EQ  LESS]; first by subst.
 {
 feed IHt_max; first by done.
 unfold sched_prefix, schedule_prefix, update_schedule at 1.
 assert (FALSE: t == t_max.+1 = false).
 {
 by apply negbTE; rewrite neq_ltn LESS orTb.
 } rewrite FALSE.
 by rewrite IHt_max.
 }
 }
 Qed.

 (* With respect to the sorted list of pending jobs, ...*)
 Let sorted_jobs (t: time) :=
 sorted_pending_jobs job_cost job_jitter num_cpus arr_seq higher_eq_priority sched t.
+ Let sorted_jobs :=
+ sorted_pending_jobs job_arrival job_cost job_jitter num_cpus arr_seq higher_eq_priority sched.
 (* ..., we show that a job is mapped to a processor based on that list, ... *)
 Lemma scheduler_nth_or_none_mapping :
 forall t cpu x,
 sched cpu t = x >
 nth_or_none (sorted_jobs t) cpu = x.
+ (* First, we recall that the schedule picks the nth highestpriority job. *)
+ Corollary scheduler_nth_or_none_mapping :
+ forall t cpu,
+ sched cpu t = nth_or_none (sorted_jobs t) cpu.
Proof.
 intros t cpu x SCHED.
 unfold sched, scheduler, schedule_prefix in *.
 destruct t.
 {
 unfold update_schedule in SCHED; rewrite eq_refl in SCHED.
 rewrite SCHED; f_equal.
 unfold sorted_jobs, sorted_pending_jobs; f_equal.
 unfold jobs_pending_at; apply eq_filter; red; intro j'.
 unfold pending; f_equal; f_equal.
 unfold completed, service.
 by rewrite big_geq // big_geq //.
 }
 {
 unfold update_schedule at 1 in SCHED; rewrite eq_refl in SCHED.
 rewrite SCHED; f_equal.
 unfold sorted_jobs, sorted_pending_jobs; f_equal.
 unfold jobs_pending_at; apply eq_filter; red; intro j'.
 unfold pending; f_equal; f_equal.
 unfold completed, service; f_equal.
 apply eq_big_nat; move => t0 /andP [_ LT].
 unfold service_at; apply eq_bigl; red; intros cpu'.
 unfold scheduled_on; f_equal.
 fold (schedule_prefix job_cost job_jitter num_cpus arr_seq higher_eq_priority).
 have SAME := scheduler_same_prefix; unfold sched_prefix, sched in *.
 by rewrite /schedule_prefix SAME.
 }
+ intros t cpu.
+ by rewrite /sched scheduler_uses_construction_function.
Qed.
 (* ..., a scheduled job is mapped to a cpu corresponding to its position, ... *)
 Lemma scheduler_nth_or_none_scheduled :
 forall j t,
 scheduled sched j t >
 exists (cpu: processor num_cpus),
 nth_or_none (sorted_jobs t) cpu = Some j.
 Proof.
 move => j t /existsP [cpu /eqP SCHED]; exists cpu.
 by apply scheduler_nth_or_none_mapping.
 Qed.

 (* ..., and that a backlogged job has a position larger than or equal to the number
+ (* We also prove that a backlogged job has priority larger than or equal to the number
of processors. *)
Lemma scheduler_nth_or_none_backlogged :
forall j t,
 backlogged job_cost job_jitter sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost job_jitter sched j t >
exists i,
nth_or_none (sorted_jobs t) i = Some j /\ i >= num_cpus.
Proof.
 have SAME := scheduler_same_prefix.
 intros j t BACK.
+ intros j t ARRj BACK.
move: BACK => /andP [PENDING /negP NOTCOMP].
assert (IN: j \in sorted_jobs t).
{
rewrite mem_sort mem_filter PENDING andTb.
move: PENDING => /andP [ARRIVED _].
 rewrite JobIn_arrived.
 rewrite /arrived_before ltnS.
 by apply leq_trans with (n := job_arrival j + job_jitter j);
 first by apply leq_addr.
+ by apply arrived_between_implies_in_actual_arrivals with (job_arrival0 := job_arrival).
}
apply nth_or_none_mem_exists in IN; des.
exists n; split; first by done.
rewrite leqNgt; apply/negP; red; intro LT.
apply NOTCOMP; clear NOTCOMP PENDING.
apply/existsP; exists (Ordinal LT); apply/eqP.
 unfold sorted_jobs in *; clear sorted_jobs.
 unfold sched, scheduler, schedule_prefix in *; clear sched.
 destruct t.
 {
 unfold update_schedule; rewrite eq_refl.
 rewrite IN; f_equal.
 fold (schedule_prefix job_cost job_jitter num_cpus arr_seq higher_eq_priority).
 unfold sorted_pending_jobs; f_equal.
 apply eq_filter; red; intros x.
 unfold pending; f_equal; f_equal.
 unfold completed; f_equal.
 by unfold service; rewrite 2?big_geq //.
 }
 {
 unfold update_schedule at 1; rewrite eq_refl.
 rewrite IN; f_equal.
 unfold sorted_pending_jobs; f_equal.
 apply eq_filter; red; intros x.
 unfold pending; f_equal; f_equal.
 unfold completed; f_equal.
 unfold service; apply eq_big_nat; move => i /andP [_ LTi].
 unfold service_at; apply eq_bigl; red; intro cpu.
 unfold scheduled_on; f_equal.
 fold (schedule_prefix job_cost job_jitter num_cpus arr_seq higher_eq_priority).
 by unfold sched_prefix in *; rewrite /schedule_prefix SAME.
 }
+ by rewrite scheduler_nth_or_none_mapping.
Qed.
End HelperLemmas.
(* Now, we prove the important properties about the implementation. *)
 (* Jobs do not execute before the jitter, ...*)
+ (* First, we show that scheduled jobs come from the arrival sequence. *)
+ Lemma scheduler_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+ Proof.
+ move => j t /existsP [cpu /eqP SCHED].
+ rewrite scheduler_nth_or_none_mapping in SCHED.
+ apply nth_or_none_mem in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ move: SCHED => /andP [_ ARR].
+ rewrite /actual_arrivals_up_to in ARR.
+ by eapply in_actual_arrivals_between_implies_arrived; eauto 1.
+ Qed.
+
+ (* Next, we show that jobs do not execute before the jitter has passed...*)
Theorem scheduler_jobs_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Proof.
 unfold jobs_must_arrive_to_execute.
 intros j t SCHED.
 move: SCHED => /existsP [cpu /eqP SCHED].
 unfold sched, scheduler, schedule_prefix in SCHED.
 destruct t.
 {
 rewrite /update_schedule eq_refl in SCHED.
 apply (nth_or_none_mem _ cpu j) in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 by move: SCHED => /andP [/andP [PENDING _] _].
 }
 {
 unfold update_schedule at 1 in SCHED; rewrite eq_refl /= in SCHED.
 apply (nth_or_none_mem _ cpu j) in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 by move: SCHED => /andP [/andP [PENDING _] _].
 }
+ move => j t /existsP [cpu /eqP SCHED].
+ rewrite scheduler_nth_or_none_mapping in SCHED.
+ apply nth_or_none_mem in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ by move: SCHED => /andP [/andP [ARR _] _].
Qed.
 (* ..., jobs are sequential, ... *)
+ (* ...jobs are sequential, ... *)
Theorem scheduler_sequential_jobs: sequential_jobs sched.
Proof.
 unfold sequential_jobs, sched, scheduler, schedule_prefix.
intros j t cpu1 cpu2 SCHED1 SCHED2.
 destruct t; rewrite /update_schedule eq_refl in SCHED1 SCHED2;
 have UNIQ := nth_or_none_uniq _ cpu1 cpu2 j _ SCHED1 SCHED2; (apply ord_inj, UNIQ);
 rewrite sort_uniq filter_uniq //;
 by apply JobIn_uniq.
+ rewrite 2!scheduler_nth_or_none_mapping in SCHED1 SCHED2.
+ set l := sorted_pending_jobs _ _ _ _ _ _ _ _ in SCHED1 SCHED2.
+ apply ord_inj, nth_or_none_uniq with (l0 := l) (x := j); try (by done).
+ by rewrite sort_uniq filter_uniq // /actual_arrivals_up_to; apply actual_arrivals_uniq.
Qed.

+
(* ... and jobs do not execute after completion. *)
Theorem scheduler_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
Proof.
 rename H_job_cost_positive into GT0.
 unfold completed_jobs_dont_execute, service.
intros j t.
 induction t; first by rewrite big_geq.
+ induction t;
+ first by rewrite /service /service_during big_geq //.
+ rewrite /service /service_during big_nat_recr //=.
+ rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LT]; last first.
{
 rewrite big_nat_recr // /=.
 rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LESS]; last first.
+ apply: leq_trans LT; rewrite addn1.
+ apply leq_add; first by done.
+ rewrite /service_at.
+ case (boolP ([exists cpu, scheduled_on sched j cpu t])) => [EX  ALL]; last first.
{
 destruct (job_cost j); first by rewrite ltn0 in LESS.
 rewrite addn1; rewrite ltnS in LESS.
 apply leq_add; first by done.
 by apply service_at_most_one, scheduler_sequential_jobs.
 }
 rewrite EQ {2}[job_cost j]addn0; apply leq_add; first by done.
 destruct t.
 {
 rewrite big_geq // in EQ.
 specialize (GT0 j); unfold job_cost_positive in *.
 by rewrite EQ ltn0 in GT0.
 }
 {
 unfold service_at; rewrite big_mkcond.
 apply leq_trans with (n := \sum_(cpu < num_cpus) 0);
 last by rewrite big_const_ord iter_addn mul0n addn0.
 apply leq_sum; intros cpu _; desf.
 move: Heq => /eqP SCHED.
 unfold scheduler, schedule_prefix in SCHED.
 unfold sched, scheduler, schedule_prefix, update_schedule at 1 in SCHED.
 rewrite eq_refl in SCHED.
 apply (nth_or_none_mem _ cpu j) in SCHED.
 rewrite mem_sort mem_filter in SCHED.
 fold (update_schedule job_cost job_jitter num_cpus arr_seq higher_eq_priority) in SCHED.
 move: SCHED => /andP [/andP [_ /negP NOTCOMP] _].
 exfalso; apply NOTCOMP; clear NOTCOMP.
 unfold completed; apply/eqP.
 unfold service; rewrite EQ.
 rewrite big_nat_cond [\sum_(_ <= _ < _  true)_]big_nat_cond.
 apply eq_bigr; move => i /andP [/andP [_ LT] _].
 apply eq_bigl; red; ins.
 unfold scheduled_on; f_equal.
 fold (schedule_prefix job_cost job_jitter num_cpus arr_seq higher_eq_priority).
 by rewrite scheduler_same_prefix.
+ rewrite negb_exists in ALL; move: ALL => /forallP ALL.
+ rewrite big1 //; intros cpu SCHED.
+ by specialize (ALL cpu); rewrite SCHED in ALL.
}
+ move: EX => /existsP [cpu SCHED].
+ rewrite (bigD1 cpu) /=; last by done.
+ rewrite big1; first by rewrite addn0.
+ move => cpu' /andP [SCHED' NEQ].
+ move: NEQ => /eqP NEQ; exfalso; apply NEQ, ord_inj.
+ move: SCHED SCHED' => /eqP SCHED /eqP SCHED'.
+ rewrite 2!scheduler_nth_or_none_mapping in SCHED SCHED'.
+ set l := sorted_pending_jobs _ _ _ _ _ _ _ _ in SCHED SCHED'.
+ apply nth_or_none_uniq with (l0 := l) (x := j); try (by done).
+ by rewrite sort_uniq filter_uniq //; apply actual_arrivals_uniq.
}
+ rewrite [job_cost _]addn0; apply leq_add; first by rewrite EQ.
+ rewrite leqn0 /service_at big1 // /scheduled_on.
+ move => cpu /eqP SCHED.
+ rewrite scheduler_nth_or_none_mapping in SCHED.
+ apply nth_or_none_mem in SCHED.
+ rewrite mem_sort mem_filter in SCHED.
+ move: SCHED => /andP [/andP [_ NOTCOMP] _].
+ by rewrite /completed EQ eq_refl in NOTCOMP.
Qed.

 (* In addition, the scheduler is work conserving ... *)
+
+ (* In addition, the scheduler is (jitteraware) work conserving, ... *)
Theorem scheduler_work_conserving:
 work_conserving job_cost job_jitter sched.
+ work_conserving job_arrival job_cost job_jitter arr_seq sched.
Proof.
 unfold work_conserving; intros j t BACK cpu.
 set jobs := sorted_pending_jobs job_cost job_jitter num_cpus arr_seq higher_eq_priority sched t.
 destruct (sched cpu t) eqn:SCHED; first by exists j0; apply/eqP.
 apply scheduler_nth_or_none_backlogged in BACK.
+ intros j t ARRj BACK cpu.
+ set jobs := sorted_pending_jobs job_arrival job_cost job_jitter num_cpus
+ arr_seq higher_eq_priority sched t.
+ destruct (sched cpu t) as [j0 ] eqn:SCHED; first by exists j0; apply/eqP.
+ apply scheduler_nth_or_none_backlogged in BACK; last by done.
destruct BACK as [cpu_out [NTH GE]].
exfalso; rewrite leqNgt in GE; move: GE => /negP GE; apply GE.
apply leq_ltn_trans with (n := cpu); last by done.
 apply scheduler_nth_or_none_mapping in SCHED.
+ rewrite scheduler_nth_or_none_mapping in SCHED.
apply nth_or_none_size_none in SCHED.
apply leq_trans with (n := size jobs); last by done.
by apply nth_or_none_size_some in NTH; apply ltnW.
Qed.
 (* ... and respects the JLDP policy. *)
+ (* ...and respects the JLDP policy. *)
Theorem scheduler_respects_policy :
 respects_JLDP_policy job_cost job_jitter sched higher_eq_priority.
+ respects_JLDP_policy job_arrival job_cost job_jitter arr_seq sched higher_eq_priority.
Proof.
 unfold respects_JLDP_policy; intros j j_hp t BACK SCHED.
 set jobs := sorted_pending_jobs job_cost job_jitter num_cpus arr_seq higher_eq_priority sched t.
 apply scheduler_nth_or_none_backlogged in BACK.
+ move => j j_hp t ARRj BACK /existsP [cpu /eqP SCHED].
+ apply scheduler_nth_or_none_backlogged in BACK; last by done.
+ set jobs := sorted_pending_jobs _ _ _ _ _ _ _ _ in BACK.
destruct BACK as [cpu_out [SOME GE]].
 apply scheduler_nth_or_none_scheduled in SCHED.
 destruct SCHED as [cpu SCHED].
+ rewrite scheduler_nth_or_none_mapping in SCHED.
have EQ1 := nth_or_none_nth jobs cpu j_hp j SCHED.
have EQ2 := nth_or_none_nth jobs cpu_out j j SOME.
rewrite EQ1 {2}EQ2.
 apply sorted_lt_idx_implies_rel; [by done  by apply sort_sorted  ].
+ apply sorted_lt_idx_implies_rel; try (by done); last 2 first.
 by apply leq_trans with (n := num_cpus).
 by apply nth_or_none_size_some in SOME.
+  by apply sort_sorted, H_priority_total.
Qed.
End Proofs.
diff git a/implementation/global/parallel/bertogna_edf_example.v b/implementation/global/parallel/bertogna_edf_example.v
index a7dd072..7790be6 100644
 a/implementation/global/parallel/bertogna_edf_example.v
+++ b/implementation/global/parallel/bertogna_edf_example.v
@@ 96,12 +96,12 @@ Module ResponseTimeAnalysisEDF.
Let arr_seq := periodic_arrival_sequence ts.
(* Let sched be the workconserving EDF scheduler. *)
 Let sched := scheduler job_cost num_cpus arr_seq
 (JLFP_to_JLDP arr_seq (EDF job_deadline)).
+ Let sched := scheduler job_arrival job_cost num_cpus arr_seq
+ (JLFP_to_JLDP (EDF job_arrival job_deadline)).
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, we prove that ts is schedulable with the result of the test. *)
Corollary ts_is_schedulable:
@@ 114,23 +114,21 @@ Module ResponseTimeAnalysisEDF.
have TSVALID := ts_has_valid_parameters.
unfold valid_sporadic_job, valid_realtime_job in *; des.
apply taskset_schedulable_by_edf_rta with (task_cost := task_cost)
 (task_period := task_period) (task_deadline := task_deadline) (ts0 := ts).
  by apply ts_has_valid_parameters.
+ (task_period := task_period) (task_deadline := task_deadline) (ts0 := ts); try (by done).
 by apply ts_has_constrained_deadlines.
 by apply periodic_arrivals_all_jobs_from_taskset.
  by apply periodic_arrivals_valid_job_parameters, ts_has_valid_parameters.
 by apply periodic_arrivals_are_sporadic.
  by compute.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_must_arrive_to_execute.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_work_conserving.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
 apply scheduler_respects_policy.
  by intro t; apply EDF_is_transitive.
  by intro t; apply EDF_is_total.
+  by apply periodic_arrivals_are_consistent.
+  by intros t; apply RM_is_transitive.
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
  by apply IN.
Qed.
End ExampleRTA.
diff git a/implementation/global/parallel/bertogna_fp_example.v b/implementation/global/parallel/bertogna_fp_example.v
index 4042b4b..f502aa4 100644
 a/implementation/global/parallel/bertogna_fp_example.v
+++ b/implementation/global/parallel/bertogna_fp_example.v
@@ 125,8 +125,7 @@ Module ResponseTimeAnalysisFP.
Let arr_seq := periodic_arrival_sequence ts.
(* Assume ratemonotonic priorities. *)
 Let higher_priority : JLDP_policy arr_seq :=
 (FP_to_JLDP job_task arr_seq (RM task_period)).
+ Let higher_priority := FP_to_JLDP job_task (RM task_period).
Section FactsAboutPriorityOrder.
@@ 151,11 +150,11 @@ Module ResponseTimeAnalysisFP.
End FactsAboutPriorityOrder.
(* Let sched be the workconserving RM scheduler. *)
 Let sched := scheduler job_cost num_cpus arr_seq higher_priority.
+ Let sched := scheduler job_arrival job_cost num_cpus arr_seq higher_priority.
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, we prove that ts is schedulable with the result of the test. *)
Corollary ts_is_schedulable:
@@ 176,17 +175,16 @@ Module ResponseTimeAnalysisFP.
 by apply RM_is_transitive.
 by apply periodic_arrivals_all_jobs_from_taskset.
 by apply periodic_arrivals_are_sporadic.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_must_arrive_to_execute.
  apply scheduler_completed_jobs_dont_execute; intro j'.
  by specialize (VALID j'); des.
+  apply scheduler_completed_jobs_dont_execute.
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
  by apply scheduler_work_conserving.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
 apply scheduler_respects_policy.
+  by apply periodic_arrivals_are_consistent.
 by intros t; apply RM_is_transitive.
 {
 unfold FP_to_JLDP; intros t x y; apply/orP.
 by apply priority_is_total; rewrite periodic_arrivals_all_jobs_from_taskset.
 }
+  by intros t x y; apply leq_total.
 by apply schedulability_test_succeeds.
Qed.
diff git a/implementation/job.v b/implementation/job.v
index 276725c..4dfc0ad 100644
 a/implementation/job.v
+++ b/implementation/job.v
@@ 13,6 +13,7 @@ Module ConcreteJob.
Record concrete_job :=
{
job_id: nat;
+ job_arrival: time;
job_cost: time;
job_deadline: time;
job_task: concrete_task_eqType
@@ 22,6 +23,7 @@ Module ConcreteJob.
equality for concrete jobs. *)
Definition job_eqdef (j1 j2: concrete_job) :=
(job_id j1 == job_id j2) &&
+ (job_arrival j1 == job_arrival j2) &&
(job_cost j1 == job_cost j2) &&
(job_deadline j1 == job_deadline j2) &&
(job_task j1 == job_task j2).
@@ 33,7 +35,7 @@ Module ConcreteJob.
destruct (job_eqdef x y) eqn:EQ.
{
apply ReflectT; unfold job_eqdef in *.
 move: EQ => /andP [/andP [/andP [/eqP ID /eqP COST] /eqP DL] /eqP TASK].
+ move: EQ => /andP [/andP [/andP [/andP [/eqP ID /eqP ARR] /eqP COST] /eqP DL] /eqP TASK].
by destruct x, y; simpl in *; subst.
}
{
@@ 42,13 +44,17 @@ Module ConcreteJob.
apply negbT in EQ; rewrite negb_and in EQ.
destruct x, y.
rewrite negb_and in EQ.
 move: EQ => /orP [EQ  /eqP TASK]; last by apply TASK; inversion BUG.
+ move: EQ => /orP [EQ  /eqP TASK].
move: EQ => /orP [EQ  /eqP DL].
rewrite negb_and in EQ.
 move: EQ => /orP [/eqP ID  /eqP COST].
+ move: EQ => /orP [EQ  /eqP COST].
+ rewrite negb_and in EQ.
+ move: EQ => /orP [/eqP ID  /eqP ARR].
by apply ID; inversion BUG.
+ by apply ARR; inversion BUG.
by apply COST; inversion BUG.
by apply DL; inversion BUG.
+ by apply TASK; inversion BUG.
}
Qed.
diff git a/implementation/uni/basic/fp_rta_example.v b/implementation/uni/basic/fp_rta_example.v
index 2e02636..57f4932 100644
 a/implementation/uni/basic/fp_rta_example.v
+++ b/implementation/uni/basic/fp_rta_example.v
@@ 106,7 +106,7 @@ Module ResponseTimeAnalysisFP.
Let arr_seq := periodic_arrival_sequence ts.
(* Assume ratemonotonic priorities... *)
 Let higher_eq_priority : JLDP_policy arr_seq := (FP_to_JLDP job_task arr_seq (RM task_period)).
+ Let higher_eq_priority := FP_to_JLDP job_task (RM task_period).
(* ... and recall that this priority assignment is total. *)
Fact priority_is_total:
@@ 120,11 +120,11 @@ Module ResponseTimeAnalysisFP.
Qed.
(* Let sched be the workconserving RM scheduler. *)
 Let sched := scheduler job_cost arr_seq higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost arr_seq higher_eq_priority.
(* Recall the definition of deadline miss. *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Next, by using the result of the RTA, we prove that the task set is schedulable. *)
Corollary ts_is_schedulable:
@@ 139,15 +139,17 @@ Module ResponseTimeAnalysisFP.
apply taskset_schedulable_by_fp_rta with (task_cost := task_cost)
(task_period := task_period) (task_deadline := task_deadline)
(ts0 := ts) (higher_eq_priority0 := RM task_period); try (by done).
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
 by apply periodic_arrivals_all_jobs_from_taskset.
 by apply periodic_arrivals_are_sporadic.
 by apply RM_is_reflexive.
 by apply RM_is_transitive.
  by apply scheduler_jobs_must_arrive_to_execute.
  by apply scheduler_completed_jobs_dont_execute; intro j'; specialize (VALID j'); des.
  by apply scheduler_work_conserving.
  apply scheduler_respects_policy.
+  by apply scheduler_jobs_come_from_arrival_sequence, periodic_arrivals_are_consistent.
+  by apply scheduler_jobs_must_arrive_to_execute, periodic_arrivals_are_consistent.
+  apply scheduler_completed_jobs_dont_execute, periodic_arrivals_are_consistent.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
+  apply scheduler_respects_policy; first by apply periodic_arrivals_are_consistent.
 by intros t; apply RM_is_transitive.
 by apply priority_is_total.
 by apply schedulability_test_succeeds.
diff git a/implementation/uni/basic/schedule.v b/implementation/uni/basic/schedule.v
index 1d9771c..8b77cdd 100644
 a/implementation/uni/basic/schedule.v
+++ b/implementation/uni/basic/schedule.v
@@ 2,58 +2,83 @@ Require Import rt.util.all.
Require Import rt.model.arrival.basic.job rt.model.arrival.basic.arrival_sequence rt.model.priority.
Require Import rt.model.schedule.uni.schedule.
Require Import rt.model.schedule.uni.basic.platform.
+Require Import rt.model.schedule.uni.transformation.construction.
From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat fintype bigop seq path.
Module ConcreteScheduler.
 Import Job ArrivalSequence UniprocessorSchedule Platform Priority.
+ Import Job ArrivalSequence UniprocessorSchedule Platform Priority ScheduleConstruction.
(* In this section, we implement a prioritybased uniprocessor scheduler *)
Section Implementation.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
 (* Let arr_seq be any arrival sequence.*)
+ (* Let arr_seq be any job arrival sequence with consistent arrivals.*)
Variable arr_seq: arrival_sequence Job.

+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+
(* Assume a JLDP policy is given. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.

 (* Consider the list of pending jobs at time t. *)
 Definition jobs_pending_at (sched: schedule arr_seq) (t: time) :=
 [seq j < jobs_arrived_up_to arr_seq t  pending job_cost sched j t].

 (* First, we sort this list by priority. *)
 Definition sorted_pending_jobs (sched: schedule arr_seq) (t: time) :=
 sort (higher_eq_priority t) (jobs_pending_at sched t).

 (* Then, starting from the empty schedule as a base, ... *)
 Definition empty_schedule : schedule arr_seq :=
 fun t => None.
+ Variable higher_eq_priority: JLDP_policy Job.
 (* ..., we redefine the mapping of jobs to processors at any time t as follows.
 The job to be scheduled is either the head of the sorted list or None, in case
 there is no pending job. *)
 Definition update_schedule (prev_sched: schedule arr_seq)
 (t_next: time) : schedule arr_seq :=
 fun t =>
 if t == t_next then
 ohead (sorted_pending_jobs prev_sched t) (* head of the list, if it exists *)
 else prev_sched t.

 (* The schedule is iteratively constructed by applying assign_jobs at every time t. *)
 Fixpoint schedule_prefix (t_max: time) : schedule arr_seq :=
 if t_max is t_prev.+1 then
 (* At time t_prev + 1, schedule jobs that have not completed by time t_prev. *)
 update_schedule (schedule_prefix t_prev) t_prev.+1
 else
 (* At time 0, schedule any jobs that arrive. *)
 update_schedule empty_schedule 0.

 (* This iteration yields the following scheduler implementation. *)
 Definition scheduler (t: time) := (schedule_prefix t) t.
+ (* Next, we show how to recursively construct the schedule. *)
+ Section ScheduleConstruction.
+ (* For any time t, suppose that we have generated the schedule prefix in the
+ interval [0, t). Then, we must define what should be scheduled at time t. *)
+ Variable sched_prefix: schedule Job.
+ Variable t: time.
+
+ (* For simplicity, let's use some local names. *)
+ Let is_pending := pending job_arrival job_cost sched_prefix.
+
+ (* Consider the list of pending jobs at time t. *)
+ Definition pending_jobs :=
+ [seq j < jobs_arrived_up_to arr_seq t  is_pending j t].
+
+ (* To make the scheduling decision, we just pick one of the highestpriority jobs
+ that are pending (if it exists). *)
+ Definition highest_priority_job :=
+ seq_min (higher_eq_priority t) pending_jobs.
+
+ End ScheduleConstruction.
+
+ (* Starting from the empty schedule, the final schedule is obtained by iteratively
+ picking the highestpriority job. *)
+ Let empty_schedule : schedule Job := fun t => None.
+ Definition scheduler :=
+ build_schedule_from_prefixes highest_priority_job empty_schedule.
+
+ (* Then, by showing that the construction function depends only on the prefix, ... *)
+ Lemma scheduler_depends_only_on_prefix:
+ forall sched1 sched2 t,
+ (forall t0, t0 < t > sched1 t0 = sched2 t0) >
+ highest_priority_job sched1 t = highest_priority_job sched2 t.
+ Proof.
+ intros sched1 sched2 t ALL.
+ rewrite /highest_priority_job.
+ suff SAME: pending_jobs sched1 t = pending_jobs sched2 t by rewrite SAME.
+ apply eq_in_filter.
+ intros j ARR.
+ apply in_arrivals_implies_arrived_before with (job_arrival0 := job_arrival) in ARR;
+ last by done.
+ rewrite /arrived_before ltnS in ARR.
+ rewrite /pending /has_arrived ARR 2!andTb; f_equal.
+ rewrite /completed_by; f_equal.
+ apply eq_big_nat; move => i /= LTi.
+ by rewrite /service_at /scheduled_at ALL.
+ Qed.
+
+ (* ...we infer that the generated schedule is indeed based on the construction function. *)
+ Corollary scheduler_uses_construction_function:
+ forall t, scheduler t = highest_priority_job scheduler t.
+ Proof.
+ by ins; apply prefix_dependent_schedule_construction,
+ scheduler_depends_only_on_prefix.
+ Qed.
+
End Implementation.
(* In this section, we prove the properties of the scheduler that are used
@@ 61,211 +86,104 @@ Module ConcreteScheduler.
Section Proofs.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
 (* Let arr_seq be any job arrival sequence with no duplicates. *)
+ (* Let arr_seq be any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
(* Consider any JLDP policy that is transitive and total. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
 Hypothesis H_priority_transitive: forall t, transitive (higher_eq_priority t).
 Hypothesis H_priority_total: forall t, total (higher_eq_priority t).
+ Variable higher_eq_priority: JLDP_policy Job.
+ Hypothesis H_priority_is_transitive: forall t, transitive (higher_eq_priority t).
+ Hypothesis H_priority_is_total: forall t, total (higher_eq_priority t).
(* Let sched denote our concrete scheduler implementation. *)
 Let sched := scheduler job_cost arr_seq higher_eq_priority.

 (* Next, we prove some helper lemmas about the scheduler construction. *)
 Section HelperLemmas.
+ Let sched := scheduler job_arrival job_cost arr_seq higher_eq_priority.
 (* Let's use a shorter name for the schedule prefix function. *)
 Let sched_prefix := schedule_prefix job_cost arr_seq higher_eq_priority.

 (* First, we show that the scheduler preserves its prefixes. *)
 Lemma scheduler_same_prefix :
 forall t t_max,
 t <= t_max >
 sched_prefix t_max t = sched t.
 Proof.
 intros t t_max LEt.
 induction t_max.
 {
 by rewrite leqn0 in LEt; move: LEt => /eqP EQ; subst.
 }
 {
 rewrite leq_eqVlt in LEt.
 move: LEt => /orP [/eqP EQ  LESS]; first by subst.
 {
 feed IHt_max; first by done.
 unfold sched_prefix, schedule_prefix, update_schedule at 1.
 assert (FALSE: t == t_max.+1 = false).
 {
 by apply negbTE; rewrite neq_ltn LESS orTb.
 } rewrite FALSE.
 by rewrite IHt_max.
 }
 }
 Qed.

 (* Moreover, given the sorted list of pending jobs, ...*)
 Let sorted_jobs (t: time) :=
 sorted_pending_jobs job_cost arr_seq higher_eq_priority sched t.

 (* ..., we prove that the scheduler always picks the first job of the list. *)
 Lemma scheduler_picks_first_job:
 forall t,
 sched t = ohead (sorted_jobs t).
+ (* To conclude, we prove the important properties of the scheduler implementation. *)
+
+ (* First, we show that scheduled jobs come from the arrival sequence. *)
+ Lemma scheduler_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
Proof.
 unfold sched, scheduler, schedule_prefix in *.
 destruct t.
 {
 rewrite /update_schedule eq_refl; f_equal.
 unfold sorted_jobs, sorted_pending_jobs; f_equal.
 unfold jobs_pending_at; apply eq_filter; red; intro j'.
 unfold pending; f_equal; f_equal.
 unfold completed_by, service, service_during.
 by rewrite big_geq // big_geq //.
 }
 {
 rewrite {1}/update_schedule eq_refl; f_equal.
 unfold sorted_jobs, sorted_pending_jobs; f_equal.
 unfold jobs_pending_at; apply eq_filter; red; intro j'.
 unfold pending; f_equal; f_equal.
 unfold completed_by, service, service_during; f_equal.
 apply eq_big_nat; move => t0 /andP [_ LT].
 unfold service_at, scheduled_at.
 fold (schedule_prefix job_cost arr_seq higher_eq_priority).
 have SAME := scheduler_same_prefix.
 unfold sched_prefix, sched in *.
 by rewrite /schedule_prefix SAME.
 }
+ move => j t /eqP SCHED.
+ rewrite /sched scheduler_uses_construction_function // /highest_priority_job in SCHED.
+ apply seq_min_in_seq in SCHED.
+ rewrite mem_filter in SCHED.
+ move: SCHED => /andP [_ ARR].
+ by eapply in_arrivals_implies_arrived, ARR.
Qed.
 End HelperLemmas.

 (* To conclude, we prove the important properties of the scheduler implementation. *)

 (* First, we show that jobs do not execute before they arrive...*)
+ (* Next, we show that jobs do not execute before they arrive...*)
Theorem scheduler_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Proof.
 unfold jobs_must_arrive_to_execute.
 intros j t SCHED.
 unfold sched, scheduled_at, scheduler, schedule_prefix in SCHED.
 destruct t.
 {
 rewrite /update_schedule eq_refl in SCHED.
 set jobs := sorted_pending_jobs _ _ _ _ _ in SCHED.
 suff IN: j \in jobs.
 {
 rewrite mem_sort mem_filter in IN; move: IN => /andP [_ ARR].
 by apply JobIn_arrived in ARR.
 }
 case SORT: jobs => [ j0 l /=]; first by rewrite SORT /= in SCHED.
 rewrite SORT /= in SCHED.
 move: SCHED; move/eqP; case; intro EQ; subst.
 by rewrite in_cons eq_refl orTb.
 }
 {
 rewrite /update_schedule eq_refl in SCHED.
 set jobs := sorted_pending_jobs _ _ _ _ _ in SCHED.
 suff IN: j \in jobs.
 {
 rewrite mem_sort mem_filter in IN; move: IN => /andP [_ ARR].
 by apply JobIn_arrived in ARR.
 }
 case SORT: jobs => [ j0 l /=]; first by rewrite SORT /= in SCHED.
 rewrite SORT /= in SCHED.
 move: SCHED; move/eqP; case; intro EQ; subst.
 by rewrite in_cons eq_refl orTb.
 }
+ move => j t /eqP SCHED.
+ rewrite /sched scheduler_uses_construction_function // /highest_priority_job in SCHED.
+ apply seq_min_in_seq in SCHED.
+ rewrite mem_filter in SCHED.
+ by move: SCHED => /andP [/andP [ARR _] _].
Qed.
(* ... nor after completion. *)
Theorem scheduler_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
Proof.
 unfold completed_jobs_dont_execute, service, service_during.
intros j t.
 induction t; first by rewrite big_geq.
+ induction t;
+ first by rewrite /service /service_during big_geq //.
+ rewrite /service /service_during big_nat_recr //=.
+ rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LT]; last first.
{
 rewrite big_nat_recr // /=.
 rewrite leq_eqVlt in IHt; move: IHt => /orP [/eqP EQ  LESS]; last first.
 {
 destruct (job_cost j); first by rewrite ltn0 in LESS.
 rewrite addn1; rewrite ltnS in LESS.
+ apply: leq_trans LT; rewrite addn1.
by apply leq_add; last by apply leq_b1.
 }
 rewrite EQ {2}[job_cost j]addn0; apply leq_add; first by done.
 destruct t.
 {
 rewrite /service_at /scheduled_at.
 destruct (sched 0 == Some j) eqn:SCHED; last by done.
 move: SCHED => /eqP SCHED.
 rewrite scheduler_picks_first_job in SCHED.
 set jobs := sorted_pending_jobs _ _ _ _ _ in SCHED.
 have IN: j \in jobs.
 by destruct jobs; last by move: SCHED => /=; case => SAME; subst; rewrite in_cons eq_refl.
 rewrite mem_sort mem_filter in IN; move: IN => /andP [/andP [_ NOTCOMP] _].
 by rewrite /completed_by EQ eq_refl in NOTCOMP.
 }
 {
 unfold service_at, scheduled_at.
 rewrite leqn0 eqb0; apply/eqP; intro SCHED.
 unfold sched, scheduler, schedule_prefix, update_schedule at 1 in SCHED.
 rewrite eq_refl in SCHED.
 set jobs := sorted_pending_jobs _ _ _ _ _ in SCHED.
 have IN: j \in jobs.
 by destruct jobs; last by move: SCHED => /=; case => SAME; subst; rewrite in_cons eq_refl.
 rewrite mem_sort mem_filter in IN; move: IN => /andP [/andP [_ /negP NOTCOMP] _].
 apply NOTCOMP.
 rewrite /completed_by /service /service_during EQ.
 apply/eqP.
 rewrite big_nat_cond [in RHS]big_nat_cond.
 apply eq_bigr; move => i /andP [/andP [_ LT] _].
 rewrite /service_at /scheduled_at /sched /scheduler.
 fold (schedule_prefix job_cost arr_seq higher_eq_priority).
 by rewrite scheduler_same_prefix.
 }
}
+ rewrite [job_cost _]addn0; apply leq_add; first by rewrite EQ.
+ rewrite leqn0 eqb0 /scheduled_at.
+ rewrite /sched scheduler_uses_construction_function //.
+ rewrite /highest_priority_job.
+ apply/eqP; intro HP.
+ apply seq_min_in_seq in HP.
+ by rewrite mem_filter /pending /completed_by EQ eq_refl andbF andFb in HP.
Qed.
 (* In addition, the scheduler is work conserving ... *)
+ (* In addition, the scheduler is work conserving, ... *)
Theorem scheduler_work_conserving:
 work_conserving job_cost sched.
+ work_conserving job_arrival job_cost arr_seq sched.
Proof.
 unfold work_conserving; intros j t BACK.
 set jobs := sorted_pending_jobs job_cost arr_seq higher_eq_priority sched t.
 destruct (sched t) eqn:SCHED; first by exists j0; apply/eqP.
 rewrite scheduler_picks_first_job /jobs in SCHED.
 destruct jobs eqn:EMPTY; [clear SCHED  by done].
 suff IN: j \in jobs by rewrite EMPTY in_nil in IN.
 move: BACK => /andP [PEND _].
 rewrite mem_sort mem_filter PEND andTb.
 by apply JobIn_arrived; move: PEND => /andP [ARR _].
+ intros j t IN BACK.
+ move: BACK => /andP [/andP [ARR NOTCOMP] NOTSCHED].
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in NOTSCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function //.
+ case HP: (highest_priority_job _ _ _ _ ) => [j_hp]; first by exists j_hp.
+ set hp := highest_priority_job _ _ _ _ _ _ in NOTSCHED HP.
+ suff BUG: hp != None by rewrite HP in BUG.
+ apply seq_min_exists with (x := j).
+ rewrite mem_filter /pending ARR NOTCOMP /=.
+ by eapply arrived_between_implies_in_arrivals, ARR.
Qed.
 (* ... and respects the JLDP policy. *)
+ (* ...and respects the JLDP policy. *)
Theorem scheduler_respects_policy :
 respects_JLDP_policy job_cost sched higher_eq_priority.
+ respects_JLDP_policy job_arrival job_cost arr_seq sched higher_eq_priority.
Proof.
 unfold respects_JLDP_policy; move => j j_hp t BACK /eqP SCHED.
 move: (SCHED) => OHEAD.
 rewrite scheduler_picks_first_job in OHEAD.
 set jobs := sorted_pending_jobs job_cost arr_seq higher_eq_priority sched t in OHEAD.
 have SORT: sorted (higher_eq_priority t) jobs by apply sort_sorted.
 have IN: j \in jobs.
+ rename H_priority_is_transitive into TRANS, H_priority_is_total into TOTAL.
+ move => j1 j2 t ARR1 BACK /eqP SCHED.
+ move: BACK => /andP [/andP [ARR NOTCOMP] NOTSCHED].
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in NOTSCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in SCHED.
+ rewrite /highest_priority_job in SCHED NOTSCHED.
+ set jobs := pending_jobs _ _ _ _ _ in SCHED NOTSCHED.
+ have IN: j1 \in jobs.
{
 rewrite mem_sort mem_filter.
 move: BACK => /andP [PEND _]; rewrite PEND andTb.
 by move: PEND => /andP [ARR _]; apply JobIn_arrived.
+ rewrite mem_filter /pending ARR NOTCOMP /=.
+ by eapply arrived_between_implies_in_arrivals, ARR.
}
 destruct jobs as [j0 l] eqn:JOBS; first by done.
 move: OHEAD => /=; case => EQ; subst.
 move: IN; rewrite in_cons => /orP [/eqP SAME  OTHER];
 first by move:BACK => /andP [_ /eqP NOTSCHED]; rewrite /scheduled_at SCHED SAME in NOTSCHED.
 suff ALL: all (higher_eq_priority t j_hp) l by move: ALL => /allP ALL; apply ALL.
 by apply order_path_min.
+ apply seq_min_computes_min with (y := j1) in SCHED; try (by done).
+ by intros x y; rewrite 2!mem_filter; move => /andP [_ INx] /andP [_ INy];
+ apply TOTAL; eapply in_arrivals_implies_arrived; eauto 2.
Qed.
End Proofs.
diff git a/implementation/uni/jitter/arrival_sequence.v b/implementation/uni/jitter/arrival_sequence.v
index c37d401..3f3eb9d 100644
 a/implementation/uni/jitter/arrival_sequence.v
+++ b/implementation/uni/jitter/arrival_sequence.v
@@ 14,9 +14,10 @@ Module ConcreteArrivalSequence.
(* At any time t, we release Some job of tsk if t is a multiple of the period,
otherwise we release None. *)
 Definition add_job (t: time) (tsk: concrete_task) :=
 if task_period tsk % t then
 Some (Build_concrete_job (t %/ task_period tsk) (task_cost tsk) (task_deadline tsk) tsk)
+ Definition add_job (arr_time: time) (tsk: concrete_task) :=
+ if task_period tsk % arr_time then
+ Some (Build_concrete_job (arr_time %/ task_period tsk) arr_time
+ (task_cost tsk) (task_deadline tsk) tsk)
else
None.
@@ 35,14 +36,23 @@ Module ConcreteArrivalSequence.
(* Regarding the periodic arrival sequence built from ts, we prove that...*)
Let arr_seq := periodic_arrival_sequence ts.
+ (* ... arrival times are consistent, ... *)
+ Theorem periodic_arrivals_are_consistent:
+ arrival_times_are_consistent job_arrival arr_seq.
+ Proof.
+ move => j t ARRj.
+ rewrite /arrives_at mem_pmap in ARRj.
+ move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
+ by unfold add_job in *; desf.
+ Qed.
+
(* ... every job comes from the task set, ... *)
Theorem periodic_arrivals_all_jobs_from_taskset:
 forall (j: JobIn arr_seq),
 job_task (job_of_job_in j) \in ts. (* TODO: fix coercion *)
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
Proof.
 intros j.
 destruct j as [j arr ARRj]; simpl.
 unfold arr_seq, arrives_at, periodic_arrival_sequence in *.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj.
move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
by unfold add_job in *; desf.
@@ 50,13 +60,13 @@ Module ConcreteArrivalSequence.
(* ..., jobs have valid parameters, ... *)
Theorem periodic_arrivals_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
Proof.
rename H_valid_task_parameters into PARAMS.
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
 intros j; destruct j as [j arr ARRj]; simpl.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in ARRj.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj; move: ARRj => /mapP [tsk IN SOME].
unfold add_job in SOME; desf.
specialize (PARAMS tsk IN); des.
@@ 66,12 +76,10 @@ Module ConcreteArrivalSequence.
(* ... job arrivals satisfy the sporadic task model, ... *)
Theorem periodic_arrivals_are_sporadic:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Proof.
 unfold sporadic_task_model; move => j j' /eqP DIFF SAMEtsk LE.
 destruct j as [j arr ARR], j' as [j' arr' ARR']; simpl in *.
 rewrite eqE /= /jobin_eqdef negb_and /= in DIFF.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in *.
+ move => j j' /eqP DIFF [arr ARR] [arr' ARR'] SAMEtsk LE.
+ rewrite eqE /= /job_eqdef negb_and /= SAMEtsk eq_refl orbF in DIFF.
rewrite 2!mem_pmap in ARR ARR'.
move: ARR ARR' => /mapP [tsk_j INj SOMEj] /mapP [tsk_j' INj' SOMEj'].
unfold add_job in SOMEj, SOMEj'; desf; simpl in *;
@@ 81,18 +89,11 @@ Module ConcreteArrivalSequence.
rewrite leq_eqVlt in LE; move: LE => /orP [/eqP EQ  LESS].
{
exfalso; move: DIFF => /negP DIFF; apply DIFF.
 by subst; rewrite EQ.
+ by subst; rewrite EQ !eq_refl.
}
subst; rewrite leq_mul2r; apply/orP; right.
by rewrite ltn_mul2r in LESS; move: LESS => /andP [_ LT].
}
 {
 assert (LT: arr < arr'). by rewrite ltn_neqAle; apply/andP.
 clear LE DIFF; subst tsk_j' arr arr'.
 rewrite ltn_mul2r in LT; move: LT => /andP [_ LT].
 by apply leq_trans with (n := k.+1 * task_period tsk_j);
 [by rewrite mulSnr  by rewrite leq_mul2r; apply/orP; right].
 }
Qed.
(* ... and the arrival sequence has no duplicate jobs. *)
diff git a/implementation/uni/jitter/fp_rta_example.v b/implementation/uni/jitter/fp_rta_example.v
index 0c3bd1b..1482a0c 100644
 a/implementation/uni/jitter/fp_rta_example.v
+++ b/implementation/uni/jitter/fp_rta_example.v
@@ 1,8 +1,9 @@
Require Import rt.util.all.
Require Import rt.model.priority.
Require Import rt.model.arrival.basic.task.
Require Import rt.model.schedule.uni.schedule rt.model.schedule.uni.schedulability.
+Require Import rt.model.schedule.uni.schedulability.
Require Import rt.model.arrival.jitter.job.
+Require Import rt.model.schedule.uni.jitter.schedule.
Require Import rt.analysis.uni.jitter.workload_bound_fp
rt.analysis.uni.jitter.fp_rta_comp.
Require Import rt.implementation.uni.jitter.job
@@ 13,7 +14,7 @@ From mathcomp Require Import ssreflect ssrbool ssrnat eqtype seq bigop div.
Module ResponseTimeAnalysisFP.
 Import JobWithJitter UniprocessorSchedule SporadicTaskset Priority Schedulability
+ Import JobWithJitter UniprocessorScheduleWithJitter SporadicTaskset Priority Schedulability
WorkloadBoundFP ResponseTimeIterationFP.
Import ConcreteJob ConcreteTask ConcreteArrivalSequence ConcreteScheduler.
@@ 120,20 +121,21 @@ Module ResponseTimeAnalysisFP.
Let arr_seq := periodic_arrival_sequence ts.
(* ...subject to ratemonotonic priority. *)
 Let higher_eq_priority : JLDP_policy arr_seq := (FP_to_JLDP job_task arr_seq (RM task_period)).
+ Let higher_eq_priority := FP_to_JLDP job_task (RM task_period).
(* Assume that jobs have jitter that is no larger than the jitter of their tasks. *)
Variable job_jitter: concrete_job > time.
Hypothesis H_jitter_is_bounded:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
job_jitter_leq_task_jitter task_jitter job_jitter job_task j.
(* Next, let sched be the jitteraware RM schedule with those jitter values. *)
 Let sched := scheduler job_cost job_jitter arr_seq higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost job_jitter arr_seq higher_eq_priority.
(* To conclude, based on the definition of deadline miss,... *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* ...we use the result of the jitteraware FP RTA to conclude that
no task misses its deadline. *)
@@ 142,6 +144,7 @@ Module ResponseTimeAnalysisFP.
tsk \in ts >
no_deadline_missed_by tsk.
Proof.
+ rename H_jitter_is_bounded into JIT.
intros tsk IN.
have VALID := periodic_arrivals_valid_job_parameters ts ts_has_valid_parameters.
have TSVALID := ts_has_valid_parameters.
@@ 150,18 +153,20 @@ Module ResponseTimeAnalysisFP.
(task_period := task_period) (task_deadline := task_deadline) (ts0 := ts)
(higher_eq_priority0 := RM task_period) (job_jitter0 := job_jitter)
(task_jitter := task_jitter); try (by done).
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
 by apply periodic_arrivals_all_jobs_from_taskset.
  by intros j; specialize (VALID j); des; repeat split.
+  by intros j ARRj; specialize (VALID j ARRj); des; repeat split; try (apply JIT).
 by apply periodic_arrivals_are_sporadic.
 by apply RM_is_reflexive.
 by apply RM_is_transitive.
+  by apply scheduler_jobs_come_from_arrival_sequence.
 by apply scheduler_jobs_execute_after_jitter.
 by apply scheduler_completed_jobs_dont_execute.
  by apply scheduler_work_conserving.
  apply scheduler_respects_policy.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
+  apply scheduler_respects_policy; first by apply periodic_arrivals_are_consistent.
 by intros t; apply RM_is_transitive.
  by intros _ j1 j2; apply leq_total.
+  intros j1 j2 t ARR1 ARR2; apply leq_total.
 by apply schedulability_test_succeeds.
Qed.
diff git a/implementation/uni/jitter/job.v b/implementation/uni/jitter/job.v
index cedfbbd..c72bf1c 100644
 a/implementation/uni/jitter/job.v
+++ b/implementation/uni/jitter/job.v
@@ 12,6 +12,7 @@ Module ConcreteJob.
Record concrete_job :=
{
job_id: nat;
+ job_arrival: nat;
job_cost: nat;
job_deadline: nat;
job_task: concrete_task_eqType
@@ 21,6 +22,7 @@ Module ConcreteJob.
equality for concrete jobs. *)
Definition job_eqdef (j1 j2: concrete_job) :=
(job_id j1 == job_id j2) &&
+ (job_arrival j1 == job_arrival j2) &&
(job_cost j1 == job_cost j2) &&
(job_deadline j1 == job_deadline j2) &&
(job_task j1 == job_task j2).
@@ 32,7 +34,7 @@ Module ConcreteJob.
destruct (job_eqdef x y) eqn:EQ.
{
apply ReflectT; unfold job_eqdef in *.
 move: EQ => /andP [/andP [/andP [/eqP ID /eqP COST] /eqP DL] /eqP TASK].
+ move: EQ => /andP [/andP [/andP [/andP [/eqP ID /eqP ARR] /eqP COST] /eqP DL] /eqP TASK].
by destruct x, y; simpl in *; subst.
}
{
@@ 41,11 +43,17 @@ Module ConcreteJob.
apply negbT in EQ; rewrite negb_and in EQ.
destruct x, y.
rewrite negb_and in EQ.
 move: EQ => /orP [EQ  /eqP TASK]; last by apply TASK; inversion BUG.
 move: EQ => /orP [EQ  /eqP DL]; last by apply DL; inversion BUG.
+ move: EQ => /orP [EQ  /eqP TASK].
+ move: EQ => /orP [EQ  /eqP DL].
rewrite negb_and in EQ.
 move: EQ => /orP [/eqP ID  /eqP COST]; last by apply COST; inversion BUG.
+ move: EQ => /orP [EQ  /eqP COST].
+ rewrite negb_and in EQ.
+ move: EQ => /orP [/eqP ID  /eqP ARR].
by apply ID; inversion BUG.
+ by apply ARR; inversion BUG.
+ by apply COST; inversion BUG.
+ by apply DL; inversion BUG.
+ by apply TASK; inversion BUG.
}
Qed.
diff git a/implementation/uni/jitter/schedule.v b/implementation/uni/jitter/schedule.v
index d98663d..273b2f0 100644
 a/implementation/uni/jitter/schedule.v
+++ b/implementation/uni/jitter/schedule.v
@@ 14,6 +14,7 @@ Module ConcreteScheduler.
Section Implementation.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
@@ 21,36 +22,35 @@ Module ConcreteScheduler.
Variable arr_seq: arrival_sequence Job.
(* Also, assume that a JLDP policy is given. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* Next, we show how to recursively construct the schedule. *)
Section ScheduleConstruction.
(* For any time t, suppose that we have generated the schedule prefix in the
interval [0, t). Then, we must define what should be scheduled at time t. *)
 Variable sched_prefix: schedule arr_seq.
+ Variable sched_prefix: schedule Job.
Variable t: time.
(* For simplicity, let's use some local names. *)
 Let is_pending := pending job_cost job_jitter sched_prefix.
+ Let is_pending := pending job_arrival job_cost job_jitter sched_prefix.
 (* Consider the list of pending jobs at time t. *)
+ (* Consider the list of pending jobs with actual arrivals up to t. *)
Definition pending_jobs :=
 [seq j < actual_arrivals_up_to job_jitter arr_seq t  is_pending j t].
+ [seq j < actual_arrivals_up_to job_arrival job_jitter arr_seq t  is_pending j t].
 (* Then, we sort this list by priority... *)
 Definition sorted_jobs := sort (higher_eq_priority t) pending_jobs.

 (* ...and pick the highestpriority job. *)
 Definition highest_priority_job := ohead sorted_jobs.
+ (* To make the scheduling decision, we just pick one of the highestpriority jobs
+ that are pending (if it exists). *)
+ Definition highest_priority_job :=
+ seq_min (higher_eq_priority t) pending_jobs.
End ScheduleConstruction.
(* Starting from the empty schedule, the final schedule is obtained by iteratively
picking the highestpriority job. *)
 Let empty_schedule : schedule arr_seq := fun t => None.
+ Let empty_schedule : schedule Job := fun t => None.
Definition scheduler :=
 build_schedule_from_prefixes arr_seq highest_priority_job empty_schedule.
+ build_schedule_from_prefixes highest_priority_job empty_schedule.
(* Then, by showing that the construction function depends only on the prefix, ... *)
Lemma scheduler_depends_only_on_prefix:
@@ 59,12 +59,12 @@ Module ConcreteScheduler.
highest_priority_job sched1 t = highest_priority_job sched2 t.
Proof.
intros sched1 sched2 t ALL.
 rewrite /highest_priority_job /sorted_jobs.
+ rewrite /highest_priority_job.
suff SAME: pending_jobs sched1 t = pending_jobs sched2 t by rewrite SAME.
apply eq_in_filter.
intros j IN; rewrite mem_filter in IN.
move: IN => /andP [ARR IN].
 rewrite ltnS in ARR.
+ rewrite ltnS /= in ARR.
rewrite /pending /jitter_has_passed ARR 2!andTb; f_equal.
rewrite /completed_by; f_equal.
apply eq_big_nat; move => i /= LTi.
@@ 86,39 +86,48 @@ Module ConcreteScheduler.
Section Proofs.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
 (* Let arr_seq be any job arrival sequence with no duplicates. *)
+ (* Assume any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
 Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
(* Consider any JLDP policy that is reflexive, transitive and total. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
Hypothesis H_priority_is_reflexive: JLDP_is_reflexive higher_eq_priority.
Hypothesis H_priority_is_transitive: JLDP_is_transitive higher_eq_priority.
 Hypothesis H_priority_is_total: JLDP_is_total higher_eq_priority.
+ Hypothesis H_priority_is_total: JLDP_is_total arr_seq higher_eq_priority.
(* Let sched denote our concrete scheduler implementation. *)
 Let sched := scheduler job_cost job_jitter arr_seq higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost job_jitter arr_seq higher_eq_priority.
(* To conclude, we prove the important properties of the scheduler implementation. *)
 (* First, we show that jobs only execute after the jitter has passed... *)
+ (* First, we show that scheduled jobs come from the arrival sequence. *)
+ Lemma scheduler_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+ Proof.
+ move => j t /eqP SCHED.
+ rewrite /sched scheduler_uses_construction_function // /highest_priority_job in SCHED.
+ apply seq_min_in_seq in SCHED.
+ rewrite mem_filter in SCHED.
+ move: SCHED => /andP [_ ARR].
+ rewrite /actual_arrivals_up_to in ARR.
+ by apply in_actual_arrivals_between_implies_arrived in ARR.
+ Qed.
+
+ (* Next, we show that jobs do not execute before they arrive...*)
Theorem scheduler_jobs_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Proof.
move => j t /eqP SCHED.
 rewrite /sched scheduler_uses_construction_function in SCHED.
 rewrite /highest_priority_job in SCHED.
 set jobs := sorted_jobs _ _ _ _ _ _ in SCHED.
 suff IN: j \in jobs.
 {
 rewrite mem_sort mem_filter in IN.
 by move: IN => /andP [/andP [ARR _] _].
 }
 destruct jobs; first by done.
 by case: SCHED => SAME; subst; rewrite in_cons eq_refl.
+ rewrite /sched scheduler_uses_construction_function // /highest_priority_job in SCHED.
+ apply seq_min_in_seq in SCHED.
+ rewrite mem_filter in SCHED.
+ by move: SCHED => /andP [/andP [ARR _] _].
Qed.
(* ... nor after completion. *)
@@ 136,56 +145,49 @@ Module ConcreteScheduler.
}
rewrite [job_cost _]addn0; apply leq_add; first by rewrite EQ.
rewrite leqn0 eqb0 /scheduled_at.
 rewrite /sched scheduler_uses_construction_function.
 rewrite /highest_priority_job.
+ rewrite /sched scheduler_uses_construction_function /highest_priority_job.
apply/eqP; intro HP.
 set jobs := sorted_jobs _ _ _ _ _ _ in HP.
 suff IN: j \in jobs.
 {
 rewrite mem_sort mem_filter in IN.
 move: IN => /andP [/andP [_ NOTCOMP] _].
 by rewrite /completed_by /sched EQ eq_refl in NOTCOMP.
 }
 destruct jobs; first by done.
 by case: HP => SAME; subst; rewrite in_cons eq_refl.
+ apply seq_min_in_seq in HP.
+ by rewrite mem_filter /pending /completed_by EQ eq_refl andbF /= in HP.
Qed.
(* In addition, the scheduler is work conserving... *)
Theorem scheduler_work_conserving:
 work_conserving job_cost job_jitter sched.
+ work_conserving job_arrival job_cost job_jitter arr_seq sched.
Proof.
 intros j t BACK.
+ intros j t IN BACK.
move: BACK => /andP [/andP [ARR NOTCOMP] NOTSCHED].
 rewrite /scheduled_at /sched scheduler_uses_construction_function in NOTSCHED.
 rewrite /scheduled_at /sched scheduler_uses_construction_function.
 case HP: (highest_priority_job _ _ _ _ _ ) => [j_hp];
 first by exists j_hp.
 rewrite /highest_priority_job in HP.
 set jobs := sorted_jobs _ _ _ _ _ _ in HP.
 suff IN: j \in jobs by destruct jobs.
 by rewrite mem_sort mem_filter /pending ARR NOTCOMP /=; apply actual_arrivals_arrived.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function /= in NOTSCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function /=.
+ case HP: (highest_priority_job _ _ _ _ _ ) => [j_hp]; first by exists j_hp.
+ set hp := highest_priority_job _ _ _ _ _ _ _ in NOTSCHED HP.
+ suff BUG: hp != None by rewrite HP in BUG.
+ apply seq_min_exists with (x := j).
+ rewrite mem_filter /pending ARR NOTCOMP /=.
+ by eapply arrived_between_implies_in_actual_arrivals, ARR.
Qed.
(* ... and respects the JLDP policy. *)
Theorem scheduler_respects_policy :
 respects_JLDP_policy job_cost job_jitter sched higher_eq_priority.
+ respects_JLDP_policy job_arrival job_cost job_jitter arr_seq sched higher_eq_priority.
Proof.
rename H_priority_is_transitive into TRANS, H_priority_is_total into TOTAL.
 move => j1 j2 t BACK /eqP SCHED.
+ move => j1 j2 t ARR1 BACK /eqP SCHED.
move: BACK => /andP [/andP [ARR NOTCOMP] NOTSCHED].
 rewrite /scheduled_at /sched scheduler_uses_construction_function in NOTSCHED.
 rewrite /scheduled_at /sched scheduler_uses_construction_function in SCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in NOTSCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in SCHED.
rewrite /highest_priority_job in SCHED NOTSCHED.
 set jobs := sorted_jobs _ _ _ _ _ _ in SCHED NOTSCHED.
+ set jobs := pending_jobs _ _ _ _ _ _ in SCHED NOTSCHED.
have IN: j1 \in jobs.
 by rewrite mem_sort mem_filter /pending ARR NOTCOMP /=; apply actual_arrivals_arrived.
 have SORT: sorted (higher_eq_priority t) jobs by apply sort_sorted.
 destruct jobs as [j0 l]; first by done.
 rewrite in_cons in IN; move: IN => /orP [/eqP EQ  IN];
 first by subst; rewrite /= eq_refl in NOTSCHED.
 case: SCHED => SAME; subst.
 simpl in SORT; apply order_path_min in SORT; last by done.
 by move: SORT => /allP ALL; apply ALL.
+ {
+ rewrite mem_filter /pending ARR NOTCOMP /=.
+ by eapply arrived_between_implies_in_actual_arrivals, ARR.
+ }
+ apply seq_min_computes_min with (y := j1) in SCHED; try (by done).
+ intros x y; rewrite /jobs mem_filter [y \in _]mem_filter.
+ move => /andP [_ INx] /andP [_ INy].
+ rewrite /actual_arrivals_up_to in INx INy.
+ by apply TOTAL; eapply in_actual_arrivals_between_implies_arrived; eauto 2.
Qed.
End Proofs.
diff git a/implementation/uni/susp/dynamic/arrival_sequence.v b/implementation/uni/susp/dynamic/arrival_sequence.v
index 4b2592b..64a12b2 100644
 a/implementation/uni/susp/dynamic/arrival_sequence.v
+++ b/implementation/uni/susp/dynamic/arrival_sequence.v
@@ 12,11 +12,12 @@ Module ConcreteArrivalSequence.
Variable ts: concrete_taskset.
 (* At any time t, we release Some job of tsk if t is a multiple of the period,
+ (* At any time arr_time, we release Some job of tsk if t is a multiple of the period,
otherwise we release None. *)
 Definition add_job (t: time) (tsk: concrete_task) :=
 if task_period tsk % t then
 Some (Build_concrete_job (t %/ task_period tsk) (task_cost tsk) (task_deadline tsk) tsk)
+ Definition add_job (arr_time: time) (tsk: concrete_task) :=
+ if task_period tsk % arr_time then
+ Some (Build_concrete_job (arr_time %/ task_period tsk) arr_time
+ (task_cost tsk) (task_deadline tsk) tsk)
else
None.
@@ 35,14 +36,23 @@ Module ConcreteArrivalSequence.
(* Regarding the periodic arrival sequence built from ts, we prove that...*)
Let arr_seq := periodic_arrival_sequence ts.
+ (* ... arrival times are consistent, ... *)
+ Theorem periodic_arrivals_are_consistent:
+ arrival_times_are_consistent job_arrival arr_seq.
+ Proof.
+ move => j t ARRj.
+ rewrite /arrives_at mem_pmap in ARRj.
+ move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
+ by unfold add_job in *; desf.
+ Qed.
+
(* ... every job comes from the task set, ... *)
Theorem periodic_arrivals_all_jobs_from_taskset:
 forall (j: JobIn arr_seq),
 job_task (job_of_job_in j) \in ts. (* TODO: fix coercion *)
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
Proof.
 intros j.
 destruct j as [j arr ARRj]; simpl.
 unfold arr_seq, arrives_at, periodic_arrival_sequence in *.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj.
move: ARRj => /mapP ARRj; destruct ARRj as [tsk IN SOME].
by unfold add_job in *; desf.
@@ 50,13 +60,13 @@ Module ConcreteArrivalSequence.
(* ..., jobs have valid parameters, ... *)
Theorem periodic_arrivals_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
Proof.
rename H_valid_task_parameters into PARAMS.
unfold valid_sporadic_taskset, is_valid_sporadic_task in *.
 intros j; destruct j as [j arr ARRj]; simpl.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in ARRj.
+ move => j [t ARRj].
rewrite mem_pmap in ARRj; move: ARRj => /mapP [tsk IN SOME].
unfold add_job in SOME; desf.
specialize (PARAMS tsk IN); des.
@@ 66,12 +76,10 @@ Module ConcreteArrivalSequence.
(* ... job arrivals satisfy the sporadic task model, ... *)
Theorem periodic_arrivals_are_sporadic:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
Proof.
 unfold sporadic_task_model; move => j j' /eqP DIFF SAMEtsk LE.
 destruct j as [j arr ARR], j' as [j' arr' ARR']; simpl in *.
 rewrite eqE /= /jobin_eqdef negb_and /= in DIFF.
 unfold arrives_at, arr_seq, periodic_arrival_sequence in *.
+ move => j j' /eqP DIFF [arr ARR] [arr' ARR'] SAMEtsk LE.
+ rewrite eqE /= /job_eqdef negb_and /= SAMEtsk eq_refl orbF in DIFF.
rewrite 2!mem_pmap in ARR ARR'.
move: ARR ARR' => /mapP [tsk_j INj SOMEj] /mapP [tsk_j' INj' SOMEj'].
unfold add_job in SOMEj, SOMEj'; desf; simpl in *;
@@ 81,18 +89,11 @@ Module ConcreteArrivalSequence.
rewrite leq_eqVlt in LE; move: LE => /orP [/eqP EQ  LESS].
{
exfalso; move: DIFF => /negP DIFF; apply DIFF.
 by subst; rewrite EQ.
+ by subst; rewrite EQ !eq_refl.
}
subst; rewrite leq_mul2r; apply/orP; right.
by rewrite ltn_mul2r in LESS; move: LESS => /andP [_ LT].
}
 {
 assert (LT: arr < arr'). by rewrite ltn_neqAle; apply/andP.
 clear LE DIFF; subst tsk_j' arr arr'.
 rewrite ltn_mul2r in LT; move: LT => /andP [_ LT].
 by apply leq_trans with (n := k.+1 * task_period tsk_j);
 [by rewrite mulSnr  by rewrite leq_mul2r; apply/orP; right].
 }
Qed.
(* ... and the arrival sequence has no duplicate jobs. *)
diff git a/implementation/uni/susp/dynamic/job.v b/implementation/uni/susp/dynamic/job.v
index 7705733..07d881a 100644
 a/implementation/uni/susp/dynamic/job.v
+++ b/implementation/uni/susp/dynamic/job.v
@@ 12,6 +12,7 @@ Module ConcreteJob.
Record concrete_job :=
{
job_id: nat;
+ job_arrival: nat;
job_cost: nat;
job_deadline: nat;
job_task: concrete_task_eqType
@@ 21,6 +22,7 @@ Module ConcreteJob.
equality for concrete jobs. *)
Definition job_eqdef (j1 j2: concrete_job) :=
(job_id j1 == job_id j2) &&
+ (job_arrival j1 == job_arrival j2) &&
(job_cost j1 == job_cost j2) &&
(job_deadline j1 == job_deadline j2) &&
(job_task j1 == job_task j2).
@@ 32,7 +34,7 @@ Module ConcreteJob.
destruct (job_eqdef x y) eqn:EQ.
{
apply ReflectT; unfold job_eqdef in *.
 move: EQ => /andP [/andP [/andP [/eqP ID /eqP COST] /eqP DL] /eqP TASK].
+ move: EQ => /andP [/andP [/andP [/andP [/eqP ID /eqP ARR] /eqP COST] /eqP DL] /eqP TASK].
by destruct x, y; simpl in *; subst.
}
{
@@ 41,11 +43,17 @@ Module ConcreteJob.
apply negbT in EQ; rewrite negb_and in EQ.
destruct x, y.
rewrite negb_and in EQ.
 move: EQ => /orP [EQ  /eqP TASK]; last by apply TASK; inversion BUG.
 move: EQ => /orP [EQ  /eqP DL]; last by apply DL; inversion BUG.
+ move: EQ => /orP [EQ  /eqP TASK].
+ move: EQ => /orP [EQ  /eqP DL].
rewrite negb_and in EQ.
 move: EQ => /orP [/eqP ID  /eqP COST]; last by apply COST; inversion BUG.
+ move: EQ => /orP [EQ  /eqP COST].
+ rewrite negb_and in EQ.
+ move: EQ => /orP [/eqP ID  /eqP ARR].
by apply ID; inversion BUG.
+ by apply ARR; inversion BUG.
+ by apply COST; inversion BUG.
+ by apply DL; inversion BUG.
+ by apply TASK; inversion BUG.
}
Qed.
diff git a/implementation/uni/susp/dynamic/oblivious/fp_rta_example.v b/implementation/uni/susp/dynamic/oblivious/fp_rta_example.v
index 33b1548..248eb95 100644
 a/implementation/uni/susp/dynamic/oblivious/fp_rta_example.v
+++ b/implementation/uni/susp/dynamic/oblivious/fp_rta_example.v
@@ 136,14 +136,14 @@ Module ResponseTimeAnalysisFP.
dynamic_suspension_model job_cost job_task next_suspension task_suspension_bound.
(* Also assume ratemonotonic priorities. *)
 Let higher_eq_priority : JLDP_policy arr_seq := (FP_to_JLDP job_task arr_seq (RM task_period)).
+ Let higher_eq_priority := FP_to_JLDP job_task (RM task_period).
(* Next, let sched be the suspensionaware RM schedule with those job suspension times. *)
 Let sched := scheduler job_cost arr_seq next_suspension higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost arr_seq next_suspension higher_eq_priority.
(* To conclude, based on the definition of deadline miss,... *)
Let no_deadline_missed_by :=
 task_misses_no_deadline job_cost job_deadline job_task sched.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* ...we use the result of the suspensionoblivious FP RTA to conclude that
no task misses its deadline. *)
@@ 160,20 +160,22 @@ Module ResponseTimeAnalysisFP.
(task_period := task_period) (task_deadline := task_deadline) (ts0 := ts)
(higher_eq_priority0 := RM task_period) (next_suspension0 := next_suspension)
(task_suspension_bound := task_suspension_bound); try (by done).
+  by apply periodic_arrivals_are_consistent.
 by apply periodic_arrivals_is_a_set.
 by apply periodic_arrivals_all_jobs_from_taskset.
 by apply periodic_arrivals_are_sporadic.
 by apply RM_is_reflexive.
 by apply RM_is_transitive.
 by intros tsk_a tsk_b INa INb; apply/orP; apply leq_total.
  by apply inflated_cost_le_deadline_and_period.
  by apply scheduler_jobs_must_arrive_to_execute.
  by apply scheduler_completed_jobs_dont_execute; intro j'; specialize (VALID j'); des.
  by apply scheduler_work_conserving.
  apply scheduler_respects_policy.
+  by apply inflated_cost_le_deadline_and_period.
+  by apply scheduler_jobs_come_from_arrival_sequence, periodic_arrivals_are_consistent.
+  by apply scheduler_jobs_must_arrive_to_execute, periodic_arrivals_are_consistent.
+  by apply scheduler_completed_jobs_dont_execute, periodic_arrivals_are_consistent.
+  by apply scheduler_work_conserving, periodic_arrivals_are_consistent.
+  apply scheduler_respects_policy; first by apply periodic_arrivals_are_consistent.
 by intros t; apply RM_is_transitive.
  by intros _ j1 j2; apply leq_total.
  by apply scheduler_respects_self_suspensions.
+  by intros j1 j2 _ _ _; apply leq_total.
+  by apply scheduler_respects_self_suspensions, periodic_arrivals_are_consistent.
 by apply schedulability_test_succeeds.
Qed.
diff git a/implementation/uni/susp/schedule.v b/implementation/uni/susp/schedule.v
index 1c19f70..ae90886 100644
 a/implementation/uni/susp/schedule.v
+++ b/implementation/uni/susp/schedule.v
@@ 14,47 +14,48 @@ Module ConcreteScheduler.
Section Implementation.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
 (* Let arr_seq be any job arrival sequence...*)
+ (* Let arr_seq be any consistent job arrival sequence...*)
Variable arr_seq: arrival_sequence Job.

+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+
(* ...that is subject to job suspensions. *)
Variable next_suspension: job_suspension Job.
(* Also, assume that a JLDP policy is given. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* Next, we show how to recursively construct the schedule. *)
Section ScheduleConstruction.
(* For any time t, suppose that we have generated the schedule prefix in the
interval [0, t). Then, we must define what should be scheduled at time t. *)
 Variable sched_prefix: schedule arr_seq.
+ Variable sched_prefix: schedule Job.
Variable t: time.
(* For simplicity, let's use some local names. *)
 Let is_pending := pending job_cost sched_prefix.
+ Let is_pending := pending job_arrival job_cost sched_prefix.
Let is_suspended :=
 suspended_at job_cost next_suspension sched_prefix.
+ suspended_at job_arrival job_cost next_suspension sched_prefix.
(* Consider the list of pending, nonsuspended jobs at time t. *)
Definition pending_jobs :=
[seq j < jobs_arrived_up_to arr_seq t  is_pending j t && ~~ is_suspended j t].

 (* Then, we sort this list by priority... *)
 Definition sorted_jobs := sort (higher_eq_priority t) pending_jobs.
 (* ...and pick the highestpriority job. *)
 Definition highest_priority_job := ohead sorted_jobs.
+ (* To make the scheduling decision, we just pick one of the highestpriority jobs
+ that are pending (if it exists). *)
+ Definition highest_priority_job :=
+ seq_min (higher_eq_priority t) pending_jobs.
End ScheduleConstruction.
(* Starting from the empty schedule, the final schedule is obtained by iteratively
picking the highestpriority job. *)
 Let empty_schedule : schedule arr_seq := fun t => None.
+ Let empty_schedule : schedule Job := fun t => None.
Definition scheduler :=
 build_schedule_from_prefixes arr_seq highest_priority_job empty_schedule.
+ build_schedule_from_prefixes highest_priority_job empty_schedule.
(* Then, by showing that the construction function depends only on the prefix, ... *)
Lemma scheduler_depends_only_on_prefix:
@@ 63,10 +64,12 @@ Module ConcreteScheduler.
highest_priority_job sched1 t = highest_priority_job sched2 t.
Proof.
intros sched1 sched2 t ALL.
 rewrite /highest_priority_job /sorted_jobs.
+ rewrite /highest_priority_job.
suff SAME: pending_jobs sched1 t = pending_jobs sched2 t by rewrite SAME.
apply eq_in_filter.
 intros j IN; apply JobIn_arrived in IN.
+ rewrite /jobs_arrived_up_to; intros j IN.
+ apply in_arrivals_implies_arrived_before with (job_arrival0 := job_arrival) in IN;
+ last by done.
rewrite /arrived_before ltnS in IN.
rewrite /pending /has_arrived IN 2!andTb.
have COMP: completed_by job_cost sched1 j t =
@@ 92,16 +95,16 @@ Module ConcreteScheduler.
by apply/existsP; exists t0; rewrite /scheduled_at ALL.
}
}
 have BEG: time_after_last_execution sched1 j t =
 time_after_last_execution sched2 j t.
+ have BEG: time_after_last_execution job_arrival sched1 j t =
+ time_after_last_execution job_arrival sched2 j t.
{
rewrite /time_after_last_execution EX.
case: ifP => _; last by done.
f_equal; apply eq_bigl.
by intros t0; rewrite /scheduled_at ALL.
}
 have SUSP: suspension_duration next_suspension sched1 j t =
 suspension_duration next_suspension sched2 j t.
+ have SUSP: suspension_duration job_arrival next_suspension sched1 j t =
+ suspension_duration job_arrival next_suspension sched2 j t.
{
rewrite /suspension_duration BEG; f_equal.
rewrite /service /service_during big_nat_cond [in RHS]big_nat_cond.
@@ 129,42 +132,48 @@ Module ConcreteScheduler.
Section Proofs.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
 (* Let arr_seq be any job arrival sequence with no duplicates... *)
+ (* Assume any job arrival sequence with consistent, nonduplicate arrivals... *)
Variable arr_seq: arrival_sequence Job.
 Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+ Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
(* ...that is subject to suspension times. *)
Variable next_suspension: job_suspension Job.
(* Consider any JLDP policy that is reflexive, transitive and total. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
 Hypothesis H_priority_is_reflexive: JLDP_is_reflexive higher_eq_priority.
+ Variable higher_eq_priority: JLDP_policy Job.
Hypothesis H_priority_is_transitive: JLDP_is_transitive higher_eq_priority.
 Hypothesis H_priority_is_total: JLDP_is_total higher_eq_priority.
+ Hypothesis H_priority_is_total: JLDP_is_total arr_seq higher_eq_priority.
(* Let sched denote our concrete scheduler implementation. *)
 Let sched := scheduler job_cost arr_seq next_suspension higher_eq_priority.
+ Let sched := scheduler job_arrival job_cost arr_seq next_suspension higher_eq_priority.
(* To conclude, we prove the important properties of the scheduler implementation. *)
 (* First, we show that jobs do not execute before they arrive...*)
+ (* First, we show that scheduled jobs come from the arrival sequence. *)
+ Lemma scheduler_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+ Proof.
+ move => j t /eqP SCHED.
+ rewrite /sched scheduler_uses_construction_function // /highest_priority_job in SCHED.
+ apply seq_min_in_seq in SCHED.
+ rewrite mem_filter in SCHED.
+ move: SCHED => /andP [_ ARR].
+ by eapply in_arrivals_implies_arrived, ARR.
+ Qed.
+
+ (* Next, we show that jobs do not execute before they arrive...*)
Theorem scheduler_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Proof.
 unfold jobs_must_arrive_to_execute.
move => j t /eqP SCHED.
 rewrite /sched scheduler_uses_construction_function in SCHED.
 rewrite /highest_priority_job in SCHED.
 set jobs := sorted_jobs _ _ _ _ _ _ in SCHED.
 suff IN: j \in jobs.
 {
 rewrite mem_sort mem_filter in IN.
 by move: IN => /andP [/andP [/andP [ARR _] _] _].
 }
 destruct jobs; first by done.
 by case: SCHED => SAME; subst; rewrite in_cons eq_refl.
+ rewrite /sched scheduler_uses_construction_function // /highest_priority_job in SCHED.
+ apply seq_min_in_seq in SCHED.
+ rewrite mem_filter in SCHED.
+ by move: SCHED => /andP [/andP [/andP [ARR _] _] _].
Qed.
(* ... nor after completion. *)
@@ 182,73 +191,59 @@ Module ConcreteScheduler.
}
rewrite [job_cost _]addn0; apply leq_add; first by rewrite EQ.
rewrite leqn0 eqb0 /scheduled_at.
 rewrite /sched scheduler_uses_construction_function.
+ rewrite /sched scheduler_uses_construction_function //.
rewrite /highest_priority_job.
apply/eqP; intro HP.
 set jobs := sorted_jobs _ _ _ _ _ _ in HP.
 suff IN: j \in jobs.
 {
 rewrite mem_sort mem_filter in IN.
 move: IN => /andP [/andP [/andP [_ NOTCOMP] _] _].
 by rewrite /completed_by /sched EQ eq_refl in NOTCOMP.
 }
 destruct jobs; first by done.
 by case: HP => SAME; subst; rewrite in_cons eq_refl.
+ apply seq_min_in_seq in HP.
+ by rewrite mem_filter /pending /completed_by EQ eq_refl andbF 2!andFb in HP.
Qed.
(* In addition, the scheduler is work conserving, ... *)
Theorem scheduler_work_conserving:
 work_conserving job_cost next_suspension sched.
+ work_conserving job_arrival job_cost next_suspension arr_seq sched.
Proof.
 intros j t BACK.
+ intros j t IN BACK.
move: BACK => /andP [/andP [/andP [ARR NOTCOMP] NOTSCHED] NOTSUSP].
 rewrite /scheduled_at /sched scheduler_uses_construction_function in NOTSCHED.
 rewrite /scheduled_at /sched scheduler_uses_construction_function.
 case HP: (highest_priority_job _ _ _ _ _ ) => [j_hp];
 first by exists j_hp.
 rewrite /highest_priority_job in HP.
 set jobs := sorted_jobs _ _ _ _ _ _ in HP.
 suff IN: j \in jobs by destruct jobs.
 by rewrite mem_sort mem_filter /pending ARR NOTCOMP NOTSUSP /=; apply JobIn_arrived.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in NOTSCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function //.
+ case HP: (highest_priority_job _ _ _ _ _ ) => [j_hp]; first by exists j_hp.
+ set hp := highest_priority_job _ _ _ _ _ _ _ in NOTSCHED HP.
+ suff BUG: hp != None by rewrite HP in BUG.
+ apply seq_min_exists with (x := j).
+ rewrite mem_filter /pending NOTSUSP ARR NOTCOMP /=.
+ by eapply arrived_between_implies_in_arrivals, ARR.
Qed.
(* ... respects the JLDP policy..., *)
Theorem scheduler_respects_policy :
 respects_JLDP_policy job_cost next_suspension sched higher_eq_priority.
+ respects_JLDP_policy job_arrival job_cost next_suspension arr_seq sched higher_eq_priority.
Proof.
rename H_priority_is_transitive into TRANS, H_priority_is_total into TOTAL.
 move => j1 j2 t BACK /eqP SCHED.
+ move => j1 j2 t ARR1 BACK /eqP SCHED.
move: BACK => /andP [/andP [/andP [ARR NOTCOMP] NOTSCHED] NOTSUSP].
 rewrite /scheduled_at /sched scheduler_uses_construction_function in NOTSCHED.
 rewrite /scheduled_at /sched scheduler_uses_construction_function in SCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in NOTSCHED.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in SCHED.
rewrite /highest_priority_job in SCHED NOTSCHED.
 set jobs := sorted_jobs _ _ _ _ _ _ in SCHED NOTSCHED.
+ set jobs := pending_jobs _ _ _ _ _ _ in SCHED NOTSCHED.
have IN: j1 \in jobs.
 by rewrite mem_sort mem_filter /pending ARR NOTCOMP NOTSUSP /=; apply JobIn_arrived.
 have SORT: sorted (higher_eq_priority t) jobs by apply sort_sorted.
 destruct jobs as [j0 l]; first by done.
 rewrite in_cons in IN; move: IN => /orP [/eqP EQ  IN];
 first by subst; rewrite /= eq_refl in NOTSCHED.
 case: SCHED => SAME; subst.
 simpl in SORT; apply order_path_min in SORT; last by done.
 by move: SORT => /allP ALL; apply ALL.
+ {
+ rewrite mem_filter /pending ARR NOTCOMP NOTSUSP /=.
+ by eapply arrived_between_implies_in_arrivals, ARR.
+ }
+ apply seq_min_computes_min with (y := j1) in SCHED; try (by done).
+ by intros x y; rewrite 2!mem_filter; move => /andP [_ INx] /andP [_ INy];
+ apply TOTAL; eapply in_arrivals_implies_arrived; eauto 2.
Qed.
(* ... and respects selfsuspensions. *)
Theorem scheduler_respects_self_suspensions:
 respects_self_suspensions job_cost next_suspension sched.
+ respects_self_suspensions job_arrival job_cost next_suspension sched.
Proof.
move => j t /eqP SCHED.
 rewrite /scheduled_at /sched scheduler_uses_construction_function in SCHED.
 rewrite /highest_priority_job in SCHED.
 set jobs := sorted_jobs _ _ _ _ _ _ in SCHED.
 have IN: j \in jobs.
 {
 destruct jobs; first by done.
 by case: SCHED => SAME; subst; rewrite in_cons eq_refl.
 }
 rewrite mem_sort mem_filter in IN.
 by move: IN => /andP [/andP [_ NOTSUSP] _]; apply/negP.
+ rewrite /scheduled_at /sched scheduler_uses_construction_function // in SCHED.
+ rewrite /highest_priority_job in SCHED; apply seq_min_in_seq in SCHED.
+ rewrite mem_filter in SCHED.
+ by move: SCHED => /andP [/andP [_ NOTSUSP] _]; apply/negP.
Qed.
End Proofs.
diff git a/model/arrival/basic/arrival_bounds.v b/model/arrival/basic/arrival_bounds.v
index 6862761..0cfbb40 100644
 a/model/arrival/basic/arrival_bounds.v
+++ b/model/arrival/basic/arrival_bounds.v
@@ 15,19 +15,20 @@ Module ArrivalBounds.
Variable task_period: Task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > Task.
 (* Consider any job arrival sequence that does not contain duplicate jobs. *)
+ (* Consider any job arrival sequence with consistent, nonduplicate arrivals. *)
Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
 (* In this section, we prove an upper bound on the number of jobs that can arrive
 in any interval. *)
+ (* In this section, we upper bound the number of jobs that can arrive in any interval. *)
Section BoundOnSporadicArrivals.
(* Assume that jobs are sporadic. *)
 Hypothesis H_sporadic_tasks: sporadic_task_model task_period arr_seq job_task.
+ Hypothesis H_sporadic_tasks: sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider any time interval [t1, t2)... *)
Variable t1 t2: time.
@@ 73,9 +74,10 @@ Module ArrivalBounds.
destruct arriving_jobs as [ j l] eqn:EQ; first by done.
have IN: j \in arriving_jobs by rewrite EQ in_cons eq_refl orTb.
rewrite mem_filter in IN; move: IN => /andP [_ ARR].
 rewrite mem_filter in ARR; move: ARR => /andP [GE ARR].
 apply JobIn_arrived in ARR.
 by apply leq_ltn_trans with (n := job_arrival j).
+ apply in_arrivals_implies_arrived_between with (job_arrival0 := job_arrival) in ARR;
+ last by done.
+ move: ARR => /andP [GE LT].
+ by apply: (leq_ltn_trans GE).
Qed.
(* Therefore, if there is one job of tsk arriving during [t1, t2), ... *)
@@ 106,16 +108,16 @@ Module ArrivalBounds.
Hypothesis H_many_arrivals: div_ceil (t2  t1) (task_period tsk) < num_arrivals.
(* Consider the list of jobs ordered by arrival times. *)
 Let by_arrival_time (j j': JobIn arr_seq) := job_arrival j <= job_arrival j'.
+ Let by_arrival_time j j' := job_arrival j <= job_arrival j'.
Let sorted_jobs := sort by_arrival_time arriving_jobs.
(* Based on the notation for the nth job in the sorted list of arrivals, ... *)
 Variable elem: JobIn arr_seq.
 Let nth_task := nth elem sorted_jobs.
+ Variable elem: Job.
+ Let nth_job := nth elem sorted_jobs.
(* ...we identify the first and last jobs and their respective arrival times. *)
 Let j_first := nth_task 0.
 Let j_last := nth_task (num_arrivals.1).
+ Let j_first := nth_job 0.
+ Let j_last := nth_job (num_arrivals.1).
Let a_first := job_arrival j_first.
Let a_last := job_arrival j_last.
@@ 123,8 +125,9 @@ Module ArrivalBounds.
Corollary sporadic_arrival_bound_properties_of_nth:
forall idx,
idx < num_arrivals >
 t1 <= job_arrival (nth_task idx) < t2 /\
 job_task (nth_task idx) = tsk.
+ t1 <= job_arrival (nth_job idx) < t2 /\
+ job_task (nth_job idx) = tsk /\
+ arrives_in arr_seq (nth_job idx).
Proof.
intros idx LTidx.
by apply sorted_arrivals_properties_of_nth.
@@ 196,10 +199,10 @@ Module ArrivalBounds.
rename H_at_least_two_jobs into TWO.
set l := arrivals_of_task_between job_task arr_seq tsk t1 t2; fold l in TWO.
apply contraT; rewrite ltnNge; intro MANY; exfalso.
 have DUMMY: exists (j: JobIn arr_seq), True.
+ have DUMMY: exists (j: Job), True.
{
destruct l eqn:EQ; first by rewrite /= ltn0 in TWO.
 by exists j.
+ by exists s.
} destruct DUMMY as [elem _].
by apply CONTRA; last by apply elem.
Qed.
diff git a/model/arrival/basic/arrival_sequence.v b/model/arrival/basic/arrival_sequence.v
index 59b4b85..cc12c85 100644
 a/model/arrival/basic/arrival_sequence.v
+++ b/model/arrival/basic/arrival_sequence.v
@@ 6,174 +6,235 @@ Module ArrivalSequence.
Export Time.
 (* Next, we define a job arrival sequence (can be infinite). *)
+ (* We begin by defining a job arrival sequence. *)
Section ArrivalSequenceDef.
(* Given any job type with decidable equality, ... *)
Variable Job: eqType.
 (* ..., an arrival sequence is a mapping from time to a sequence of jobs. *)
+ (* ..., an arrival sequence is a mapping from any time to a (finite) sequence of jobs. *)
Definition arrival_sequence := time > seq Job.
End ArrivalSequenceDef.
 (* Note that Job denotes the universe of all possible jobs.
 In order to distinguish jobs of different arrival sequences, next we
 define a subtype of Job called JobIn. *)
 Section JobInArrivalSequence.
+ (* Next, we define properties of jobs in a given arrival sequence. *)
+ Section JobProperties.
+ (* Consider any job arrival sequence. *)
Context {Job: eqType}.
+ Variable arr_seq: arrival_sequence Job.
 (* First we define whether a job arrives in a particular sequence at time t. *)
 Definition arrives_at (j: Job) (arr_seq: arrival_sequence Job) (t: time) :=
 j \in arr_seq t.

 (* Next, we define the type (JobIn arr_seq) to represent a job that belongs to arr_seq.
 (Note: The notation might seem complicated, but it just means that the type JobIn is
 constructed using a Job j, a time t, and a proof of arrival. *)
 Inductive JobIn (arr_seq: arrival_sequence Job) :=
 Build_JobIn j t of (arrives_at j arr_seq t).

 (* Next, we define a coercion that returns the Job contained in the type JobIn. *)
 Coercion job_of_job_in {arr_seq} (j: JobIn arr_seq) : Job :=
 let: Build_JobIn actual_job _ _ := j in actual_job.

 (* Similarly, we define a function that returns the arrival time of the job. *)
 Definition job_arrival {arr_seq: arrival_sequence Job} (j: JobIn arr_seq) :=
 let: Build_JobIn _ arr _ := j in arr.
+ (* First, we define the sequence of jobs arriving at time t. *)
+ Definition jobs_arriving_at (t: time) := arr_seq t.
 (* Finally, we define a decidable equality for JobIn, in order to make
 it compatible with ssreflect (see jobin_eqdec.v). *)
 Load jobin_eqdec.
+ (* Next, we say that job j arrives at a given time t iff it belongs to the
+ corresponding sequence. *)
+ Definition arrives_at (j: Job) (t: time) := j \in jobs_arriving_at t.
 End JobInArrivalSequence.
+ (* Similarly, we define whether job j arrives at some (unknown) time t, i.e.,
+ whether it belongs to the arrival sequence. *)
+ Definition arrives_in (j: Job) := exists t, j \in jobs_arriving_at t.
 (* A valid arrival sequence must satisfy some properties. *)
+ End JobProperties.
+
+ (* Next, we define properties of a valid arrival sequence. *)
Section ArrivalSequenceProperties.
+ (* Assume that job arrival times are known. *)
Context {Job: eqType}.
 Variable arr_seq: arrival_sequence Job.
+ Variable job_arrival: Job > time.
 (* The same job j cannot arrive at two different times. *)
 Definition no_multiple_arrivals :=
 forall (j: Job) t1 t2,
 arrives_at j arr_seq t1 > arrives_at j arr_seq t2 > t1 = t2.
+ (* Consider any job arrival sequence. *)
+ Variable arr_seq: arrival_sequence Job.
 (* The sequence of arrivals at a particular time has no duplicates. *)
 Definition arrival_sequence_is_a_set := forall t, uniq (arr_seq t).
+ (* We say that arrival times are consistent if any job that arrives in the sequence
+ has the corresponding arrival time. *)
+ Definition arrival_times_are_consistent :=
+ forall j t,
+ arrives_at arr_seq j t > job_arrival j = t.
+
+ (* We say that the arrival sequence is a set iff it doesn't contain duplicate jobs
+ at any given time. *)
+ Definition arrival_sequence_is_a_set := forall t, uniq (jobs_arriving_at arr_seq t).
End ArrivalSequenceProperties.
 (* Next, we define whether a job has arrived in an interval. *)
 Section ArrivingJobs.
+ (* Next, we define properties of job arrival times. *)
+ Section PropertiesOfArrivalTime.
+ (* Assume that job arrival times are known. *)
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
 Variable j: JobIn arr_seq.
+ Variable job_arrival: Job > time.
 (* A job has arrived at time t iff it arrives at some time t_0, with 0 <= t_0 <= t. *)
+ (* Let j be any job. *)
+ Variable j: Job.
+
+ (* We say that job j has arrived at time t iff it arrives at some time t_0 with t_0 <= t. *)
Definition has_arrived (t: time) := job_arrival j <= t.
 (* A job arrived before t iff it arrives at some time t_0, with 0 <= t_0 < t. *)
+ (* Next, we say that job j arrived before t iff it arrives at some time t_0 with t_0 < t. *)
Definition arrived_before (t: time) := job_arrival j < t.
 (* A job arrives between t1 and t2 iff it arrives at some time t with t1 <= t < t2. *)
+ (* Finally, we say that job j arrives between t1 and t2 iff it arrives at some time t with
+ t1 <= t < t2. *)
Definition arrived_between (t1 t2: time) := t1 <= job_arrival j < t2.
 End ArrivingJobs.
+ End PropertiesOfArrivalTime.
 (* In this section, we define prefixes of arrival sequences based on JobIn.
 This is not required in the main proofs, but important for instantiating
 a concrete schedule. Feel free to skip this section. *)
+ (* In this section, we define arrival sequence prefixes, which are useful
+ to define (computable) properties over sets of jobs in the schedule. *)
Section ArrivalSequencePrefix.
+ (* Assume that job arrival times are known. *)
Context {Job: eqType}.
 Variable arr_seq: arrival_sequence Job.
+ Variable job_arrival: Job > time.
 (* Let's define a function that takes a job j and converts it to
 Some JobIn (if j arrives at time t), or None otherwise. *)
 Program Definition is_JobIn (t: time) (j: Job) :=
 if (j \in arr_seq t) is true then
 Some (Build_JobIn arr_seq j t _)
 else None.

 (* Now we define the list of every JobIn that arrives at time t as the partial
 map of is_JobIn. *)
 Definition jobs_arriving_at (t: time) := pmap (is_JobIn t) (arr_seq t).
+ (* Consider any job arrival sequence. *)
+ Variable arr_seq: arrival_sequence Job.
 (* By concatenation, we can construct the list of every JobIn that arrived before t2. *)
 Definition jobs_arrived_before (t2: time) :=
 \cat_(t < t2) jobs_arriving_at t.
+ (* By concatenation, we construct the list of jobs that arrived in the interval [t1, t2). *)
+ Definition jobs_arrived_between (t1 t2: time) :=
+ \cat_(t1 <= t < t2) jobs_arriving_at arr_seq t.
 (* Based on that, we define the list of every JobIn that has arrived up to time t2, ... *)
 Definition jobs_arrived_up_to (t2: time) :=
 jobs_arrived_before t2.+1.
+ (* Based on that, we define the list of jobs that arrived up to time t, ...*)
+ Definition jobs_arrived_up_to (t: time) := jobs_arrived_between 0 t.+1.
 (* ...and the list of every JobIn that arrived in the interval [t1, t2). *)
 Definition jobs_arrived_between (t1 t2: time) :=
 [seq j < jobs_arrived_before t2  job_arrival j >= t1].
+ (* ...and the list of jobs that arrived strictly before time t. *)
+ Definition jobs_arrived_before (t: time) := jobs_arrived_between 0 t.
+ (* In this section, we prove some lemmas about arrival sequence prefixes. *)
Section Lemmas.

 (* There's an inverse function for recovering the original Job from JobIn. *)
 Lemma is_JobIn_inverse :
 forall t,
 ocancel (is_JobIn t) job_of_job_in.
 Proof.
 by intros t; red; intros x; unfold is_JobIn; des_eqrefl.
 Qed.

 (* Prove that a member of the list indeed satisfies the property. *)
 Lemma JobIn_arrived:
 forall j t,
 j \in jobs_arrived_before t <> arrived_before j t.
 Proof.
 intros j t; split.
 {
 intros IN; apply mem_bigcat_ord_exists in IN; destruct IN as [t0 IN].
 unfold jobs_arriving_at in IN.
 rewrite mem_pmap in IN.
 move: IN => /mapP [j' IN SOME].
 unfold is_JobIn in SOME.
 des_eqrefl; last by done.
 inversion SOME; subst.
 unfold has_arrived; simpl.
 by apply ltn_ord.
 }
 {
 unfold has_arrived; intros ARRIVED.
 apply mem_bigcat_ord with (j := Ordinal ARRIVED); first by done.
 rewrite mem_pmap; apply/mapP; exists j;
 first by destruct j as [j arr_j ARR].
 destruct j as [j arr_j ARR].
 unfold is_JobIn; des_eqrefl; first by repeat f_equal; apply bool_irrelevance.
 by simpl in *; unfold arrives_at in *; rewrite ARR in EQ.
 }
 Qed.

 (* If the arrival sequence doesn't allow duplicates,
 the same applies for the list of JobIn that arrive. *)
 Lemma JobIn_uniq :
 arrival_sequence_is_a_set arr_seq >
 forall t, uniq (jobs_arrived_before t).
 Proof.
 unfold jobs_arrived_up_to; intros SET t.
 apply bigcat_ord_uniq.
 {
 intros i; unfold jobs_arriving_at.
 apply pmap_uniq with (g := job_of_job_in); first by apply is_JobIn_inverse.
 by apply SET.
 }
 {
 intros x t1 t2 IN1 IN2.
 rewrite 2!mem_pmap in IN1 IN2.
 move: IN1 IN2 => /mapP IN1 /mapP IN2.
 destruct IN1 as [j1 IN1 SOME1], IN2 as [j2 IN2 SOME2].
 unfold is_JobIn in SOME1; des_eqrefl; last by done.
 unfold is_JobIn in SOME2; des_eqrefl; last by done.
 by rewrite SOME1 in SOME2; inversion SOME2; apply ord_inj.
 }
 Qed.
+
+ (* We begin with basic lemmas for manipulating the sequences. *)
+ Section Basic.
+
+ (* First, we show that the set of arriving jobs can be split
+ into disjoint intervals. *)
+ Lemma jobs_arrived_between_mem_cat:
+ forall j t1 t t2,
+ t1 <= t >
+ t <= t2 >
+ j \in jobs_arrived_between t1 t2 =
+ (j \in jobs_arrived_between t1 t ++ jobs_arrived_between t t2).
+ Proof.
+ unfold jobs_arrived_between; intros j t1 t t2 GE LE.
+ apply/idP/idP.
+ {
+ intros IN.
+ apply mem_bigcat_nat_exists in IN; move: IN => [arr [IN /andP [GE1 LT2]]].
+ rewrite mem_cat; apply/orP.
+ by destruct (ltnP arr t); [left  right];
+ apply mem_bigcat_nat with (j := arr); try (by apply/andP; split).
+ }
+ {
+ rewrite mem_cat; move => /orP [LEFT  RIGHT].
+ {
+ apply mem_bigcat_nat_exists in LEFT; move: LEFT => [t0 [IN0 /andP [GE0 LT0]]].
+ apply mem_bigcat_nat with (j := t0); last by done.
+ by rewrite GE0 /=; apply: (leq_trans LT0).
+ }
+ {
+ apply mem_bigcat_nat_exists in RIGHT; move: RIGHT => [t0 [IN0 /andP [GE0 LT0]]].
+ apply mem_bigcat_nat with (j := t0); last by done.
+ by rewrite LT0 andbT; apply: (leq_trans _ GE0).
+ }
+ }
+ Qed.
+
+ Lemma jobs_arrived_between_sub:
+ forall j t1 t1' t2 t2',
+ t1' <= t1 >
+ t2 <= t2' >
+ j \in jobs_arrived_between t1 t2 >
+ j \in jobs_arrived_between t1' t2'.
+ Proof.
+ intros j t1 t1' t2 t2' GE1 LE2 IN.
+ move: (leq_total t1 t2) => /orP [BEFORE  AFTER];
+ last by rewrite /jobs_arrived_between big_geq // in IN.
+ rewrite /jobs_arrived_between.
+ rewrite > big_cat_nat with (n := t1); [simpl  by done  by apply: (leq_trans BEFORE)].
+ rewrite mem_cat; apply/orP; right.
+ rewrite > big_cat_nat with (n := t2); [simpl  by done  by done].
+ by rewrite mem_cat; apply/orP; left.
+ Qed.
+
+ End Basic.
+
+ (* Next, we relate the arrival prefixes with job arrival times. *)
+ Section ArrivalTimes.
+
+ (* Assume that job arrival times are consistent. *)
+ Hypothesis H_arrival_times_are_consistent:
+ arrival_times_are_consistent job_arrival arr_seq.
+
+ (* First, we prove that if a job belongs to the prefix (jobs_arrived_before t),
+ then it arrives in the arrival sequence. *)
+ Lemma in_arrivals_implies_arrived:
+ forall j t1 t2,
+ j \in jobs_arrived_between t1 t2 >
+ arrives_in arr_seq j.
+ Proof.
+ rename H_arrival_times_are_consistent into CONS.
+ intros j t1 t2 IN.
+ apply mem_bigcat_nat_exists in IN.
+ move: IN => [arr [IN _]].
+ by exists arr.
+ Qed.
+
+ (* Next, we prove that if a job belongs to the prefix (jobs_arrived_between t1 t2),
+ then it indeed arrives between t1 and t2. *)
+ Lemma in_arrivals_implies_arrived_between:
+ forall j t1 t2,
+ j \in jobs_arrived_between t1 t2 >
+ arrived_between job_arrival j t1 t2.
+ Proof.
+ rename H_arrival_times_are_consistent into CONS.
+ intros j t1 t2 IN.
+ apply mem_bigcat_nat_exists in IN.
+ move: IN => [t0 [IN /= LT]].
+ by apply CONS in IN; rewrite /arrived_between IN.
+ Qed.
+
+ (* Similarly, if a job belongs to the prefix (jobs_arrived_before t),
+ then it indeed arrives before time t. *)
+ Lemma in_arrivals_implies_arrived_before:
+ forall j t,
+ j \in jobs_arrived_before t >
+ arrived_before job_arrival j t.
+ Proof.
+ intros j t IN.
+ suff: arrived_between job_arrival j 0 t by rewrite /arrived_between /=.
+ by apply in_arrivals_implies_arrived_between.
+ Qed.
+
+ (* Similarly, we prove that if a job from the arrival sequence arrives before t,
+ then it belongs to the sequence (jobs_arrived_before t). *)
+ Lemma arrived_between_implies_in_arrivals:
+ forall j t1 t2,
+ arrives_in arr_seq j >
+ arrived_between job_arrival j t1 t2 >
+ j \in jobs_arrived_between t1 t2.
+ Proof.
+ rename H_arrival_times_are_consistent into CONS.
+ move => j t1 t2 [a_j ARRj] BEFORE.
+ have SAME := ARRj; apply CONS in SAME; subst a_j.
+ by apply mem_bigcat_nat with (j := (job_arrival j)).
+ Qed.
+
+ (* Next, we prove that if the arrival sequence doesn't contain duplicate jobs,
+ the same applies for any of its prefixes. *)
+ Lemma arrivals_uniq :
+ arrival_sequence_is_a_set arr_seq >
+ forall t1 t2, uniq (jobs_arrived_between t1 t2).
+ Proof.
+ rename H_arrival_times_are_consistent into CONS.
+ unfold jobs_arrived_up_to; intros SET t1 t2.
+ apply bigcat_nat_uniq; first by done.
+ intros x t t' IN1 IN2.
+ by apply CONS in IN1; apply CONS in IN2; subst.
+ Qed.
+
+ End ArrivalTimes.
End Lemmas.
diff git a/model/arrival/basic/jobin_eqdec.v b/model/arrival/basic/jobin_eqdec.v
deleted file mode 100644
index 7b36dda..0000000
 a/model/arrival/basic/jobin_eqdec.v
+++ /dev/null
@@ 1,29 +0,0 @@
(* The decidable equality for JobIn checks whether the Job
 and the arrival times are the same. *)
Definition jobin_eqdef arr_seq (j1 j2: JobIn arr_seq) :=
 (job_of_job_in j1 == job_of_job_in j2) && (job_arrival j1 == job_arrival j2).

Lemma eqn_jobin : forall arr_seq, Equality.axiom (jobin_eqdef arr_seq).
Proof.
 unfold Equality.axiom; intros arr_seq x y.
 destruct (jobin_eqdef arr_seq x y) eqn:EQ.
 {
 apply ReflectT.
 unfold jobin_eqdef in *.
 move: EQ => /andP [/eqP EQjob /eqP EQarr].
 destruct x, y; ins; subst.
 f_equal; apply bool_irrelevance.
 }
 {
 apply ReflectF.
 unfold jobin_eqdef, not in *; intro BUG.
 apply negbT in EQ; rewrite negb_and in EQ.
 destruct x, y.
 move: EQ => /orP [/negP DIFFjob  /negP DIFFarr].
 by apply DIFFjob; inversion BUG; subst; apply/eqP.
 by apply DIFFarr; inversion BUG; subst; apply/eqP.
 }
Qed.

Canonical jobin_eqMixin arr_seq := EqMixin (eqn_jobin arr_seq).
Canonical jobin_eqType arr_seq := Eval hnf in EqType (JobIn arr_seq) (jobin_eqMixin arr_seq).
\ No newline at end of file
diff git a/model/arrival/basic/task_arrival.v b/model/arrival/basic/task_arrival.v
index 89b8261..a55fa51 100644
 a/model/arrival/basic/task_arrival.v
+++ b/model/arrival/basic/task_arrival.v
@@ 13,16 +13,20 @@ Module TaskArrival.
Variable task_period: Task > time.
Context {Job: eqType}.
 Variable arr_seq: arrival_sequence Job.
+ Variable job_arrival: Job > time.
Variable job_task: Job > Task.
+ (* Consider any job arrival sequence. *)
+ Variable arr_seq: arrival_sequence Job.
+
(* Then, we define the sporadic task model as follows.*)

Definition sporadic_task_model :=
 forall (j j': JobIn arr_seq),
 j <> j' > (* Given two different jobs j and j' ... *)
 job_task j = job_task j' > (* ... of the same task, ... *)
 job_arrival j <= job_arrival j' > (* ... if the arrival of j precedes the arrival of j' ..., *)
+ forall (j j': Job),
+ j <> j' > (* Given two different jobs j and j' ... *)
+ arrives_in arr_seq j > (* ...that belong to the arrival sequence... *)
+ arrives_in arr_seq j' >
+ job_task j = job_task j' > (* ... and that are spawned by the same task, ... *)
+ job_arrival j <= job_arrival j' > (* ... if the arrival of j precedes the arrival of j' ..., *)
(* then the arrival of j and the arrival of j' are separated by at least one period. *)
job_arrival j' >= job_arrival j + task_period (job_task j).
@@ 32,6 +36,7 @@ Module TaskArrival.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_task: Job > Task.
(* Consider any job arrival sequence ...*)
@@ 44,7 +49,7 @@ Module TaskArrival.
Variable tsk: Task.
(* By checking the task that spawns each job, ...*)
 Definition is_job_of_task (j: JobIn arr_seq) := job_task j == tsk.
+ Definition is_job_of_task (j: Job) := job_task j == tsk.
(* ...we can identify the jobs of tsk that arrived in any interval [t1, t2) ... *)
Definition arrivals_of_task_between (t1 t2: time) :=
@@ 62,21 +67,24 @@ Module TaskArrival.
Context {Task: eqType}.
Variable task_period: Task > time.
+
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_task: Job > Task.
 (* Consider any arrival sequence with no duplicate arrivals, ... *)
+ (* Consider any arrival sequence with consistent, nonduplicate arrivals, ... *)
Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_consistent_arrivals: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
 (* ...where jobs are sporadic. *)
+ (* ...where jobs follow the sporadic task model. *)
Hypothesis H_sporadic_jobs:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Let tsk be any task to be scheduled. *)
Variable tsk: Task.
 (* Consider any time interval [t1, t2)... *)
+ (* Consider any time interval [t1, t2). *)
Variable t1 t2: time.
(* Recall the jobs of tsk during [t1, t2), along with the number of arrivals. *)
@@ 84,11 +92,11 @@ Module TaskArrival.
Let num_arrivals := num_arrivals_of_task job_task arr_seq tsk t1 t2.
(* Consider the sequence of jobs ordered by arrival times. *)
 Let by_arrival_time (j j': JobIn arr_seq) := job_arrival j <= job_arrival j'.
+ Let by_arrival_time (j j': Job) := job_arrival j <= job_arrival j'.
Let sorted_jobs := sort by_arrival_time arriving_jobs.
(* Let (nth_job i) denote the ith job in the sorted sequence. *)
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let nth_job := nth elem sorted_jobs.
(* First, we recall some trivial properties about nth_job. *)
@@ 96,15 +104,17 @@ Module TaskArrival.
forall idx,
idx < num_arrivals >
t1 <= job_arrival (nth_job idx) < t2 /\
 job_task (nth_job idx) = tsk.
+ job_task (nth_job idx) = tsk /\
+ arrives_in arr_seq (nth_job idx).
Proof.
+ rename H_consistent_arrivals into CONS.
intros idx LTidx.
have IN: nth_job idx \in sorted_jobs by rewrite mem_nth // size_sort.
 rewrite mem_sort in IN.
 rewrite 2!mem_filter in IN.
 move: IN => /andP [JOB /andP [GE LT]]; apply JobIn_arrived in LT.
 split; last by apply/eqP.
 by apply/andP; split.
+ rewrite mem_sort mem_filter in IN.
+ move: IN => /andP [JOB IN]; move: (IN) => LT.
+ apply in_arrivals_implies_arrived in IN.
+ eapply in_arrivals_implies_arrived_between in LT; last by eauto.
+ by repeat split; try (by done); apply/eqP.
Qed.
(* Next, we conclude that consecutive jobs are different. *)
@@ 119,16 +129,9 @@ Module TaskArrival.
rewrite nth_uniq ?size_sort /arriving_jobs
/(num_arrivals_of_task _ _ _ _ _) /num_arrivals;
first by rewrite neq_ltn ltnSn orTb.
 {
 by apply leq_trans with (n := n.+1); last by rewrite EQ.
 }
 {
 by rewrite EQ ltnS.
 }
 {
 rewrite sort_uniq filter_uniq // filter_uniq //.
 by apply JobIn_uniq.
 }
+  by apply leq_trans with (n := n.+1); last by rewrite EQ.
+  by rewrite EQ ltnS.
+  by rewrite sort_uniq filter_uniq //; eapply arrivals_uniq; eauto 1.
Qed.
(* Since the list is sorted, we prove that each job arrives at
@@ 147,9 +150,9 @@ Module TaskArrival.
exploit (NTH idx);
[by apply leq_trans with (n := n.+1)  intro NTH1].
exploit (NTH idx.+1); [by rewrite ltnS  intro NTH2].
 move: NTH1 NTH2 => [_ JOB1] [_ JOB2].
+ move: NTH1 NTH2 => [_ [JOB1 ARR1]] [_ [JOB2 ARR2]].
rewrite JOB1.
 apply SPO; [by apply NEQ  by rewrite JOB1 JOB2 ].
+ apply SPO; try (by done); [by apply NEQ  by rewrite JOB1 JOB2 ].
suff ORDERED: by_arrival_time (nth_job idx) (nth_job idx.+1) by done.
apply sort_ordered;
first by apply sort_sorted; intros x y; apply leq_total.
diff git a/model/arrival/jitter/arrival_bounds.v b/model/arrival/jitter/arrival_bounds.v
index 83726d3..6828eb9 100644
 a/model/arrival/jitter/arrival_bounds.v
+++ b/model/arrival/jitter/arrival_bounds.v
@@ 19,27 +19,31 @@ Module ArrivalBounds.
Variable task_jitter: Task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
Variable job_task: Job > Task.
 (* Consider any job arrival sequence that does not contain duplicate jobs,... *)
+ (* Consider any job arrival sequence with consistent, nonduplicate arrivals... *)
Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_arrival_sequence_is_a_set: arrival_sequence_is_a_set arr_seq.
(* ...where the jitter of each job is bounded by the jitter of its task. *)
Hypothesis H_job_jitter_bounded:
 forall (j: JobIn arr_seq), job_jitter_leq_task_jitter task_jitter job_jitter job_task j.
+ forall j,
+ arrives_in arr_seq j >
+ job_jitter_leq_task_jitter task_jitter job_jitter job_task j.
(* For simplicity, let's define some local names. *)
 Let actual_job_arrival (j: JobIn arr_seq) := actual_arrival job_jitter j.
+ Let actual_job_arrival := actual_arrival job_arrival job_jitter.
(* In this section, we prove an upper bound on the number of jobs with actual arrival time
in a given interval. *)
Section UpperBoundOn.
(* Assume that jobs are sporadic. *)
 Hypothesis H_sporadic_tasks: sporadic_task_model task_period arr_seq job_task.
+ Hypothesis H_sporadic_tasks: sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider any time interval [t1, t2)... *)
Variable t1 t2: time.
@@ 50,8 +54,10 @@ Module ArrivalBounds.
(* Recall the jobs of tsk with actual arrival time in [t1, t2), along with the corresponding
number of arrivals. *)
 Let actual_arrivals := actual_arrivals_of_task_between job_jitter job_task arr_seq tsk t1 t2.
 Let num_actual_arrivals := num_actual_arrivals_of_task job_jitter job_task arr_seq tsk t1 t2.
+ Let actual_arrivals := actual_arrivals_of_task_between job_arrival job_jitter
+ job_task arr_seq tsk t1 t2.
+ Let num_actual_arrivals := num_actual_arrivals_of_task job_arrival job_jitter job_task
+ arr_seq tsk t1 t2.
(* We will establish an upper bound on the number of actual arrivals of tsk.
The proof follows by case analysis. *)
@@ 86,8 +92,7 @@ Module ArrivalBounds.
have IN: j \in actual_arrivals by rewrite EQ in_cons eq_refl orTb.
rewrite mem_filter in IN; move: IN => /andP [_ ARR].
rewrite mem_filter in ARR; move: ARR => /andP [GE ARR].
 apply actual_arrivals_arrived in ARR.
 by apply leq_ltn_trans with (n := actual_arrival job_jitter j).
+ by move: GE => /andP [GE LE]; apply: (leq_ltn_trans GE).
Qed.
(* Therefore, if there is one job of tsk with actual arrival time in [t1, t2), ... *)
@@ 120,16 +125,16 @@ Module ArrivalBounds.
div_ceil (t2 + task_jitter tsk  t1) (task_period tsk) < num_actual_arrivals.
(* Consider the list of jobs ordered by arrival times. *)
 Let by_arrival_time (j j': JobIn arr_seq) := job_arrival j <= job_arrival j'.
+ Let by_arrival_time j j' := job_arrival j <= job_arrival j'.
Let sorted_jobs := sort by_arrival_time actual_arrivals.
(* Based on the notation for the nth job in the sorted list of arrivals, ... *)
 Variable elem: JobIn arr_seq.
 Let nth_task := nth elem sorted_jobs.
+ Variable elem: Job.
+ Let nth_job := nth elem sorted_jobs.
(* ...we identify the first and last jobs and their respective arrival times. *)
 Let j_first := nth_task 0.
 Let j_last := nth_task (num_actual_arrivals.1).
+ Let j_first := nth_job 0.
+ Let j_last := nth_job (num_actual_arrivals.1).
Let a_first := job_arrival j_first.
Let a_last := job_arrival j_last.
@@ 138,8 +143,9 @@ Module ArrivalBounds.
Corollary sporadic_arrival_bound_properties_of_nth:
forall idx,
idx < num_actual_arrivals >
 t1 <= actual_job_arrival (nth_task idx) < t2 /\
 job_task (nth_task idx) = tsk.
+ t1 <= actual_job_arrival (nth_job idx) < t2 /\
+ job_task (nth_job idx) = tsk /\
+ arrives_in arr_seq (nth_job idx).
Proof.
by intros idx LTidx; apply sorted_arrivals_properties_of_nth.
Qed.
@@ 216,10 +222,10 @@ Module ArrivalBounds.
rename H_at_least_two_jobs into TWO.
set l := actual_arrivals_of_task_between _ _ _ _ _ _; fold l in TWO.
apply contraT; rewrite ltnNge; intro MANY; exfalso.
 have DUMMY: exists (j: JobIn arr_seq), True.
+ have DUMMY: exists (j: Job), True.
{
destruct l eqn:EQ; first by rewrite /= ltn0 in TWO.
 by exists j.
+ by exists s.
} destruct DUMMY as [elem _].
by apply CONTRA; last by apply elem.
Qed.
diff git a/model/arrival/jitter/arrival_sequence.v b/model/arrival/jitter/arrival_sequence.v
index 8879658..3ddeb69 100644
 a/model/arrival/jitter/arrival_sequence.v
+++ b/model/arrival/jitter/arrival_sequence.v
@@ 10,11 +10,11 @@ Module ArrivalSequenceWithJitter.
Section ActualArrival.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_jitter: Job > time.
 (* Let j be any job in the arrival sequence. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* We define the actual arrival of job j as the time when the jitter ends. *)
Definition actual_arrival := job_arrival j + job_jitter j.
@@ 35,34 +35,187 @@ Module ArrivalSequenceWithJitter.
Section ArrivingJobs.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_jitter: Job > time.
Variable arr_seq: arrival_sequence Job.
 (* First, we define the actual job arrivals (including jitter) in the interval [0, t)... *)
 Definition actual_arrivals_before (t: time) :=
 [seq j < jobs_arrived_before arr_seq t  actual_arrival job_jitter j < t].
+ (* For simplicity, let's define some local names. *)
+ Let actual_job_arrival := actual_arrival job_arrival job_jitter.
+ Let actual_job_arrival_between := actual_arrival_between job_arrival job_jitter.
+ Let actual_job_arrival_before := actual_arrival_before job_arrival job_jitter.
+ Let arrivals_before := jobs_arrived_before arr_seq.
 (* ...and in the interval [0, t]. *)
 Definition actual_arrivals_up_to (t: time) := actual_arrivals_before t.+1.

 (* Similarly, we also define the actual job arrivals in the interval [t1, t2). *)
+ (* First, we define the actual job arrivals in the interval [t1, t2). *)
Definition actual_arrivals_between (t1 t2: time) :=
 [seq j < actual_arrivals_before t2  actual_arrival job_jitter j >= t1].
+ [seq j < arrivals_before t2  t1 <= actual_job_arrival j < t2].
+
+ (* Similarly, we define the actual job arrivals up to time t... *)
+ Definition actual_arrivals_up_to (t: time) := actual_arrivals_between 0 t.+1.
+
+ (* ...and the actual job arrivals strictly before time t. *)
+ Definition actual_arrivals_before (t: time) := actual_arrivals_between 0 t.
+ (* In this section, we prove some lemmas about the arrival sequence prefixes. *)
Section Lemmas.

 (* We prove that jobs are in the list of actual arrivals iff they actually arrived. *)
 Lemma actual_arrivals_arrived:
 forall j t,
 j \in actual_arrivals_before t <> actual_arrival_before job_jitter j t.
 Proof.
 intros j t; split; first by rewrite mem_filter; move => /andP [LE IN].
 intros ARRIVED.
 rewrite mem_filter; apply/andP; split; first by done.
 apply JobIn_arrived.
 by apply leq_ltn_trans with (n := actual_arrival job_jitter j); first by apply leq_addr.
 Qed.

+
+ (* Assume that job arrival times are consistent. *)
+ Hypothesis H_arrival_times_are_consistent:
+ arrival_times_are_consistent job_arrival arr_seq.
+
+ (* We begin with basic lemmas for manipulating the sequences. *)
+ Section Basic.
+
+ (* First, we show that the set of arriving jobs can be split
+ into disjoint intervals. *)
+ Lemma actual_arrivals_between_mem_cat:
+ forall j t1 t t2,
+ t1 <= t >
+ t <= t2 >
+ j \in actual_arrivals_between t1 t2 =
+ (j \in actual_arrivals_between t1 t ++ actual_arrivals_between t t2).
+ Proof.
+ unfold actual_arrivals_between; intros j t1 t t2 GE LE.
+ apply/idP/idP.
+ {
+ intros IN.
+ rewrite mem_filter in IN; move: IN => /andP [/andP [GE1 LT2] IN].
+ rewrite mem_cat; apply/orP.
+ rewrite 2!mem_filter.
+ case (ltnP (actual_job_arrival j) t) => [BEFORE  AFTER]; last by right; rewrite LT2.
+ left; rewrite GE1 /=.
+ have INarr: arrives_in arr_seq j by apply in_arrivals_implies_arrived in IN.
+ apply arrived_between_implies_in_arrivals with (job_arrival0 := job_arrival);
+ try (by done).
+ by apply: (leq_ltn_trans _ BEFORE); apply leq_addr.
+ }
+ {
+ rewrite mem_cat; move => /orP [LEFT  RIGHT].
+ {
+ rewrite mem_filter in LEFT; move: LEFT => /andP [ /andP [GE0 LT0] IN0].
+ rewrite mem_filter GE0 /=.
+ apply/andP; split; first by apply: (leq_trans _ LE).
+ have INarr: arrives_in arr_seq j by apply in_arrivals_implies_arrived in IN0.
+ apply arrived_between_implies_in_arrivals with (job_arrival0 := job_arrival);
+ try (by done).
+ rewrite /arrived_between /=.
+ by apply: (leq_trans _ LE); apply: (leq_ltn_trans _ LT0); apply leq_addr.
+ }
+ {
+ rewrite mem_filter in RIGHT; move: RIGHT => /andP [/andP [GE0 LT0] IN0].
+ rewrite mem_filter LT0 /= andbT.
+ apply/andP; split; first by apply: (leq_trans GE).
+ have INarr: arrives_in arr_seq j by apply in_arrivals_implies_arrived in IN0.
+ apply arrived_between_implies_in_arrivals with (job_arrival0 := job_arrival);
+ try (by done).
+ by apply: (leq_ltn_trans _ LT0); apply leq_addr.
+ }
+ }
+ Qed.
+
+ Lemma actual_arrivals_between_sub:
+ forall j t1 t1' t2 t2',
+ t1' <= t1 >
+ t2 <= t2' >
+ j \in actual_arrivals_between t1 t2 >
+ j \in actual_arrivals_between t1' t2'.
+ Proof.
+ intros j t1 t1' t2 t2' GE1 LE2 IN.
+ rewrite mem_filter in IN; move: IN => /andP [/andP [GE LE] IN].
+ move: (leq_total t1 t2) => /orP [BEFORE  AFTER]; last first.
+ {
+ suff BUG: t2 < t2 by rewrite ltnn in BUG.
+ by apply: (leq_ltn_trans AFTER); apply: (leq_ltn_trans GE).
+ }
+ rewrite > actual_arrivals_between_mem_cat with (t := t1);
+ [ by done  by apply: (leq_trans BEFORE)].
+ rewrite mem_cat; apply/orP; right.
+ rewrite > actual_arrivals_between_mem_cat with (t := t2);
+ [ by done  by done].
+ rewrite mem_cat; apply/orP; left.
+ by rewrite mem_filter; repeat (apply/andP; split).
+ Qed.
+
+ End Basic.
+
+ (* Next, we relate the arrival prefixes with job arrival times. *)
+ Section ArrivalTimes.
+
+ (* First, we prove that if a job belongs to the prefix (actual_arrivals_before t),
+ then it arrives in the arrival sequence. *)
+ Lemma in_actual_arrivals_between_implies_arrived:
+ forall j t1 t2,
+ j \in actual_arrivals_between t1 t2 >
+ arrives_in arr_seq j.
+ Proof.
+ rename H_arrival_times_are_consistent into CONS.
+ intros j t1 t2 IN.
+ rewrite mem_filter in IN; move: IN => /andP [_ IN].
+ apply mem_bigcat_nat_exists in IN.
+ by move: IN => [t0 /= [IN _]]; exists t0.
+ Qed.
+
+ Lemma in_actual_arrivals_before_implies_arrived:
+ forall j t,
+ j \in actual_arrivals_before t >
+ arrives_in arr_seq j.
+ Proof.
+ rename H_arrival_times_are_consistent into CONS.
+ intros j t IN.
+ rewrite mem_filter in IN; move: IN => /andP [_ IN].
+ apply mem_bigcat_nat_exists in IN.
+ by move: IN => [t0 /= [IN _]]; exists t0.
+ Qed.
+
+ (* Next, we prove that if a job belongs to the prefix (actual_arrivals_before t),
+ then its actual job arrival occured before t. *)
+ Lemma in_actual_arrivals_implies_arrived_before:
+ forall j t,
+ j \in actual_arrivals_before t >
+ actual_job_arrival_before j t.
+ Proof.
+ intros j t IN.
+ by rewrite mem_filter /= in IN; move: IN => /andP [LTt _].
+ Qed.
+
+ (* We also prove that if a job belongs to the prefix (actual_arrivals_between t1 t2),
+ then its actual job arrival occured between t1 and t2. *)
+ Lemma in_actual_arrivals_implies_arrived_between:
+ forall j t1 t2,
+ j \in actual_arrivals_between t1 t2 >
+ actual_job_arrival_between j t1 t2.
+ Proof.
+ intros j t1 t2 IN.
+ by rewrite mem_filter /= in IN; move: IN => /andP [LTt _].
+ Qed.
+
+ (* Similarly, we prove that if a job from the arrival sequence has actual arrival
+ before time t, then it belongs to the sequence (actual_arrivals_before t). *)
+ Lemma arrived_between_implies_in_actual_arrivals:
+ forall j t1 t2,
+ arrives_in arr_seq j >
+ actual_job_arrival_between j t1 t2 >
+ j \in actual_arrivals_between t1 t2.
+ Proof.
+ intros j t1 t2 IN BEFORE.
+ rewrite mem_filter; apply/andP; split; first by done.
+ eapply arrived_between_implies_in_arrivals; [by eauto  by done ].
+ rewrite /arrived_between /=.
+ move: BEFORE => /andP [_ LE].
+ by apply: (leq_ltn_trans _ LE); apply leq_addr.
+ Qed.
+
+ (* Next, we prove that if the arrival sequence doesn't contain duplicate jobs,
+ the same applies for any of its prefixes. *)
+ Lemma actual_arrivals_uniq :
+ arrival_sequence_is_a_set arr_seq >
+ forall t1 t2, uniq (actual_arrivals_between t1 t2).
+ Proof.
+ intros SET t1 t2.
+ by eapply filter_uniq, arrivals_uniq, SET; eauto 1.
+ Qed.
+
+ End ArrivalTimes.
+
End Lemmas.
End ArrivingJobs.
diff git a/model/arrival/jitter/task_arrival.v b/model/arrival/jitter/task_arrival.v
index f650293..f924394 100644
 a/model/arrival/jitter/task_arrival.v
+++ b/model/arrival/jitter/task_arrival.v
@@ 16,6 +16,7 @@ Module TaskArrivalWithJitter.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_jitter: Job > time.
Variable job_task: Job > Task.
@@ 23,13 +24,13 @@ Module TaskArrivalWithJitter.
Variable arr_seq: arrival_sequence Job.
(* ...and recall the list of jobs with actual arrival time in a given interval. *)
 Let arrivals_between := actual_arrivals_between job_jitter arr_seq.
+ Let arrivals_between := actual_arrivals_between job_arrival job_jitter arr_seq.
(* Next, let tsk be any task. *)
Variable tsk: Task.
(* By checking the jobs spawned by tsk... *)
 Definition is_job_of_tsk := is_job_of_task job_task arr_seq tsk.
+ Definition is_job_of_tsk := is_job_of_task job_task tsk.
(* ...we identify the jobs of tsk that arrived in any interval [t1, t2) ... *)
Definition actual_arrivals_of_task_between (t1 t2: time) :=
@@ 49,19 +50,21 @@ Module TaskArrivalWithJitter.
Variable task_period: Task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_jitter: Job > time.
Variable job_task: Job > Task.
 (* Consider any arrival sequence with no duplicate arrivals, ... *)
+ (* Consider any arrival sequence with consistent, nonduplicate arrivals, ... *)
Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_consistent_arrivals: arrival_times_are_consistent job_arrival arr_seq.
Hypothesis H_no_duplicate_arrivals: arrival_sequence_is_a_set arr_seq.
(* ...where jobs are sporadic. *)
Hypothesis H_sporadic_jobs:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* For simplicity, let's define some local names. *)
 Let actual_job_arrival (j: JobIn arr_seq) := actual_arrival job_jitter j.
+ Let actual_job_arrival := actual_arrival job_arrival job_jitter.
(* Next, let tsk be any task to be scheduled. *)
Variable tsk: Task.
@@ 70,15 +73,16 @@ Module TaskArrivalWithJitter.
Variable t1 t2: time.
(* ...and the associated actual arrivals of task tsk. *)
 Let arriving_jobs := actual_arrivals_of_task_between job_jitter job_task arr_seq tsk t1 t2.
 Let num_arrivals := num_actual_arrivals_of_task job_jitter job_task arr_seq tsk t1 t2.
+ Let arriving_jobs := actual_arrivals_of_task_between job_arrival job_jitter
+ job_task arr_seq tsk t1 t2.
+ Let num_arrivals := num_actual_arrivals_of_task job_arrival job_jitter job_task arr_seq tsk t1 t2.
(* Then, consider the sequence of such jobs ordered by arrival times... *)
 Let by_arrival_time (j j': JobIn arr_seq) := job_arrival j <= job_arrival j'.
+ Let by_arrival_time j j' := job_arrival j <= job_arrival j'.
Let sorted_jobs := sort by_arrival_time arriving_jobs.
(* ...and let (nth_job i) denote the ith job in the sorted sequence. *)
 Variable elem: JobIn arr_seq.
+ Variable elem: Job.
Let nth_job := nth elem sorted_jobs.
(* First, we recall some trivial properties about nth_job. *)
@@ 86,15 +90,16 @@ Module TaskArrivalWithJitter.
forall idx,
idx < num_arrivals >
t1 <= actual_job_arrival (nth_job idx) < t2 /\
 job_task (nth_job idx) = tsk.
+ job_task (nth_job idx) = tsk /\
+ arrives_in arr_seq (nth_job idx).
Proof.
intros idx LTidx.
have IN: nth_job idx \in sorted_jobs by rewrite mem_nth // size_sort.
 rewrite mem_sort in IN.
 rewrite 2!mem_filter in IN.
 move: IN => /andP [JOB /andP [GE LT]]; apply actual_arrivals_arrived in LT.
 split; last by apply/eqP.
 by apply/andP; split.
+ rewrite mem_sort mem_filter in IN.
+ move: IN => /andP [JOB IN]; move: (IN) => LT.
+ apply in_actual_arrivals_between_implies_arrived in IN.
+ eapply in_actual_arrivals_implies_arrived_between in LT.
+ by repeat split; try (by done); apply/eqP.
Qed.
(* Next, we conclude that consecutive jobs are different. *)
@@ 107,11 +112,11 @@ Module TaskArrivalWithJitter.
destruct num_arrivals eqn:EQ; first by rewrite ltn0 in LT.
destruct n; [by rewrite ltn0 in LT  simpl in LT].
rewrite nth_uniq ?size_sort /arriving_jobs
 /(num_actual_arrivals_of_task _ _ _ _ _ _) /num_arrivals;
+ /(num_actual_arrivals_of_task _ _ _ _ _ _ _) /num_arrivals;
first by rewrite neq_ltn ltnSn orTb.
 by apply leq_trans with (n := n.+1); last by rewrite EQ.
 by rewrite EQ ltnS.
  by rewrite sort_uniq; do 3 rewrite filter_uniq //; apply JobIn_uniq.
+  by rewrite sort_uniq filter_uniq //; apply actual_arrivals_uniq; eauto 1.
Qed.
(* Since the list is sorted, we prove that each job arrives at
@@ 130,14 +135,14 @@ Module TaskArrivalWithJitter.
exploit (NTH idx);
[by apply leq_trans with (n := n.+1)  intro NTH1].
exploit (NTH idx.+1); [by rewrite ltnS  intro NTH2].
 move: NTH1 NTH2 => [_ JOB1] [_ JOB2].
+ move: NTH1 NTH2 => [_ [JOB1 ARR1]] [_ [JOB2 ARR2]].
rewrite JOB1.
 apply SPO; [by apply NEQ  by rewrite JOB1 JOB2 ].
+ apply SPO; try (by done); [by apply NEQ  by rewrite JOB1 JOB2 ].
suff ORDERED: by_arrival_time (nth_job idx) (nth_job idx.+1) by done.
apply sort_ordered;
first by apply sort_sorted; intros x y; apply leq_total.
rewrite size_sort.
 rewrite /arriving_jobs /(num_actual_arrivals_of_task _ _ _ _ _ _) /num_arrivals.
+ rewrite /arriving_jobs /(num_actual_arrivals_of_task _ _ _ _ _ _ _) /num_arrivals.
by rewrite EQ.
Qed.
diff git a/model/priority.v b/model/priority.v
index 327047a..3166c51 100644
 a/model/priority.v
+++ b/model/priority.v
@@ 9,42 +9,17 @@ Module Priority.
Section PriorityDefs.
 Section FP.

 (* Let Task denote any type of task. *)
 Variable Task: eqType.

 (* We define an FP policy as a relation between tasks. *)
 Definition FP_policy := rel Task.

 End FP.
+ Variable Task: eqType.
+ Variable Job: eqType.
 Section JLFP.

 (* Consider any job arrival sequence. *)
 Context {Job: eqType}.
 Variable arr_seq: arrival_sequence Job.

 (* We define a JLFP policy as a relation between jobs in the arrival sequence. *)
 Definition JLFP_policy := rel (JobIn arr_seq).

 End JLFP.

 Section JLDP.
+ (* We define an FP policy as a relation between tasks, ... *)
+ Definition FP_policy := rel Task.
 (* Consider any job arrival sequence. *)
 Context {Job: eqType}.
 Variable arr_seq: arrival_sequence Job.

 (* We define a JLDP policy as a timedependent relation between jobs
 in the arrival sequence.
 Although this definition doesn't specify how the policy was constructed
 (e.g., whether it depends on the schedule, on job parameters, etc.), it is
 as general as possible. Knowing the priority of the jobs is sufficient
 to make scheduling decisions. *)
 Definition JLDP_policy := time > rel (JobIn arr_seq).
+ (* ...JLFP policy as a relation between jobs, ... *)
+ Definition JLFP_policy := rel Job.
 End JLDP.
+ (* ...and JLDP as any timedependent relation between jobs. *)
+ Definition JLDP_policy := time > rel Job.
End PriorityDefs.
@@ 56,19 +31,18 @@ Module Priority.
Context {Task: eqType}.
Context {Job: eqType}.
Variable job_task: Job > Task.
 Variable arr_seq: arrival_sequence Job.
(* We show how to convert FP to JLFP,... *)
 Definition FP_to_JLFP (task_hp: FP_policy Task) : JLFP_policy arr_seq :=
 fun (jhigh jlow: JobIn arr_seq) =>
+ Definition FP_to_JLFP (task_hp: FP_policy Task) :=
+ fun (jhigh jlow: Job) =>
task_hp (job_task jhigh) (job_task jlow).
(* ...FP to JLDP, ... *)
 Definition FP_to_JLDP (task_hp: FP_policy Task) : JLDP_policy arr_seq :=
+ Definition FP_to_JLDP (task_hp: FP_policy Task) :=
fun (t: time) => FP_to_JLFP task_hp.
(* ...and JLFP to JLDP. *)
 Definition JLFP_to_JLDP (job_hp: JLFP_policy arr_seq) : JLDP_policy arr_seq :=
+ Definition JLFP_to_JLDP (job_hp: JLFP_policy Job) :=
fun (t: time) => job_hp.
End Generalization.
@@ 81,10 +55,7 @@ Module Priority.
Context {Task: eqType}.
Variable job_task: Job > Task.
 (* Consider any job arrival sequence... *)
 Variable arr_seq: arrival_sequence Job.

 (* ...and let task_priority be any FP policy. *)
+ (* Let task_priority be any FP policy. *)
Variable task_priority: FP_policy Task.
(* Now we define the properties. *)
@@ 122,8 +93,9 @@ Module Priority.
(* Consider any JLFP policy. *)
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
 Variable job_priority: JLFP_policy arr_seq.
+ Variable arr_seq: arrival_sequence Job.
+
+ Variable job_priority: JLFP_policy Job.
(* Now we define the properties. *)
@@ 136,8 +108,12 @@ Module Priority.
(* Whether the JLFP policy is transitive. *)
Definition JLFP_is_transitive := transitive job_priority.
 (* Whether the JLFP policy is total. *)
 Definition JLFP_is_total := total job_priority.
+ (* Whether the JLFP policy is total over the arrival sequence. *)
+ Definition JLFP_is_total :=
+ forall j1 j2,
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ job_priority j1 j2  job_priority j2 j1.
End PropertiesJLFP.
@@ 146,8 +122,9 @@ Module Priority.
(* Consider any JLDP policy. *)
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
 Variable job_priority: JLDP_policy arr_seq.
+ Variable arr_seq: arrival_sequence Job.
+
+ Variable job_priority: JLDP_policy Job.
(* Now we define the properties. *)
@@ 165,7 +142,10 @@ Module Priority.
(* Whether the JLDP policy is total. *)
Definition JLDP_is_total :=
 forall t, total (job_priority t).
+ forall j1 j2 t,
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ job_priority t j1 j2  job_priority t j2 j1.
End PropertiesJLDP.
@@ 188,8 +168,6 @@ Module Priority.
Section Properties.
 Variable arr_seq: arrival_sequence Job.

(* RM is reflexive. *)
Lemma RM_is_reflexive : FP_is_reflexive RM.
Proof.
@@ 226,11 +204,13 @@ Module Priority.
Section KnownJLFPPolicies.
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
+ Variable job_arrival: Job > time.
Variable job_deadline: Job > time.
 (* Earliest deadline first (EDF) orders jobs by absolute deadlines. *)
 Definition EDF (j1 j2: JobIn arr_seq) :=
+ Variable arr_seq: arrival_sequence Job.
+
+ (* We define earliest deadline first (EDF) as ordering jobs by absolute deadlines. *)
+ Definition EDF (j1 j2: Job) :=
job_arrival j1 + job_deadline j1 <= job_arrival j2 + job_deadline j2.
Section Properties.
@@ 248,11 +228,11 @@ Module Priority.
Qed.
(* EDF is total. *)
 Lemma EDF_is_total : JLFP_is_total EDF.
+ Lemma EDF_is_total : JLFP_is_total arr_seq EDF.
Proof.
 unfold EDF; intros x y.
 by case (leqP (job_arrival x + job_deadline x)
 (job_arrival y + job_deadline y));
+ unfold EDF; intros x y ARRx ARRy.
+ case (leqP (job_arrival x + job_deadline x)
+ (job_arrival y + job_deadline y));
[by rewrite orTb  by move/ltnW => >].
Qed.
diff git a/model/schedule/apa/affinity.v b/model/schedule/apa/affinity.v
index 76e79c9..2ddd529 100644
 a/model/schedule/apa/affinity.v
+++ b/model/schedule/apa/affinity.v
@@ 51,8 +51,7 @@ Module Affinity.
Variable job_task: Job > sporadic_task.
(* Consider any schedule, ... *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* ... and some affinity alpha. *)
Variable alpha: affinity num_cpus.
diff git a/model/schedule/apa/constrained_deadlines.v b/model/schedule/apa/constrained_deadlines.v
index eecdaca..f3d6c70 100644
 a/model/schedule/apa/constrained_deadlines.v
+++ b/model/schedule/apa/constrained_deadlines.v
@@ 17,23 +17,27 @@ Module ConstrainedDeadlines.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence ... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ... and any schedule of this arrival sequence. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* Assume that every task has a processor affinity alpha. *)
Variable alpha: task_affinity sporadic_task num_cpus.
(* Assume all jobs have valid parameters, ...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* In this section we prove the absence of multiple jobs of the same
@@ 41,47 +45,48 @@ Module ConstrainedDeadlines.
Section NoMultipleJobs.
(* Assume any workconserving prioritybased scheduler. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
Hypothesis H_work_conserving:
 apa_work_conserving job_cost job_task sched alpha.
+ apa_work_conserving job_arrival job_cost job_task arr_seq sched alpha.
Hypothesis H_respects_JLDP_policy:
 respects_JLDP_policy_under_weak_APA job_cost job_task sched alpha higher_eq_priority.
+ respects_JLDP_policy_under_weak_APA job_arrival job_cost job_task arr_seq
+ sched alpha higher_eq_priority.
(* Consider task set ts. *)
Variable ts: taskset_of sporadic_task.
(* Assume that all jobs come from the taskset. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Suppose that jobs are sequential, ...*)
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* ... jobs only execute after they arrive, ... *)
 Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
(* ... and jobs do not execute after completion. *)
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Assume that the schedule satisfies the sporadic task model ...*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider a valid task tsk, ...*)
Variable tsk: sporadic_task.
Hypothesis H_valid_task: is_valid_sporadic_task task_cost task_period task_deadline tsk.
(*... whose job j ... *)
 Variable j: JobIn arr_seq.
 Variable H_job_of_tsk: job_task j = tsk.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
+ Hypothesis H_job_of_tsk: job_task j = tsk.
(*... is backlogged at time t. *)
Variable t: time.
 Hypothesis H_j_backlogged: backlogged job_cost sched j t.
+ Hypothesis H_j_backlogged: backlogged job_arrival job_cost sched j t.
(* Assume that any previous jobs of tsk have completed by the period. *)
Hypothesis H_all_previous_jobs_completed :
 forall (j_other: JobIn arr_seq) tsk_other,
+ forall j_other tsk_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
job_arrival j_other + task_period tsk_other <= t >
completed job_cost sched j_other (job_arrival j_other + task_period (job_task j_other)).
@@ 92,18 +97,20 @@ Module ConstrainedDeadlines.
(* Then, there can be at most one pending job of each task at time t. *)
Lemma platform_at_most_one_pending_job_of_each_task :
forall j1 j2,
 pending job_cost sched j1 t >
 pending job_cost sched j2 t >
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ pending job_arrival job_cost sched j1 t >
+ pending job_arrival job_cost sched j2 t >
job_task j1 = job_task j2 >
j1 = j2.
Proof.
rename H_sporadic_tasks into SPO, H_all_previous_jobs_completed into PREV.
 intros j1 j2 PENDING1 PENDING2 SAMEtsk.
+ intros j1 j2 ARR1 ARR2 PENDING1 PENDING2 SAMEtsk.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: PENDING1 PENDING2 => /andP [ARRIVED1 /negP NOTCOMP1] /andP [ARRIVED2 /negP NOTCOMP2].
destruct (leqP (job_arrival j1) (job_arrival j2)) as [BEFORE1  BEFORE2].
{
 specialize (SPO j1 j2 DIFF SAMEtsk BEFORE1).
+ specialize (SPO j1 j2 DIFF ARR1 ARR2 SAMEtsk BEFORE1).
assert (LEt: job_arrival j1 + task_period (job_task j1) <= t).
{
by apply leq_trans with (n := job_arrival j2); first by done.
@@ 114,7 +121,7 @@ Module ConstrainedDeadlines.
}
{
apply ltnW in BEFORE2.
 exploit (SPO j2 j1); [by red; ins; subst  by rewrite SAMEtsk  by done  intro SPO'].
+ exploit (SPO j2 j1); try (by done); [by red; ins; subst  intro SPO'].
assert (LEt: job_arrival j2 + task_period (job_task j2) <= t).
{
by apply leq_trans with (n := job_arrival j1); first by done.
@@ 134,41 +141,44 @@ Module ConstrainedDeadlines.
(* Assume any workconserving prioritybased scheduler. *)
Variable higher_eq_priority: FP_policy sporadic_task.
 Hypothesis H_work_conserving: apa_work_conserving job_cost job_task sched alpha.
+ Hypothesis H_work_conserving: apa_work_conserving job_arrival job_cost job_task
+ arr_seq sched alpha.
Hypothesis H_respects_JLDP_policy:
 respects_FP_policy_under_weak_APA job_cost job_task sched alpha higher_eq_priority.
+ respects_FP_policy_under_weak_APA job_arrival job_cost job_task arr_seq
+ sched alpha higher_eq_priority.
(* Consider any task set ts. *)
Variable ts: taskset_of sporadic_task.
(* Assume that all jobs come from the taskset. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Suppose that jobs are sequential, ...*)
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* ... jobs only execute after the jitter, ... *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* ... and jobs do not execute after completion. *)
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
(* Assume that the schedule satisfies the sporadic task model ...*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider a valid task tsk, ...*)
Variable tsk: sporadic_task.
Hypothesis H_valid_task: is_valid_sporadic_task task_cost task_period task_deadline tsk.
(*... whose job j ... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Variable H_job_of_tsk: job_task j = tsk.
(*... is backlogged at time t <= job_arrival j + task_period tsk. *)
Variable t: time.
 Hypothesis H_j_backlogged: backlogged job_cost sched j t.
+ Hypothesis H_j_backlogged: backlogged job_arrival job_cost sched j t.
Hypothesis H_t_before_period: t < job_arrival j + task_period tsk.
(* Recall the definition of a higherpriority task in affinity (alpha' tsk). *)
@@ 176,14 +186,16 @@ Module ConstrainedDeadlines.
(* Assume that any jobs of higherpriority tasks complete by their period. *)
Hypothesis H_all_previous_jobs_completed :
 forall (j_other: JobIn arr_seq) tsk_other,
+ forall j_other tsk_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
hp_task_in (alpha tsk) tsk_other >
completed job_cost sched j_other (job_arrival j_other + task_period tsk_other).
(* Assume that any jobs of tsk prior to j complete by their period. *)
Hypothesis H_all_previous_jobs_of_tsk_completed :
 forall j0 : JobIn arr_seq,
+ forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
completed job_cost sched j0 (job_arrival j0 + task_period tsk).
@@ 195,8 +207,10 @@ Module ConstrainedDeadlines.
(* Then, there can be at most one pending job of higherpriority tasks at time t. *)
Lemma platform_fp_no_multiple_jobs_of_interfering_tasks :
forall j1 j2,
 pending job_cost sched j1 t >
 pending job_cost sched j2 t >
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ pending job_arrival job_cost sched j1 t >
+ pending job_arrival job_cost sched j2 t >
job_task j1 = job_task j2 >
hp_task_in (alpha tsk) (job_task j1) >
j1 = j2.
@@ 204,24 +218,24 @@ Module ConstrainedDeadlines.
unfold sporadic_task_model in *.
rename H_sporadic_tasks into SPO, H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_all_previous_jobs_completed into PREV.
 intros j1 j2 PENDING1 PENDING2 SAMEtsk INTERF.
+ intros j1 j2 ARR1 ARR2 PENDING1 PENDING2 SAMEtsk INTERF.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: PENDING1 PENDING2 => /andP [ARRIVED1 /negP NOTCOMP1] /andP [ARRIVED2 /negP NOTCOMP2].
destruct (leqP (job_arrival j1) (job_arrival j2)) as [BEFORE1  BEFORE2].
{
 specialize (SPO j1 j2 DIFF SAMEtsk BEFORE1).
+ specialize (SPO j1 j2 DIFF ARR1 ARR2 SAMEtsk BEFORE1).
assert (LEt: job_arrival j1 + task_period (job_task j1) <= t).
by apply leq_trans with (n := job_arrival j2).
 exploit (PREV j1 (job_task j1)); [by done  by apply INTERF  intros COMP1].
+ exploit (PREV j1 (job_task j1) ARR1); [by done  by apply INTERF  intros COMP1].
apply NOTCOMP1.
by apply completion_monotonic with (t0 := job_arrival j1 + task_period (job_task j1)).
}
{
apply ltnW in BEFORE2.
 exploit (SPO j2 j1); [by red; ins; subst j2  by rewrite SAMEtsk  by done  intro SPO'].
+ exploit (SPO j2 j1); try (by done); [by red; ins; subst j2  intro SPO'].
assert (LEt: job_arrival j2 + task_period (job_task j2) <= t).
by apply leq_trans with (n := job_arrival j1).
 exploit (PREV j2 (job_task j2));
+ exploit (PREV j2 (job_task j2) ARR2);
[by done  by rewrite SAMEtsk  intro COMP2 ].
apply NOTCOMP2.
by apply completion_monotonic with (t0 := job_arrival j2 + task_period (job_task j2)).
@@ 230,10 +244,11 @@ Module ConstrainedDeadlines.
(* Also, there can be at most one pending job of tsk at time t. *)
Lemma platform_fp_no_multiple_jobs_of_tsk :
 forall j',
 pending job_cost sched j' t >
 job_task j' = tsk >
 j' = j.
+ forall j',
+ arrives_in arr_seq j' >
+ pending job_arrival job_cost sched j' t >
+ job_task j' = tsk >
+ j' = j.
Proof.
unfold sporadic_task_model in *.
rename H_sporadic_tasks into SPO,
@@ 241,18 +256,18 @@ Module ConstrainedDeadlines.
H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_all_previous_jobs_completed into PREV,
H_j_backlogged into BACK, H_job_of_tsk into JOBtsk.
 intros j' PENDING' SAMEtsk.
+ intros j' ARR' PENDING' SAMEtsk.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: BACK PENDING' => /andP [/andP [ARRIVED /negP NOTCOMP] NOTSCHED]
/andP [ARRIVED' /negP NOTCOMP'].
destruct (leqP (job_arrival j') (job_arrival j)) as [BEFORE  BEFORE'].
{
 exploit (SPO j' j DIFF); [by rewrite JOBtsk  by done  intro SPO'].
+ exploit (SPO j' j DIFF ARR' H_j_arrives); [by rewrite JOBtsk  by done  intro SPO'].
assert (LEt: job_arrival j' + task_period tsk <= t).
by apply leq_trans with (n := job_arrival j); first by rewrite SAMEtsk.
apply NOTCOMP'.
apply completion_monotonic with (t0 := job_arrival j' + task_period tsk); [by done  by done ].
 apply PREVtsk; first by done.
+ apply PREVtsk; try (by done).
apply leq_trans with (n := job_arrival j' + task_period tsk); last by rewrite SAMEtsk.
rewrite addn1; apply leq_add; first by done.
by unfold is_valid_sporadic_task in *; des.
@@ 261,7 +276,7 @@ Module ConstrainedDeadlines.
unfold has_arrived in *.
rewrite leqNgt in ARRIVED'; move: ARRIVED' => /negP BUG; apply BUG.
apply leq_trans with (n := job_arrival j + task_period tsk); first by done.
 by rewrite JOBtsk; apply SPO;
+ by rewrite JOBtsk; apply SPO; try (by done);
[by red; ins; subst j'  by rewrite SAMEtsk  by apply ltnW].
}
Qed.
diff git a/model/schedule/apa/interference.v b/model/schedule/apa/interference.v
index 8398ed6..8cbd271 100644
 a/model/schedule/apa/interference.v
+++ b/model/schedule/apa/interference.v
@@ 70,6 +70,7 @@ Module Interference.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
@@ 78,16 +79,16 @@ Module Interference.
(* ... and any schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Assume that every job at any time has a processor affinity alpha. *)
Variable alpha: task_affinity sporadic_task num_cpus.
(* Consider any job j that incurs interference. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Recall the definition of backlogged (pending and not scheduled). *)
 Let job_is_backlogged (t: time) := backlogged job_cost sched j t.
+ Let job_is_backlogged (t: time) := backlogged job_arrival job_cost sched j t.
(* First, we define total interference. *)
Section TotalInterference.
@@ 103,7 +104,7 @@ Module Interference.
Section JobInterference.
(* Let job_other be a job that interferes with j. *)
 Variable job_other: JobIn arr_seq.
+ Variable job_other: Job.
(* The interference caused by job_other during [t1, t2) is the cumulative
time in which j is backlogged while job_other is scheduled. *)
@@ 243,7 +244,7 @@ Module Interference.
apply leq_sum; move => t /andP [LEt _].
rewrite exchange_big /=.
apply leq_sum; intros cpu _.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
last by rewrite andFb (eq_bigr (fun x => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
rewrite andTb.
diff git a/model/schedule/apa/interference_edf.v b/model/schedule/apa/interference_edf.v
index cab2414..f4896a2 100644
 a/model/schedule/apa/interference_edf.v
+++ b/model/schedule/apa/interference_edf.v
@@ 13,16 +13,17 @@ Module InterferenceEDF.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* Consider any schedule. *)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Assume that every job at any time has a processor affinity alpha. *)
Variable alpha: task_affinity sporadic_task num_cpus.
@@ 31,28 +32,30 @@ Module InterferenceEDF.
for EDF, i.e., if any job of tsk is backlogged, every processor
must be busy with jobs with no larger absolute deadline. *)
Hypothesis H_scheduler_uses_EDF:
 respects_JLFP_policy_under_weak_APA job_cost job_task sched alpha (EDF job_deadline).
+ respects_JLFP_policy_under_weak_APA job_arrival job_cost job_task arr_seq sched
+ alpha (EDF job_arrival job_deadline).
(* Under EDF scheduling, a job only causes interference if its deadline
is not larger than the deadline of the analyzed job. *)
Lemma interference_under_edf_implies_shorter_deadlines :
 forall (j j': JobIn arr_seq) t1 t2,
 job_interference job_cost job_task sched alpha j' j t1 t2 != 0 >
+ forall j j' t1 t2,
+ arrives_in arr_seq j' >
+ job_interference job_arrival job_cost job_task sched alpha j' j t1 t2 != 0 >
job_arrival j + job_deadline j <= job_arrival j' + job_deadline j'.
Proof.
rename H_scheduler_uses_EDF into PRIO.
unfold respects_JLDP_policy_under_weak_APA in *.
 intros j j' t1 t2 INTERF.
+ intros j j' t1 t2 ARR' INTERF.
unfold job_interference in INTERF.
destruct ([exists t': 'I_t2,
[exists cpu: processor num_cpus,
(t' >= t1) &&
 backlogged job_cost sched j' t' &&
+ backlogged job_arrival job_cost sched j' t' &&
can_execute_on alpha (job_task j') cpu &&
scheduled_on sched j cpu t']]) eqn:EX.
{
move: EX => /existsP [t' /existsP [cpu /andP [/andP [/andP [LE BACK] CAN] SCHED]]].
 by specialize (PRIO j' j cpu t' BACK SCHED CAN).
+ by specialize (PRIO j' j cpu t' ARR' BACK SCHED CAN).
}
{
apply negbT in EX; rewrite negb_exists in EX; move: EX => /forallP ALL.
@@ 65,7 +68,7 @@ Module InterferenceEDF.
rewrite (eq_bigr (fun x => 0));
first by rewrite big_const_ord iter_addn mul0n addn0.
intros cpu _; specialize (ALL cpu); simpl in ALL.
 destruct (backlogged job_cost sched j' i); last by rewrite andFb.
+ destruct (backlogged job_arrival job_cost sched j' i); last by rewrite andFb.
rewrite GEi 2!andTb in ALL; rewrite andTb.
by apply negbTE in ALL; rewrite ALL.
}
diff git a/model/schedule/apa/platform.v b/model/schedule/apa/platform.v
index bb6e1bf..136732d 100644
 a/model/schedule/apa/platform.v
+++ b/model/schedule/apa/platform.v
@@ 17,16 +17,17 @@ Module Platform.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence ... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ... and any schedule of this arrival sequence. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Assume that every task has a processor affinity alpha. *)
Variable alpha: task_affinity sporadic_task num_cpus.
@@ 37,7 +38,8 @@ Module Platform.
processors *on which j can be scheduled* are busy with other jobs. *)
Definition apa_work_conserving :=
forall j t,
 backlogged job_cost sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
forall cpu,
can_execute_on alpha (job_task j) cpu >
exists j_other,
@@ 62,8 +64,9 @@ Module Platform.
executing on j's affinity, then j_hp's task priority
must be as high as j's task priority. *)
Definition respects_FP_policy_under_weak_APA :=
 forall (j j_hp: JobIn arr_seq) cpu t,
 backlogged job_cost sched j t >
+ forall j j_hp cpu t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled_on sched j_hp cpu t >
can_execute_on alpha (job_task j) cpu >
higher_eq_priority (job_task j_hp) (job_task j).
@@ 73,15 +76,16 @@ Module Platform.
Section JLFP.
(* A JLFP policy ...*)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* ... is respected by a weak APA scheduler iff for
any backlogged job j, if there is another job j_hp
executing on j's affinity, then j_hp's priority
must be as high as j's priority. *)
Definition respects_JLFP_policy_under_weak_APA :=
 forall (j j_hp: JobIn arr_seq) cpu t,
 backlogged job_cost sched j t >
+ forall j j_hp cpu t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled_on sched j_hp cpu t >
can_execute_on alpha (job_task j) cpu >
higher_eq_priority j_hp j.
@@ 91,15 +95,16 @@ Module Platform.
Section JLDP.
(* A JLFP/JLDP policy ...*)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* ... is respected by a weak APA scheduler iff at any time t,
for any backlogged job j, if there is another job j_hp
executing on j's affinity, then j_hp's priority must be
as high as j's priority. *)
Definition respects_JLDP_policy_under_weak_APA :=
 forall (j j_hp: JobIn arr_seq) cpu t,
 backlogged job_cost sched j t >
+ forall j j_hp cpu t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled_on sched j_hp cpu t >
can_execute_on alpha (job_task j) cpu >
higher_eq_priority t j_hp j.
diff git a/model/schedule/global/basic/constrained_deadlines.v b/model/schedule/global/basic/constrained_deadlines.v
index 09fa69a..42226bb 100644
 a/model/schedule/global/basic/constrained_deadlines.v
+++ b/model/schedule/global/basic/constrained_deadlines.v
@@ 17,20 +17,24 @@ Module ConstrainedDeadlines.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence ... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ... and any schedule of this arrival sequence. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
(* Assume all jobs have valid parameters, ...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* In this section we prove the absence of multiple jobs of the same
@@ 38,17 +42,18 @@ Module ConstrainedDeadlines.
Section NoMultipleJobs.
(* Assume any workconserving prioritybased scheduler. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Variable higher_eq_priority: JLDP_policy Job.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_respects_JLDP_policy:
 respects_JLDP_policy job_cost sched higher_eq_priority.
+ respects_JLDP_policy job_arrival job_cost arr_seq sched higher_eq_priority.
(* Consider task set ts. *)
Variable ts: taskset_of sporadic_task.
(* Assume that all jobs come from the taskset. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j > job_task j \in ts.
(* Suppose that jobs are sequential, ...*)
Hypothesis H_sequential_jobs: sequential_jobs sched.
@@ 57,27 +62,29 @@ Module ConstrainedDeadlines.
completed_jobs_dont_execute job_cost sched.
(* ... and jobs do not execute after completion. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* Assume that the schedule satisfies the sporadic task model ...*)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider a valid task tsk, ...*)
Variable tsk: sporadic_task.
Hypothesis H_valid_task: is_valid_sporadic_task task_cost task_period task_deadline tsk.
(*... whose job j ... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Variable H_job_of_tsk: job_task j = tsk.
(*... is backlogged at time t. *)
Variable t: time.
 Hypothesis H_j_backlogged: backlogged job_cost sched j t.
+ Hypothesis H_j_backlogged: backlogged job_arrival job_cost sched j t.
(* Assume that any previous jobs of tsk have completed by the period. *)
Hypothesis H_all_previous_jobs_completed :
 forall (j_other: JobIn arr_seq) tsk_other,
+ forall j_other tsk_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
job_arrival j_other + task_period tsk_other <= t >
completed job_cost sched j_other (job_arrival j_other + task_period (job_task j_other)).
@@ 88,19 +95,21 @@ Module ConstrainedDeadlines.
(* Then, there can be at most one pending job of each task at time t. *)
Lemma platform_at_most_one_pending_job_of_each_task :
forall j1 j2,
 pending job_cost sched j1 t >
 pending job_cost sched j2 t >
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ pending job_arrival job_cost sched j1 t >
+ pending job_arrival job_cost sched j2 t >
job_task j1 = job_task j2 >
j1 = j2.
Proof.
rename H_sporadic_tasks into SPO, H_all_previous_jobs_completed into PREV.
 intros j1 j2 PENDING1 PENDING2 SAMEtsk.
+ intros j1 j2 ARR1 ARR2 PENDING1 PENDING2 SAMEtsk.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: PENDING1 PENDING2 => /andP [ARRIVED1 /negP NOTCOMP1] /andP [ARRIVED2 /negP NOTCOMP2].
destruct (leqP (job_arrival j1) (job_arrival j2)) as [BEFORE1  BEFORE2].
{
 specialize (SPO j1 j2 DIFF SAMEtsk BEFORE1).
 exploit (PREV j1 (job_task j1));
+ specialize (SPO j1 j2 DIFF ARR1 ARR2 SAMEtsk BEFORE1).
+ exploit (PREV j1 (job_task j1) ARR1);
[by done  by apply leq_trans with (n := job_arrival j2)  intros COMP1].
apply NOTCOMP1.
apply completion_monotonic with (t0 := job_arrival j1 + task_period (job_task j1));
@@ 109,8 +118,8 @@ Module ConstrainedDeadlines.
}
{
apply ltnW in BEFORE2.
 exploit (SPO j2 j1); [by red; ins; subst  by rewrite SAMEtsk  by done  intro SPO'].
 exploit (PREV j2 (job_task j2));
+ exploit (SPO j2 j1); try (by done); [by red; ins; subst  intro SPO'].
+ exploit (PREV j2 (job_task j2) ARR2);
[by done  by apply leq_trans with (n := job_arrival j1)  intros COMP2].
apply NOTCOMP2.
apply completion_monotonic with (t0 := job_arrival j2 + task_period (job_task j2));
@@ 125,15 +134,12 @@ Module ConstrainedDeadlines.
Proof.
have UNIQ := platform_at_most_one_pending_job_of_each_task.
rename H_all_jobs_from_taskset into FROMTS,
 H_sequential_jobs into SEQUENTIAL,
 H_work_conserving into WORK,
+ H_sequential_jobs into SEQUENTIAL, H_work_conserving into WORK,
H_respects_JLDP_policy into PRIO,
 H_j_backlogged into BACK,
 H_job_of_tsk into JOBtsk,
 H_valid_job_parameters into JOBPARAMS,
+ H_j_backlogged into BACK, H_jobs_come_from_arrival_sequence into FROMarr,
+ H_job_of_tsk into JOBtsk, H_valid_job_parameters into JOBPARAMS,
H_valid_task into TASKPARAMS,
 H_all_previous_jobs_completed into PREV,
 H_completed_jobs_dont_execute into COMP,
+ H_all_previous_jobs_completed into PREV, H_completed_jobs_dont_execute into COMP,
H_jobs_must_arrive_to_execute into ARRIVE.
apply work_conserving_eq_work_conserving_count in WORK.
unfold valid_sporadic_job, valid_realtime_job,
@@ 157,18 +163,21 @@ Module ConstrainedDeadlines.
}
{
rewrite (WORK j t) // count_predT.
 apply leq_trans with (n := count (fun j: JobIn arr_seq => scheduled_task_other_than tsk (job_task j)) (jobs_scheduled_at sched t));
+ apply leq_trans with (n := count (fun j => scheduled_task_other_than tsk (job_task j)) (jobs_scheduled_at sched t));
last first.
{
rewrite count_map.
 apply count_sub_uniqr;
 last by red; move => tsk' /mapP [j' _ JOBtsk']; subst; apply FROMTS.
+ apply count_sub_uniqr; last first.
+ {
+ move => tsk' /mapP [j' INj' JOBtsk']; subst; apply FROMTS.
+ by rewrite mem_scheduled_jobs_eq_scheduled in INj'; eauto 2.
+ }
rewrite map_inj_in_uniq; first by apply scheduled_jobs_uniq.
red; intros j1 j2 SCHED1 SCHED2 SAMEtsk.
rewrite 2!mem_scheduled_jobs_eq_scheduled in SCHED1 SCHED2.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in SCHED1; try (by done).
 apply scheduled_implies_pending with (job_cost0 := job_cost) in SCHED2; try (by done).
 by apply UNIQ.
+ have ARRin1: arrives_in arr_seq j1 by apply (FROMarr j1 t).
+ have ARRin2: arrives_in arr_seq j2 by apply (FROMarr j2 t).
+ by apply UNIQ; try (by done); apply scheduled_implies_pending.
}
{
apply sub_in_count; intros j' SCHED' _.
@@ 181,10 +190,10 @@ Module ConstrainedDeadlines.
{
apply/eqP; red; intro SAMEtsk; symmetry in SAMEtsk.
move: BACK => /andP [PENDING NOTSCHED].
 generalize SCHED'; intro PENDING'.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING'; try (by done).
 exploit (UNIQ j j' PENDING PENDING'); [by rewrite SAMEtsk  intro EQjob; subst].
 by rewrite SCHED' in NOTSCHED.
+ have ARRin': arrives_in arr_seq j' by apply (FROMarr j' t).
+ exploit (UNIQ j j'); try (by done);
+ [by apply scheduled_implies_pending  by rewrite SAMEtsk ].
+ by intro EQjob; subst; rewrite SCHED' in NOTSCHED.
}
}
}
@@ 199,16 +208,17 @@ Module ConstrainedDeadlines.
(* Assume any workconserving prioritybased scheduler. *)
Variable higher_eq_priority: FP_policy sporadic_task.
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_respects_JLDP_policy:
 respects_FP_policy job_cost job_task sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_task arr_seq sched higher_eq_priority.
(* Consider any task set ts. *)
Variable ts: taskset_of sporadic_task.
(* Assume that all jobs come from the taskset. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j > job_task j \in ts.
(* Suppose that jobs are sequential, ...*)
Hypothesis H_sequential_jobs: sequential_jobs sched.
@@ 217,23 +227,24 @@ Module ConstrainedDeadlines.
completed_jobs_dont_execute job_cost sched.
(* ... and jobs do not execute after completion. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* Assume that jobs arrive sporadically. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider a valid task tsk, ...*)
Variable tsk: sporadic_task.
Hypothesis H_valid_task: is_valid_sporadic_task task_cost task_period task_deadline tsk.
(*... whose job j ... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Variable H_job_of_tsk: job_task j = tsk.
(*... is backlogged at time t <= job_arrival j + task_period tsk. *)
Variable t: time.
 Hypothesis H_j_backlogged: backlogged job_cost sched j t.
+ Hypothesis H_j_backlogged: backlogged job_arrival job_cost sched j t.
Hypothesis H_t_before_period: t < job_arrival j + task_period tsk.
(* Recall the definition of a higherpriority task (with respect to tsk). *)
@@ 241,14 +252,16 @@ Module ConstrainedDeadlines.
(* Assume that any jobs of higherpriority tasks complete by their period. *)
Hypothesis H_all_previous_jobs_completed :
 forall (j_other: JobIn arr_seq) tsk_other,
+ forall j_other tsk_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
is_hp_task tsk_other >
completed job_cost sched j_other (job_arrival j_other + task_period tsk_other).
(* Assume that any jobs of tsk prior to j complete by their period. *)
Hypothesis H_all_previous_jobs_of_tsk_completed :
 forall j0 : JobIn arr_seq,
+ forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
completed job_cost sched j0 (job_arrival j0 + task_period tsk).
@@ 259,23 +272,25 @@ Module ConstrainedDeadlines.
(* Then, there can be at most one pending job of higherpriority tasks at time t. *)
Lemma platform_fp_no_multiple_jobs_of_interfering_tasks :
 forall j1 j2,
 pending job_cost sched j1 t >
 pending job_cost sched j2 t >
 job_task j1 = job_task j2 >
 is_hp_task (job_task j1) >
 j1 = j2.
+ forall j1 j2,
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ pending job_arrival job_cost sched j1 t >
+ pending job_arrival job_cost sched j2 t >
+ job_task j1 = job_task j2 >
+ is_hp_task (job_task j1) >
+ j1 = j2.
Proof.
unfold sporadic_task_model in *.
rename H_sporadic_tasks into SPO, H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_all_previous_jobs_completed into PREV.
 intros j1 j2 PENDING1 PENDING2 SAMEtsk INTERF.
+ intros j1 j2 ARR1 ARR2 PENDING1 PENDING2 SAMEtsk INTERF.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: PENDING1 PENDING2 => /andP [ARRIVED1 /negP NOTCOMP1] /andP [ARRIVED2 /negP NOTCOMP2].
destruct (leqP (job_arrival j1) (job_arrival j2)) as [BEFORE1  BEFORE2].
{
 specialize (SPO j1 j2 DIFF SAMEtsk BEFORE1).
 exploit (PREV j1 (job_task j1)); [by done  by apply INTERF  intros COMP1].
+ specialize (SPO j1 j2 DIFF ARR1 ARR2 SAMEtsk BEFORE1).
+ exploit (PREV j1 (job_task j1) ARR1); [by done  by apply INTERF  intros COMP1].
apply NOTCOMP1.
apply completion_monotonic with (t0 := job_arrival j1 + task_period (job_task j1));
try (by done).
@@ 283,8 +298,8 @@ Module ConstrainedDeadlines.
}
{
apply ltnW in BEFORE2.
 exploit (SPO j2 j1); [by red; ins; subst j2  by rewrite SAMEtsk  by done  intro SPO' ].
 exploit (PREV j2 (job_task j2));
+ exploit (SPO j2 j1); try (by done); [by red; ins; subst j2  intro SPO'].
+ exploit (PREV j2 (job_task j2) ARR2);
[by done  by rewrite SAMEtsk  intro COMP2 ].
apply NOTCOMP2.
apply completion_monotonic with (t0 := job_arrival j2 + task_period (job_task j2));
@@ 295,10 +310,11 @@ Module ConstrainedDeadlines.
(* Also, there can be at most one pending job of tsk at time t. *)
Lemma platform_fp_no_multiple_jobs_of_tsk :
 forall j',
 pending job_cost sched j' t >
 job_task j' = tsk >
 j' = j.
+ forall j',
+ arrives_in arr_seq j' >
+ pending job_arrival job_cost sched j' t >
+ job_task j' = tsk >
+ j' = j.
Proof.
unfold sporadic_task_model in *.
rename H_sporadic_tasks into SPO,
@@ 306,18 +322,18 @@ Module ConstrainedDeadlines.
H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_all_previous_jobs_completed into PREV,
H_j_backlogged into BACK, H_job_of_tsk into JOBtsk.
 intros j' PENDING' SAMEtsk.
+ intros j' ARR' PENDING' SAMEtsk.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: BACK PENDING' => /andP [/andP [ARRIVED /negP NOTCOMP] NOTSCHED]
/andP [ARRIVED' /negP NOTCOMP'].
destruct (leqP (job_arrival j') (job_arrival j)) as [BEFORE  BEFORE'].
{
 exploit (SPO j' j DIFF); [by rewrite JOBtsk  by done  intro SPO'].
+ exploit (SPO j' j DIFF ARR' H_j_arrives); [by rewrite JOBtsk  by done  intro SPO'].
apply NOTCOMP'.
apply completion_monotonic with (t0 := job_arrival j' + task_period tsk); try (by done);
first by apply leq_trans with (n := job_arrival j); [by rewrite SAMEtsk  by done].
{
 apply PREVtsk; first by done.
+ apply PREVtsk; try (by done).
apply leq_trans with (n := job_arrival j' + task_period tsk); last by rewrite SAMEtsk.
rewrite addn1; apply leq_add; first by done.
by unfold is_valid_sporadic_task in *; des.
@@ 327,7 +343,7 @@ Module ConstrainedDeadlines.
unfold has_arrived in *.
rewrite leqNgt in ARRIVED'; move: ARRIVED' => /negP BUG; apply BUG.
apply leq_trans with (n := job_arrival j + task_period tsk); first by done.
 by rewrite JOBtsk; apply SPO;
+ by rewrite JOBtsk; apply SPO; try (by done);
[by red; ins; subst j'  by rewrite SAMEtsk  by apply ltnW].
}
Qed.
@@ 338,17 +354,12 @@ Module ConstrainedDeadlines.
Proof.
have UNIQ := platform_fp_no_multiple_jobs_of_interfering_tasks.
have UNIQ' := platform_fp_no_multiple_jobs_of_tsk.
 rename H_all_jobs_from_taskset into FROMTS,
 H_sequential_jobs into SEQUENTIAL,
 H_work_conserving into WORK,
 H_respects_JLDP_policy into PRIO,
 H_j_backlogged into BACK,
 H_job_of_tsk into JOBtsk,
 H_sporadic_tasks into SPO,
 H_valid_job_parameters into JOBPARAMS,
 H_valid_task into TASKPARAMS,
 H_all_previous_jobs_completed into PREV,
 H_completed_jobs_dont_execute into COMP,
+ rename H_all_jobs_from_taskset into FROMTS, H_sequential_jobs into SEQUENTIAL,
+ H_work_conserving into WORK, H_respects_JLDP_policy into PRIO,
+ H_j_backlogged into BACK, H_job_of_tsk into JOBtsk,
+ H_sporadic_tasks into SPO, H_valid_job_parameters into JOBPARAMS,
+ H_valid_task into TASKPARAMS, H_all_previous_jobs_completed into PREV,
+ H_completed_jobs_dont_execute into COMP, H_jobs_come_from_arrival_sequence into FROMarr,
H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_jobs_must_arrive_to_execute into ARRIVE.
apply work_conserving_eq_work_conserving_count in WORK.
@@ 374,22 +385,22 @@ Module ConstrainedDeadlines.
}
{
rewrite (WORK j t) // count_predT.
 apply leq_trans with (n := count (fun j: JobIn arr_seq =>
+ apply leq_trans with (n := count (fun j =>
scheduled_task_with_higher_eq_priority tsk (job_task j)) (jobs_scheduled_at sched t));
last first.
{
rewrite count_map.
 apply leq_trans with (n := count predT [seq x < (map (fun (j: JobIn arr_seq) => job_task j) (jobs_scheduled_at sched t))  scheduled_task_with_higher_eq_priority tsk x]);
+ apply leq_trans with (n := count predT [seq x < (map (fun j => job_task j) (jobs_scheduled_at sched t))  scheduled_task_with_higher_eq_priority tsk x]);
first by rewrite count_filter; apply sub_count; red; ins.
apply leq_trans with (n := count predT [seq x < ts  scheduled_task_with_higher_eq_priority tsk x]);
last by rewrite count_predT size_filter.
 apply count_sub_uniqr;
 last first.
+ apply count_sub_uniqr; last first.
{
red; intros tsk' IN'.
rewrite mem_filter in IN'; move: IN' => /andP [SCHED IN'].
rewrite mem_filter; apply/andP; split; first by done.
 by move: IN' => /mapP [j' _] >; apply FROMTS.
+ move: IN' => /mapP [j' IN'] >; apply FROMTS.
+ by rewrite mem_scheduled_jobs_eq_scheduled in IN'; eauto 2.
}
{
rewrite filter_map.
@@ 398,9 +409,9 @@ Module ConstrainedDeadlines.
rewrite 2!mem_filter in SCHED1 SCHED2.
move: SCHED1 SCHED2 => /andP [/andP [_ HP1] SCHED1] /andP [/andP [_ HP2] SCHED2].
rewrite 2!mem_scheduled_jobs_eq_scheduled in SCHED1 SCHED2.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in SCHED1; try (by done).
 apply scheduled_implies_pending with (job_cost0 := job_cost) in SCHED2; try (by done).
 by apply UNIQ.
+ have ARRin1: arrives_in arr_seq j1 by apply (FROMarr j1 t).
+ have ARRIn2: arrives_in arr_seq j2 by apply (FROMarr j2 t).
+ by apply UNIQ; try (by done); apply scheduled_implies_pending.
}
}
{
@@ 415,8 +426,10 @@ Module ConstrainedDeadlines.
{
apply/eqP; red; intro SAMEtsk.
generalize SCHED'; intro PENDING'.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING'; try (by done).
 specialize (UNIQ' j' PENDING' SAMEtsk); subst j'.
+ have ARRin': arrives_in arr_seq j' by apply (FROMarr j' t).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) in PENDING'; try (by done).
+ specialize (UNIQ' j' ARRin' PENDING' SAMEtsk); subst j'.
by move: BACK => /andP [_ NOTSCHED]; rewrite SCHED' in NOTSCHED.
}
}
diff git a/model/schedule/global/basic/interference.v b/model/schedule/global/basic/interference.v
index f31a7d0..14ef4ee 100644
 a/model/schedule/global/basic/interference.v
+++ b/model/schedule/global/basic/interference.v
@@ 12,22 +12,23 @@ Module Interference.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
(* Assume any job arrival sequence...*)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ... and any schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Consider any job j that incurs interference. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Recall the definition of backlogged (pending and not scheduled). *)
Let job_is_backlogged (t: time) :=
 backlogged job_cost sched j t.
+ backlogged job_arrival job_cost sched j t.
(* First, we define total interference. *)
Section TotalInterference.
@@ 43,7 +44,7 @@ Module Interference.
Section JobInterference.
(* Let job_other be a job that interferes with j. *)
 Variable job_other: JobIn arr_seq.
+ Variable job_other: Job.
(* The interference caused by job_other during [t1, t2) is the cumulative
time in which j is backlogged while job_other is scheduled. *)
@@ 85,7 +86,7 @@ Module Interference.
(* Now we prove some basic lemmas about interference. *)
Section BasicLemmas.
 (* Interference cannot be larger than the considered time window. *)
+ (* First, we show that the total interference cannot be larger than the interval length. *)
Lemma total_interference_le_delta :
forall t1 t2,
total_interference t1 t2 <= t2  t1.
@@ 96,7 +97,7 @@ Module Interference.
by rewrite big_const_nat iter_addn mul1n addn0 leqnn.
Qed.
 (* Job interference is bounded by the service of the interfering job. *)
+ (* Next, we show that job interference is bounded by the service of the interfering job. *)
Lemma job_interference_le_service :
forall j_other t1 t2,
job_interference j_other t1 t2 <= service_during sched j_other t1 t2.
@@ 109,7 +110,7 @@ Module Interference.
by destruct (scheduled_on sched j_other cpu t).
Qed.
 (* Task interference is bounded by the workload of the interfering task. *)
+ (* We also prove that task interference is bounded by the workload of the interfering task. *)
Lemma task_interference_le_workload :
forall tsk t1 t2,
task_interference tsk t1 t2 <= workload job_task sched tsk t1 t2.
@@ 178,7 +179,7 @@ Module Interference.
apply leq_sum; move => t /andP [LEt _].
rewrite exchange_big /=.
apply leq_sum; intros cpu _.
 destruct (backlogged job_cost sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost sched j t) eqn:BACK;
last by rewrite andFb (eq_bigr (fun x => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
rewrite andTb.
@@ 191,8 +192,7 @@ Module Interference.
}
{
unfold jobs_scheduled_between.
 rewrite mem_undup; apply mem_bigcat_nat with (j := t);
 first by done.
+ rewrite mem_undup; apply mem_bigcat_nat with (j := t); first by done.
apply mem_bigcat_ord with (j := cpu); first by apply ltn_ord.
by unfold make_sequence; rewrite SOME mem_seq1 eq_refl.
}
diff git a/model/schedule/global/basic/interference_edf.v b/model/schedule/global/basic/interference_edf.v
index 0972973..27cba24 100644
 a/model/schedule/global/basic/interference_edf.v
+++ b/model/schedule/global/basic/interference_edf.v
@@ 11,6 +11,7 @@ Module InterferenceEDF.
Section Lemmas.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
@@ 19,32 +20,34 @@ Module InterferenceEDF.
(* Consider any schedule. *)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Assume that the schedule satisfies the global scheduling invariant
for EDF, i.e., if any job of tsk is backlogged, every processor
must be busy with jobs with no larger absolute deadline. *)
Hypothesis H_scheduler_uses_EDF:
 respects_JLFP_policy job_cost sched (EDF job_deadline).
+ respects_JLFP_policy job_arrival job_cost arr_seq sched (EDF job_arrival job_deadline).
(* Under EDF scheduling, a job only causes interference if its deadline
is not larger than the deadline of the analyzed job. *)
Lemma interference_under_edf_implies_shorter_deadlines :
 forall (j j': JobIn arr_seq) t1 t2,
 job_interference job_cost sched j' j t1 t2 != 0 >
+ forall j j' t1 t2,
+ arrives_in arr_seq j >
+ arrives_in arr_seq j' >
+ job_interference job_arrival job_cost sched j' j t1 t2 != 0 >
job_arrival j + job_deadline j <= job_arrival j' + job_deadline j'.
Proof.
rename H_scheduler_uses_EDF into PRIO.
 intros j j' t1 t2 INTERF.
+ intros j j' t1 t2 ARR1 ARR2 INTERF.
unfold job_interference in INTERF.
destruct ([exists t': 'I_t2,
[exists cpu: processor num_cpus,
(t' >= t1) &&
 backlogged job_cost sched j' t' &&
+ backlogged job_arrival job_cost sched j' t' &&
scheduled_on sched j cpu t']]) eqn:EX.
{
move: EX => /existsP [t' /existsP [cpu /andP [/andP [LE BACK] SCHED]]].
 apply PRIO with (t := t'); first by done.
+ apply PRIO with (t := t'); try (by done).
by apply/existsP; exists cpu.
}
{
@@ 58,7 +61,7 @@ Module InterferenceEDF.
rewrite (eq_bigr (fun x => 0));
first by rewrite big_const_ord iter_addn mul0n addn0.
intros cpu _; specialize (ALL cpu); simpl in ALL.
 destruct (backlogged job_cost sched j' i); last by rewrite andFb.
+ destruct (backlogged job_arrival job_cost sched j' i); last by rewrite andFb.
rewrite GEi 2!andTb in ALL; rewrite andTb.
by apply negbTE in ALL; rewrite ALL.
}
diff git a/model/schedule/global/basic/platform.v b/model/schedule/global/basic/platform.v
index 75f3d7e..68c4896 100644
 a/model/schedule/global/basic/platform.v
+++ b/model/schedule/global/basic/platform.v
@@ 15,16 +15,17 @@ Module Platform.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
(* Consider any job arrival sequence ... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ... and any schedule of this arrival sequence. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
Section Execution.
@@ 32,7 +33,8 @@ Module Platform.
all processors are busy with other jobs. *)
Definition work_conserving :=
forall j t,
 backlogged job_cost sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
forall cpu, exists j_other,
scheduled_on sched j_other cpu t.
@@ 40,7 +42,8 @@ Module Platform.
based on counting the number of scheduled jobs. *)
Definition work_conserving_count :=
forall j t,
 backlogged job_cost sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
size (jobs_scheduled_at sched t) = num_cpus.
End Execution.
@@ 53,8 +56,9 @@ Module Platform.
(* ... is respected by the scheduler iff every scheduled
job has higher (or same) priority than (as) a backlogged job. *)
Definition respects_FP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled sched j_hp t >
higher_eq_priority (job_task j_hp) (job_task j).
@@ 63,14 +67,15 @@ Module Platform.
Section JLFP.
(* A JLFP policy ...*)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* ... is respected by the scheduler iff at any time t,
a scheduled job has higher (or same) priority than (as)
a backlogged job. *)
Definition respects_JLFP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled sched j_hp t >
higher_eq_priority j_hp j.
@@ 79,14 +84,15 @@ Module Platform.
Section JLDP.
(* A JLDP policy ...*)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* ... is respected by the scheduler iff at any time t,
a scheduled job has higher (or same) priority than (as)
a backlogged job. *)
Definition respects_JLDP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled sched j_hp t >
higher_eq_priority t j_hp j.
@@ 96,7 +102,8 @@ Module Platform.
(* Assume all jobs have valid parameters, ...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* In this section, we prove that the two definitions of workconserving are equivalent. *)
@@ 107,8 +114,8 @@ Module Platform.
Proof.
unfold work_conserving, work_conserving_count; split.
{
 intros EX j t BACK.
 specialize (EX j t BACK).
+ intros EX j t ARRj BACK.
+ specialize (EX j t ARRj BACK).
apply eq_trans with (y := size (enum (processor num_cpus)));
last by rewrite size_enum_ord.
unfold jobs_scheduled_at.
@@ 127,14 +134,14 @@ Module Platform.
by apply eq_bigr.
}
{
 intros SIZE j t BACK cpu.
 specialize (SIZE j t BACK).
+ intros SIZE j t ARRj BACK cpu.
+ specialize (SIZE j t ARRj BACK).
destruct ([exists cpu, sched cpu t == None]) eqn:EX; last first.
{
apply negbT in EX; rewrite negb_exists in EX.
move: EX => /forallP ALL; specialize (ALL cpu).
destruct (sched cpu t) eqn:SOME; last by done.
 by exists j0; apply/eqP.
+ by exists s; apply/eqP.
}
{
move: EX => /existsP [cpu' /eqP EX].
diff git a/model/schedule/global/basic/schedule.v b/model/schedule/global/basic/schedule.v
index e6fa04e..973eb78 100644
 a/model/schedule/global/basic/schedule.v
+++ b/model/schedule/global/basic/schedule.v
@@ 12,16 +12,16 @@ Module Schedule.
Section ScheduleDef.
 Context {Job: eqType}.
+ (* Consider any type of job. *)
+ Variable Job: eqType.
 (* Given the number of processors and an arrival sequence, ...*)
+ (* Given the number of processors... *)
Variable num_cpus: nat.
 Variable arr_seq: arrival_sequence Job.
(* ... we define a schedule as a mapping such that each processor
at each time contains either a job from the sequence or none. *)
Definition schedule :=
 processor num_cpus > time > option (JobIn arr_seq).
+ processor num_cpus > time > option Job.
End ScheduleDef.
@@ 29,6 +29,7 @@ Module Schedule.
Section ScheduledJobs.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
(* Given an arrival sequence, ... *)
Context {arr_seq: arrival_sequence Job}.
@@ 39,8 +40,8 @@ Module Schedule.
Context {num_cpus: nat}.
(* ... we define the following properties for job j in schedule sched. *)
 Variable sched: schedule num_cpus arr_seq.
 Variable j: JobIn arr_seq.
+ Variable sched: schedule Job num_cpus.
+ Variable j: Job.
(* A job j is scheduled on processor cpu at time t iff such a mapping exists. *)
Definition scheduled_on (cpu: processor num_cpus) (t: time) :=
@@ 70,18 +71,18 @@ Module Schedule.
Definition completed (t: time) := service t == job_cost j.
(* Job j is pending at time t iff it has arrived but has not completed. *)
 Definition pending (t: time) := has_arrived j t && ~~completed t.
+ Definition pending (t: time) := has_arrived job_arrival j t && ~~completed t.
(* Job j is backlogged at time t iff it is pending and not scheduled. *)
Definition backlogged (t: time) := pending t && ~~scheduled t.
(* Job j is carryin in interval [t1, t2) iff it arrives before t1 and is
not complete at time t1 *)
 Definition carried_in (t1: time) := arrived_before j t1 && ~~ completed t1.
+ Definition carried_in (t1: time) := arrived_before job_arrival j t1 && ~~ completed t1.
(* Job j is carryout in interval [t1, t2) iff it arrives after t1 and is
not complete at time t2 *)
 Definition carried_out (t1 t2: time) := arrived_before j t2 && ~~ completed t2.
+ Definition carried_out (t1 t2: time) := arrived_before job_arrival j t2 && ~~ completed t2.
(* The list of scheduled jobs at time t is the concatenation of the jobs
scheduled on each processor. *)
@@ 98,14 +99,13 @@ Module Schedule.
(* In this section, we define properties of valid schedules. *)
Section ValidSchedules.
 Context {Job: eqType}. (* Assume a job type with decidable equality, ...*)
 Context {arr_seq: arrival_sequence Job}. (* ..., an arrival sequence, ...*)

 Variable job_cost: Job > time. (* ... a cost function, .... *)
+ Context {Job: eqType}.
+ Variable job_arrival: Job > time.
+ Variable job_cost: Job > time.
 (* ... and a schedule. *)
+ (* Consider any multiprocessor schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Next, we define whether job are sequential, ... *)
Definition sequential_jobs :=
@@ 114,30 +114,33 @@ Module Schedule.
(* ... whether a job can only be scheduled if it has arrived, ... *)
Definition jobs_must_arrive_to_execute :=
 forall j t, scheduled sched j t > has_arrived j t.
+ forall j t,
+ scheduled sched j t >
+ has_arrived job_arrival j t.
(* ... whether a job can be scheduled after it completes. *)
Definition completed_jobs_dont_execute :=
forall j t, service sched j t <= job_cost j.
+ (* We also define whether jobs come from some arrival sequence. *)
+ Definition jobs_come_from_arrival_sequence (arr_seq: arrival_sequence Job) :=
+ forall j t, scheduled sched j t > arrives_in arr_seq j.
+
End ValidSchedules.
(* In this section, we prove some basic lemmas about a job. *)
Section JobLemmas.
 (* Consider an arrival sequence, ...*)
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.

 (* ... a job cost function, ...*)
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
 (* ..., and a particular schedule. *)
+ (* Consider any multiprocessor schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Next, we prove some lemmas about the service received by a job j. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
Section Basic.
@@ 318,7 +321,7 @@ Module Schedule.
(* Assume that jobs must arrive to execute. *)
Hypothesis H_jobs_must_arrive:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* Then, job j does not receive service at any time t prior to its arrival. *)
Lemma service_before_job_arrival_zero :
@@ 329,7 +332,7 @@ Module Schedule.
rename H_jobs_must_arrive into ARR; red in ARR; intros t LT.
specialize (ARR j t).
apply contra with (c := scheduled sched j t)
 (b := has_arrived j t) in ARR;
+ (b := has_arrived job_arrival j t) in ARR;
last by rewrite ltnNge.
apply/eqP; rewrite leqn0; unfold service_at.
rewrite big_pred0 //; red.
@@ 359,7 +362,8 @@ Module Schedule.
\sum_(t0 <= t < job_arrival j + t) service_at sched j t =
\sum_(job_arrival j <= t < job_arrival j + t) service_at sched j t.
Proof.
 intros t0 t LE; rewrite > big_cat_nat with (n := job_arrival j); [ by ins  by apply leq_addr].
+ intros t0 t LE; rewrite > big_cat_nat with (n := job_arrival j);
+ [ by ins  by apply leq_addr].
by rewrite /= cumulative_service_before_job_arrival_zero; [rewrite add0n  apply leqnn].
Qed.
@@ 369,7 +373,7 @@ Module Schedule.
(* Assume that jobs must arrive to execute. *)
Hypothesis H_jobs_must_arrive:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* Assume that completed jobs do not execute. *)
Hypothesis H_completed_jobs:
@@ 379,7 +383,7 @@ Module Schedule.
Lemma scheduled_implies_pending:
forall t,
scheduled sched j t >
 pending job_cost sched j t.
+ pending job_arrival job_cost sched j t.
Proof.
rename H_jobs_must_arrive into ARRIVE,
H_completed_jobs into COMP.
@@ 405,13 +409,11 @@ Module Schedule.
scheduled at time t. *)
Section ScheduledJobsLemmas.
 (* Consider an arrival sequence ...*)
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
 (* ... and some schedule. *)
+ (* Consider any multiprocessor schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
Section Membership.
@@ 462,8 +464,8 @@ Module Schedule.
intros x i1 i2 IN1 IN2; unfold make_sequence in *.
desf; move: Heq0 Heq => SOME1 SOME2.
rewrite mem_seq1 in IN1; rewrite mem_seq1 in IN2.
 move: IN1 IN2 => /eqP IN1 /eqP IN2; subst x j0.
 specialize (SEQUENTIAL j t (widen_ord (leqnSn n) i1)
+ move: IN1 IN2 => /eqP IN1 /eqP IN2; subst x s0.
+ specialize (SEQUENTIAL s t (widen_ord (leqnSn n) i1)
(widen_ord (leqnSn n) i2) SOME1 SOME2).
by inversion SEQUENTIAL; apply ord_inj.
}
@@ 480,8 +482,8 @@ Module Schedule.
unfold make_sequence in IN'.
desf; rename Heq into SCHEDi.
rewrite mem_seq1 in INx; rewrite mem_seq1 in IN'.
 move: INx IN' => /eqP INx /eqP IN'; subst x j0.
 specialize (SEQUENTIAL j t ord_max (widen_ord (leqnSn n) i) SCHED SCHEDi).
+ move: INx IN' => /eqP INx /eqP IN'; subst x s0.
+ specialize (SEQUENTIAL s t ord_max (widen_ord (leqnSn n) i) SCHED SCHEDi).
inversion SEQUENTIAL; destruct i as [i EQ]; simpl in *.
clear SEQUENTIAL SCHEDi.
by rewrite H0 ltnn in EQ.
@@ 524,10 +526,9 @@ Module ScheduleOfSporadicTask.
Context {Job: eqType}.
Variable job_task: Job > sporadic_task.
 (* Consider any schedule. *)
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any multiprocessor schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Given a task tsk, ...*)
Variable tsk: sporadic_task.
@@ 544,7 +545,7 @@ Module ScheduleOfSporadicTask.
(* We also define the list of jobs scheduled during [t1, t2). *)
Definition jobs_of_task_scheduled_between (t1 t2: time) :=
 filter (fun (j: JobIn arr_seq) => job_task j == tsk)
+ filter (fun j => job_task j == tsk)
(jobs_scheduled_between sched t1 t2).
End ScheduledJobs.
@@ 556,22 +557,22 @@ Module ScheduleOfSporadicTask.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
 (* Consider any schedule. *)
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any multiprocessor schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Next we define intratask parallelism. *)
Definition jobs_of_same_task_dont_execute_in_parallel :=
 forall (j j': JobIn arr_seq) t,
+ forall j j' t,
job_task j = job_task j' >
 scheduled sched j t > scheduled sched j' t > j = j'.
+ scheduled sched j t >
+ scheduled sched j' t >
+ j = j'.
End ScheduleProperties.
Section BasicLemmas.
 (* Assume the job cost and task are known. *)
Context {sporadic_task: eqType}.
Variable task_cost: sporadic_task > time.
Variable task_deadline: sporadic_task > time.
@@ 581,18 +582,19 @@ Module ScheduleOfSporadicTask.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
 (* Then, in a valid schedule of sporadic tasks ...*)
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any valid schedule of sporadic tasks ...*)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
 (* ...such that jobs do not execute after completion, ...*)
+ (* ...such that jobs do not execute after completion.*)
Hypothesis jobs_dont_execute_after_completion :
completed_jobs_dont_execute job_cost sched.
+ (* Let tsk be any tsk...*)
Variable tsk: sporadic_task.

 Variable j: JobIn arr_seq.
+
+ (* ...and let j be any valid job of tsk. *)
+ Variable j: Job.
Hypothesis H_job_of_task: job_task j = tsk.
Hypothesis valid_job:
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
diff git a/model/schedule/global/jitter/constrained_deadlines.v b/model/schedule/global/jitter/constrained_deadlines.v
index 65de93c..9ac68ed 100644
 a/model/schedule/global/jitter/constrained_deadlines.v
+++ b/model/schedule/global/jitter/constrained_deadlines.v
@@ 17,21 +17,29 @@ Module ConstrainedDeadlines.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
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}.
+ (* Consider any job arrival sequence ... *)
+ Variable arr_seq: arrival_sequence Job.
(* ... and any schedule of this arrival sequence. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.

 (* Assume all jobs have valid parameters, ...*)
+ Variable sched: schedule Job num_cpus.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
+ (* For simplicity, let's define some local names. *)
+ Let job_is_pending := pending job_arrival job_cost job_jitter sched.
+ Let job_is_backlogged := backlogged job_arrival job_cost job_jitter sched.
+
+ (* Next, assume all jobs have valid parameters. *)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* In this section we prove the absence of multiple jobs of the same
@@ 39,47 +47,51 @@ Module ConstrainedDeadlines.
Section NoMultipleJobs.
(* Assume any workconserving prioritybased scheduler. *)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
Hypothesis H_work_conserving:
 work_conserving job_cost job_jitter sched.
+ work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_respects_JLDP_policy:
 respects_JLDP_policy job_cost job_jitter sched higher_eq_priority.
+ respects_JLDP_policy job_arrival job_cost job_jitter arr_seq sched higher_eq_priority.
(* Consider task set ts. *)
Variable ts: taskset_of sporadic_task.
(* Assume that all jobs come from the taskset. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
(* Suppose that jobs are sequential, ...*)
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* ... jobs only execute after the jitter, ... *)
Hypothesis H_jobs_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
(* ... and jobs do not execute after completion. *)
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.

 (* Assume that the schedule satisfies the sporadic task model ...*)
+
+ (* Assume that the schedule satisfies the sporadic task model. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider a valid task tsk, ...*)
Variable tsk: sporadic_task.
Hypothesis H_valid_task: is_valid_sporadic_task task_cost task_period task_deadline tsk.
(*... whose job j ... *)
 Variable j: JobIn arr_seq.
 Variable H_job_of_tsk: job_task j = tsk.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
+ Hypothesis H_job_of_tsk: job_task j = tsk.
(*... is backlogged at time t. *)
Variable t: time.
 Hypothesis H_j_backlogged: backlogged job_cost job_jitter sched j t.
+ Hypothesis H_j_backlogged: job_is_backlogged j t.
(* Assume that any previous jobs of tsk have completed by the period. *)
Hypothesis H_all_previous_jobs_completed :
 forall (j_other: JobIn arr_seq) tsk_other,
+ forall j_other tsk_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
job_arrival j_other + task_period tsk_other <= t >
completed job_cost sched j_other (job_arrival j_other + task_period (job_task j_other)).
@@ 90,19 +102,21 @@ Module ConstrainedDeadlines.
(* Then, there can be at most one pending job of each task at time t. *)
Lemma platform_at_most_one_pending_job_of_each_task :
forall j1 j2,
 pending job_cost job_jitter sched j1 t >
 pending job_cost job_jitter sched j2 t >
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ job_is_pending j1 t >
+ job_is_pending j2 t >
job_task j1 = job_task j2 >
j1 = j2.
Proof.
rename H_sporadic_tasks into SPO, H_all_previous_jobs_completed into PREV.
 intros j1 j2 PENDING1 PENDING2 SAMEtsk.
+ intros j1 j2 ARRin1 ARRin2 PENDING1 PENDING2 SAMEtsk.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: PENDING1 PENDING2 => /andP [ARRIVED1 /negP NOTCOMP1] /andP [ARRIVED2 /negP NOTCOMP2].
unfold jitter_has_passed, actual_arrival in *.
destruct (leqP (job_arrival j1) (job_arrival j2)) as [BEFORE1  BEFORE2].
{
 specialize (SPO j1 j2 DIFF SAMEtsk BEFORE1).
+ specialize (SPO j1 j2 DIFF ARRin1 ARRin2 SAMEtsk BEFORE1).
assert (LEt: job_arrival j1 + task_period (job_task j1) <= t).
{
apply leq_trans with (n := job_arrival j2); first by done.
@@ 114,7 +128,7 @@ Module ConstrainedDeadlines.
}
{
apply ltnW in BEFORE2.
 exploit (SPO j2 j1); [by red; ins; subst  by rewrite SAMEtsk  by done  intro SPO'].
+ exploit (SPO j2 j1); try (by done); [by red; ins; subst  intro SPO'].
assert (LEt: job_arrival j2 + task_period (job_task j2) <= t).
{
apply leq_trans with (n := job_arrival j1); first by done.
@@ 131,17 +145,12 @@ Module ConstrainedDeadlines.
count (scheduled_task_other_than tsk) ts = num_cpus.
Proof.
have UNIQ := platform_at_most_one_pending_job_of_each_task.
 rename H_all_jobs_from_taskset into FROMTS,
 H_sequential_jobs into SEQUENTIAL,
 H_work_conserving into WORK,
 H_respects_JLDP_policy into PRIO,
 H_j_backlogged into BACK,
 H_job_of_tsk into JOBtsk,
 H_valid_job_parameters into JOBPARAMS,
 H_valid_task into TASKPARAMS,
 H_all_previous_jobs_completed into PREV,
 H_completed_jobs_dont_execute into COMP,
 H_jobs_execute_after_jitter into JITTER.
+ rename H_all_jobs_from_taskset into FROMTS, H_sequential_jobs into SEQUENTIAL,
+ H_work_conserving into WORK, H_jobs_come_from_arrival_sequence into FROMarr,
+ H_respects_JLDP_policy into PRIO, H_j_backlogged into BACK,
+ H_job_of_tsk into JOBtsk, H_valid_job_parameters into JOBPARAMS,
+ H_valid_task into TASKPARAMS, H_all_previous_jobs_completed into PREV,
+ H_completed_jobs_dont_execute into COMP, H_jobs_execute_after_jitter into JITTER.
apply work_conserving_eq_work_conserving_count in WORK.
unfold valid_sporadic_job, valid_realtime_job,
respects_JLDP_policy, completed_jobs_dont_execute,
@@ 163,20 +172,23 @@ Module ConstrainedDeadlines.
}
{
rewrite (WORK j t) // count_predT.
 apply leq_trans with (n := count (fun j: JobIn arr_seq => scheduled_task_other_than tsk (job_task j)) (jobs_scheduled_at sched t));
+ apply leq_trans with (n := count
+ (fun j => scheduled_task_other_than tsk (job_task j))
+ (jobs_scheduled_at sched t));
last first.
{
rewrite count_map.
 apply count_sub_uniqr;
 last by red; move => tsk' /mapP [j' _ JOBtsk']; subst; apply FROMTS.
+ apply count_sub_uniqr; last first.
+ {
+ move => tsk' /mapP [j' INj' JOBtsk']; subst; apply FROMTS.
+ by rewrite mem_scheduled_jobs_eq_scheduled in INj'; eauto 2.
+ }
rewrite map_inj_in_uniq; first by apply scheduled_jobs_uniq.
red; intros j1 j2 SCHED1 SCHED2 SAMEtsk.
rewrite 2!mem_scheduled_jobs_eq_scheduled in SCHED1 SCHED2.
 apply scheduled_implies_pending with (job_cost0 := job_cost)
 (job_jitter0 := job_jitter) in SCHED1; try (by done).
 apply scheduled_implies_pending with (job_cost0 := job_cost)
 (job_jitter0 := job_jitter) in SCHED2; try (by done).
 by apply UNIQ.
+ have ARRin1: arrives_in arr_seq j1 by apply (FROMarr j1 t).
+ have ARRin2: arrives_in arr_seq j2 by apply (FROMarr j2 t).
+ by apply UNIQ; try (by done); apply scheduled_implies_pending.
}
{
apply sub_in_count; intros j' SCHED' _.
@@ 190,10 +202,10 @@ Module ConstrainedDeadlines.
apply/eqP; red; intro SAMEtsk; symmetry in SAMEtsk.
move: BACK => /andP [PENDING NOTSCHED].
generalize SCHED'; intro PENDING'.
 apply scheduled_implies_pending with (job_cost0 := job_cost)
 (job_jitter0 := job_jitter) in PENDING'; try (by done).
 exploit (UNIQ j j' PENDING PENDING'); [by rewrite SAMEtsk  intro EQjob; subst].
 by rewrite SCHED' in NOTSCHED.
+ have ARRin': arrives_in arr_seq j' by apply (FROMarr j' t).
+ exploit (UNIQ j j'); try (by done);
+ [by apply scheduled_implies_pending  by rewrite SAMEtsk ].
+ by intro EQjob; subst; rewrite SCHED' in NOTSCHED.
}
}
}
@@ 208,41 +220,44 @@ Module ConstrainedDeadlines.
(* Assume any workconserving prioritybased scheduler. *)
Variable higher_eq_priority: FP_policy sporadic_task.
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_respects_JLDP_policy:
 respects_FP_policy job_cost job_task job_jitter sched higher_eq_priority.
+ respects_FP_policy job_arrival job_cost job_task job_jitter arr_seq sched higher_eq_priority.
(* Consider any task set ts. *)
Variable ts: taskset_of sporadic_task.
(* Assume that all jobs come from the taskset. *)
Hypothesis H_all_jobs_from_taskset:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j,
+ arrives_in arr_seq j >
+ job_task j \in ts.
(* Suppose that jobs are sequential, ...*)
Hypothesis H_sequential_jobs: sequential_jobs sched.
(* ... jobs only execute after the jitter, ... *)
Hypothesis H_jobs_execute_after_jitter:
 jobs_execute_after_jitter job_jitter sched.
+ jobs_execute_after_jitter job_arrival job_jitter sched.
(* ... and jobs do not execute after completion. *)
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
 (* Assume that the schedule satisfies the sporadic task model ...*)
+ (* Assume that the schedule satisfies the sporadic task model. *)
Hypothesis H_sporadic_tasks:
 sporadic_task_model task_period arr_seq job_task.
+ sporadic_task_model task_period job_arrival job_task arr_seq.
(* Consider a valid task tsk, ...*)
Variable tsk: sporadic_task.
Hypothesis H_valid_task: is_valid_sporadic_task task_cost task_period task_deadline tsk.
(*... whose job j ... *)
 Variable j: JobIn arr_seq.
 Variable H_job_of_tsk: job_task j = tsk.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
+ Hypothesis H_job_of_tsk: job_task j = tsk.
(*... is backlogged at time t <= job_arrival j + task_period tsk. *)
Variable t: time.
 Hypothesis H_j_backlogged: backlogged job_cost job_jitter sched j t.
+ Hypothesis H_j_backlogged: job_is_backlogged j t.
Hypothesis H_t_before_period: t < job_arrival j + task_period tsk.
(* Recall the definition of a higherpriority task (with respect to tsk). *)
@@ 250,14 +265,16 @@ Module ConstrainedDeadlines.
(* Assume that any jobs of higherpriority tasks complete by their period. *)
Hypothesis H_all_previous_jobs_completed :
 forall (j_other: JobIn arr_seq) tsk_other,
+ forall j_other tsk_other,
+ arrives_in arr_seq j_other >
job_task j_other = tsk_other >
is_hp_task tsk_other >
completed job_cost sched j_other (job_arrival j_other + task_period tsk_other).
(* Assume that any jobs of tsk prior to j complete by their period. *)
Hypothesis H_all_previous_jobs_of_tsk_completed :
 forall j0 : JobIn arr_seq,
+ forall j0,
+ arrives_in arr_seq j0 >
job_task j0 = tsk >
job_arrival j0 < job_arrival j >
completed job_cost sched j0 (job_arrival j0 + task_period tsk).
@@ 268,40 +285,44 @@ Module ConstrainedDeadlines.
(* Then, there can be at most one pending job of higherpriority tasks at time t. *)
Lemma platform_fp_no_multiple_jobs_of_interfering_tasks :
 forall j1 j2,
 pending job_cost job_jitter sched j1 t >
 pending job_cost job_jitter sched j2 t >
 job_task j1 = job_task j2 >
 is_hp_task (job_task j1) >
 j1 = j2.
+ forall j1 j2,
+ arrives_in arr_seq j1 >
+ arrives_in arr_seq j2 >
+ job_is_pending j1 t >
+ job_is_pending j2 t >
+ job_task j1 = job_task j2 >
+ is_hp_task (job_task j1) >
+ j1 = j2.
Proof.
unfold sporadic_task_model in *.
rename H_sporadic_tasks into SPO, H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_all_previous_jobs_completed into PREV.
 intros j1 j2 PENDING1 PENDING2 SAMEtsk INTERF.
+ intros j1 j2 ARRin1 ARRin2 PENDING1 PENDING2 SAMEtsk INTERF.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: PENDING1 PENDING2 => /andP [ARRIVED1 /negP NOTCOMP1] /andP [ARRIVED2 /negP NOTCOMP2].
destruct (leqP (job_arrival j1) (job_arrival j2)) as [BEFORE1  BEFORE2].
{
 specialize (SPO j1 j2 DIFF SAMEtsk BEFORE1).
+ specialize (SPO j1 j2 DIFF ARRin1 ARRin2 SAMEtsk BEFORE1).
assert (LEt: job_arrival j1 + task_period (job_task j1) <= t).
{
apply leq_trans with (n := job_arrival j2); first by done.
by apply leq_trans with (n := job_arrival j2 + job_jitter j2); first by apply leq_addr.
}
 exploit (PREV j1 (job_task j1)); [by done  by apply INTERF  intros COMP1].
+ exploit (PREV j1 (job_task j1) ARRin1); [by done  by apply INTERF  intros COMP1].
apply NOTCOMP1.
by apply completion_monotonic with (t0 := job_arrival j1 + task_period (job_task j1)).
}
{
apply ltnW in BEFORE2.
 exploit (SPO j2 j1); [by red; ins; subst j2  by rewrite SAMEtsk  by done  intro SPO'].
+ feed (SPO j2 j1); first by red; ins; subst j2.
+ feed (SPO ARRin2 ARRin1); first by rewrite SAMEtsk.
+ feed SPO; first by done.
assert (LEt: job_arrival j2 + task_period (job_task j2) <= t).
{
apply leq_trans with (n := job_arrival j1); first by done.
by apply leq_trans with (n := job_arrival j1 + job_jitter j1); first by apply leq_addr.
}
 exploit (PREV j2 (job_task j2));
+ exploit (PREV j2 (job_task j2) ARRin2);
[by done  by rewrite SAMEtsk  intro COMP2 ].
apply NOTCOMP2.
by apply completion_monotonic with (t0 := job_arrival j2 + task_period (job_task j2)).
@@ 310,10 +331,11 @@ Module ConstrainedDeadlines.
(* Also, there can be at most one pending job of tsk at time t. *)
Lemma platform_fp_no_multiple_jobs_of_tsk :
 forall j',
 pending job_cost job_jitter sched j' t >
 job_task j' = tsk >
 j' = j.
+ forall j',
+ arrives_in arr_seq j' >
+ job_is_pending j' t >
+ job_task j' = tsk >
+ j' = j.
Proof.
unfold sporadic_task_model in *.
rename H_sporadic_tasks into SPO,
@@ 321,21 +343,21 @@ Module ConstrainedDeadlines.
H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_all_previous_jobs_completed into PREV,
H_j_backlogged into BACK, H_job_of_tsk into JOBtsk.
 intros j' PENDING' SAMEtsk.
+ intros j' ARRin' PENDING' SAMEtsk.
apply/eqP; rewrite [_ == _]negbK; apply/negP; red; move => /eqP DIFF.
move: BACK PENDING' => /andP [/andP [ARRIVED /negP NOTCOMP] NOTSCHED]
/andP [ARRIVED' /negP NOTCOMP'].
destruct (leqP (job_arrival j') (job_arrival j)) as [BEFORE  BEFORE'].
{
 exploit (SPO j' j DIFF); [by rewrite JOBtsk  by done  intro SPO'].
+ exploit (SPO j' j DIFF ARRin' H_j_arrives); [by rewrite JOBtsk  by done  intro SPO'].
assert (LEt: job_arrival j' + task_period tsk <= t).
{
apply leq_trans with (n := job_arrival j); first by rewrite SAMEtsk.
by apply leq_trans with (n := job_arrival j + job_jitter j); first by apply leq_addr.
}
apply NOTCOMP'.
 apply completion_monotonic with (t0 := job_arrival j' + task_period tsk); [by done  by done ].
 apply PREVtsk; first by done.
+ apply completion_monotonic with (t0 := job_arrival j' + task_period tsk); try (by done).
+ apply PREVtsk; try (by done).
apply leq_trans with (n := job_arrival j' + task_period tsk); last by rewrite SAMEtsk.
rewrite addn1; apply leq_add; first by done.
by unfold is_valid_sporadic_task in *; des.
@@ 345,7 +367,7 @@ Module ConstrainedDeadlines.
rewrite leqNgt in ARRIVED'; move: ARRIVED' => /negP BUG; apply BUG.
apply leq_trans with (n := job_arrival j'); last by apply leq_addr.
apply leq_trans with (n := job_arrival j + task_period tsk); first by done.
 by rewrite JOBtsk; apply SPO;
+ by rewrite JOBtsk; apply SPO; try (by done);
[by red; ins; subst j'  by rewrite SAMEtsk  by apply ltnW].
}
Qed.
@@ 356,17 +378,13 @@ Module ConstrainedDeadlines.
Proof.
have UNIQ := platform_fp_no_multiple_jobs_of_interfering_tasks.
have UNIQ' := platform_fp_no_multiple_jobs_of_tsk.
 rename H_all_jobs_from_taskset into FROMTS,
 H_sequential_jobs into SEQUENTIAL,
 H_work_conserving into WORK,
 H_respects_JLDP_policy into PRIO,
 H_j_backlogged into BACK,
 H_job_of_tsk into JOBtsk,
 H_sporadic_tasks into SPO,
 H_valid_job_parameters into JOBPARAMS,
 H_valid_task into TASKPARAMS,
 H_all_previous_jobs_completed into PREV,
+ rename H_all_jobs_from_taskset into FROMTS, H_sequential_jobs into SEQUENTIAL,
+ H_work_conserving into WORK, H_respects_JLDP_policy into PRIO,
+ H_j_backlogged into BACK, H_job_of_tsk into JOBtsk,
+ H_sporadic_tasks into SPO, H_valid_job_parameters into JOBPARAMS,
+ H_valid_task into TASKPARAMS, H_all_previous_jobs_completed into PREV,
H_completed_jobs_dont_execute into COMP,
+ H_jobs_come_from_arrival_sequence into FROMarr,
H_all_previous_jobs_of_tsk_completed into PREVtsk,
H_jobs_execute_after_jitter into JITTER.
apply work_conserving_eq_work_conserving_count in WORK.
@@ 391,22 +409,25 @@ Module ConstrainedDeadlines.
}
{
rewrite (WORK j t) // count_predT.
 apply leq_trans with (n := count (fun j: JobIn arr_seq =>
+ apply leq_trans with (n := count (fun j =>
scheduled_task_with_higher_eq_priority (job_task j)) (jobs_scheduled_at sched t));
last first.
{
rewrite count_map.
 apply leq_trans with (n := count predT [seq x < (map (fun (j: JobIn arr_seq) => job_task j) (jobs_scheduled_at sched t))  scheduled_task_with_higher_eq_priority x]);
 first by rewrite count_filter; apply sub_count; red; ins.
 apply leq_trans with (n := count predT [seq x < ts  scheduled_task_with_higher_eq_priority x]);
+ apply leq_trans with (n := count predT
+ [seq x < (map (fun j => job_task j) (jobs_scheduled_at sched t))
+  scheduled_task_with_higher_eq_priority x]);
+ first by rewrite count_filter; apply sub_count; red; ins.
+ apply leq_trans with (n := count predT
+ [seq x < ts  scheduled_task_with_higher_eq_priority x]);
last by rewrite count_predT size_filter.
 apply count_sub_uniqr;
 last first.
+ apply count_sub_uniqr; last first.
{
red; intros tsk' IN'.
rewrite mem_filter in IN'; move: IN' => /andP [SCHED IN'].
rewrite mem_filter; apply/andP; split; first by done.
 by move: IN' => /mapP [j' _] >; apply FROMTS.
+ move: IN' => /mapP [j' IN'] >; apply FROMTS.
+ by rewrite mem_scheduled_jobs_eq_scheduled in IN'; eauto 2.
}
{
rewrite filter_map.
@@ 415,11 +436,9 @@ Module ConstrainedDeadlines.
rewrite 2!mem_filter in SCHED1 SCHED2.
move: SCHED1 SCHED2 => /andP [/andP [_ HP1] SCHED1] /andP [/andP [_ HP2] SCHED2].
rewrite 2!mem_scheduled_jobs_eq_scheduled in SCHED1 SCHED2.
 apply scheduled_implies_pending with (job_cost0 := job_cost)
 (job_jitter0 := job_jitter) in SCHED1; try (by done).
 apply scheduled_implies_pending with (job_cost0 := job_cost)
 (job_jitter0 := job_jitter) in SCHED2; try (by done).
 by apply UNIQ.
+ have ARRin1: arrives_in arr_seq j1 by apply (FROMarr j1 t).
+ have ARRIn2: arrives_in arr_seq j2 by apply (FROMarr j2 t).
+ by apply UNIQ; try (by done); apply scheduled_implies_pending.
}
}
{
@@ 434,9 +453,10 @@ Module ConstrainedDeadlines.
{
apply/eqP; red; intro SAMEtsk.
generalize SCHED'; intro PENDING'.
 apply scheduled_implies_pending with (job_cost0 := job_cost)
 (job_jitter0 := job_jitter) in PENDING'; try (by done).
 specialize (UNIQ' j' PENDING' SAMEtsk); subst j'.
+ have ARRin': arrives_in arr_seq j' by apply (FROMarr j' t).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) (job_jitter0 := job_jitter) in PENDING'; try (by done).
+ specialize (UNIQ' j' ARRin' PENDING' SAMEtsk); subst j'.
by move: BACK => /andP [_ NOTSCHED]; rewrite SCHED' in NOTSCHED.
}
}
diff git a/model/schedule/global/jitter/interference.v b/model/schedule/global/jitter/interference.v
index 5da3135..15b6add 100644
 a/model/schedule/global/jitter/interference.v
+++ b/model/schedule/global/jitter/interference.v
@@ 17,23 +17,23 @@ Module Interference.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
Variable job_jitter: Job > time.
 (* Assume any job arrival sequence...*)
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any job arrival sequence...*)
+ Variable arr_seq: arrival_sequence Job.
 (* ... and any schedule. *)
+ (* ... and any schedule of those jobs. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Consider any job j that incurs interference. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Recall the definition of backlogged (pending and not scheduled). *)
 Let job_is_backlogged (t: time) :=
 backlogged job_cost job_jitter sched j t.
+ Let job_is_backlogged := backlogged job_arrival job_cost job_jitter sched j.
(* First, we define total interference. *)
Section TotalInterference.
@@ 49,7 +49,7 @@ Module Interference.
Section JobInterference.
(* Let job_other be a job that interferes with j. *)
 Variable job_other: JobIn arr_seq.
+ Variable job_other: Job.
(* The interference caused by job_other during [t1, t2) is the cumulative
time in which j is backlogged while job_other is scheduled. *)
@@ 92,7 +92,7 @@ Module Interference.
(* Now we prove some basic lemmas about interference. *)
Section BasicLemmas.
 (* Interference cannot be larger than the considered time window. *)
+ (* First, we show that total interference cannot be larger than the interval length. *)
Lemma total_interference_le_delta :
forall t1 t2,
total_interference t1 t2 <= t2  t1.
@@ 103,7 +103,7 @@ Module Interference.
by rewrite big_const_nat iter_addn mul1n addn0 leqnn.
Qed.
 (* Job interference is bounded by the service of the interfering job. *)
+ (* Next, we prove that job interference is bounded by the service of the interfering job. *)
Lemma job_interference_le_service :
forall j_other t1 t2,
job_interference j_other t1 t2 <= service_during sched j_other t1 t2.
@@ 116,7 +116,7 @@ Module Interference.
by destruct (scheduled_on sched j_other cpu t).
Qed.
 (* Task interference is bounded by the workload of the interfering task. *)
+ (* We also prove that task interference is bounded by the workload of the interfering task. *)
Lemma task_interference_le_workload :
forall tsk t1 t2,
task_interference tsk t1 t2 <= workload job_task sched tsk t1 t2.
@@ 185,7 +185,7 @@ Module Interference.
apply leq_sum; move => t /andP [LEt _].
rewrite exchange_big /=.
apply leq_sum; intros cpu _.
 destruct (backlogged job_cost job_jitter sched j t) eqn:BACK;
+ destruct (backlogged job_arrival job_cost job_jitter sched j t) eqn:BACK;
last by rewrite andFb (eq_bigr (fun x => 0));
first by rewrite big_const_seq iter_addn mul0n addn0.
rewrite andTb.
diff git a/model/schedule/global/jitter/interference_edf.v b/model/schedule/global/jitter/interference_edf.v
index 0d11e66..84e1592 100644
 a/model/schedule/global/jitter/interference_edf.v
+++ b/model/schedule/global/jitter/interference_edf.v
@@ 13,41 +13,45 @@ Module InterferenceEDF.
Section Lemmas.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_jitter: Job > time.
(* Assume any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* Consider any schedule. *)
Variable num_cpus: nat.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Assume that the schedule satisfies the global scheduling invariant
for EDF, i.e., if any job of tsk is backlogged, every processor
must be busy with jobs with no larger absolute deadline. *)
Hypothesis H_scheduler_uses_EDF:
 respects_JLFP_policy job_cost job_jitter sched (EDF job_deadline).
+ respects_JLFP_policy job_arrival job_cost job_jitter arr_seq sched
+ (EDF job_arrival job_deadline).
(* Under EDF scheduling, a job only causes interference if its deadline
is not larger than the deadline of the analyzed job. *)
Lemma interference_under_edf_implies_shorter_deadlines :
 forall (j j': JobIn arr_seq) t1 t2,
 job_interference job_cost job_jitter sched j' j t1 t2 != 0 >
+ forall j j' t1 t2,
+ arrives_in arr_seq j >
+ arrives_in arr_seq j' >
+ job_interference job_arrival job_cost job_jitter sched j' j t1 t2 != 0 >
job_arrival j + job_deadline j <= job_arrival j' + job_deadline j'.
Proof.
rename H_scheduler_uses_EDF into PRIO.
 intros j j' t1 t2 INTERF.
+ intros j j' t1 t2 ARR ARR' INTERF.
unfold job_interference in INTERF.
destruct ([exists t': 'I_t2,
[exists cpu: processor num_cpus,
(t' >= t1) &&
 backlogged job_cost job_jitter sched j' t' &&
+ backlogged job_arrival job_cost job_jitter sched j' t' &&
scheduled_on sched j cpu t']]) eqn:EX.
{
move: EX => /existsP [t' /existsP [cpu /andP [/andP [LE BACK] SCHED]]].
 apply PRIO with (t := t'); first by done.
+ apply PRIO with (t := t'); try (by done).
by apply/existsP; exists cpu.
}
{
@@ 61,7 +65,7 @@ Module InterferenceEDF.
rewrite (eq_bigr (fun x => 0));
first by rewrite big_const_ord iter_addn mul0n addn0.
intros cpu _; specialize (ALL cpu); simpl in ALL.
 destruct (backlogged job_cost job_jitter sched j' i); last by rewrite andFb.
+ destruct (backlogged job_arrival job_cost job_jitter sched j' i); last by rewrite andFb.
rewrite GEi 2!andTb in ALL; rewrite andTb.
by apply negbTE in ALL; rewrite ALL.
}
diff git a/model/schedule/global/jitter/platform.v b/model/schedule/global/jitter/platform.v
index 2717493..f2cd32e 100644
 a/model/schedule/global/jitter/platform.v
+++ b/model/schedule/global/jitter/platform.v
@@ 16,18 +16,22 @@ Module Platform.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
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}.
+ Variable arr_seq: arrival_sequence Job.
(* Consider any schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ (* For simplicity, let's define local names. *)
+ Let job_is_backlogged := backlogged job_arrival job_cost job_jitter sched.
+
Section Execution.
(* A scheduler is workconserving iff when a job j is backlogged,
@@ 35,7 +39,8 @@ Module Platform.
Note: backlogged means that jitter has already passed. *)
Definition work_conserving :=
forall j t,
 backlogged job_cost job_jitter sched j t >
+ arrives_in arr_seq j >
+ job_is_backlogged j t >
forall cpu, exists j_other,
scheduled_on sched j_other cpu t.
@@ 43,7 +48,8 @@ Module Platform.
based on counting the number of scheduled jobs. *)
Definition work_conserving_count :=
forall j t,
 backlogged job_cost job_jitter sched j t >
+ arrives_in arr_seq j >
+ job_is_backlogged j t >
size (jobs_scheduled_at sched t) = num_cpus.
End Execution.
@@ 56,8 +62,9 @@ Module Platform.
(* ... is respected by the schedule iff every scheduled
job has higher (or same) priority than (as) a backlogged job. *)
Definition respects_FP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost job_jitter sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ job_is_backlogged j t >
scheduled sched j_hp t >
higher_eq_priority (job_task j_hp) (job_task j).
@@ 66,14 +73,15 @@ Module Platform.
Section JLFP.
(* A JLFP policy ...*)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* ... is respected by the schedule iff at any time t,
a scheduled job has higher (or same) priority than (as)
a backlogged job. *)
Definition respects_JLFP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost job_jitter sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ job_is_backlogged j t >
scheduled sched j_hp t >
higher_eq_priority j_hp j.
@@ 82,14 +90,15 @@ Module Platform.
Section JLDP.
(* A JLDP policy ...*)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* ... is respected by the schedule iff at any time t,
a scheduled job has higher (or same) priority than (as)
a backlogged job. *)
Definition respects_JLDP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost job_jitter sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ job_is_backlogged j t >
scheduled sched j_hp t >
higher_eq_priority t j_hp j.
@@ 99,7 +108,8 @@ Module Platform.
(* Assume all jobs have valid parameters, ...*)
Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
(* In this section, we prove that the two definitions of workconserving are equivalent. *)
@@ 110,8 +120,8 @@ Module Platform.
Proof.
unfold work_conserving, work_conserving_count; split.
{
 intros EX j t BACK.
 specialize (EX j t BACK).
+ intros EX j t ARRin BACK.
+ specialize (EX j t ARRin BACK).
apply eq_trans with (y := size (enum (processor num_cpus)));
last by rewrite size_enum_ord.
unfold jobs_scheduled_at.
@@ 130,13 +140,13 @@ Module Platform.
by apply eq_bigr.
}
{
 intros SIZE j t BACK cpu.
 specialize (SIZE j t BACK).
+ intros SIZE j t ARRin BACK cpu.
+ specialize (SIZE j t ARRin BACK).
destruct ([exists cpu, sched cpu t == None]) eqn:EX; last first.
{
apply negbT in EX; rewrite negb_exists in EX.
move: EX => /forallP ALL; specialize (ALL cpu).
 destruct (sched cpu t) eqn:SOME; last by done.
+ destruct (sched cpu t) as [j0] eqn:SOME; last by done.
by exists j0; apply/eqP.
}
{
@@ 159,7 +169,8 @@ Module Platform.
}
des; rewrite {5}DIFF.
rewrite big_nat_recl; last by apply leq_addr.
 apply leq_trans with (n := (\sum_(0 <= i < cpu') 1) + 1 + (\sum_(cpu' <= i < cpu' + k) 1));
+ apply leq_trans with (n := (\sum_(0 <= i < cpu') 1) + 1 +
+ (\sum_(cpu' <= i < cpu' + k) 1));
last first.
{
rewrite 2!big_const_nat 2!iter_addn 2!mul1n addn0 subn0.
diff git a/model/schedule/global/jitter/schedule.v b/model/schedule/global/jitter/schedule.v
index 53a7f69..fe904b3 100644
 a/model/schedule/global/jitter/schedule.v
+++ b/model/schedule/global/jitter/schedule.v
@@ 14,48 +14,43 @@ Module ScheduleWithJitter.
Section ArrivalDependentProperties.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
 (* Given an arrival sequence, ... *)
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
 (* ... we define the following properties for job j in schedule sched. *)
+ (* ...and any schedule of these jobs. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
+ (* In this section we define properties of a job in the schedule. *)
Section JobProperties.
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
 (* The actual arrival of job j occurs after the jitter. *)
+ (* We define the actual arrival of job j as the time when the jitter ends. *)
Definition actual_arrival := job_arrival j + job_jitter j.
 (* Whether job j's jitter has passed by time t. *)
+ (* Next, we define whether job j's jitter has passed by time t... *)
Definition jitter_has_passed (t: time) := actual_arrival <= t.
 (* Whether job j actually arrived before time t. *)
+ (* ...and whether job j actually arrived before time t. *)
Definition actual_arrival_before (t: time) := actual_arrival < t.
 (* Job j is pending at time t iff the jitter has passed but j has not completed. *)
+ (* We say that job j is pending at time t iff the jitter has passed but j has not completed. *)
Definition pending (t: time) := jitter_has_passed t && ~~ completed job_cost sched j t.
 (* Job j is backlogged at time t iff it is pending and not scheduled. *)
+ (* We say that job j is backlogged at time t iff it is pending and not scheduled. *)
Definition backlogged (t: time) := pending t && ~~ scheduled sched j t.
 (* Job j is carryin in interval [t1, t2) iff it arrives before t1 and is
 not complete at time t1 *)
 Definition carried_in (t1: time) := actual_arrival_before t1 && ~~ completed job_cost sched j t1.

 (* Job j is carryout in interval [t1, t2) iff it arrives after t1 and is
 not complete at time t2 *)
 Definition carried_out (t1 t2: time) := actual_arrival_before t2 && ~~ completed job_cost sched j t2.

End JobProperties.
Section ScheduleProperties.
 (* A job can only be scheduled after the jitter has passed. *)
+ (* In a valid schedule, a job can only be scheduled after the jitter has passed. *)
Definition jobs_execute_after_jitter :=
forall j t,
scheduled sched j t > jitter_has_passed j t.
@@ 100,19 +95,19 @@ Module ScheduleWithJitter.
Section Service.
 (* If a job only executes after the jitter, it also only
 executes after its arrival time. *)
+ (* First, we prove that if a job cannot execute before the jitter has passed,
+ then it cannot execute before its arrival time. *)
Lemma arrival_before_jitter :
 jobs_must_arrive_to_execute sched.
 Proof.
 unfold jobs_execute_after_jitter, jobs_must_arrive_to_execute.
 intros j t SCHED; unfold ArrivalSequence.has_arrived.

 rewrite (leq_add2r (job_jitter j)).
 by apply leq_trans with (n := t);
 [by apply H_jobs_execute_after_jitter  by apply leq_addr].
 Qed.
+ jobs_must_arrive_to_execute job_arrival sched.
+ Proof.
+ unfold jobs_execute_after_jitter, jobs_must_arrive_to_execute.
+ intros j t SCHED; unfold ArrivalSequence.has_arrived.
+ rewrite (leq_add2r (job_jitter j)).
+ by apply leq_trans with (n := t);
+ [by apply H_jobs_execute_after_jitter  by apply leq_addr].
+ Qed.
+ (* Next, we show that the service received before the jitter is zero. *)
Lemma service_before_jitter_zero :
forall j t,
t < job_arrival j + job_jitter j >
@@ 123,6 +118,7 @@ Module ScheduleWithJitter.
by apply AFTER, (leq_trans LT) in SCHED; rewrite ltnn in SCHED.
Qed.
+ (* The same applies to the cumulative service. *)
Lemma cumulative_service_before_jitter_zero :
forall j t1 t2,
t2 <= job_arrival j + job_jitter j >
@@ 158,15 +154,14 @@ Module ScheduleOfSporadicTaskWithJitter.
Context {Job: eqType}.
Variable job_task: Job > sporadic_task.
 (* Consider any schedule. *)
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any multiprocessor schedule. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Given a task tsk, ...*)
Variable tsk: sporadic_task.
 (* ..., we we can state that tsk is scheduled on cpu at time t as follows. *)
+ (* ..., we can state that tsk is scheduled on cpu at time t as follows. *)
Definition task_scheduled_on (cpu: processor num_cpus) (t: time) :=
if (sched cpu t) is Some j then
(job_task j == tsk)
@@ 178,7 +173,7 @@ Module ScheduleOfSporadicTaskWithJitter.
(* We also define the list of jobs scheduled during [t1, t2). *)
Definition jobs_of_task_scheduled_between (t1 t2: time) :=
 filter (fun (j: JobIn arr_seq) => job_task j == tsk)
+ filter (fun j => job_task j == tsk)
(jobs_scheduled_between sched t1 t2).
End ScheduledJobs.
@@ 192,15 +187,16 @@ Module ScheduleOfSporadicTaskWithJitter.
Variable job_task: Job > sporadic_task.
(* Consider any schedule. *)
 Context {arr_seq: arrival_sequence Job}.
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Next we define intratask parallelism. *)
Definition jobs_of_same_task_dont_execute_in_parallel :=
 forall (j j': JobIn arr_seq) t,
+ forall j j' t,
job_task j = job_task j' >
 scheduled sched j t > scheduled sched j' t > j = j'.
+ scheduled sched j t >
+ scheduled sched j' t >
+ j = j'.
End ScheduleProperties.
@@ 216,23 +212,29 @@ Module ScheduleOfSporadicTaskWithJitter.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
 (* Then, in a valid schedule of sporadic tasks ...*)
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* ...and any schedule of these jobs. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
 (* ...such that jobs do not execute after completion, ...*)
+ (* Assume that jobs do not execute after completion.*)
Hypothesis jobs_dont_execute_after_completion :
completed_jobs_dont_execute job_cost sched.
+ (* Let tsk be any task...*)
Variable tsk: sporadic_task.

 Variable j: JobIn arr_seq.
+
+ (* ...and let j be any valid job of this task. *)
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_task: job_task j = tsk.
Hypothesis valid_job:
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
 (* Remember that for any job of tsk, service <= task_cost tsk *)
+ (* Then, we can prove that the service received by j is no larger than the cost
+ of its task. *)
Lemma cumulative_service_le_task_cost :
forall t t',
service_during sched j t t' <= task_cost tsk.
diff git a/model/schedule/global/response_time.v b/model/schedule/global/response_time.v
index 79d2ff7..33f2c6a 100644
 a/model/schedule/global/response_time.v
+++ b/model/schedule/global/response_time.v
@@ 12,132 +12,129 @@ Module ResponseTime.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
 (* Given a task ...*)
 Variable tsk: sporadic_task.
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
 (* ... and a particular schedule, ...*)
+ (* ...and any multiprocessor schedule of these jobs. *)
Context {num_cpus : nat}.
 Variable sched: schedule num_cpus arr_seq.

 (* ... R is a responsetime bound of tsk in this schedule ... *)
 Variable R: time.
+ Variable sched: schedule Job num_cpus.
+ (* For simplicity, let's define some local names.*)
Let job_has_completed_by := completed job_cost sched.
 (* ... iff any job j of tsk in this arrival sequence has
 completed by (job_arrival j + R). *)
 Definition is_response_time_bound_of_task :=
 forall (j: JobIn arr_seq),
 job_task j = tsk >
 job_has_completed_by j (job_arrival j + R).

 End ResponseTimeBound.
+ Section Definitions.
+
+ (* Given a task tsk...*)
+ Variable tsk: sporadic_task.
 Section BasicLemmas.
+ (* ... we say that R is a responsetime bound of tsk in this schedule ... *)
+ Variable R: time.
 Context {sporadic_task: eqType}.
 Context {Job: eqType}.
 Variable job_cost: Job > time.
 Variable job_task: Job > sporadic_task.
+ (* ... iff any job j of tsk in this arrival sequence has completed by (job_arrival j + R). *)
+ Definition is_response_time_bound_of_task :=
+ forall j,
+ arrives_in arr_seq j >
+ job_task j = tsk >
+ job_has_completed_by j (job_arrival j + R).
 Context {arr_seq: arrival_sequence Job}.
+ End Definitions.
 (* Consider any valid schedule... *)
 Context {num_cpus : nat}.
 Variable sched: schedule num_cpus arr_seq.

 Let job_has_completed_by := completed job_cost sched.

 (* ... where jobs dont execute after completion. *)
 Hypothesis H_completed_jobs_dont_execute:
 completed_jobs_dont_execute job_cost sched.

 Section SpecificJob.

 (* Then, for any job j ...*)
 Variable j: JobIn arr_seq.

 (* ...with responsetime bound R in this schedule, ... *)
 Variable R: time.
 Hypothesis response_time_bound:
 job_has_completed_by j (job_arrival j + R).

 (* the service received by j at any time t' after its response time is 0. *)
 Lemma service_after_job_rt_zero :
 forall t',
 t' >= job_arrival j + R >
 service_at sched j t' = 0.
 Proof.
 rename response_time_bound into RT,
 H_completed_jobs_dont_execute into EXEC; ins.
 unfold is_response_time_bound_of_task, completed,
 completed_jobs_dont_execute in *.
 apply/eqP; rewrite leqn0.
 rewrite < leq_add2l with (p := job_cost j).
 move: RT => /eqP RT; rewrite {1}RT addn0.
 apply leq_trans with (n := service sched j t'.+1);
 last by apply EXEC.
 unfold service; rewrite > big_cat_nat with
 (p := t'.+1) (n := job_arrival j + R);
 [rewrite leq_add2l /=  by ins  by apply ltnW].
+ Section BasicLemmas.
+
+ (* Assume that jobs dont execute after completion. *)
+ Hypothesis H_completed_jobs_dont_execute:
+ completed_jobs_dont_execute job_cost sched.
+
+ Section SpecificJob.
+
+ (* Then, for any job j ...*)
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
+
+ (* ...with responsetime bound R in this schedule, ... *)
+ Variable R: time.
+ Hypothesis response_time_bound:
+ job_has_completed_by j (job_arrival j + R).
+
+ (* ...the service received by j at any time t' after its response time is 0. *)
+ Lemma service_after_job_rt_zero :
+ forall t',
+ t' >= job_arrival j + R >
+ service_at sched j t' = 0.
+ Proof.
+ rename response_time_bound into RT,
+ H_completed_jobs_dont_execute into EXEC; ins.
+ unfold is_response_time_bound_of_task, completed,
+ completed_jobs_dont_execute in *.
+ apply/eqP; rewrite leqn0.
+ rewrite < leq_add2l with (p := job_cost j).
+ move: RT => /eqP RT; rewrite {1}RT addn0.
+ apply leq_trans with (n := service sched j t'.+1);
+ last by apply EXEC.
+ unfold service; rewrite > big_cat_nat with
+ (p := t'.+1) (n := job_arrival j + R);
+ [rewrite leq_add2l /=  by ins  by apply ltnW].
by rewrite big_nat_recr // /=; apply leq_addl.
 Qed.

 (* The same applies for the cumulative service of job j. *)
 Lemma cumulative_service_after_job_rt_zero :
 forall t' t'',
 t' >= job_arrival j + R >
 \sum_(t' <= t < t'') service_at sched j t = 0.
 Proof.
 ins; apply/eqP; rewrite leqn0.
 rewrite big_nat_cond; rewrite > eq_bigr with (F2 := fun i => 0);
 first by rewrite big_const_seq iter_addn mul0n addn0 leqnn.
 intro i; rewrite andbT; move => /andP [LE _].
 by rewrite service_after_job_rt_zero;
 [by ins  by apply leq_trans with (n := t')].
 Qed.

 End SpecificJob.

 Section AllJobs.
+ Qed.
+
+ (* The same applies for the cumulative service of job j. *)
+ Lemma cumulative_service_after_job_rt_zero :
+ forall t' t'',
+ t' >= job_arrival j + R >
+ \sum_(t' <= t < t'') service_at sched j t = 0.
+ Proof.
+ ins; apply/eqP; rewrite leqn0.
+ rewrite big_nat_cond; rewrite > eq_bigr with (F2 := fun i => 0);
+ first by rewrite big_const_seq iter_addn mul0n addn0 leqnn.
+ intro i; rewrite andbT; move => /andP [LE _].
+ by rewrite service_after_job_rt_zero;
+ [by ins  by apply leq_trans with (n := t')].
+ Qed.
+
+ End SpecificJob.
+
+ Section AllJobs.
+
+ (* Consider any task tsk ...*)
+ Variable tsk: sporadic_task.
+
+ (* ... for which a responsetime bound R is known. *)
+ Variable R: time.
+ Hypothesis response_time_bound:
+ is_response_time_bound_of_task tsk R.
+
+ (* Then, for any job j of this task, ...*)
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
+ Hypothesis H_job_of_task: job_task j = tsk.
+
+ (* ...the service received by job j at any time t' after the response time is 0. *)
+ Lemma service_after_task_rt_zero :
+ forall t',
+ t' >= job_arrival j + R >
+ service_at sched j t' = 0.
+ Proof.
+ by ins; apply service_after_job_rt_zero with (R := R); [apply response_time_bound ].
+ Qed.
+
+ (* The same applies for the cumulative service of job j. *)
+ Lemma cumulative_service_after_task_rt_zero :
+ forall t' t'',
+ t' >= job_arrival j + R >
+ \sum_(t' <= t < t'') service_at sched j t = 0.
+ Proof.
+ by ins; apply cumulative_service_after_job_rt_zero with (R := R);
+ first by apply response_time_bound.
+ Qed.
+
+ End AllJobs.
+
+ End BasicLemmas.
 (* Consider any task tsk ...*)
 Variable tsk: sporadic_task.

 (* ... for which a responsetime bound R is known. *)
 Variable R: time.
 Hypothesis response_time_bound:
 is_response_time_bound_of_task job_cost job_task tsk sched R.

 (* Then, for any job j of this task, ...*)
 Variable j: JobIn arr_seq.
 Hypothesis H_job_of_task: job_task j = tsk.

 (* the service received by job j at any time t' after the response time is 0. *)
 Lemma service_after_task_rt_zero :
 forall t',
 t' >= job_arrival j + R >
 service_at sched j t' = 0.
 Proof.
 by ins; apply service_after_job_rt_zero with (R := R); [apply response_time_bound ].
 Qed.

 (* The same applies for the cumulative service of job j. *)
 Lemma cumulative_service_after_task_rt_zero :
 forall t' t'',
 t' >= job_arrival j + R >
 \sum_(t' <= t < t'') service_at sched j t = 0.
 Proof.
 by ins; apply cumulative_service_after_job_rt_zero with (R := R);
 first by apply response_time_bound.
 Qed.

 End AllJobs.
+ End ResponseTimeBound.
 End BasicLemmas.

End ResponseTime.
\ No newline at end of file
diff git a/model/schedule/global/schedulability.v b/model/schedule/global/schedulability.v
index 60a0335..6bde685 100644
 a/model/schedule/global/schedulability.v
+++ b/model/schedule/global/schedulability.v
@@ 10,21 +10,27 @@ Module Schedulability.
Section SchedulableDefs.
 (* Assume that the cost and deadline of a job is known. *)
+ Context {sporadic_task: eqType}.
+
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.

 Section ScheduleOfJobs.
+ Variable job_task: Job > sporadic_task.
+
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* ...and any multiprocessor schedule of these jobs. *)
+ Context {num_cpus: nat}.
+ Variable sched: schedule Job num_cpus.
 (* For any job j in schedule sched, ...*)
 Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Section ScheduleOfJobs.
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
 (* job j misses no deadline in sched if it completed by its absolute deadline. *)
+ (* We say that job j misses no deadline in sched if it completed by its absolute deadline. *)
Definition job_misses_no_deadline :=
completed job_cost sched j (job_arrival j + job_deadline j).
@@ 32,28 +38,24 @@ Module Schedulability.
Section ScheduleOfTasks.
 Context {sporadic_task: eqType}.
 Variable job_task: Job > sporadic_task.

 Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.

(* Consider any task tsk. *)
Variable tsk: sporadic_task.
(* Task tsk doesn't miss its deadline iff all of its jobs don't miss their deadline. *)
Definition task_misses_no_deadline :=
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
job_task j = tsk >
 job_misses_no_deadline sched j.
+ job_misses_no_deadline j.
(* Task tsk doesn't miss its deadline before time t' iff all of its jobs don't miss
their deadline by that time. *)
Definition task_misses_no_deadline_before (t': time) :=
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
job_task j = tsk >
job_arrival j + job_deadline j < t' >
 job_misses_no_deadline sched j.
+ job_misses_no_deadline j.
End ScheduleOfTasks.
@@ 67,15 +69,17 @@ Module Schedulability.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
 Context {arr_seq: arrival_sequence Job}.
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
 (* Consider any valid schedule... *)
+ (* ...and any schedule of these jobs... *)
Context {num_cpus : nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* ... where jobs dont execute after completion. *)
Hypothesis H_completed_jobs_dont_execute:
@@ 84,11 +88,12 @@ Module Schedulability.
Section SpecificJob.
(* Then, for any job j ...*)
 Variable j: JobIn arr_seq.

+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
+
(* ...that doesn't miss a deadline in this schedule, ... *)
Hypothesis no_deadline_miss:
 job_misses_no_deadline job_cost job_deadline sched j.
+ job_misses_no_deadline job_arrival job_cost job_deadline sched j.
(* the service received by j at any time t' after its deadline is 0. *)
Lemma service_after_job_deadline_zero :
@@ 133,10 +138,11 @@ Module Schedulability.
(* ... that doesn't miss any deadline. *)
Hypothesis no_deadline_misses:
 task_misses_no_deadline job_cost job_deadline job_task sched tsk.
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched tsk.
(* Then, for any valid job j of this task, ...*)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
Hypothesis H_job_of_task: job_task j = tsk.
Hypothesis H_valid_job:
valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
diff git a/model/schedule/global/transformation/construction.v b/model/schedule/global/transformation/construction.v
new file mode 100644
index 0000000..7eaf5bf
 /dev/null
+++ b/model/schedule/global/transformation/construction.v
@@ 0,0 +1,151 @@
+Require Import rt.util.all.
+Require Import rt.model.arrival.basic.arrival_sequence.
+Require Import rt.model.schedule.global.basic.schedule.
+From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat fintype bigop seq path finfun.
+
+Module ScheduleConstruction.
+
+ Import ArrivalSequence Schedule.
+
+ (* In this section, we construct a schedule recursively by augmenting prefixes. *)
+ Section ConstructionFromPrefixes.
+
+ Context {Job: eqType}.
+
+ (* Let arr_seq be any arrival sequence.*)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* Let num_cpus denote the number of processors. *)
+ Variable num_cpus: nat.
+
+ (* Assume we are given a function that takes an existing schedule prefix [0, t)
+ and returns what should be scheduled at time t on each processor. *)
+ Variable build_schedule:
+ schedule Job num_cpus > schedule Job num_cpus.
+
+ (* Then, starting from a base schedule, ... *)
+ Variable base_sched: schedule Job num_cpus.
+
+ (* ...we can update individual times using the build_schedule function, ... *)
+ Definition update_schedule (prev_sched: schedule Job num_cpus)
+ (t_next: time) : schedule Job num_cpus :=
+ fun (cpu: processor num_cpus) t =>
+ if t == t_next then
+ build_schedule prev_sched cpu t
+ else prev_sched cpu t.
+
+ (* ...which recursively generates schedule prefixes up to time t_max. *)
+ Fixpoint schedule_prefix (t_max: time) : schedule Job num_cpus :=
+ if t_max is t_prev.+1 then
+ update_schedule (schedule_prefix t_prev) t_prev.+1
+ else
+ update_schedule base_sched 0.
+
+ (* Based on the schedule prefixes, we construct a complete schedule. *)
+ Definition build_schedule_from_prefixes := fun cpu t => schedule_prefix t cpu t.
+
+ (* In this section, we prove some lemmas about the construction. *)
+ Section Lemmas.
+
+ (* Let sched be the generated schedule. *)
+ Let sched := build_schedule_from_prefixes.
+
+ (* First, we show that the scheduler preserves its prefixes. *)
+ Lemma prefix_construction_same_prefix:
+ forall t t_max cpu,
+ t <= t_max >
+ schedule_prefix t_max cpu t = sched cpu t.
+ Proof.
+ intros t t_max cpu LEt.
+ induction t_max;
+ first by rewrite leqn0 in LEt; move: LEt => /eqP EQ; subst.
+ rewrite leq_eqVlt in LEt.
+ move: LEt => /orP [/eqP EQ  LESS]; first by subst.
+ {
+ feed IHt_max; first by done.
+ unfold schedule_prefix, update_schedule at 1.
+ assert (FALSE: t == t_max.+1 = false).
+ {
+ by apply negbTE; rewrite neq_ltn LESS orTb.
+ } rewrite FALSE.
+ by rewrite IHt_max.
+ }
+ Qed.
+
+ Section ServiceDependent.
+
+ (* If the generation function only depends on the service
+ received by jobs during the schedule prefix, ...*)
+ Hypothesis H_depends_only_on_service:
+ forall sched1 sched2 cpu t,
+ (forall j, service sched1 j t = service sched2 j t) >
+ build_schedule sched1 cpu t = build_schedule sched2 cpu t.
+
+ (* ...then we can prove that the final schedule, at any time t,
+ is exactly the result of the construction function. *)
+ Lemma service_dependent_schedule_construction:
+ forall cpu t,
+ sched cpu t = build_schedule sched cpu t.
+ Proof.
+ intros cpu t.
+ feed (prefix_construction_same_prefix t t cpu); [by done  intros EQ].
+ rewrite {}EQ.
+ induction t as [t IH] using strong_ind.
+ destruct t.
+ {
+ rewrite /= /update_schedule eq_refl.
+ apply H_depends_only_on_service.
+ by intros j; rewrite /service /service_during big_geq // big_geq //.
+ }
+ {
+ rewrite /= /update_schedule eq_refl.
+ apply H_depends_only_on_service.
+ intros j; rewrite /service /service_during.
+ rewrite big_nat_recr //= big_nat_recr //=; f_equal.
+ apply eq_big_nat; move => i /= LT.
+ rewrite /service_at.
+ apply eq_bigl; intros cpu'; rewrite /scheduled_on.
+ by rewrite prefix_construction_same_prefix; last by apply ltnW.
+ }
+ Qed.
+
+ End ServiceDependent.
+
+ Section PrefixDependent.
+
+ (* If the generation function only depends on the schedule prefix, ... *)
+ Hypothesis H_depends_only_on_prefix:
+ forall (sched1 sched2: schedule Job num_cpus) cpu t,
+ (forall t0 cpu, t0 < t > sched1 cpu t0 = sched2 cpu t0) >
+ build_schedule sched1 cpu t = build_schedule sched2 cpu t.
+
+ (* ...then we can prove that the final schedule, at any time t,
+ is exactly the result of the construction function. *)
+ Lemma prefix_dependent_schedule_construction:
+ forall cpu t, sched cpu t = build_schedule sched cpu t.
+ Proof.
+ intros cpu t.
+ feed (prefix_construction_same_prefix t t cpu); [by done  intros EQ].
+ rewrite {}EQ.
+ induction t using strong_ind.
+ destruct t.
+ {
+ rewrite /= /update_schedule eq_refl.
+ apply H_depends_only_on_prefix.
+ by intros t; rewrite ltn0.
+ }
+ {
+ rewrite /= /update_schedule eq_refl.
+ apply H_depends_only_on_prefix.
+ intros t0 cpu0 LT.
+ by rewrite prefix_construction_same_prefix.
+ }
+ Qed.
+
+ End PrefixDependent.
+
+ End Lemmas.
+
+ End ConstructionFromPrefixes.
+
+End ScheduleConstruction.
\ No newline at end of file
diff git a/model/schedule/global/workload.v b/model/schedule/global/workload.v
index 07324e6..fcb606f 100644
 a/model/schedule/global/workload.v
+++ b/model/schedule/global/workload.v
@@ 14,22 +14,24 @@ Module Workload.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
Variable job_task: Job > sporadic_task.
 Context {arr_seq: arrival_sequence Job}.

+
+ (* Consider any job arrival sequence ...*)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* ...and any schedule of these jobs. *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
 (* Consider some task *)
+ (* Let tsk be any task. *)
Variable tsk: sporadic_task.
(* First, we define a function that returns the amount of service
received by this task in a particular processor. *)
Definition service_of_task (cpu: processor num_cpus)
 (j: option (JobIn arr_seq)) : time :=
 match j with
  Some j' => (job_task j' == tsk)
  None => 0
 end.
+ (scheduled_job: option Job) : time :=
+ if scheduled_job is Some j' then
+ (job_task j' == tsk)
+ else 0.
(* Next, workload is defined as the service received by jobs of
the task in the interval [t1,t2). *)
@@ 58,7 +60,7 @@ Module Workload.
last by ins; rewrite big_mkcond; apply eq_bigr; ins; rewrite mulnbl.
rewrite exchange_big /=; apply eq_bigr.
intros cpu LEcpu; rewrite big_filter.
 destruct (sched cpu t) eqn:SCHED; simpl;
+ destruct (sched cpu t) as [j] eqn:SCHED; simpl;
last by rewrite big_const_seq iter_addn mul0n addn0.
destruct (job_task j == tsk) eqn:EQtsk;
try rewrite mul1n; try rewrite mul0n.
@@ 68,9 +70,8 @@ Module Workload.
rewrite > eq_bigr with (F2 := fun i => 0); last first.
{
intros i DIFF.
 destruct (Some j == Some i) eqn:SOME; rewrite SOME; last by done.
 move: SOME => /eqP SOME; inversion SOME as [EQ].
 by rewrite EQ eq_refl in DIFF.
+ apply/eqP; rewrite eqb0; apply/eqP; case => SAME; subst.
+ by rewrite eq_refl in DIFF.
}
by rewrite /= big_const_seq iter_addn mul0n 2!addn0 eq_refl.
}
@@ 93,4 +94,4 @@ Module Workload.
End WorkloadDef.
End Workload.
+End Workload.
\ No newline at end of file
diff git a/model/schedule/partitioned/schedulability.v b/model/schedule/partitioned/schedulability.v
index 96105d0..f7994ac 100644
 a/model/schedule/partitioned/schedulability.v
+++ b/model/schedule/partitioned/schedulability.v
@@ 15,19 +15,20 @@ Module PartitionSchedulability.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > Task.
(* Consider any job arrival sequence that is to be scheduled. *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* Assume that all jobs in the arrival sequence come from a task set ts. *)
Variable ts: list Task.
Hypothesis H_all_jobs_from_ts:
 forall (j: JobIn arr_seq), job_task j \in ts.
+ forall j, arrives_in arr_seq j > job_task j \in ts.
(* Also assume that every task is assigned to a processor, ... *)
Variable assigned_cpu: Task > processor num_cpus.
@@ 39,16 +40,20 @@ Module PartitionSchedulability.
Section SameService.
(* Consider the partition where each job is assigned to. *)
 Let partition_of (j: JobIn arr_seq) := assigned_cpu (job_task j).
+ Let partition_of j := assigned_cpu (job_task j).
+ (* Let j be any job. *)
+ Variable j: Job.
+ Hypothesis H_j_arrives: arrives_in arr_seq j.
+
(* We prove that the service received by job j (on the multiprocessor)
is the same as the service received by job j in its partition. *)
Lemma same_per_processor_service :
 forall j t1 t2,
+ forall t1 t2,
service_during sched j t1 t2 =
uni.service_during (sched (partition_of j)) j t1 t2.
Proof.
 intros j t1 t2.
+ intros t1 t2.
unfold partitioned_schedule, task_local_to_processor,
job_local_to_processor, service_during, service_at,
uni.service_during, uni.service_at,
@@ 56,7 +61,9 @@ Module PartitionSchedulability.
rename H_partitioned into PART, H_all_jobs_from_ts into FROMTS.
apply eq_bigr; intros t _.
unfold uni.service_at, uni.scheduled_at.
 feed (PART (job_task j) (FROMTS j) j); [by done  specialize (PART t)].
+ feed (PART (job_task j)); first by apply FROMTS.
+ feed (PART j); first by done.
+ specialize (PART t).
destruct (scheduled sched j t) eqn:SCHED; last first.
{
apply negbT in SCHED; rewrite negb_exists in SCHED.
@@ 86,8 +93,11 @@ Module PartitionSchedulability.
(* Recall the definitions of schedulability on a uniprocessor and on
a multiprocessor. *)
 Let schedulable_on tsk cpu := uni_sched.task_misses_no_deadline job_cost job_deadline job_task (sched cpu) tsk.
 Let schedulable := task_misses_no_deadline job_cost job_deadline job_task sched.
+ Let schedulable_on tsk cpu :=
+ uni_sched.task_misses_no_deadline job_arrival job_cost job_deadline job_task
+ arr_seq (sched cpu) tsk.
+ Let schedulable :=
+ task_misses_no_deadline job_arrival job_cost job_deadline job_task arr_seq sched.
(* Here we prove that if every task is schedulable in their assigned processors, ...*)
@@ 108,11 +118,11 @@ Module PartitionSchedulability.
uni_sched.job_misses_no_deadline, uni.completed_by in *.
rename H_locally_schedulable into SCHED,
H_partitioned into PART.
 intros tsk IN j JOBtsk.
 specialize (SCHED tsk IN j JOBtsk).
+ intros tsk IN j ARRj JOBtsk.
+ specialize (SCHED tsk IN j ARRj JOBtsk).
move: SCHED => /eqP <.
unfold service, uni.service, service_during, uni.service_during in *.
 by apply/eqP; rewrite SAME JOBtsk.
+ by apply/eqP; rewrite SAME // JOBtsk.
Qed.
End Schedulability.
diff git a/model/schedule/partitioned/schedule.v b/model/schedule/partitioned/schedule.v
index 3e84dae..fc2fa30 100644
 a/model/schedule/partitioned/schedule.v
+++ b/model/schedule/partitioned/schedule.v
@@ 19,12 +19,11 @@ Module Partitioned.
Variable job_task: Job > Task.
(* Consider any job arrival sequence. *)
 Context {arr_seq: arrival_sequence Job}.

+ Variable arr_seq: arrival_sequence Job.
(* Given any multiprocessor schedule of these jobs, ... *)
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
(* ... we define a notion of "partitioned scheduling" (= no migrations) on
a perjob, pertask, and finally wholeschedule level. *)
@@ 35,7 +34,7 @@ Module Partitioned.
* executes on the same processor whenever it is scheduled. *)
(* So any job j... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* ... never migrates iff the following holds: ... *)
Definition never_migrates :=
@@ 74,8 +73,9 @@ Module Partitioned.
(* ...iff every job of tsk executes exclusively on assigned_cpu. *)
Definition task_local_to_processor :=
 forall j : JobIn arr_seq,
 job_task j = tsk > job_local_to_processor j assigned_cpu.
+ forall j,
+ job_task j = tsk >
+ job_local_to_processor j assigned_cpu.
End NoTaskMigration.
@@ 104,13 +104,12 @@ Module Partitioned.
Context {Job: eqType}.
 Context {arr_seq: arrival_sequence Job}.
Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.
+ Variable sched: schedule Job num_cpus.
Section NoJobMigrationLemmas.
 Variable j: JobIn arr_seq.
+ Variable j: Job.
Lemma local_jobs_dont_migrate:
forall cpu,
@@ 127,112 +126,4 @@ Module Partitioned.
End SimpleProperties.
 Section PartitionedAsUniprocessor.

 Context {Task: eqType}.
 Context {Job: eqType}.
 Variable job_cost: Job > time.
 Variable job_deadline: Job > time.
 Variable job_task: Job > Task.

 (* Consider any job arrival sequence that is to be scheduled. *)
 Context {arr_seq: arrival_sequence Job}.
 Context {num_cpus: nat}.
 Variable sched: schedule num_cpus arr_seq.

 (* Assume that all jobs in the arrival sequence come from a task set ts. *)
 Variable ts: list Task.
 Hypothesis H_all_jobs_from_ts:
 forall (j: JobIn arr_seq), job_task j \in ts.

 (* Also assume that every task is assigned to a processor, ... *)
 Variable assigned_cpu: Task > processor num_cpus.

 (* ...forming a partitioned schedule. *)
 Hypothesis H_partitioned: partitioned_schedule job_task sched ts assigned_cpu.

 (* Next, we related total service with perprocessor service received by each job. *)
 Section SameService.

 (* Consider the partition where each job is assigned to. *)
 Let partition_of (j: JobIn arr_seq) := assigned_cpu (job_task j).

 (* We prove that the service received by job j (on the multiprocessor)
 is the same as the service received by job j in its partition. *)
 Lemma same_per_processor_service :
 forall j t1 t2,
 service_during sched j t1 t2 =
 uni.service_during (sched (partition_of j)) j t1 t2.
 Proof.
 intros j t1 t2.
 unfold partitioned_schedule, task_local_to_processor,
 job_local_to_processor, service_during, service_at,
 uni.service_during, uni.service_at,
 uni.scheduled_at, scheduled_on, partition_of in *.
 rename H_partitioned into PART, H_all_jobs_from_ts into FROMTS.
 apply eq_bigr; intros t _.
 unfold uni.service_at, uni.scheduled_at.
 feed (PART (job_task j) (FROMTS j) j); [by done  specialize (PART t)].
 destruct (scheduled sched j t) eqn:SCHED; last first.
 {
 apply negbT in SCHED; rewrite negb_exists in SCHED.
 move: SCHED => /forallP SCHED.
 have SCHEDcpu := SCHED (assigned_cpu (job_task j)); apply negbTE in SCHEDcpu.
 unfold scheduled_on in *; rewrite SCHEDcpu.
 rewrite big1; first by done.
 move => cpu /eqP SCHED'.
 by specialize (SCHED cpu); rewrite SCHED' eq_refl in SCHED.
 }
 {
 move: SCHED => /existsP [cpu SCHED].
 rewrite (bigD1 cpu) /=; last by done.
 have SAME := PART cpu SCHED; rewrite SAME.
 unfold scheduled_on in *; rewrite SCHED.
 rewrite add1n; apply/eqP; rewrite eqSS; apply/eqP.
 rewrite big1; first by done.
 move => cpu' /andP [SCHED' NEQ].
 have SAME' := (PART cpu' SCHED'); subst cpu cpu'.
 by rewrite eq_refl in NEQ.
 }
 Qed.

 End SameService.

 Section Schedulability.

 (* Recall the definitions of schedulability on a uniprocessor and on
 a multiprocessor. *)
 Let schedulable_on tsk cpu := uni_sched.task_misses_no_deadline job_cost job_deadline job_task (sched cpu) tsk.
 Let schedulable := task_misses_no_deadline job_cost job_deadline job_task sched.


 (* Here we prove that if every task is schedulable in their assigned processors, ...*)
 Hypothesis H_locally_schedulable:
 forall tsk,
 tsk \in ts > schedulable_on tsk (assigned_cpu tsk).

 (* ...then every task is schedulable at the level of the multiprocessor system. *)
 Lemma schedulable_at_system_level:
 forall tsk,
 tsk \in ts > schedulable tsk.
 Proof.
 have SAME := same_per_processor_service.
 unfold partitioned_schedule, task_local_to_processor,
 job_local_to_processor, schedulable, schedulable_on,
 task_misses_no_deadline, job_misses_no_deadline,
 completed, uni_sched.task_misses_no_deadline,
 uni_sched.job_misses_no_deadline, uni.completed_by in *.
 rename H_locally_schedulable into SCHED,
 H_partitioned into PART.
 intros tsk IN j JOBtsk.
 specialize (SCHED tsk IN j JOBtsk).
 move: SCHED => /eqP <.
 unfold service, uni.service, service_during, uni.service_during in *.
 by apply/eqP; rewrite SAME JOBtsk.
 Qed.

 End Schedulability.

 End PartitionedAsUniprocessor.

End Partitioned.
\ No newline at end of file
diff git a/model/schedule/uni/basic/busy_interval.v b/model/schedule/uni/basic/busy_interval.v
index 313e741..14b277f 100644
 a/model/schedule/uni/basic/busy_interval.v
+++ b/model/schedule/uni/basic/busy_interval.v
@@ 16,30 +16,38 @@ Module BusyInterval.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > Task.
 (* Consider any uniprocessor schedule, ... *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* Consider any arrival sequence with consistent arrival times... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
+
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
 (* ...along with a JLFP policy. *)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ (* Assume a given JLFP policy. *)
+ Variable higher_eq_priority: JLFP_policy Job.
(* Let j be the job to be analyzed. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_from_arrival_sequence: arrives_in arr_seq j.
(* For simplicity, let's define some local names. *)
 Let job_pending_at := pending job_cost sched.
+ Let job_pending_at := pending job_arrival job_cost sched.
Let job_scheduled_at := scheduled_at sched.
Let job_completed_by := completed_by job_cost sched.
 (* We say that t is a quiet time for j iff every higherpriority
 job that arrived before t has completed by that time. *)
+ (* We say that t is a quiet time for j iff every higherpriority job from
+ the arrival sequence that arrived before t has completed by that time. *)
Definition quiet_time (t: time) :=
 forall (j_hp: JobIn arr_seq),
+ forall j_hp,
+ arrives_in arr_seq j_hp >
higher_eq_priority j_hp j >
 arrived_before j_hp t >
+ arrived_before job_arrival j_hp t >
job_completed_by j_hp t.
(* Based on the definition of quiet time, we say that interval
@@ 88,7 +96,7 @@ Module BusyInterval.
H_during_interval into INT, H_job_is_pending into PEND.
move: BUSY => [_ QUIET].
move: INT => /andP [_ LT2].
 apply QUIET; first by apply REFL.
+ apply QUIET; [by done  by apply REFL ].
apply leq_ltn_trans with (n := t); last by done.
by move: PEND => /andP [ARR _].
Qed.
@@ 115,7 +123,7 @@ Module BusyInterval.
move: INT => /andP [LE _].
exfalso; apply NOTCOMP.
apply completion_monotonic with (t0 := t1); try (by done).
 by apply QUIET; first by apply REFL.
+ by apply QUIET; [by done  by apply REFL ].
Qed.
End ArrivesDuringBusyInterval.
@@ 140,8 +148,9 @@ Module BusyInterval.
(* Then, we prove that there exists a job pending at time t2
that has higher or equal priority (with respect ot tsk). *)
Lemma not_quiet_implies_exists_pending_job:
 exists (j_hp: JobIn arr_seq),
 arrived_between j_hp t1 t2 /\
+ exists j_hp,
+ arrives_in arr_seq j_hp /\
+ arrived_between job_arrival j_hp t1 t2 /\
higher_eq_priority j_hp j /\
~ job_completed_by j_hp t2.
Proof.
@@ 150,18 +159,20 @@ Module BusyInterval.
(arrivals_between t1 t2)) eqn:COMP.
{
move: COMP => /hasP [j_hp ARR /andP [NOTCOMP HP]].
 exists j_hp; repeat split; [  by done  by apply/negP].
 rewrite mem_filter in ARR; move: ARR => /andP [GE ARR].
 by apply/andP; split; last by apply JobIn_arrived.
+ move: (ARR) => INarr.
+ apply in_arrivals_implies_arrived_between with (job_arrival0 := job_arrival) in ARR;
+ last by done.
+ apply in_arrivals_implies_arrived in INarr.
+ by exists j_hp; repeat split; last by apply/negP.
}
{
apply negbT in COMP; rewrite all_predC in COMP.
move: COMP => /allP COMP.
 exfalso; apply NOTQUIET; intros j_hp HP ARR.
+ exfalso; apply NOTQUIET; intros j_hp IN HP ARR.
destruct (ltnP (job_arrival j_hp) t1) as [BEFORE  AFTER];
 first by specialize (QUIET j_hp HP BEFORE); apply completion_monotonic with (t := t1).
 feed (COMP j_hp);
 first by rewrite mem_filter; apply/andP; split; last by apply JobIn_arrived.
+ first by specialize (QUIET j_hp IN HP BEFORE); apply completion_monotonic with (t := t1).
+ feed (COMP j_hp).
+ by eapply arrived_between_implies_in_arrivals; eauto 1; apply/andP; split.
by rewrite /= HP andbT negbK in COMP.
}
Qed.
@@ 174,9 +185,9 @@ Module BusyInterval.
(* Assume that the schedule is workconserving and that jobs do
not execute before their arrival or after completion. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
 Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute sched.
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
(* Consider any interval [t1, t2] such that t1 < t2 and t1 is the only quiet time. *)
Variable t1 t2: time.
@@ 198,13 +209,13 @@ Module BusyInterval.
subst t.
feed (NOTQUIET t1.+1); first by apply/andP; split.
apply NOTQUIET.
 intros j_hp HP ARR.
+ intros j_hp IN HP ARR.
apply completion_monotonic with (t := t1); [by done  by done ].
apply contraT; intro NOTCOMP.
destruct (scheduled_at sched j_hp t1) eqn:SCHEDhp;
first by move: SCHEDhp => /eqP SCHEDhp; rewrite IDLE in SCHEDhp.
apply negbT in SCHEDhp.
 feed (WORK j_hp t1);
+ feed (WORK j_hp t1 IN);
first by rewrite /arrived_before ltnS in ARR; repeat (apply/andP; split).
move: WORK => [j_other /eqP SCHEDother].
by rewrite IDLE in SCHEDother.
@@ 212,12 +223,12 @@ Module BusyInterval.
{
feed (NOTQUIET t); first by apply/andP; split.
apply NOTQUIET; clear NOTQUIET.
 intros j_hp HP ARR.
+ intros j_hp IN HP ARR.
apply contraT; intros NOTCOMP.
destruct (scheduled_at sched j_hp t) eqn:SCHEDhp;
first by move: SCHEDhp => /eqP SCHEDhp; rewrite IDLE in SCHEDhp.
apply negbT in SCHEDhp.
 feed (WORK j_hp t);
+ feed (WORK j_hp t IN);
first by repeat (apply/andP; split); first by apply ltnW.
move: WORK => [j_other /eqP SCHEDother].
by rewrite IDLE in SCHEDother.
@@ 229,21 +240,23 @@ Module BusyInterval.
(* If the JLFP policy is transitive and is respected by the schedule, ...*)
Hypothesis H_priority_is_transitive: JLFP_is_transitive higher_eq_priority.
 Hypothesis H_respects_policy: respects_JLFP_policy job_cost sched higher_eq_priority.
+ Hypothesis H_respects_policy:
+ respects_JLFP_policy job_arrival job_cost arr_seq sched higher_eq_priority.
(* ... then the processor is always busy with a job of higher or equal priority. *)
Lemma not_quiet_implies_exists_scheduled_hp_job:
forall t,
t1 <= t < t2 >
exists j_hp,
 arrived_between j_hp t1 t2 /\
+ arrived_between job_arrival j_hp t1 t2 /\
higher_eq_priority j_hp j /\
job_scheduled_at j_hp t.
Proof.
have NOTIDLE := not_quiet_implies_not_idle.
unfold is_idle, FP_is_transitive, transitive in *.
rename H_not_quiet into NOTQUIET, H_quiet into QUIET, H_priority_is_transitive into TRANS,
 H_work_conserving into WORK, H_respects_policy into PRIO.
+ H_work_conserving into WORK, H_respects_policy into PRIO,
+ H_jobs_come_from_arrival_sequence into CONS.
move => t /andP [GEt LEt].
feed (NOTIDLE t); first by apply/andP; split; last by apply ltnW.
destruct (sched t) as [j_hp] eqn:SCHED; [clear NOTIDLE  by exfalso; apply NOTIDLE].
@@ 254,9 +267,9 @@ Module BusyInterval.
apply contraT; move => /negP NOTHP; exfalso.
feed (NOTQUIET t.+1); first by apply/andP; split.
apply NOTQUIET.
 unfold quiet_time in *; intros j_hp' HP ARR.
+ unfold quiet_time in *; intros j_hp' IN HP ARR.
apply contraT; move => /negP NOTCOMP'; exfalso.
 have BACK: backlogged job_cost sched j_hp' t.
+ have BACK: backlogged job_arrival job_cost sched j_hp' t.
{
apply/andP; split; last first.
{
@@ 268,17 +281,19 @@ Module BusyInterval.
apply/negP; intro COMP; apply NOTCOMP'.
by apply completion_monotonic with (t0 := t).
}
 feed (PRIO j_hp' j_hp t BACK); first by done.
+ feed (PRIO j_hp' j_hp t IN BACK); first by done.
by apply NOTHP, TRANS with (y := j_hp').
}
repeat split; [ by done  by done].
{
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING; try (by done).
+ eapply scheduled_implies_pending with (job_cost0 := job_cost) in PENDING;
+ [ by eauto  by done].
apply/andP; split;
last by apply leq_ltn_trans with (n := t); first by move: PENDING => /andP [ARR _].
apply contraT; rewrite ltnNge; intro LT; exfalso.
 specialize (QUIET j_hp HP LT).
+ feed (QUIET j_hp); first by eapply CONS, SCHED.
+ specialize (QUIET HP LT).
have COMP: job_completed_by j_hp t by apply completion_monotonic with (t0 := t1).
apply completed_implies_not_scheduled in COMP; last by done.
by move: COMP => /negP COMP; apply COMP.
@@ 299,23 +314,30 @@ Module BusyInterval.
arrival_sequence_is_a_set arr_seq.
(* ...and that jobs do not execute before their arrival or after completion. *)
+ Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute job_arrival sched.
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
 Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute sched.
(* Also assume a workconserving FP schedule, ... *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
 Hypothesis H_respects_policy: respects_JLFP_policy job_cost sched higher_eq_priority.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
+ Hypothesis H_respects_policy:
+ respects_JLFP_policy job_arrival job_cost arr_seq sched higher_eq_priority.
(* ...in which the priority relation is reflexive and transitive. *)
Hypothesis H_priority_is_reflexive: JLFP_is_reflexive higher_eq_priority.
Hypothesis H_priority_is_transitive: JLFP_is_transitive higher_eq_priority.
+
+ (* Next, we recall the notion of workload of all jobs released in a given interval
+ [t1, t2) that have higherorequal priority than the job j being analyzed. *)
+ Let hp_workload t1 t2 :=
+ workload_of_higher_or_equal_priority_jobs job_cost (arrivals_between t1 t2)
+ higher_eq_priority j.
 (* Let's recall the notions of service and workload of tasks with higher or equal
 priority (with respect to tsk). *)
 Let hp_service :=
 service_of_higher_or_equal_priority_jobs sched higher_eq_priority j.
 Let hp_workload :=
 workload_of_higher_or_equal_priority_jobs job_cost arr_seq higher_eq_priority j.
+ (* With regard to the jobs with higherorequal priority that are released
+ in a given interval [t1, t2), we also recall the service received by these
+ jobs in the same interval [t1, t2). *)
+ Let hp_service t1 t2 :=
+ service_of_higher_or_equal_priority_jobs sched (arrivals_between t1 t2)
+ higher_eq_priority j t1 t2.
(* Now we begin the proof. First, we show that the busy interval is bounded. *)
Section BoundingBusyInterval.
@@ 335,12 +357,12 @@ Module BusyInterval.
t1 <= job_arrival j <= t_busy.
Proof.
rename H_j_is_pending into PEND, H_respects_policy into PRIO,
 H_work_conserving into WORK, H_priority_is_reflexive into REFL.
+ H_work_conserving into WORK, H_priority_is_reflexive into REFL,
+ H_from_arrival_sequence into FROM.
unfold busy_interval_prefix.
set dec_quiet :=
 fun t => all
 (fun (j_hp: JobIn arr_seq) =>
 higher_eq_priority j_hp j ==> (completed_by job_cost sched j_hp t))
+ fun t => all (fun j_hp =>
+ higher_eq_priority j_hp j ==> (completed_by job_cost sched j_hp t))
(jobs_arrived_before arr_seq t).
destruct ([exists t:'I_t_busy.+1, dec_quiet t]) eqn:EX.
{
@@ 350,16 +372,17 @@ Module BusyInterval.
have QUIET: quiet_time last.
{
move: PRED => /allP PRED.
 intros j_hp HP ARR; apply JobIn_arrived in ARR.
 specialize (PRED j_hp ARR).
 by move: PRED => /implyP PRED; apply PRED.
+ intros j_hp IN HP ARR.
+ feed (PRED j_hp).
+ by apply arrived_between_implies_in_arrivals with (job_arrival0 := job_arrival).
+ by rewrite HP implyTb in PRED.
}
exists last.
split; last first.
{
apply/andP; split; last by move: PEND => /andP [ARR _].
apply contraT; rewrite ltnNge; intros BEFORE.
 feed (QUIET j); first by apply REFL.
+ feed (QUIET j FROM); first by apply REFL.
specialize (QUIET BEFORE).
move: PEND => /andP [_ NOTCOMP].
apply completion_monotonic with (t' := t_busy) in QUIET;
@@ 373,8 +396,9 @@ Module BusyInterval.
have PRED0: dec_quiet t0.
{
apply/allP; intros j_hp ARR; apply/implyP; intros HP.
 apply JobIn_arrived in ARR.
 by apply QUIET0.
+ apply QUIET0; [ by done ].
+  by eapply in_arrivals_implies_arrived; eauto.
+  by eapply in_arrivals_implies_arrived_before; eauto.
}
have BUG: t0 <= last.
{
@@ 391,13 +415,14 @@ Module BusyInterval.
exists 0; split;
last by apply/andP; split; last by move: PEND => /andP [ARR _].
split; first by done.
 split; first by intros j_hp _ ARR; rewrite /arrived_before ltn0 in ARR.
+ split; first by intros j_hp _ _ ARR; rewrite /arrived_before ltn0 in ARR.
move => t /andP [GE LT].
specialize (ALL (Ordinal LT)); move: ALL => /negP ALL.
intros QUIET; apply ALL; simpl.
apply/allP; intros j_hp ARR; apply/implyP; intros HP.
 apply JobIn_arrived in ARR.
 by apply QUIET.
+ apply QUIET; [ by done ].
+  by eapply in_arrivals_implies_arrived; eauto.
+  by eapply in_arrivals_implies_arrived_before; eauto.
}
Qed.
@@ 442,8 +467,8 @@ Module BusyInterval.
rewrite exchange_big /=.
apply eq_big_nat; move => t /andP [GEt LTt].
move: PREFIX => [_ [QUIET _]].
 have EX: exists j_hp : JobIn arr_seq,
 arrived_between j_hp t1 (t1 + delta) /\
+ have EX: exists j_hp,
+ arrived_between job_arrival j_hp t1 (t1 + delta) /\
higher_eq_priority j_hp j /\
scheduled_at sched j_hp t.
{
@@ 452,9 +477,11 @@ Module BusyInterval.
by rewrite addn1; apply leq_add.
} clear EXISTS.
move: EX => [j_hp [/andP [GE LT] [HP SCHED]]].
+ have ARRhp: arrives_in arr_seq j_hp.
+ by apply (H_jobs_come_from_arrival_sequence j_hp t).
rewrite big_mkcond (bigD1_seq j_hp) /=; first last.
  by rewrite filter_uniq //; apply JobIn_uniq.
  by rewrite mem_filter; apply/andP; split; last by apply JobIn_arrived.
+  by eapply arrivals_uniq; eauto 1.
+  by eapply arrived_between_implies_in_arrivals; eauto 1; apply/andP; split.
rewrite HP big1; first by rewrite /service_at SCHED addn0.
intros j' NEQ; destruct (higher_eq_priority j' j); last by done.
apply/eqP; rewrite eqb0; apply/negP; move => SCHED'.
@@ 483,10 +510,10 @@ Module BusyInterval.
first by rewrite addn1; apply leq_add.
feed (PEND t1 (t1 + delta)); first by apply leq_addr.
specialize (PEND QUIET NOTQUIET').
 move: PEND => [j0 [/andP [GE0 LT0] [HP0 NOTCOMP0]]].
+ move: PEND => [j0 [ARR0 [/andP [GE0 LT0] [HP0 NOTCOMP0]]]].
have IN0: j0 \in l.
 by rewrite mem_filter; apply/andP; split; last by apply JobIn_arrived.
 have UNIQ: uniq l by rewrite filter_uniq //; apply JobIn_uniq.
+ by eapply arrived_between_implies_in_arrivals; eauto 1; apply/andP; split.
+ have UNIQ: uniq l by eapply arrivals_uniq; eauto 1.
rewrite big_mkcond [\sum_(_ < _  hep _ _)_]big_mkcond.
rewrite (bigD1_seq j0); [simpl  by done  by done].
rewrite (bigD1_seq j0); [simpl  by done  by done].
@@ 500,7 +527,7 @@ Module BusyInterval.
}
rewrite ltn_neqAle; apply/andP; split; last by apply cumulative_service_le_job_cost.
unfold service_during.
 rewrite ignore_service_before_arrival; rewrite //; [ by apply ltnW].
+ rewrite (ignore_service_before_arrival job_arrival); rewrite //; [ by apply ltnW].
rewrite < ignore_service_before_arrival with (t2:=0); rewrite //; [by apply ltnW].
by apply/negP.
Qed.
@@ 528,10 +555,9 @@ Module BusyInterval.
rename H_is_busy_prefix into PREFIX.
set dec_quiet :=
 fun t => all
 (fun (j_hp: JobIn arr_seq) =>
 higher_eq_priority j_hp j ==> (completed_by job_cost sched j_hp t))
 (jobs_arrived_before arr_seq t).
+ fun t =>
+ all (fun j_hp => higher_eq_priority j_hp j ==> (completed_by job_cost sched j_hp t))
+ (jobs_arrived_before arr_seq t).
destruct ([exists t2:'I_(t1 + delta).+1, (t2 > t1) && dec_quiet t2]) eqn:EX.
{
@@ 546,9 +572,10 @@ Module BusyInterval.
exists t2; split; first by done.
split; last first.
{
 intros j_hp HP ARR.
+ intros j_hp IN HP ARR.
move: QUIET => /allP QUIET.
 feed (QUIET j_hp); first by rewrite JobIn_arrived.
+ feed (QUIET j_hp);
+ first by eapply arrived_between_implies_in_arrivals; last by apply ARR.
by move: QUIET => /implyP QUIET; apply QUIET.
}
split; first by done.
@@ 560,7 +587,9 @@ Module BusyInterval.
first by apply/andP; split;
last by apply leq_trans with (n := t2); [by apply ltnW ].
apply/allP; intros j_hp ARR; apply/implyP; intro HP.
 by apply BUG; last by rewrite JobIn_arrived.
+ apply BUG; [ by done ].
+  by eapply in_arrivals_implies_arrived, ARR.
+  by eapply in_arrivals_implies_arrived_before, ARR.
}
by apply leq_ltn_trans with (p := t2) in MIN; first by rewrite ltnn in MIN.
}
@@ 573,7 +602,9 @@ Module BusyInterval.
specialize (ALL' (Ordinal LEt)); rewrite negb_and /= GTt orFb in ALL'.
move: ALL' => /negP ALL'; apply ALL'; clear ALL'.
apply/allP; intros j_hp ARR; apply/implyP; intro HP.
 by apply QUIET; last by rewrite JobIn_arrived.
+ apply QUIET; [ by done ].
+  by eapply in_arrivals_implies_arrived, ARR.
+  by eapply in_arrivals_implies_arrived_before, ARR.
} exfalso; clear ALL'.
specialize (TOOMUCH ALL).
by have BUG := leq_trans TOOMUCH BOUNDED; rewrite ltnn in BUG.
@@ 613,7 +644,7 @@ Module BusyInterval.
{
apply/andP; split; first by apply leqnn.
rewrite /completed_by /service /service_during.
 rewrite ignore_service_before_arrival //.
+ rewrite (ignore_service_before_arrival job_arrival) //.
rewrite big_geq; last by apply leqnn.
by rewrite eq_sym lt0n H_positive_cost.
}
@@ 668,7 +699,7 @@ Module BusyInterval.
try (by done); first by apply/andP; split.
apply/andP; split; first by apply leqnn.
rewrite /completed_by /service /service_during.
 rewrite ignore_service_before_arrival //.
+ rewrite (ignore_service_before_arrival job_arrival) //.
rewrite big_geq; last by apply leqnn.
by rewrite eq_sym lt0n.
Qed.
diff git a/model/schedule/uni/basic/platform.v b/model/schedule/uni/basic/platform.v
index 9fa1ee3..74c0c36 100644
 a/model/schedule/uni/basic/platform.v
+++ b/model/schedule/uni/basic/platform.v
@@ 16,13 +16,16 @@ Module Platform.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
+
+ (* Consider any job arrival sequence ...*)
+ Variable arr_seq: arrival_sequence Job.
 (* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
(* First, we define properties related to execution. *)
Section Execution.
@@ 31,7 +34,8 @@ Module Platform.
is backlogged, the processor is always busy with another job. *)
Definition work_conserving :=
forall j t,
 backlogged job_cost sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
exists j_other, scheduled_at sched j_other t.
End Execution.
@@ 45,8 +49,9 @@ Module Platform.
(* ...is respected by the schedule iff a scheduled task has
higher (or same) priority than (as) any backlogged task. *)
Definition respects_FP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled_at sched j_hp t >
higher_eq_priority (job_task j_hp) (job_task j).
@@ 56,13 +61,14 @@ Module Platform.
Section JLFP.
(* We say that a JLFP policy ...*)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* ... is respected by the scheduler iff a scheduled job has
higher (or same) priority than (as) any backlogged job. *)
Definition respects_JLFP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled_at sched j_hp t >
higher_eq_priority j_hp j.
@@ 72,13 +78,14 @@ Module Platform.
Section JLDP.
(* We say that a JLFP/JLDP policy ...*)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* ... is respected by the scheduler iff at any time t, a scheduled job
has higher (or same) priority than (as) any backlogged job. *)
Definition respects_JLDP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost sched j t >
scheduled_at sched j_hp t >
higher_eq_priority t j_hp j.
@@ 95,17 +102,20 @@ Module Platform.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_task: Job > sporadic_task.
 (* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* Consider any job arrival sequence ...*)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
(* For simplicity, let's define some local names. *)
 Let job_backlogged_at := backlogged job_cost sched.
 Let job_pending_at := pending job_cost sched.
+ Let job_backlogged_at := backlogged job_arrival job_cost sched.
+ Let job_pending_at := pending job_arrival job_cost sched.
Let job_completed_by := completed_by job_cost sched.
(* First we prove that if a job is never backlogged, then it doesn't take longer
@@ 114,14 +124,16 @@ Module Platform.
(* Assume that jobs only execute after they arrive and no longer
than their execution costs. *)
 Hypothesis H_jobs_must_arrive_to_execute: jobs_must_arrive_to_execute sched.
 Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
+ Hypothesis H_jobs_must_arrive_to_execute:
+ jobs_must_arrive_to_execute job_arrival sched.
+ Hypothesis H_completed_jobs_dont_execute:
+ completed_jobs_dont_execute job_cost sched.
(* Assume that the schedule is workconserving. *)
 Hypothesis H_work_conserving: work_conserving job_cost sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost arr_seq sched.
(* Let j be any job... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* ...that j is never backlogged during its execution. *)
Hypothesis H_j_is_never_backlogged:
@@ 139,7 +151,8 @@ Module Platform.
H_work_conserving into WORK.
intros R GECOST.
rewrite /job_completed_by /completed_by /service /service_during.
 rewrite ignore_service_before_arrival; [  by done  by done  by apply leq_addr].
+ rewrite (ignore_service_before_arrival job_arrival);
+ [  by done  by done  by apply leq_addr].
rewrite eqn_leq; apply/andP; split;
first by apply cumulative_service_le_job_cost.
apply leq_trans with (n := \sum_(job_arrival j <= t < job_arrival j + job_cost j) 1);
@@ 161,7 +174,7 @@ Module Platform.
rewrite /service /service_during.
rewrite > big_cat_nat with (n := job_arrival j);
[simpl  by done  by done].
 rewrite cumulative_service_before_job_arrival_zero;
+ rewrite (cumulative_service_before_job_arrival_zero job_arrival);
[rewrite add0n  by done  by apply leqnn].
apply leq_ltn_trans with (n := \sum_(job_arrival j <= i < t) 1);
first by apply leq_sum; ins; apply leq_b1.
diff git a/model/schedule/uni/jitter/busy_interval.v b/model/schedule/uni/jitter/busy_interval.v
index 076d899..5cb8548 100644
 a/model/schedule/uni/jitter/busy_interval.v
+++ b/model/schedule/uni/jitter/busy_interval.v
@@ 1,8 +1,9 @@
Require Import rt.util.all.
Require Import rt.model.arrival.basic.task rt.model.arrival.basic.job rt.model.arrival.basic.arrival_sequence
+Require Import rt.model.arrival.basic.task rt.model.arrival.basic.job
+ rt.model.arrival.basic.arrival_sequence
rt.model.priority rt.model.arrival.basic.task_arrival.
Require Import rt.model.schedule.uni.jitter.schedule rt.model.schedule.uni.jitter.platform
 rt.model.schedule.uni.jitter.service rt.model.schedule.uni.jitter.workload.
+Require Import rt.model.schedule.uni.service rt.model.schedule.uni.workload.
+Require Import rt.model.schedule.uni.jitter.schedule rt.model.schedule.uni.jitter.platform.
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop.
(* In this file, we provide definitions and lemmas about busy intervals
@@ 17,32 +18,41 @@ Module BusyInterval.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
Variable job_task: Job > Task.
 (* Consider any uniprocessor schedule ... *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* Consider any arrival sequence with consistent arrival times... *)
+ Variable arr_seq: arrival_sequence Job.
+ Hypothesis H_arrival_times_are_consistent: arrival_times_are_consistent job_arrival arr_seq.
 (* ...subject to a JLFP policy. *)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
+ Hypothesis H_jobs_come_from_arrival_sequence:
+ jobs_come_from_arrival_sequence sched arr_seq.
+
+ (* Consider any JLFP policy. *)
+ Variable higher_eq_priority: JLFP_policy Job.
(* Let j be any job to be analyzed. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_from_arrival_sequence: arrives_in arr_seq j.
(* For simplicity, let's define some local names. *)
 Let job_pending_at := pending job_cost job_jitter sched.
+ Let job_pending_at := pending job_arrival job_cost job_jitter sched.
Let job_scheduled_at := scheduled_at sched.
Let job_completed_by := completed_by job_cost sched.
 Let actual_job_arrival (j: JobIn arr_seq) := actual_arrival job_jitter j.
+ Let actual_job_arrival := actual_arrival job_arrival job_jitter.
+ Let actual_job_arrival_between := actual_arrival_between job_arrival job_jitter.
(* We say that t is a quiet time for j iff every higherpriority job that
has an actual arrival time (with jitter) before t has completed by that time. *)
Definition quiet_time (t: time) :=
 forall (j_hp: JobIn arr_seq),
+ forall j_hp,
+ arrives_in arr_seq j_hp >
higher_eq_priority j_hp j >
 actual_arrival_before job_jitter j_hp t >
+ actual_arrival_before job_arrival job_jitter j_hp t >
job_completed_by j_hp t.
(* Based on the definition of quiet time, we say that interval
@@ 64,7 +74,7 @@ Module BusyInterval.
(* Recall the list of jobs with actual arrival time (including jitter) in the
interval [t1, t2). *)
 Let actual_arrivals t1 t2 := actual_arrivals_between job_jitter arr_seq t1 t2.
+ Let actual_arrivals t1 t2 := actual_arrivals_between job_arrival job_jitter arr_seq t1 t2.
(* We begin by proving basic lemmas about the arrival and
completion of jobs that are pending during a busy interval. *)
@@ 92,7 +102,7 @@ Module BusyInterval.
H_during_interval into INT, H_job_is_pending into PEND.
move: BUSY => [_ QUIET].
move: INT => /andP [_ LT2].
 apply QUIET; first by apply REFL.
+ apply QUIET; [by done  by apply REFL ].
apply leq_ltn_trans with (n := t); last by done.
by move: PEND => /andP [ARR _].
Qed.
@@ 108,7 +118,7 @@ Module BusyInterval.
(* Then, we prove that job j's actual arrival (with jitter) occurs no earlier than t1. *)
Lemma job_arrives_within_busy_interval:
 t1 <= actual_arrival job_jitter j.
+ t1 <= actual_job_arrival j.
Proof.
rename H_priority_is_reflexive into REFL, H_busy_interval into BUSY,
H_during_interval into INT, H_job_is_pending into PEND.
@@ 118,7 +128,7 @@ Module BusyInterval.
move: INT => /andP [LE _].
exfalso; apply NOTCOMP.
apply completion_monotonic with (t0 := t1); try (by done).
 by apply QUIET; first by apply REFL.
+ by apply QUIET; [by done  by apply REFL ].
Qed.
End ArrivesDuringBusyInterval.
@@ 143,8 +153,9 @@ Module BusyInterval.
(* Then, we prove that there exists a job pending at time t2
that has higher or equal priority (with respect ot tsk). *)
Lemma not_quiet_implies_exists_pending_job:
 exists (j_hp: JobIn arr_seq),
 actual_arrival_between job_jitter j_hp t1 t2 /\
+ exists j_hp,
+ arrives_in arr_seq j_hp /\
+ actual_job_arrival_between j_hp t1 t2 /\
higher_eq_priority j_hp j /\
~ job_completed_by j_hp t2.
Proof.
@@ 153,19 +164,19 @@ Module BusyInterval.
(actual_arrivals t1 t2)) eqn:COMP.
{
move: COMP => /hasP [j_hp ARR /andP [NOTCOMP HP]].
 exists j_hp; repeat split; [  by done  by apply/negP].
 rewrite mem_filter in ARR; move: ARR => /andP [GE ARR].
 apply/andP; split; first by done.
 by apply actual_arrivals_arrived.
+ rewrite /actual_arrivals in ARR; have ARRin := ARR.
+ apply in_actual_arrivals_between_implies_arrived in ARRin.
+ apply in_actual_arrivals_implies_arrived_between in ARR.
+ by exists j_hp; repeat split; last by apply/negP.
}
{
apply negbT in COMP; rewrite all_predC in COMP.
move: COMP => /allP COMP.
 exfalso; apply NOTQUIET; intros j_hp HP ARR.
+ exfalso; apply NOTQUIET; intros j_hp IN HP ARR.
destruct (ltnP (actual_job_arrival j_hp) t1) as [BEFORE  AFTER];
 first by specialize (QUIET j_hp HP BEFORE); apply completion_monotonic with (t := t1).
 feed (COMP j_hp);
 first by rewrite mem_filter; apply/andP; split; last by apply actual_arrivals_arrived.
+ first by specialize (QUIET j_hp IN HP BEFORE); apply completion_monotonic with (t := t1).
+ feed (COMP j_hp).
+ by apply arrived_between_implies_in_actual_arrivals; last by apply/andP; split.
by rewrite /= HP andbT negbK in COMP.
}
Qed.
@@ 178,9 +189,10 @@ Module BusyInterval.
(* Assume that the schedule is workconserving and that jobs do
not execute before the jitter has passed nor after completion. *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
 Hypothesis H_jobs_execute_after_jitter: jobs_execute_after_jitter job_jitter sched.
+ Hypothesis H_jobs_execute_after_jitter:
+ jobs_execute_after_jitter job_arrival job_jitter sched.
(* Consider any interval [t1, t2] such that t1 < t2 and t1 is the only quiet time. *)
Variable t1 t2: time.
@@ 202,25 +214,25 @@ Module BusyInterval.
subst t.
feed (NOTQUIET t1.+1); first by apply/andP; split.
apply NOTQUIET.
 intros j_hp HP ARR.
+ intros j_hp IN HP ARR.
apply completion_monotonic with (t := t1); [by done  by done ].
apply contraT; intro NOTCOMP.
destruct (scheduled_at sched j_hp t1) eqn:SCHEDhp;
first by move: SCHEDhp => /eqP SCHEDhp; rewrite IDLE in SCHEDhp.
apply negbT in SCHEDhp.
 feed (WORK j_hp t1); first by repeat (apply/andP; split).
+ feed (WORK j_hp t1 IN); first by repeat (apply/andP; split).
move: WORK => [j_other /eqP SCHEDother].
by rewrite IDLE in SCHEDother.
}
{
feed (NOTQUIET t); first by apply/andP; split.
apply NOTQUIET; clear NOTQUIET.
 intros j_hp HP ARR.
+ intros j_hp IN HP ARR.
apply contraT; intros NOTCOMP.
destruct (scheduled_at sched j_hp t) eqn:SCHEDhp;
first by move: SCHEDhp => /eqP SCHEDhp; rewrite IDLE in SCHEDhp.
apply negbT in SCHEDhp.
 feed (WORK j_hp t);
+ feed (WORK j_hp t IN);
first by repeat (apply/andP; split); first by apply ltnW.
move: WORK => [j_other /eqP SCHEDother].
by rewrite IDLE in SCHEDother.
@@ 233,7 +245,7 @@ Module BusyInterval.
(* If the JLFP policy is transitive and is respected by the schedule, ...*)
Hypothesis H_priority_is_transitive: JLFP_is_transitive higher_eq_priority.
Hypothesis H_respects_policy:
 respects_JLFP_policy job_cost job_jitter sched higher_eq_priority.
+ respects_JLFP_policy job_arrival job_cost job_jitter arr_seq sched higher_eq_priority.
(* ... then the processor is always busy with a job of higher or equal priority
and actual arrival time in the interval. *)
@@ 241,14 +253,15 @@ Module BusyInterval.
forall t,
t1 <= t < t2 >
exists j_hp,
 actual_arrival_between job_jitter j_hp t1 t2 /\
+ actual_job_arrival_between j_hp t1 t2 /\
higher_eq_priority j_hp j /\
job_scheduled_at j_hp t.
Proof.
have NOTIDLE := not_quiet_implies_not_idle.
unfold is_idle, FP_is_transitive, transitive in *.
rename H_not_quiet into NOTQUIET, H_quiet into QUIET, H_priority_is_transitive into TRANS,
 H_work_conserving into WORK, H_respects_policy into PRIO.
+ H_work_conserving into WORK, H_respects_policy into PRIO,
+ H_jobs_come_from_arrival_sequence into FROM.
move => t /andP [GEt LEt].
feed (NOTIDLE t); first by apply/andP; split; last by apply ltnW.
destruct (sched t) as [j_hp] eqn:SCHED; [clear NOTIDLE  by exfalso; apply NOTIDLE].
@@ 259,9 +272,9 @@ Module BusyInterval.
apply contraT; move => /negP NOTHP; exfalso.
feed (NOTQUIET t.+1); first by apply/andP; split.
apply NOTQUIET.
 unfold quiet_time in *; intros j_hp' HP ARR.
+ unfold quiet_time in *; intros j_hp' IN HP ARR.
apply contraT; move => /negP NOTCOMP'; exfalso.
 have BACK: backlogged job_cost job_jitter sched j_hp' t.
+ have BACK: backlogged job_arrival job_cost job_jitter sched j_hp' t.
{
apply/andP; split; last first.
{
@@ 273,18 +286,19 @@ Module BusyInterval.
apply/negP; intro COMP; apply NOTCOMP'.
by apply completion_monotonic with (t0 := t).
}
 feed (PRIO j_hp' j_hp t BACK); first by done.
+ feed (PRIO j_hp' j_hp t IN BACK); first by done.
by apply NOTHP, TRANS with (y := j_hp').
}
repeat split; [ by done  by done].
{
move: (SCHED) => PENDING.
 apply scheduled_implies_pending with (job_cost0 := job_cost)
 (job_jitter0 := job_jitter) in PENDING; try (by done).
+ apply scheduled_implies_pending with (job_arrival0 := job_arrival)
+ (job_cost0 := job_cost) (job_jitter0 := job_jitter) in PENDING; try (by done).
apply/andP; split;
last by apply leq_ltn_trans with (n := t); first by move: PENDING => /andP [ARR _].
apply contraT; rewrite ltnNge; intro LT; exfalso.
 specialize (QUIET j_hp HP LT).
+ feed (QUIET j_hp); first by eapply FROM, SCHED.
+ specialize (QUIET HP LT).
have COMP: job_completed_by j_hp t by apply completion_monotonic with (t0 := t1).
apply completed_implies_not_scheduled in COMP; last by done.
by move: COMP => /negP COMP; apply COMP.
@@ 304,25 +318,33 @@ Module BusyInterval.
Hypothesis H_arrival_sequence_is_a_set:
arrival_sequence_is_a_set arr_seq.
 (* ...and that jobs do not execute before their arrival or after completion. *)
+ (* ...and that jobs do not execute before the jitter has passed nor after completion. *)
+ Hypothesis H_jobs_execute_after_jitter:
+ jobs_execute_after_jitter job_arrival job_jitter sched.
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
 Hypothesis H_jobs_execute_after_jitter: jobs_execute_after_jitter job_jitter sched.
(* Also assume a workconserving FP schedule, ... *)
 Hypothesis H_work_conserving: work_conserving job_cost job_jitter sched.
+ Hypothesis H_work_conserving: work_conserving job_arrival job_cost job_jitter arr_seq sched.
Hypothesis H_respects_policy:
 respects_JLFP_policy job_cost job_jitter sched higher_eq_priority.
+ respects_JLFP_policy job_arrival job_cost job_jitter arr_seq sched higher_eq_priority.
(* ...in which the priority relation is reflexive and transitive. *)
Hypothesis H_priority_is_reflexive: JLFP_is_reflexive higher_eq_priority.
Hypothesis H_priority_is_transitive: JLFP_is_transitive higher_eq_priority.
 (* Let's recall the notions of service and workload of tasks with higher or equal
 priority (with respect to tsk). *)
 Let actual_hp_service :=
 service_of_higher_or_equal_priority_jobs job_jitter sched higher_eq_priority j.
 Let actual_hp_workload :=
 workload_of_higher_or_equal_priority_jobs job_cost job_jitter arr_seq higher_eq_priority j.
+ (* Next, we recall the notion of workload of all jobs with actual arrival time
+ in a given interval [t1, t2) that have higherorequal priority than the
+ job j being analyzed. *)
+ Let actual_hp_workload t1 t2 :=
+ workload_of_higher_or_equal_priority_jobs job_cost (actual_arrivals t1 t2)
+ higher_eq_priority j.
+
+ (* With regard to the jobs with higherorequal priority that have actual
+ arrival time in a given interval [t1, t2), we also recall the service
+ received by these jobs in the same interval [t1, t2). *)
+ Let actual_hp_service t1 t2 :=
+ service_of_higher_or_equal_priority_jobs sched (actual_arrivals t1 t2)
+ higher_eq_priority j t1 t2.
(* Now we begin the proof. First, we show that the busy interval is bounded. *)
Section BoundingBusyInterval.
@@ 342,13 +364,13 @@ Module BusyInterval.
t1 <= actual_job_arrival j <= t_busy.
Proof.
rename H_j_is_pending into PEND, H_respects_policy into PRIO,
 H_work_conserving into WORK, H_priority_is_reflexive into REFL.
+ H_work_conserving into WORK, H_priority_is_reflexive into REFL,
+ H_from_arrival_sequence into FROM.
unfold busy_interval_prefix.
set dec_quiet :=
 fun t => all
 (fun (j_hp: JobIn arr_seq) =>
+ fun t => all (fun j_hp =>
higher_eq_priority j_hp j ==> (completed_by job_cost sched j_hp t))
 (actual_arrivals_before job_jitter arr_seq t).
+ (actual_arrivals_before job_arrival job_jitter arr_seq t).
destruct ([exists t:'I_t_busy.+1, dec_quiet t]) eqn:EX.
{
set last := \max_(t < t_busy.+1  dec_quiet t) t.
@@ 357,16 +379,17 @@ Module BusyInterval.
have QUIET: quiet_time last.
{
move: PRED => /allP PRED.
 intros j_hp HP ARR; apply actual_arrivals_arrived in ARR.
 specialize (PRED j_hp ARR).
 by move: PRED => /implyP PRED; apply PRED.
+ intros j_hp IN HP ARR.
+ feed (PRED j_hp).
+ by apply arrived_between_implies_in_actual_arrivals; try (apply/andP; split).
+ by rewrite HP implyTb in PRED.
}
exists last.
split; last first.
{
apply/andP; split; last by move: PEND => /andP [ARR _].
apply contraT; rewrite ltnNge; intros BEFORE.
 feed (QUIET j); first by apply REFL.
+ feed (QUIET j FROM); first by apply REFL.
specialize (QUIET BEFORE).
move: PEND => /andP [_ NOTCOMP].
apply completion_monotonic with (t' := t_busy) in QUIET;
@@ 380,8 +403,9 @@ Module BusyInterval.
have PRED0: dec_quiet t0.
{
apply/allP; intros j_hp ARR; apply/implyP; intros HP.
 apply actual_arrivals_arrived in ARR.
 by apply QUIET0.
+ apply QUIET0; [ by done ].
+  by eapply in_actual_arrivals_before_implies_arrived; eauto 1.
+  by eapply in_actual_arrivals_implies_arrived_before; eauto 1.
}
have BUG: t0 <= last.
{
@@ 398,13 +422,14 @@ Module BusyInterval.
exists 0; split;
last by apply/andP; split; last by move: PEND => /andP [ARR _].
split; first by done.
 split; first by intros j_hp _ ARR; rewrite /actual_arrival_before ltn0 in ARR.
+ split; first by intros j_hp _ _ ARR; rewrite /actual_arrival_before ltn0 in ARR.
move => t /andP [GE LT].
specialize (ALL (Ordinal LT)); move: ALL => /negP ALL.
intros QUIET; apply ALL; simpl.
apply/allP; intros j_hp ARR; apply/implyP; intros HP.
 apply actual_arrivals_arrived in ARR.
 by apply QUIET.
+ apply QUIET; [ by done ].
+  by eapply in_actual_arrivals_before_implies_arrived; eauto 1.
+  by eapply in_actual_arrivals_implies_arrived_before; eauto 1.
}
Qed.
@@ 450,8 +475,8 @@ Module BusyInterval.
rewrite exchange_big /=.
apply eq_big_nat; move => t /andP [GEt LTt].
move: PREFIX => [_ [QUIET _]].
 have EX: exists j_hp : JobIn arr_seq,
 actual_arrival_between job_jitter j_hp t1 (t1 + delta) /\
+ have EX: exists j_hp : Job,
+ actual_job_arrival_between j_hp t1 (t1 + delta) /\
higher_eq_priority j_hp j /\
scheduled_at sched j_hp t.
{
@@ 460,14 +485,19 @@ Module BusyInterval.
by rewrite addn1; apply leq_add.
} clear EXISTS.
move: EX => [j_hp [/andP [GE LT] [HP SCHED]]].
 rewrite big_mkcond (bigD1_seq j_hp) /=; first last.
  by rewrite filter_uniq //; apply filter_uniq, JobIn_uniq.
  by rewrite mem_filter; apply/andP; split; last by apply actual_arrivals_arrived.
 rewrite HP big1; first by rewrite /service_at SCHED addn0.
 intros j' NEQ; destruct (higher_eq_priority j' j); last by done.
 apply/eqP; rewrite eqb0; apply/negP; move => SCHED'.
 move: NEQ => /eqP NEQ; apply NEQ.
 by apply only_one_job_scheduled with (sched0 := sched) (t0 := t).
+ rewrite big_mkcond (bigD1_seq j_hp) /=; last by apply actual_arrivals_uniq.
+ {
+ rewrite HP big1; first by rewrite /service_at SCHED addn0.
+ intros j' NEQ; destruct (higher_eq_priority j' j); last by done.
+ apply/eqP; rewrite eqb0; apply/negP; move => SCHED'.
+ move: NEQ => /eqP NEQ; apply NEQ.
+ by apply only_one_job_scheduled with (sched0 := sched) (t0 := t).
+ }
+ {
+ apply H_jobs_come_from_arrival_sequence in SCHED.
+ apply arrived_between_implies_in_actual_arrivals; [by done  by done ].
+ by apply/andP; split.
+ }
Qed.
(* Moreover, the fact that the interval is not quiet also implies
@@ 479,7 +509,7 @@ Module BusyInterval.
H_completed_jobs_dont_execute.
rename H_no_quiet_time into NOTQUIET,
H_is_busy_prefix into PREFIX, H_respects_policy into PRIO.
 set l := actual_arrivals_between job_jitter arr_seq t1 (t1 + delta).
+ set l := actual_arrivals_between job_arrival job_jitter arr_seq t1 (t1 + delta).
set hep := higher_eq_priority.
unfold actual_hp_service, service_of_higher_or_equal_priority_jobs, service_of_jobs,
actual_hp_workload, workload_of_higher_or_equal_priority_jobs, workload_of_jobs.
@@ 491,10 +521,10 @@ Module BusyInterval.
first by rewrite addn1; apply leq_add.
feed (PEND t1 (t1 + delta)); first by apply leq_addr.
specialize (PEND QUIET NOTQUIET').
 move: PEND => [j0 [/andP [GE0 LT0] [HP0 NOTCOMP0]]].
+ move: PEND => [j0 [ARR0 [/andP [GE0 LT0] [HP0 NOTCOMP0]]]].
have IN0: j0 \in l.
 by rewrite mem_filter; apply/andP; split; last by apply actual_arrivals_arrived.
 have UNIQ: uniq l by apply filter_uniq, filter_uniq, JobIn_uniq.
+ by apply arrived_between_implies_in_actual_arrivals; last by apply/andP; split.
+ have UNIQ: uniq l by eapply actual_arrivals_uniq; eauto 1.
rewrite big_mkcond [\sum_(_ < _  hep _ _)_]big_mkcond.
rewrite (bigD1_seq j0); [simpl  by done  by done].
rewrite (bigD1_seq j0); [simpl  by done  by done].
@@ 508,7 +538,7 @@ Module BusyInterval.
}
rewrite ltn_neqAle; apply/andP; split; last by apply cumulative_service_le_job_cost.
unfold service_during.
 rewrite (ignore_service_before_jitter job_jitter) //;
+ rewrite (ignore_service_before_jitter job_arrival job_jitter) //;
last by apply/andP; split; last by apply ltnW.
rewrite < ignore_service_before_jitter with (t2:=0); rewrite //; [by apply ltnW].
by apply/negP.
@@ 537,10 +567,9 @@ Module BusyInterval.
rename H_is_busy_prefix into PREFIX.
set dec_quiet :=
 fun t => all
 (fun (j_hp: JobIn arr_seq) =>
+ fun t => all (fun j_hp =>
higher_eq_priority j_hp j ==> (completed_by job_cost sched j_hp t))
 (actual_arrivals_before job_jitter arr_seq t).
+ (actual_arrivals_before job_arrival job_jitter arr_seq t).
destruct ([exists t2:'I_(t1 + delta).+1, (t2 > t1) && dec_quiet t2]) eqn:EX.
{
@@ 555,9 +584,10 @@ Module BusyInterval.
exists t2; split; first by done.
split; last first.
{
 intros j_hp HP ARR.
+ intros j_hp IN HP ARR.
move: QUIET => /allP QUIET.
 feed (QUIET j_hp); first by apply actual_arrivals_arrived.
+ feed (QUIET j_hp);
+ first by eapply arrived_between_implies_in_actual_arrivals; eauto 1.
by move: QUIET => /implyP QUIET; apply QUIET.
}
split; first by done.
@@ 569,7 +599,9 @@ Module BusyInterval.
first by apply/andP; split;
last by apply leq_trans with (n := t2); [by apply ltnW ].
apply/allP; intros j_hp ARR; apply/implyP; intro HP.
 by apply BUG; last by apply actual_arrivals_arrived.
+ apply BUG; [ by done ].
+  by eapply in_actual_arrivals_before_implies_arrived, ARR.
+  by eapply in_actual_arrivals_implies_arrived_before, ARR.
}
by apply leq_ltn_trans with (p := t2) in MIN; first by rewrite ltnn in MIN.
}
@@ 582,7 +614,9 @@ Module BusyInterval.
specialize (ALL' (Ordinal LEt)); rewrite negb_and /= GTt orFb in ALL'.
move: ALL' => /negP ALL'; apply ALL'; clear ALL'.
apply/allP; intros j_hp ARR; apply/implyP; intro HP.
 by apply QUIET; last by apply actual_arrivals_arrived.
+ apply QUIET; [ by done ].
+  by eapply in_actual_arrivals_before_implies_arrived, ARR.
+  by eapply in_actual_arrivals_implies_arrived_before, ARR.
} exfalso; clear ALL'.
specialize (TOOMUCH ALL).
by have BUG := leq_trans TOOMUCH BOUNDED; rewrite ltnn in BUG.
@@ 622,7 +656,7 @@ Module BusyInterval.
{
apply/andP; split; first by apply leqnn.
rewrite /completed_by /service /service_during.
 rewrite (cumulative_service_before_jitter_is_zero job_jitter) //.
+ rewrite (cumulative_service_before_jitter_is_zero job_arrival job_jitter) //.
by rewrite eq_sym lt0n H_positive_cost.
}
move: PREFIX => [t1 [PREFIX /andP [GE1 GEarr]]].
@@ 676,7 +710,7 @@ Module BusyInterval.
try (by done); first by apply/andP; split.
apply/andP; split; first by apply leqnn.
rewrite /completed_by /service /service_during.
 rewrite (cumulative_service_before_jitter_is_zero job_jitter) //.
+ rewrite (cumulative_service_before_jitter_is_zero job_arrival job_jitter) //.
by rewrite eq_sym lt0n.
Qed.
diff git a/model/schedule/uni/jitter/platform.v b/model/schedule/uni/jitter/platform.v
index af48168..6f1cda4 100644
 a/model/schedule/uni/jitter/platform.v
+++ b/model/schedule/uni/jitter/platform.v
@@ 16,14 +16,15 @@ Module Platform.
Variable task_deadline: sporadic_task > time.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
Variable job_jitter: Job > time.
Variable job_task: Job > sporadic_task.
(* Consider any jitteraware uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable arr_seq: arrival_sequence Job.
+ Variable sched: schedule Job.
(* First, we define properties related to execution. *)
Section Execution.
@@ 33,7 +34,8 @@ Module Platform.
(Note that the definition of backlogged depends on the jitter.) *)
Definition work_conserving :=
forall j t,
 backlogged job_cost job_jitter sched j t >
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost job_jitter sched j t >
exists j_other, scheduled_at sched j_other t.
End Execution.
@@ 48,8 +50,9 @@ Module Platform.
higher (or same) priority than (as) any backlogged task.
(Note that the definition of backlogged depends on the jitter.) *)
Definition respects_FP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost job_jitter sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost job_jitter sched j t >
scheduled_at sched j_hp t >
higher_eq_priority (job_task j_hp) (job_task j).
@@ 59,14 +62,15 @@ Module Platform.
Section JLFP.
(* We say that a JLFP policy ...*)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* ... is respected by the scheduler iff a scheduled job has
higher (or same) priority than (as) any backlogged job.
(Note that the definition of backlogged depends on the jitter.) *)
Definition respects_JLFP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost job_jitter sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost job_jitter sched j t >
scheduled_at sched j_hp t >
higher_eq_priority j_hp j.
@@ 76,14 +80,15 @@ Module Platform.
Section JLDP.
(* We say that a JLFP/JLDP policy ...*)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* ... is respected by the scheduler iff at any time t, a scheduled job
has higher (or same) priority than (as) any backlogged job.
(Note that the definition of backlogged depends on the jitter.) *)
Definition respects_JLDP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
 backlogged job_cost job_jitter sched j t >
+ forall j j_hp t,
+ arrives_in arr_seq j >
+ backlogged job_arrival job_cost job_jitter sched j t >
scheduled_at sched j_hp t >
higher_eq_priority t j_hp j.
diff git a/model/schedule/uni/jitter/schedule.v b/model/schedule/uni/jitter/schedule.v
index ba27c61..c8b01a3 100644
 a/model/schedule/uni/jitter/schedule.v
+++ b/model/schedule/uni/jitter/schedule.v
@@ 15,23 +15,24 @@ Module UniprocessorScheduleWithJitter.
Section RedefiningProperties.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_jitter: Job > time.
(* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable arr_seq: arrival_sequence Job.
+ Variable sched: schedule Job.
(* First, we redefine some job properties. *)
Section JobProperties.
(* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Then, we say that job j is pending at time t iff the jitter has passed but
j has not completed by time t. *)
Definition pending (t: time) :=
 jitter_has_passed job_jitter j t && ~~ completed_by job_cost sched j t.
+ jitter_has_passed job_arrival job_jitter j t && ~~ completed_by job_cost sched j t.
(* Finally, we say that job j is backlogged at time t iff it is pending and not scheduled. *)
Definition backlogged (t: time) :=
@@ 46,13 +47,17 @@ Module UniprocessorScheduleWithJitter.
the jitter has passed. *)
Definition jobs_execute_after_jitter :=
forall j t,
 scheduled_at sched j t > jitter_has_passed job_jitter j t.
+ scheduled_at sched j t > jitter_has_passed job_arrival job_jitter j t.
End ValidSchedules.
(* In this section, we prove some basic lemmas about jitteraware schedules. *)
Section Lemmas.
+ (* For simplicity, let's define some local names. *)
+ Let has_actually_arrived := jitter_has_passed job_arrival job_jitter.
+ Let actual_job_arrival := actual_arrival job_arrival job_jitter.
+
(* We begin by proving properties related to job arrivals. *)
Section Arrival.
@@ 61,20 +66,22 @@ Module UniprocessorScheduleWithJitter.
(* First, we show that every job in the schedule only executes after its arrival time. *)
Lemma jobs_with_jitter_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
Proof.
intros j t SCHED.
 apply leq_trans with (n := actual_arrival job_jitter j); first by apply leq_addr.
+ apply leq_trans with (n := actual_arrival job_arrival job_jitter j);
+ first by apply leq_addr.
by apply H_jobs_execute_after_jitter.
Qed.
 (* Now, let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Now, let j be any job. *)
+ Variable j: Job.
 (* Next, we show that if the jitter has passed, then the job must have arrived. *)
+ (* First, we show that if the jitter has passed, then the job must have arrived. *)
Lemma jitter_has_passed_implies_arrived:
forall t,
 jitter_has_passed job_jitter j t > has_arrived j t.
+ has_actually_arrived j t >
+ has_arrived job_arrival j t.
Proof.
by intros t PASS; apply: leq_trans PASS; apply leq_addr.
Qed.
@@ 83,21 +90,21 @@ Module UniprocessorScheduleWithJitter.
its actual arrival time. *)
Lemma service_before_jitter_is_zero :
forall t,
 t < actual_arrival job_jitter j >
+ t < actual_job_arrival j >
service_at sched j t = 0.
Proof.
rename H_jobs_execute_after_jitter into ARR; red in ARR; intros t LT.
specialize (ARR j t).
apply contra with (c := scheduled_at sched j t)
 (b := jitter_has_passed job_jitter j t) in ARR;
+ (b := jitter_has_passed job_arrival job_jitter j t) in ARR;
last by rewrite ltnNge.
 by apply/eqP; rewrite eqb0.
+ by apply/eqP; rewrite eqb0.
Qed.
(* Note that the same property applies to the cumulative service. *)
Lemma cumulative_service_before_jitter_is_zero :
forall t1 t2,
 t2 <= actual_arrival job_jitter j >
+ t2 <= actual_job_arrival j >
\sum_(t1 <= i < t2) service_at sched j i = 0.
Proof.
intros t1 t2 LE; apply/eqP; rewrite leqn0.
@@ 112,12 +119,12 @@ Module UniprocessorScheduleWithJitter.
(* Hence, one can ignore the service received by a job before the jitter. *)
Lemma ignore_service_before_jitter:
forall t1 t2,
 t1 <= actual_arrival job_jitter j <= t2 >
+ t1 <= actual_job_arrival j <= t2 >
\sum_(t1 <= t < t2) service_at sched j t =
 \sum_(actual_arrival job_jitter j <= t < t2) service_at sched j t.
+ \sum_(actual_job_arrival j <= t < t2) service_at sched j t.
Proof.
move => t1 t2 /andP [LE1 GE2].
 rewrite > big_cat_nat with (n := actual_arrival job_jitter j); try (by done).
+ rewrite > big_cat_nat with (n := actual_job_arrival j); try (by done).
by rewrite /= cumulative_service_before_jitter_is_zero; [rewrite add0n  apply leqnn].
Qed.
@@ 133,8 +140,8 @@ Module UniprocessorScheduleWithJitter.
Hypothesis H_completed_jobs:
completed_jobs_dont_execute job_cost sched.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* First, we show that if job j is scheduled, then it must be pending. *)
Lemma scheduled_implies_pending:
@@ 152,7 +159,7 @@ Module UniprocessorScheduleWithJitter.
unfold service, service_during; rewrite addn1 big_nat_recr // /=.
apply leq_add;
first by move: COMPLETED => /eqP COMPLETED; rewrite COMPLETED.
 by rewrite /service_at SCHED.
+ by rewrite /service_at SCHED.
Qed.
End Pending.
diff git a/model/schedule/uni/jitter/service.v b/model/schedule/uni/jitter/service.v
deleted file mode 100644
index 804ab8c..0000000
 a/model/schedule/uni/jitter/service.v
+++ /dev/null
@@ 1,89 +0,0 @@
Require Import rt.util.all.
Require Import rt.model.time rt.model.arrival.basic.task rt.model.arrival.basic.job rt.model.arrival.basic.arrival_sequence
 rt.model.priority.
Require Import rt.model.schedule.uni.jitter.schedule.
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop.

(* In this file, we define the service received by jobs with
 actual arrival time (including jitter) in a given interval. *)
Module Service.

 Import UniprocessorScheduleWithJitter Priority.

 (* First, we define the more general notion of service received by sets of jobs. *)
 Section ServiceOverSets.

 Context {Job: eqType}.
 Variable job_cost: Job > time.
 Variable job_jitter: Job > time.

 (* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.

 (* Recall the actual job arrivals in a given interval [t1, t2). *)
 Let arrivals_between := actual_arrivals_between job_jitter arr_seq.

 Section Definitions.

 (* First, we define the service received by a generic set of jobs. *)
 Section ServiceOfJobs.

 (* Given any predicate over jobs, ...*)
 Variable P: JobIn arr_seq > bool.

 (* ...we define the cumulative service received by jobs with actual
 arrival time in [t1, t2) that such a predicate. *)
 Definition service_of_jobs (t1 t2: time) :=
 \sum_(j < arrivals_between t1 t2  P j) service_during sched j t1 t2.

 End ServiceOfJobs.

 (* Then, we define the service received by tasks with higher or equal priority
 under FP policies. *)
 Section PerTaskPriority.

 Context {Task: eqType}.
 Variable job_task: Job > Task.

 (* Consider any FP policy. *)
 Variable higher_eq_priority: FP_policy Task.

 (* Let tsk be the task to be analyzed. *)
 Variable tsk: Task.

 (* Based on the definition of jobs of higher or equal priority (with respect to tsk), ... *)
 Let of_higher_or_equal_priority j := higher_eq_priority (job_task j) tsk.

 (* ...we define the service received by jobs of higherorequalpriority
 tasks with actual arrival time in [t1, t2). *)
 Definition service_of_higher_or_equal_priority_tasks (t1 t2: time) :=
 service_of_jobs of_higher_or_equal_priority t1 t2.

 End PerTaskPriority.

 (* Next, we define the service received by jobs with higher or equal priority
 under JLFP policies. *)
 Section PerJobPriority.

 (* Consider any JLDP policy. *)
 Variable higher_eq_priority: JLFP_policy arr_seq.

 (* Let j be the job to be analyzed. *)
 Variable j: JobIn arr_seq.

 (* Based on the definition of jobs of higher or equal priority, ... *)
 Let of_higher_or_equal_priority j_hp := higher_eq_priority j_hp j.

 (* ...we define the service received by jobs of higher or equal priority
 with actual arrival time in [t1, t2). *)
 Definition service_of_higher_or_equal_priority_jobs (t1 t2: time) :=
 service_of_jobs of_higher_or_equal_priority t1 t2.

 End PerJobPriority.

 End Definitions.

 End ServiceOverSets.

End Service.
\ No newline at end of file
diff git a/model/schedule/uni/jitter/workload.v b/model/schedule/uni/jitter/workload.v
deleted file mode 100644
index 03975f8..0000000
 a/model/schedule/uni/jitter/workload.v
+++ /dev/null
@@ 1,87 +0,0 @@
Require Import rt.util.all.
Require Import rt.model.time rt.model.arrival.basic.task rt.model.arrival.basic.job rt.model.priority.
Require Import rt.model.arrival.jitter.arrival_sequence.
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop.

(* In this file, we define the workload requested by jobs with
 actual arrival time (including jitter) in a given interval. *)
Module Workload.

 Import Time ArrivalSequenceWithJitter Priority.

 (* First, we define the notion of workload for sets of jobs. *)
 Section WorkloadDefs.

 Context {Task: eqType}.
 Context {Job: eqType}.
 Variable job_cost: Job > time.
 Variable job_jitter: Job > time.
 Variable job_task: Job > Task.

 (* Consider any job arrival sequence... *)
 Variable arr_seq: arrival_sequence Job.

 (* ...and recall the actual job arrivals in a given interval [t1, t2). *)
 Let arrivals_between := actual_arrivals_between job_jitter arr_seq.

 (* First, we define the workload for generic sets of jobs. *)
 Section WorkloadOfJobs.

 (* Given any predicate over Jobs, ... *)
 Variable pred: JobIn arr_seq > bool.

 (* ...we define the total workload of the jobs with actual arrival time
 in [t1, t2) that satisfy such a predicate. *)
 Definition workload_of_jobs (t1 t2: time) :=
 \sum_(j < arrivals_between t1 t2  pred j) job_cost j.

 End WorkloadOfJobs.

 (* Then, we define the workload of tasks with higher or equal priority
 under FP policies. *)
 Section PerTaskPriority.

 (* Consider any FP policy that indicates whether a task has
 higher or equal priority. *)
 Variable higher_eq_priority: FP_policy Task.

 (* Let tsk be the task to be analyzed. *)
 Variable tsk: Task.

 (* Recall the notion of a job of higher or equal priority. *)
 Let of_higher_or_equal_priority j :=
 higher_eq_priority (job_task j) tsk.

 (* Then, we define the workload of higher or equal priority requested
 in the interval [t1, t2) as the workload of all the jobs of
 higherorequalpriority tasks with actual arrival time in that interval. *)
 Definition workload_of_higher_or_equal_priority_tasks (t1 t2: time) :=
 workload_of_jobs of_higher_or_equal_priority t1 t2.

 End PerTaskPriority.

 (* Then, we define the workload of jobs with higher or equal priority
 under JLFP policies. *)
 Section PerJobPriority.

 (* Consider any JLFP policy that indicates whether a job has
 higher or equal priority. *)
 Variable higher_eq_priority: JLFP_policy arr_seq.

 (* Let j be the job to be analyzed. *)
 Variable j: JobIn arr_seq.

 (* Recall the notion of a job of higher or equal priority. *)
 Let of_higher_or_equal_priority j_hp := higher_eq_priority j_hp j.

 (* Then, we define the workload of higher or equal priority requested
 in the interval [t1, t2) as the workload of all the jobs of
 higherorequal priority with actual arrival time in that interval. *)
 Definition workload_of_higher_or_equal_priority_jobs (t1 t2: time) :=
 workload_of_jobs of_higher_or_equal_priority t1 t2.

 End PerJobPriority.

 End WorkloadDefs.

End Workload.
\ No newline at end of file
diff git a/model/schedule/uni/response_time.v b/model/schedule/uni/response_time.v
index 4ae0e4d..49799fa 100644
 a/model/schedule/uni/response_time.v
+++ b/model/schedule/uni/response_time.v
@@ 12,12 +12,15 @@ Module ResponseTime.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
 (* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
(* Let tsk be any task that is to be analyzed. *)
Variable tsk: sporadic_task.
@@ 31,7 +34,8 @@ Module ResponseTime.
(* ... iff any job j of tsk in this arrival sequence has
completed by (job_arrival j + R). *)
Definition is_response_time_bound_of_task :=
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
job_task j = tsk >
job_has_completed_by j (job_arrival j + R).
@@ 42,14 +46,17 @@ Module ResponseTime.
Context {sporadic_task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > sporadic_task.
 (* Consider any uniprocessor schedule... *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
 (* ... where jobs dont execute after completion. *)
+ (* Assume that jobs don't execute after completion. *)
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
@@ 60,7 +67,7 @@ Module ResponseTime.
Section SpecificJob.
(* Let j be any job... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* ...with responsetime bound R. *)
Variable R: time.
@@ 113,10 +120,11 @@ Module ResponseTime.
(* ... for which a responsetime bound R is known. *)
Variable R: time.
Hypothesis response_time_bound:
 is_response_time_bound_of_task job_cost job_task sched tsk R.
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched tsk R.
(* Then, for any job j of this task, ...*)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
+ Hypothesis H_from_arrival_sequence: arrives_in arr_seq j.
Hypothesis H_job_of_task: job_task j = tsk.
(* ...the service received by job j at any time t' after the response time is 0. *)
@@ 125,7 +133,9 @@ Module ResponseTime.
t' >= job_arrival j + R >
service_at sched j t' = 0.
Proof.
 by ins; apply service_after_job_rt_zero with (R := R); [apply response_time_bound ].
+ intros t' LE.
+ apply service_after_job_rt_zero with (R := R); last by done.
+ by apply response_time_bound.
Qed.
(* The same applies for the cumulative service of job j. *)
diff git a/model/schedule/uni/schedulability.v b/model/schedule/uni/schedulability.v
index 781b6dd..27d34ca 100644
 a/model/schedule/uni/schedulability.v
+++ b/model/schedule/uni/schedulability.v
@@ 11,6 +11,7 @@ Module Schedulability.
Section DeadlineMisses.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_deadline: Job > time.
@@ 18,14 +19,15 @@ Module Schedulability.
Variable job_task: Job > Task.
(* Consider any job arrival sequence... *)
 Context {arr_seq: arrival_sequence Job}.
+ Variable arr_seq: arrival_sequence Job.
(* ...and any uniprocessor schedule of these jobs. *)
 Variable sched: schedule arr_seq.
+ Variable sched: schedule Job.
(* For simplicity, let's define some local names. *)
Let job_completed_by := completed_by job_cost sched.
 Let response_time_bounded_by := is_response_time_bound_of_task job_cost job_task sched.
+ Let response_time_bounded_by :=
+ is_response_time_bound_of_task job_arrival job_cost job_task arr_seq sched.
Section Definitions.
@@ 33,7 +35,7 @@ Module Schedulability.
Section JobLevel.
(* We say that a job j...*)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* ...misses no deadline if it completes by its absolute deadline.*)
Definition job_misses_no_deadline :=
@@ 49,7 +51,8 @@ Module Schedulability.
(* ...misses no deadline if all of its jobs complete by their absolute deadline. *)
Definition task_misses_no_deadline :=
 forall (j: JobIn arr_seq),
+ forall j,
+ arrives_in arr_seq j >
job_task j = tsk >
job_misses_no_deadline j.
@@ 79,13 +82,15 @@ Module Schedulability.
(* First, we infer schedulability from the responsetime bounds of a task. *)
Section ResponseTimeIsBounded.

 (* Assume valid sporadic jobs... *)
 Hypothesis H_valid_job_parameters:
 forall (j: JobIn arr_seq),
 valid_sporadic_job task_cost task_deadline job_cost job_deadline job_task j.
 (* ...that do not execute after completion. *)
+ (* Assume that all jobs in the arrival sequence have the same deadline
+ as their tasks. *)
+ Hypothesis H_job_deadline_eq_task_deadline:
+ forall j,
+ arrives_in arr_seq j >
+ job_deadline_eq_task_deadline task_deadline job_deadline job_task j.
+
+ (* Also assume that jobs don't execute after completion. *)
Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute job_cost sched.
(* Let tsk be any task.*)
@@ 100,15 +105,13 @@ Module Schedulability.
Lemma task_completes_before_deadline:
task_misses_no_deadline tsk.
Proof.
 rename H_valid_job_parameters into JOBPARAMS.
unfold valid_sporadic_job, valid_realtime_job in *.
 intros j JOBtsk.
+ intros j ARRj JOBtsk.
apply completion_monotonic with (t := job_arrival j + R);
[by done   by apply H_response_time_bounded].
rewrite leq_add2l.
apply: (leq_trans H_R_le_deadline).
 apply eq_leq; symmetry; specialize (JOBPARAMS j); des.
 by rewrite JOBtsk JOBPARAMS1.
+ by rewrite H_job_deadline_eq_task_deadline // JOBtsk leqnn.
Qed.
End ResponseTimeIsBounded.
diff git a/model/schedule/uni/schedule.v b/model/schedule/uni/schedule.v
index ce049ca..d0dd40c 100644
 a/model/schedule/uni/schedule.v
+++ b/model/schedule/uni/schedule.v
@@ 12,14 +12,12 @@ Module UniprocessorSchedule.
(* We begin by defining a uniprocessor schedule. *)
Section ScheduleDef.
 Context {Job: eqType}.

 (* Consider any job arrival sequence. *)
 Variable arr_seq: arrival_sequence Job.
+ (* Consider any job type. *)
+ Variable Job: eqType.
 (* A uniprocessor schedule associates each point in time to either
+ (* We define a uniprocessor schedule by mapping each point in time to either
Some job that is scheduled or None, if the processor is idle. *)
 Definition schedule := time > option (JobIn arr_seq).
+ Definition schedule := time > option Job.
End ScheduleDef.
@@ 27,17 +25,17 @@ Module UniprocessorSchedule.
Section ScheduleProperties.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable sched: schedule Job.
(* Let's define properties of the jobs to be scheduled. *)
Section JobProperties.
 (* Let j be any job from the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* First, we define whether a job j is scheduled at time t, ... *)
Definition scheduled_at (t: time) := sched t == Some j.
@@ 60,10 +58,10 @@ Module UniprocessorSchedule.
Definition completed_by (t: time) := service t == job_cost j.
(* Job j is pending at time t iff it has arrived but has not yet completed. *)
 Definition pending (t: time) := has_arrived j t && ~~completed_by t.
+ Definition pending (t: time) := has_arrived job_arrival j t && ~~ completed_by t.
(* Job j is backlogged at time t iff it is pending and not scheduled. *)
 Definition backlogged (t: time) := pending t && ~~scheduled_at t.
+ Definition backlogged (t: time) := pending t && ~~ scheduled_at t.
End JobProperties.
@@ 89,17 +87,21 @@ Module UniprocessorSchedule.
Section ValidSchedules.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable sched: schedule Job.
 (* We define whether a job can only be scheduled if it has arrived ... *)
+ (* We define whether jobs come from some arrival sequence... *)
+ Definition jobs_come_from_arrival_sequence (arr_seq: arrival_sequence Job) :=
+ forall j t, scheduled_at sched j t > arrives_in arr_seq j.
+
+ (* ..., whether a job can only be scheduled if it has arrived ... *)
Definition jobs_must_arrive_to_execute :=
 forall j t, scheduled_at sched j t > has_arrived j t.
+ forall j t, scheduled_at sched j t > has_arrived job_arrival j t.
 (* ... and whether a job can be scheduled after it completes. *)
+ (* ... and whether a job cannot be scheduled after it completes. *)
Definition completed_jobs_dont_execute :=
forall j t, service sched j t <= job_cost j.
@@ 109,17 +111,17 @@ Module UniprocessorSchedule.
Section Lemmas.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable sched: schedule Job.
(* Let's begin with lemmas about service. *)
Section Service.
(* Let j be any job that is to be scheduled. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* First, we prove that the instantaneous service cannot be greater than 1, ... *)
Lemma service_at_most_one:
@@ 150,7 +152,7 @@ Module UniprocessorSchedule.
completed_jobs_dont_execute job_cost sched.
(* Let j be any job that is to be scheduled. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* We prove that after job j completes, it remains completed. *)
Lemma completion_monotonic:
@@ 205,10 +207,10 @@ Module UniprocessorSchedule.
(* Assume that jobs must arrive to execute. *)
Hypothesis H_jobs_must_arrive:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* Let j be any job that is to be scheduled. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* First, we show that job j does not receive service at any time t
prior to its arrival. *)
@@ 220,7 +222,7 @@ Module UniprocessorSchedule.
rename H_jobs_must_arrive into ARR; red in ARR; intros t LT.
specialize (ARR j t).
apply contra with (c := scheduled_at sched j t)
 (b := has_arrived j t) in ARR;
+ (b := has_arrived job_arrival j t) in ARR;
last by rewrite ltnNge.
by apply/eqP; rewrite eqb0.
Qed.
@@ 261,20 +263,20 @@ Module UniprocessorSchedule.
(* Assume that jobs must arrive to execute... *)
Hypothesis H_jobs_must_arrive:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* ...and that completed jobs do not execute. *)
Hypothesis H_completed_jobs:
completed_jobs_dont_execute job_cost sched.
(* Let j be any job. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* First, we show that if job j is scheduled, then it must be pending. *)
Lemma scheduled_implies_pending:
forall t,
scheduled_at sched j t >
 pending job_cost sched j t.
+ pending job_arrival job_cost sched j t.
Proof.
rename H_jobs_must_arrive into ARRIVE,
H_completed_jobs into COMP.
@@ 296,7 +298,7 @@ Module UniprocessorSchedule.
Section OnlyOneJobScheduled.
(* Let j1 and j2 be any jobs. *)
 Variable j1 j2: JobIn arr_seq.
+ Variable j1 j2: Job.
(* At any time t, if both j1 and j2 are scheduled, then they must be the same job. *)
Lemma only_one_job_scheduled:
@@ 325,7 +327,7 @@ Module UniprocessorSchedule.
Qed.
(* Next, consider any job j at any time t... *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
Variable t: time.
(* ...and let s0 be any value less than the service received
@@ 350,10 +352,32 @@ Module UniprocessorSchedule.
End ServiceIsAStepFunction.
+ Section ScheduledAtEarlierTime.
+
+ (* Next, we show that if the service is positive,
+ then the job is scheduled at some earlier time. *)
+ Lemma scheduled_at_earlier_time:
+ forall j t,
+ service sched j t > 0 >
+ exists t0,
+ t0 < t /\
+ scheduled_at sched j t0.
+ Proof.
+ intros j t GT.
+ case (boolP ([exists t0:'I_t, scheduled_at sched j t0])) => [EX  ALL];
+ first by move: EX => /existsP [t0 SCHED]; exists t0; split.
+ rewrite negb_exists in ALL; move: ALL => /forallP ALL.
+ rewrite /service /service_during big_nat_cond big1 in GT; first by rewrite ltnn in GT.
+ move => i => /andP [/= LT _].
+ by apply/eqP; rewrite eqb0; apply (ALL (Ordinal LT)).
+ Qed.
+
+ End ScheduledAtEarlierTime.
+
Section ServiceNotZero.
(* Let j be any job. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Assume that the service received by j during [t1, t2) is not zero. *)
Variable t1 t2: time.
@@ 390,8 +414,8 @@ Module UniprocessorSchedule.
with same service. *)
Section TimesWithSameService.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* Consider any time instants t1 and t2... *)
Variable t1 t2: time.
@@ 438,4 +462,4 @@ Module UniprocessorSchedule.
End Schedule.
End UniprocessorSchedule.
+End UniprocessorSchedule.
\ No newline at end of file
diff git a/model/schedule/uni/schedule_of_task.v b/model/schedule/uni/schedule_of_task.v
index 4c68210..41448b8 100644
 a/model/schedule/uni/schedule_of_task.v
+++ b/model/schedule/uni/schedule_of_task.v
@@ 16,8 +16,7 @@ Module ScheduleOfTask.
Variable job_task: Job > Task.
(* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable sched: schedule Job.
Section TaskProperties.
diff git a/model/schedule/uni/service.v b/model/schedule/uni/service.v
index 26e339d..cf537c9 100644
 a/model/schedule/uni/service.v
+++ b/model/schedule/uni/service.v
@@ 12,32 +12,35 @@ Module Service.
Section ServiceOverSets.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
 (* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* Consider any job arrival sequence... *)
+ Variable arr_seq: arrival_sequence Job.
 (* Recall the sequence of job arrivals in any interval [t1, t2). *)
 Let arrivals_between := jobs_arrived_between arr_seq.
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
+
+ (* Let jobs denote any (finite) set of jobs. *)
+ Variable jobs: seq Job.
Section Definitions.
(* First, we define the service received by a generic set of jobs. *)
Section ServiceOfJobs.
 (* Given any predicate over jobs, ...*)
 Variable P: JobIn arr_seq > bool.
+ (* Then, given any predicate over jobs, ...*)
+ Variable P: Job > bool.
(* ...we define the cumulative service received during [t1, t2)
by the jobs that satisfy this predicate. *)
Definition service_of_jobs (t1 t2: time) :=
 \sum_(j < arrivals_between t1 t2  P j) service_during sched j t1 t2.
+ \sum_(j < jobs  P j) service_during sched j t1 t2.
End ServiceOfJobs.
 (* Then, we define the service received by tasks with higher or equal priority
 under FP policies. *)
+ (* Next, we define the service received by tasks with higherorequal
+ priority under a given FP policy. *)
Section PerTaskPriority.
Context {Task: eqType}.
@@ 51,7 +54,7 @@ Module Service.
(* Based on the definition of jobs of higher or equal priority (with respect to tsk), ... *)
Let of_higher_or_equal_priority j := higher_eq_priority (job_task j) tsk.

+
(* ...we define the service received during [t1, t2) by jobs of higher or equal priority. *)
Definition service_of_higher_or_equal_priority_tasks (t1 t2: time) :=
service_of_jobs of_higher_or_equal_priority t1 t2.
@@ 63,10 +66,10 @@ Module Service.
Section PerJobPriority.
(* Consider any JLDP policy. *)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* Let j be the job to be analyzed. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Based on the definition of jobs of higher or equal priority, ... *)
Let of_higher_or_equal_priority j_hp := higher_eq_priority j_hp j.
@@ 81,24 +84,24 @@ Module Service.
Section Lemmas.
+ (* Let P be any predicate over jobs. *)
+ Variable P: Job > bool.
+
(* In this section, we prove that the service received by any set of jobs
is upperbounded by the corresponding workload. *)
Section ServiceBoundedByWorkload.
+ (* Recall the definition of workload. *)
+ Let workload_of := workload_of_jobs job_cost.
+
(* Assume that jobs do not execute after completion.*)
Hypothesis H_completed_jobs_dont_execute:
completed_jobs_dont_execute job_cost sched.
 (* Recall the definition of workload. *)
 Let workload_of := workload_of_jobs job_cost arr_seq.

 (* Let P be any predicate over jobs. *)
 Variable P: Job > bool.

(* Then, we prove that the service received by those jobs is no larger than their workload. *)
 Lemma service_le_workload:
+ Lemma service_of_jobs_le_workload:
forall t1 t2,
 service_of_jobs P t1 t2 <= workload_of P t1 t2.
+ service_of_jobs P t1 t2 <= workload_of jobs P.
Proof.
intros t1 t2.
apply leq_sum; intros j _.
@@ 107,6 +110,45 @@ Module Service.
End ServiceBoundedByWorkload.
+ (* In this section, we prove that the service received by any set of jobs
+ is upperbounded by the corresponding interval length. *)
+ Section ServiceBoundedByIntervalLength.
+
+ (* Assume that jobs do not execute after completion.*)
+ Hypothesis H_completed_jobs_dont_execute:
+ completed_jobs_dont_execute job_cost sched.
+
+ (* Assume that the sequence of jobs is a set. *)
+ Hypothesis H_no_duplicate_jobs: uniq jobs.
+
+ (* Then, we prove that the service received by those jobs is no larger than their workload. *)
+ Lemma service_of_jobs_le_delta:
+ forall t1 t2,
+ service_of_jobs P t1 t2 <= t2  t1.
+ Proof.
+ unfold service_of_jobs; intros t1 t2.
+ rewrite exchange_big /=.
+ apply leq_trans with (n := \sum_(t1 <= t < t2) 1); last by simpl_sum_const.
+ apply leq_sum; intros t _; rewrite /service_at.
+ case (boolP (has (fun j => P j && scheduled_at sched j t) jobs)) => [HAS  ALL].
+ {
+ move: HAS => /hasP [j0 IN0 /andP [PRED0 SCHED0]].
+ rewrite big_mkcond (bigD1_seq j0) //= PRED0 SCHED0 big1 //.
+ intros j1 NEQ; case: ifP => PRED1; last by done.
+ apply/eqP; rewrite eqb0; apply/negP; intro SCHED1.
+ apply only_one_job_scheduled with (j2 := j1) in SCHED0; last by done.
+ by rewrite SCHED0 eq_refl in NEQ.
+ }
+ {
+ rewrite all_predC in ALL; move: ALL => /allP ALL.
+ rewrite big_seq_cond big1 //.
+ move => j0 /andP [IN0 PRED0]; apply/eqP; rewrite eqb0.
+ by specialize (ALL j0 IN0); rewrite /= PRED0 /= in ALL.
+ }
+ Qed.
+
+ End ServiceBoundedByIntervalLength.
+
End Lemmas.
End ServiceOverSets.
diff git a/model/schedule/uni/susp/last_execution.v b/model/schedule/uni/susp/last_execution.v
index 4d9e55d..bf1c65f 100644
 a/model/schedule/uni/susp/last_execution.v
+++ b/model/schedule/uni/susp/last_execution.v
@@ 14,11 +14,11 @@ Module LastExecution.
Section TimeAfterLastExecution.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable sched: schedule Job.
(* For simplicity, let's define some local names. *)
Let job_scheduled_at := scheduled_at sched.
@@ 27,7 +27,7 @@ Module LastExecution.
Section Defs.
(* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Next, we will show how to find the time after the most recent
execution of a given job j in the interval [job_arrival j, t).
@@ 58,10 +58,10 @@ Module LastExecution.
(* Assume that jobs do not execute before they arrived. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* In this section, we show that the time after the last execution occurs
no earlier than the arrival of the job. *)
@@ 71,7 +71,7 @@ Module LastExecution.
interval [0, t) occurs no earlier than the arrival of j. *)
Lemma last_execution_after_arrival:
forall t,
 has_arrived j (time_after_last_execution j t).
+ has_arrived job_arrival j (time_after_last_execution j t).
Proof.
unfold time_after_last_execution, has_arrived; intros t.
case EX: [exists _, _]; last by done.
@@ 89,7 +89,7 @@ Module LastExecution.
(* Let t1 be any time no earlier than the arrival of job j. *)
Variable t1: time.
 Hypothesis H_after_arrival: has_arrived j t1.
+ Hypothesis H_after_arrival: has_arrived job_arrival j t1.
(* Then, (time_after_last_execution j) grows monotonically
after that point. *)
@@ 190,7 +190,7 @@ Module LastExecution.
(* Let t be any time no earlier than the arrival of j. *)
Variable t: time.
 Hypothesis H_after_arrival: has_arrived j t.
+ Hypothesis H_after_arrival: has_arrived job_arrival j t.
(* Then, the time following the last execution of job j in the interval [0, t)
occurs no later than time t. *)
@@ 305,9 +305,9 @@ Module LastExecution.
apply negbT in EX; rewrite negb_exists in EX.
move: EX => /forallP ALL.
rewrite /service /service_during.
 rewrite ignore_service_before_arrival // big_geq //.
+ rewrite (ignore_service_before_arrival job_arrival) // big_geq //.
rewrite big_nat_cond big1 //; move => i /andP [/= LTi _].
 by apply/eqP; rewrite eqb0; apply (ALL (Ordinal LTi)).
+ by apply/eqP; rewrite eqb0; apply (ALL (Ordinal LTi)).
}
Qed.
@@ 349,10 +349,10 @@ Module LastExecution.
{
apply/andP; split; last by rewrite COMP.
rewrite /service /service_during.
 by rewrite ignore_service_before_arrival // big_geq.
+ by rewrite (ignore_service_before_arrival job_arrival) // big_geq.
}
move: EX => [x_mid [_ SERV]]; exists x_mid.
 by rewrite SERV SAME.
+ by rewrite SERV SAME.
Qed.
End ExistsIntermediateExecution.
diff git a/model/schedule/uni/susp/platform.v b/model/schedule/uni/susp/platform.v
index d0ad3f1..a54d9cd 100644
 a/model/schedule/uni/susp/platform.v
+++ b/model/schedule/uni/susp/platform.v
@@ 12,21 +12,24 @@ Module PlatformWithSuspensions.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > Task.
(* Assume that job suspension times are given. *)
Variable next_suspension: job_suspension Job.
 (* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (* Consider any job arrival sequence ...*)
+ Variable arr_seq: arrival_sequence Job.
+
+ (* ...and any uniprocessor schedule of these jobs. *)
+ Variable sched: schedule Job.
(* For simplicity, let's recall the definitions of pending, scheduled, and backlogged job.
Note that this notion of backlogged is specific for suspensionaware schedulers. *)
 Let job_pending_at := pending job_cost sched.
+ Let job_pending_at := pending job_arrival job_cost sched.
Let job_scheduled_at := scheduled_at sched.
 Let job_backlogged_at := backlogged job_cost next_suspension sched.
+ Let job_backlogged_at := backlogged job_arrival job_cost next_suspension sched.
(* In this section, we define schedule constraints for suspensionaware schedules. *)
Section ScheduleConstraints.
@@ 38,6 +41,7 @@ Module PlatformWithSuspensions.
is backlogged, the processor is always busy with another job. *)
Definition work_conserving :=
forall j t,
+ arrives_in arr_seq j >
job_backlogged_at j t >
exists j_other, job_scheduled_at j_other t.
@@ 52,7 +56,8 @@ Module PlatformWithSuspensions.
(* ... is respected by the scheduler iff at any time t, a scheduled job
has higher (or same) priority than (as) any backlogged job. *)
Definition respects_FP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
+ forall j j_hp t,
+ arrives_in arr_seq j >
job_backlogged_at j t >
job_scheduled_at j_hp t >
higher_eq_priority (job_task j_hp) (job_task j).
@@ 63,12 +68,13 @@ Module PlatformWithSuspensions.
Section JLFP.
(* We say that a JLFP policy ...*)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* ... is respected by the scheduler iff every scheduled job
has higher (or same) priority than (as) any backlogged job. *)
Definition respects_JLFP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
+ forall j j_hp t,
+ arrives_in arr_seq j >
job_backlogged_at j t >
job_scheduled_at j_hp t >
higher_eq_priority j_hp j.
@@ 79,12 +85,13 @@ Module PlatformWithSuspensions.
Section JLDP.
(* We say that a JLDP policy ...*)
 Variable higher_eq_priority: JLDP_policy arr_seq.
+ Variable higher_eq_priority: JLDP_policy Job.
(* ... is respected by the scheduler iff at any time t, a scheduled job
has higher (or same) priority than (as) any backlogged job. *)
Definition respects_JLDP_policy :=
 forall (j j_hp: JobIn arr_seq) t,
+ forall j j_hp t,
+ arrives_in arr_seq j >
job_backlogged_at j t >
job_scheduled_at j_hp t >
higher_eq_priority t j_hp j.
diff git a/model/schedule/uni/susp/schedule.v b/model/schedule/uni/susp/schedule.v
index 7166455..eb95477 100644
 a/model/schedule/uni/susp/schedule.v
+++ b/model/schedule/uni/susp/schedule.v
@@ 13,26 +13,26 @@ Module ScheduleWithSuspensions.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Assume that job suspension times are given. *)
Variable next_suspension: job_suspension Job.
(* Consider any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ Variable sched: schedule Job.
(* Recall the predicates that denote whether a job is scheduled
and suspended. *)
 Let job_pending_at := pending job_cost sched.
+ Let job_pending_at := pending job_arrival job_cost sched.
Let job_scheduled_at := scheduled_at sched.
 Let job_suspended_at := suspended_at job_cost next_suspension sched.
+ Let job_suspended_at := suspended_at job_arrival job_cost next_suspension sched.
(* First, we redefine the notion of backlogged job to account for suspensions. *)
Section BackloggedJob.
(* We say that job j...*)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* ...is backlogged at time t iff it is pending and neither
scheduled nor suspended. *)
diff git a/model/schedule/uni/susp/suspension_intervals.v b/model/schedule/uni/susp/suspension_intervals.v
index 56b3d96..1222b48 100644
 a/model/schedule/uni/susp/suspension_intervals.v
+++ b/model/schedule/uni/susp/suspension_intervals.v
@@ 13,14 +13,15 @@ Module SuspensionIntervals.
Section DefiningSuspensionIntervals.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
(* Consider any job suspension times... *)
Variable next_suspension: job_suspension Job.
(* ...and any uniprocessor schedule. *)
 Context {arr_seq: arrival_sequence Job}.
 Variable sched: schedule arr_seq.
+ (*Context {arr_seq: arrival_sequence Job}.*)
+ Variable sched: schedule Job.
(* For simplicity, let's define some local names. *)
Let job_scheduled_at := scheduled_at sched.
@@ 30,8 +31,8 @@ Module SuspensionIntervals.
whether a job is suspended. *)
Section JobSuspension.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
Section DefiningSuspension.
@@ 41,7 +42,7 @@ Module SuspensionIntervals.
(* First, we define the beginning of the latest self suspension as the
time following the last execution of job j in the interval [0, t).
(Note that suspension_start can return time t itself.) *)
 Let suspension_start := time_after_last_execution sched j t.
+ Let suspension_start := time_after_last_execution job_arrival sched j t.
(* Next, using the service received by j in the interval [0, suspension_start), ... *)
Let current_service := service sched j suspension_start.
@@ 90,7 +91,7 @@ Module SuspensionIntervals.
(* Assume that jobs do not execute before they arrive... *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* ...and nor after completion. *)
Hypothesis H_completed_jobs_dont_execute:
@@ 99,15 +100,15 @@ Module SuspensionIntervals.
(* Assume that the schedule respects selfsuspensions. *)
Hypothesis H_respects_self_suspensions: respects_self_suspensions.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* Consider any time t after the arrival of j... *)
Variable t: time.
 Hypothesis H_has_arrived: has_arrived j t.
+ Hypothesis H_has_arrived: has_arrived job_arrival j t.
(* ...and recall the latest suspension interval of job j relative to time t. *)
 Let suspension_start := time_after_last_execution sched j t.
+ Let suspension_start := time_after_last_execution job_arrival sched j t.
Let duration := suspension_duration j t.
(* First, we analyze the service received during a suspension interval. *)
@@ 150,7 +151,7 @@ Module SuspensionIntervals.
case: (boolP (completed_by _ _ _ _)) => [COMP  NOTCOMP];
first by apply completed_implies_not_scheduled in COMP;
first by rewrite SCHED' in COMP.
 rewrite andTb (same_service_implies_same_last_execution _ _ _ suspension_start) //.
+ rewrite andTb (same_service_implies_same_last_execution _ _ _ _ suspension_start) //.
rewrite /suspension_start last_execution_idempotent //.
apply/andP; split; first by apply leq_addr.
by rewrite ltn_add2l.
@@ 178,19 +179,21 @@ Module SuspensionIntervals.
Proof.
rename H_within_suspension_interval into BETWEEN.
move: BETWEEN => /andP [GE LT].
 have ARR: has_arrived j t_in.
+ have ARR: has_arrived job_arrival j t_in.
{
 by apply leq_trans with (n := suspension_start);
 first by apply last_execution_after_arrival.
+ apply leq_trans with (n := suspension_start); last by done.
+ rewrite /(has_arrived job_arrival j suspension_start).
+ by apply last_execution_after_arrival.
}
apply/andP; split; first by done.
apply/andP; split;
first by apply last_execution_bounded_by_identity.
apply (leq_trans LT).
 have SAME: time_after_last_execution sched j t = time_after_last_execution sched j t_in.
+ have SAME: time_after_last_execution job_arrival sched j t =
+ time_after_last_execution job_arrival sched j t_in.
{
set b := _ _ t.
 rewrite [_ _ t_in](same_service_implies_same_last_execution _ _ _ b);
+ rewrite [_ _ t_in](same_service_implies_same_last_execution _ _ _ _ b);
first by rewrite last_execution_idempotent.
apply same_service_in_suspension_interval.
by apply/andP; split; last by apply ltnW.
@@ 208,17 +211,17 @@ Module SuspensionIntervals.
(* Assume that jobs do not execute before they arrived. *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* Assume that j is suspended at time t. *)
Variable t: time.
Hypothesis H_j_is_suspended: suspended_at j t.
(* First, we show that j must have arrived by time t. *)
 Lemma suspended_implies_arrived: has_arrived j t.
+ Lemma suspended_implies_arrived: has_arrived job_arrival j t.
Proof.
rename H_j_is_suspended into SUSP.
move: SUSP => /andP [_ SUSP].
@@ 238,7 +241,7 @@ Module SuspensionIntervals.
have NOTSCHED: ~~ scheduled_at sched j t'.
{
rewrite eqb0; apply/eqP.
 by apply service_before_job_arrival_zero; first by done.
+ by eapply service_before_job_arrival_zero; first by eauto.
}
by rewrite EX in NOTSCHED.
Qed.
@@ 258,7 +261,7 @@ Module SuspensionIntervals.
(* Assume that jobs do not execute before they arrive... *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* ...and nor after completion. *)
Hypothesis H_completed_jobs_dont_execute:
@@ 267,8 +270,8 @@ Module SuspensionIntervals.
(* Assume that the schedule respects selfsuspensions. *)
Hypothesis H_respects_self_suspensions: respects_self_suspensions.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* Recall the total suspension of job j as given by the dynamic suspension model. *)
Let cumulative_suspension_of_j :=
@@ 308,7 +311,7 @@ Module SuspensionIntervals.
}
move: EX => /existsP [t' /andP [GE' /eqP SERV]].
unfold suspended_at, suspension_duration.
 set b := time_after_last_execution sched j.
+ set b := time_after_last_execution job_arrival sched j.
set n := next_suspension j s.
apply leq_trans with (n := \sum_(t1 <= t < t2  b t' <= t < b t' + n) 1).
{
@@ 323,13 +326,13 @@ Module SuspensionIntervals.
move: INT => /andP [GEt LTt].
rewrite (same_service_in_suspension_interval _ _ _ _ t') //.
{
 rewrite /b [b t'](same_service_implies_same_last_execution _ _ _ t);
+ rewrite /b [b t'](same_service_implies_same_last_execution _ _ _ _ t);
last by rewrite SERV EQ.
by apply/andP; split.
}
{
rewrite /suspension_duration /b.
 rewrite [b t'](same_service_implies_same_last_execution _ _ _ t);
+ rewrite [b t'](same_service_implies_same_last_execution _ _ _ _ t);
last by rewrite SERV EQ.
by apply/andP; split; last by apply ltnW.
}
@@ 348,7 +351,7 @@ Module SuspensionIntervals.
(* Assume that jobs do not execute before they arrive... *)
Hypothesis H_jobs_must_arrive_to_execute:
 jobs_must_arrive_to_execute sched.
+ jobs_must_arrive_to_execute job_arrival sched.
(* ...and nor after completion. *)
Hypothesis H_completed_jobs_dont_execute:
@@ 357,8 +360,8 @@ Module SuspensionIntervals.
(* Assume that the schedule respects selfsuspensions. *)
Hypothesis H_respects_self_suspensions: respects_self_suspensions.
 (* Let j be any job in the arrival sequence. *)
 Variable j: JobIn arr_seq.
+ (* Let j be any job. *)
+ Variable j: Job.
(* Assume that j has completed by time t. *)
Variable t: time.
@@ 370,7 +373,8 @@ Module SuspensionIntervals.
cumulative_suspension j t = total_suspension job_cost next_suspension j.
Proof.
rename H_j_has_completed into COMP, H_jobs_must_arrive_to_execute into ARR.
 have EARLIER := exists_last_execution_with_smaller_service job_cost sched ARR j t COMP.
+ have EARLIER := exists_last_execution_with_smaller_service job_arrival
+ job_cost sched ARR j t COMP.
apply/eqP; rewrite eqn_leq; apply/andP; split;
first by apply cumulative_suspension_le_total_suspension.
rewrite /total_suspension /cumulative_suspension /cumulative_suspension_during.
@@ 400,7 +404,7 @@ Module SuspensionIntervals.
{
apply leq_sum_nat; move => s /andP [_ LTs] _.
rewrite /suspended_at /suspension_duration.
 set b := time_after_last_execution sched j.
+ set b := time_after_last_execution job_arrival sched j.
set n := next_suspension j.
move: (EARLIER s LTs) => [t' EQ'].
diff git a/model/schedule/uni/transformation/construction.v b/model/schedule/uni/transformation/construction.v
index 01b3610..c5e4099 100644
 a/model/schedule/uni/transformation/construction.v
+++ b/model/schedule/uni/transformation/construction.v
@@ 18,21 +18,21 @@ Module ScheduleConstruction.
(* Assume we are given a function that takes an existing schedule prefix
up to interval [0, t) and returns what should be scheduled at time t. *)
Variable build_schedule:
 schedule arr_seq > time > option (JobIn arr_seq).
+ schedule Job > time > option Job.
(* Then, starting from a base schedule, ... *)
 Variable base_sched: schedule arr_seq.
+ Variable base_sched: schedule Job.
(* ...we can update individual times using the build_schedule function, ... *)
 Definition update_schedule (prev_sched: schedule arr_seq)
 (t_next: time) : schedule arr_seq :=
+ Definition update_schedule (prev_sched: schedule Job)
+ (t_next: time) : schedule Job :=
fun t =>
if t == t_next then
build_schedule prev_sched t
else prev_sched t.
(* ...which recursively generates schedule prefixes up to time t_max. *)
 Fixpoint schedule_prefix (t_max: time) : schedule arr_seq :=
+ Fixpoint schedule_prefix (t_max: time) : schedule Job :=
if t_max is t_prev.+1 then
update_schedule (schedule_prefix t_prev) t_prev.+1
else
@@ 111,7 +111,7 @@ Module ScheduleConstruction.
(* If the generation function only depends on the schedule prefix, ... *)
Hypothesis H_depends_only_on_prefix:
 forall (sched1 sched2: schedule arr_seq) t,
+ forall (sched1 sched2: schedule Job) t,
(forall t0, t0 < t > sched1 t0 = sched2 t0) >
build_schedule sched1 t = build_schedule sched2 t.
@@ 142,7 +142,7 @@ Module ScheduleConstruction.
Section ImmediateProperty.
 Variable P: option (JobIn arr_seq) > Prop.
+ Variable P: option Job > Prop.
Hypothesis H_immediate_property:
forall sched_prefix t, P (build_schedule sched_prefix t).
diff git a/model/schedule/uni/workload.v b/model/schedule/uni/workload.v
index 753425e..f877e3f 100644
 a/model/schedule/uni/workload.v
+++ b/model/schedule/uni/workload.v
@@ 12,25 +12,24 @@ Module Workload.
Context {Task: eqType}.
Context {Job: eqType}.
+ Variable job_arrival: Job > time.
Variable job_cost: Job > time.
Variable job_task: Job > Task.
(* Consider any job arrival sequence... *)
Variable arr_seq: arrival_sequence Job.
 (* ...and recall the job arrivals in any interval [t1, t2). *)
 Let arrivals_between := jobs_arrived_between arr_seq.
+ (* ...and any (finite) set of jobs. *)
+ Variable jobs: seq Job.
(* First, we define the workload for generic sets of jobs. *)
Section WorkloadOfJobs.
(* Given any predicate over Jobs, ... *)
 Variable pred: JobIn arr_seq > bool.
+ Variable P: Job > bool.
 (* ...we define the total workload of the jobs released during [t1, t2)
 that satisfy such a predicate. *)
 Definition workload_of_jobs (t1 t2: time) :=
 \sum_(j < arrivals_between t1 t2  pred j) job_cost j.
+ (* ...we define the total workload of the jobs that satisfy such a predicate. *)
+ Definition workload_of_jobs := \sum_(j < jobs  P j) job_cost j.
End WorkloadOfJobs.
@@ 49,11 +48,10 @@ Module Workload.
Let of_higher_or_equal_priority j :=
higher_eq_priority (job_task j) tsk.
 (* Then, we define the workload of higher or equal priority requested
 in the interval [t1, t2) as the workload of all the jobs of
 higherorequalpriority tasks released in that interval. *)
 Definition workload_of_higher_or_equal_priority_tasks (t1 t2: time) :=
 workload_of_jobs of_higher_or_equal_priority t1 t2.
+ (* Then, we define the workload of all jobs of tasks with
+ higherorequal priority than tsk. *)
+ Definition workload_of_higher_or_equal_priority_tasks :=
+ workload_of_jobs of_higher_or_equal_priority.
End PerTaskPriority.
@@ 63,19 +61,18 @@ Module Workload.
(* Consider any JLFP policy that indicates whether a job has
higher or equal priority. *)
 Variable higher_eq_priority: JLFP_policy arr_seq.
+ Variable higher_eq_priority: JLFP_policy Job.
(* Let j be the job to be analyzed. *)
 Variable j: JobIn arr_seq.
+ Variable j: Job.
(* Recall the notion of a job of higher or equal priority. *)
Let of_higher_or_equal_priority j_hp := higher_eq_priority j_hp j.
 (* Then, we define the workload of higher or equal priority requested
 in the interval [t1, t2) as the workload of all the jobs of
 higherorequal priority released in that interval. *)
 Definition workload_of_higher_or_equal_priority_jobs (t1 t2: time) :=
 workload_of_jobs of_higher_or_equal_priority t1 t2.
+ (* Then, we define the workload of higher or equal priority of all jobs
+ with higherorequal priority than j. *)
+ Definition workload_of_higher_or_equal_priority_jobs :=
+ workload_of_jobs of_higher_or_equal_priority.
End PerJobPriority.
diff git a/util/sorting.v b/util/sorting.v
index ae0bbce..ea1da75 100644
 a/util/sorting.v
+++ b/util/sorting.v
@@ 120,4 +120,21 @@ Section Sorting.
}
Qed.
+ Lemma sort_over_list_sorted {T: eqType} (leT: rel T) (s: seq T) :
+ total_over_list leT s >
+ sorted leT (sort leT s).
+ Proof.
+ (* rewrite /sort; have allss: all sorted [::] by [].
+ elim: {s}_.+1 {2}s [::] allss (ltnSn (size s)) => // n IHn s ss allss.
+ have: sorted s > sorted (merge_sort_pop s ss).
+ elim: ss allss s => //= s2 ss IHss /andP[ord_s2 ord_ss] s ord_s.
+ exact: IHss ord_ss _ (merge_sorted ord_s ord_s2).
+ case: s => [x1 [x2 s _]]; try by auto.
+ move/ltnW/IHn; apply=> {n IHn s}; set s1 := if _ then _ else _.
+ have: sorted s1 by apply: (@merge_sorted [::x2] [::x1]).
+ elim: ss {x1 x2}s1 allss => /= [s2 ss IHss] s1; first by rewrite andbT.
+ case/andP=> ord_s2 ord_ss ord_s1.
+ by case: {1}s2=> /= [_ _]; [rewrite ord_s1  apply: IHss (merge_sorted _ _)].*)
+ Admitted.
+
End Sorting.
\ No newline at end of file

GitLab