From c99f65a9e7e7fc8dc764429be40e54d793aab4ef Mon Sep 17 00:00:00 2001
From: Sergei Bozhko <sbozhko@mpi-sws.org>
Date: Mon, 19 Feb 2024 14:26:53 +0100
Subject: [PATCH] prove simple busy-interval length bound for JLFP

---
 .../restricted_supply/bounded_bi/jlfp.v       | 325 ++++++++++++++++++
 1 file changed, 325 insertions(+)
 create mode 100644 analysis/abstract/restricted_supply/bounded_bi/jlfp.v

diff --git a/analysis/abstract/restricted_supply/bounded_bi/jlfp.v b/analysis/abstract/restricted_supply/bounded_bi/jlfp.v
new file mode 100644
index 000000000..b6da0d482
--- /dev/null
+++ b/analysis/abstract/restricted_supply/bounded_bi/jlfp.v
@@ -0,0 +1,325 @@
+Require Export prosa.analysis.abstract.restricted_supply.abstract_rta.
+Require Export prosa.analysis.abstract.restricted_supply.iw_instantiation.
+Require Export prosa.analysis.abstract.restricted_supply.bounded_bi.aux.
+Require Export prosa.analysis.facts.busy_interval.carry_in.
+Require Export prosa.analysis.definitions.sbf.busy.
+
+
+(** * Sufficient Condition for Bounded Busy Intervals for RS JLFP *)
+
+(** In this section, we show that the existence of [L] such that [B +
+    total_rbf L <= SBF L], where where [B] is the blocking bound and
+    [SBF] is a supply-bound function, is a sufficient condition for
+    the existence of bounded busy intervals under JLFP scheduling with
+    a restricted-supply processor model. Note that this is not the
+    tightest bound, but it can be useful in case the blocking bound is
+    small or zero.  *)
+Section BoundedBusyIntervals.
+
+  (** Consider any type of tasks ... *)
+  Context {Task : TaskType}.
+  Context `{TaskCost Task}.
+
+  (**  ... and any type of jobs associated with these tasks. *)
+  Context {Job : JobType}.
+  Context `{JobTask Job Task}.
+  Context `{JobArrival Job}.
+  Context `{JobCost Job}.
+
+  (** Consider any kind of fully supply-consuming unit-supply
+      uniprocessor model. *)
+  Context `{PState : ProcessorState Job}.
+  Hypothesis H_uniprocessor_proc_model : uniprocessor_model PState.
+  Hypothesis H_unit_supply_proc_model : unit_supply_proc_model PState.
+  Hypothesis H_consumed_supply_proc_model : fully_consuming_proc_model PState.
+
+  (** Consider a JLFP policy that indicates a higher-or-equal priority
+      relation, and assume that the relation is reflexive and
+      transitive. *)
+  Context {JLFP : JLFP_policy Job}.
+  Hypothesis H_priority_is_reflexive : reflexive_job_priorities JLFP.
+  Hypothesis H_priority_is_transitive : transitive_job_priorities JLFP.
+
+  (** Consider any valid arrival sequence. *)
+  Variable arr_seq : arrival_sequence Job.
+  Hypothesis H_valid_arrival_sequence : valid_arrival_sequence arr_seq.
+
+  (** Next, consider a schedule of this arrival sequence, ... *)
+  Variable sched : schedule PState.
+
+  (** ... allow for any work-bearing notion of job readiness, ... *)
+  Context `{!JobReady Job PState}.
+  Hypothesis H_job_ready : work_bearing_readiness arr_seq sched.
+
+  (** ... and assume that the schedule is valid. *)
+  Hypothesis H_sched_valid : valid_schedule sched arr_seq.
+
+  (** Assume that jobs have bounded non-preemptive segments. *)
+  Context `{JobPreemptable Job}.
+  Context `{TaskMaxNonpreemptiveSegment Task}.
+  Hypothesis H_valid_preemption_model : valid_preemption_model arr_seq sched.
+  Hypothesis H_valid_model_with_bounded_nonpreemptive_segments :
+    valid_model_with_bounded_nonpreemptive_segments arr_seq sched.
+
+  (** Furthermore, we assume that the schedule is work-conserving ... *)
+  Hypothesis H_work_conserving : work_conserving arr_seq sched.
+
+  (** ... and that it respects the scheduling policy. *)
+  Hypothesis H_respects_policy :
+    respects_JLFP_policy_at_preemption_point arr_seq sched JLFP.
+
+  (** Recall that [busy_intervals_are_bounded_by] is an abstract
+      notion. Hence, we need to introduce interference and interfering
+      workload. We will use the restricted-supply instantiations. *)
+
+  (** We say that job [j] incurs interference at time [t] iff it
+      cannot execute due to (1) the lack of supply at time [t], (2)
+      service inversion (i.e., a lower-priority job receiving service
+      at [t]), or a higher-or-equal-priority job receiving service. *)
+  #[local] Instance rs_jlfp_interference : Interference Job :=
+    rs_jlfp_interference arr_seq sched.
+
+  (** The interfering workload, in turn, is defined as the sum of the
+      blackout predicate, service inversion predicate, and the
+      interfering workload of jobs with higher or equal priority. *)
+  #[local] Instance rs_jlfp_interfering_workload : InterferingWorkload Job :=
+    rs_jlfp_interfering_workload arr_seq sched.
+
+  (** Consider an arbitrary task set [ts], ... *)
+  Variable ts : list Task.
+
+  (** ... assume that all jobs come from the task set, ... *)
+  Hypothesis H_all_jobs_from_taskset : all_jobs_from_taskset arr_seq ts.
+
+  (** ... and that the cost of a job does not exceed its task's WCET. *)
+  Hypothesis H_valid_job_cost : arrivals_have_valid_job_costs arr_seq.
+
+  (** Consider a unit SBF valid in busy intervals. That is, (1) [SBF 0
+      = 0], (2) for any duration [Δ], the supply produced during a
+      busy-interval prefix of length [Δ] is at least [SBF Δ], and (3)
+      [SBF] makes steps of at most one. *)
+  Context {SBF : SupplyBoundFunction}.
+  Hypothesis H_valid_SBF : valid_busy_sbf arr_seq sched SBF.
+  Hypothesis H_unit_SBF : unit_supply_bound_function SBF.
+
+  (** Let [max_arrivals] be a family of valid arrival curves. *)
+  Context `{MaxArrivals Task}.
+  Hypothesis H_is_arrival_curve : taskset_respects_max_arrivals arr_seq ts.
+
+  (** Let [tsk] be any task in [ts] that is to be analyzed. *)
+  Variable tsk : Task.
+  Hypothesis H_tsk_in_ts : tsk \in ts.
+
+  (** Let [blocking_bound] be a function that bounds the priority
+      inversion caused by lower-priority jobs, where the argument
+      [blocking_bound] takes is the relative offset (w.r.t. the
+      beginning of the corresponding busy interval) of a job to be
+      analyzed. *)
+  Variable blocking_bound : (* A *) duration -> duration.
+
+  (** Assume that the maximum length of a nonpreemptive segment is
+      bounded by the blocking bound, ... *)
+  Hypothesis H_priority_inversion_is_bounded_by_blocking :
+    forall j t1 t2,
+      arrives_in arr_seq j ->
+      job_of_task tsk j ->
+      busy_interval_prefix arr_seq sched j t1 t2 ->
+      max_lp_nonpreemptive_segment arr_seq j t1 <= blocking_bound (job_arrival j - t1).
+
+  (** ... and that [blocking_bound 0] is maximum. *)
+  Hypothesis H_blocking_bound_max :
+    forall A, blocking_bound 0 >= blocking_bound A.
+
+  (** Let [L] be any positive fixed point of busy-interval recurrence
+      [blocking_bound 0 + total_rbf ts L <= SBF L]. *)
+  Variable L : duration.
+  Hypothesis H_L_positive : 0 < L.
+  Hypothesis H_fixed_point :
+    blocking_bound 0 + total_request_bound_function ts L <= SBF L.
+
+  (** Next, we provide a step-by-step proof of busy-interval boundedness. *)
+  Section StepByStepProof.
+
+    (** Consider any job [j] of task [tsk] that has a positive job
+        cost and is in the arrival sequence. *)
+    Variable j : Job.
+    Hypothesis H_j_arrives : arrives_in arr_seq j.
+    Hypothesis H_job_of_tsk : job_of_task tsk j.
+    Hypothesis H_job_cost_positive : job_cost_positive j.
+
+    (** We consider two cases: (1) when the busy-interval prefix
+        continues until time instant [t1 + L] and (2) when the busy
+        interval prefix terminates earlier. In either case, we can
+        show that the busy-interval prefix is bounded. *)
+
+    (** We start with the first case, where the busy-interval prefix
+        continues until time instant [t1 + L]. *)
+    Section Case1.
+
+      (** Consider a time instant [t1] such that <<[t1, job_arrival
+          j]>> and <<[t1, t1 + L)>> are both busy-interval prefixes of
+          job [j].
+
+          Note that at this point we do not necessarily know that
+          [job_arrival j <= L]; hence, in this section (only), we
+          assume the existence of both prefixes. *)
+      Variable t1 : instant.
+      Hypothesis H_busy_prefix_arr : busy_interval_prefix arr_seq sched j t1 (job_arrival j).+1.
+      Hypothesis H_busy_prefix_L : busy_interval_prefix arr_seq sched j t1 (t1 + L).
+
+      (** The crucial point to note is that the sum of the job's cost
+          (represented as [workload_of_job]) and the interfering
+          workload in the interval <<[t1, t1 + L)>> is bounded by [L]
+          due to the fixed point [H_fixed_point]. *)
+      Local Lemma workload_is_bounded :
+        workload_of_job arr_seq j t1 (t1 + L) + cumulative_interfering_workload j t1 (t1 + L) <= L.
+      Proof.
+        rewrite (cumulative_interfering_workload_split _ _ _).
+        rewrite (leqRW (blackout_during_bound _ _ _ _ _ _ _ _ _ _ _ _)); (try apply H_busy_prefix_L) => //.
+        rewrite // addnC -!addnA.
+        have E: forall a b c, a <= c -> b <= c - a -> a + b <= c by move => ? ? ? ? ?; lia.
+        apply: E; first by lia.
+        rewrite subKn; last by apply: sbf_bounded_by_duration => //.
+        rewrite -(leqRW H_fixed_point); apply leq_add.
+        - apply: leq_trans; first apply: service_inversion_is_bounded => //.
+          by apply H_blocking_bound_max.
+        - rewrite addnC cumulative_iw_hep_eq_workload_of_ohep workload_job_and_ahep_eq_workload_hep //.
+          by apply hep_workload_le_total_rbf.
+      Qed.
+
+      (** It follows that [t1 + L] is a quiet time, which means that
+          the busy prefix ends (i.e., it is bounded). *)
+      Local Lemma busy_prefix_is_bounded_case1 :
+        exists t2,
+          job_arrival j < t2
+          /\ t2 <= t1 + L
+          /\ busy_interval arr_seq sched j t1 t2.
+      Proof.
+        have PEND : pending sched j (job_arrival j) by apply job_pending_at_arrival => //.
+        enough(exists t2, job_arrival j < t2 /\ t2 <= t1 + L /\ definitions.busy_interval sched j t1 t2) as BUSY.
+        { have [t2 [LE1 [LE2 BUSY2]]] := BUSY.
+          eexists; split; first by exact: LE1.
+          split; first by done.
+          by apply instantiated_busy_interval_equivalent_busy_interval.
+        }
+        eapply busy_interval.busy_interval_is_bounded; eauto 2 => //.
+        - by apply unit_supply_is_unit_service.
+        - by eapply instantiated_i_and_w_no_speculative_execution; eauto 2 => //.
+        - by eapply instantiated_i_and_w_are_coherent_with_schedule; eauto 2 => //.
+        - by apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix => //.
+        - by apply workload_is_bounded => //.
+      Qed.
+
+    End Case1.
+
+    (** Next, we consider the case when the interval <<[t1, t1 + L)>>
+        is not a busy-interval prefix. *)
+    Section Case2.
+
+      (** Consider a time instant [t1] such that <<[t1, job_arrival
+          j]>> is a busy-interval prefix of [j] and <<[t1, t1 + L)>>
+          is _not_. *)
+      Variable t1 : instant.
+      Hypothesis H_arrives : t1 <= job_arrival j.
+      Hypothesis H_busy_prefix_arr : busy_interval_prefix arr_seq sched j t1 (job_arrival j).+1.
+      Hypothesis H_no_busy_prefix_L : ~ busy_interval_prefix arr_seq sched j t1 (t1 + L).
+
+      (** From the properties of busy intervals, one can conclude that
+          [j]'s arrival time is less than [t1 + L]. *)
+      Local Lemma job_arrival_is_bounded :
+        job_arrival j < t1 + L.
+      Proof.
+        move_neq_up FF.
+        move: (H_busy_prefix_arr) (H_busy_prefix_arr) => PREFIX PREFIXA.
+        apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix in PREFIXA => //.
+        move: (PREFIXA) => GTC.
+        eapply workload_exceeds_interval with (Δ := L) in PREFIX => //.
+        { move_neq_down PREFIX.
+          rewrite (cumulative_interfering_workload_split _ _ _).
+          (rewrite (leqRW (blackout_during_bound _ _ _ _ _ _ _ _ _ _ _ _)); try apply GTC) => //; first last.
+          { move=> *; split; first by apply H_valid_SBF.
+            move => *; destruct H_valid_SBF as [A B].
+            apply: B => //.
+            by apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix => //.
+          }
+          rewrite addnC -!addnA.
+          have E: forall a b c, a <= c -> b <= c - a -> a + b <= c by move => ? ? ? ? ?; lia.
+          apply: E; first by lia.
+          rewrite subKn; last by apply: sbf_bounded_by_duration => //.
+          rewrite -(leqRW H_fixed_point); apply leq_add.
+          { rewrite (leqRW (service_inversion_widen _ _ _ t1 _ _ (job_arrival j).+1 _ _ )).
+            - apply: leq_trans.
+              + by apply: service_inversion_is_bounded => //.
+              + by apply H_blocking_bound_max.
+            - by done.
+            - by lia.
+          }
+          { rewrite addnC cumulative_iw_hep_eq_workload_of_ohep workload_job_and_ahep_eq_workload_hep //.
+            by apply hep_workload_le_total_rbf.
+          }
+        }
+      Qed.
+
+      (** Lemma [job_arrival_is_bounded] implies that the
+          busy-interval prefix starts at time [t1], continues until
+          [job_arrival j + 1], and then terminates before [t1 + L].
+          Or, in other words, there is point in time [t2] such that
+          (1) [j]'s arrival is bounded by [t2], (2) [t2] is bounded by
+          [t1 + L], and (3) <<[t1, t2)>> is busy interval of job
+          [j]. *)
+      Local Lemma busy_prefix_is_bounded_case2:
+        exists t2, job_arrival j < t2 /\ t2 <= t1 + L /\ busy_interval arr_seq sched j t1 t2.
+      Proof.
+        have LE: job_arrival j < t1 + L
+          by apply job_arrival_is_bounded => //; try apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix.
+        move: (H_busy_prefix_arr) => PREFIX.
+        move: (H_no_busy_prefix_L) => NOPREF.
+        apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix in PREFIX => //.
+        have BUSY := terminating_busy_prefix_is_busy_interval _ _ _ _ _ _ _ PREFIX.
+        edestruct BUSY as [t2 BUS]; clear BUSY; try apply TSK; eauto 2 => //.
+        { move => T; apply: NOPREF.
+          by apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix in T => //.
+        }
+        exists t2; split; last split.
+        { by move: BUS => [[A _] _]; lia. }
+        { move_neq_up FA.
+          apply: NOPREF; split; [lia | split; first by apply H_busy_prefix_arr].
+          split.
+          - move=> t NEQ.
+            apply abstract_busy_interval_classic_busy_interval_prefix in BUS => //.
+            by apply BUS; lia.
+          - by lia.
+        }
+        { by apply instantiated_busy_interval_equivalent_busy_interval => //. }
+      Qed.
+
+    End Case2.
+
+  End StepByStepProof.
+
+  (** Combining the cases analyzed above, we conclude that busy
+      intervals of jobs released by task [tsk] are bounded by [L].  *)
+  Lemma busy_intervals_are_bounded_rs_jlfp :
+    busy_intervals_are_bounded_by arr_seq sched tsk L.
+  Proof.
+    move => j ARR TSK POS.
+    have PEND : pending sched j (job_arrival j) by apply job_pending_at_arrival => //.
+    edestruct ( busy_interval_prefix_exists) as [t1 [GE PREFIX]]; eauto 2.
+    exists t1.
+    enough(exists t2, job_arrival j < t2 /\ t2 <= t1 + L /\ busy_interval arr_seq sched j t1 t2) as BUSY.
+    { move: BUSY => [t2 [LT [LE BUSY]]]; eexists; split; last first.
+      { split; first by exact: LE.
+        by apply instantiated_busy_interval_equivalent_busy_interval. }
+      { by apply/andP; split. }
+    }
+    { have [LPREF|NOPREF] := busy_interval_prefix_case ltac:(eauto) j t1 (t1 + L).
+      { apply busy_prefix_is_bounded_case1 => //.
+        by apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix => //. }
+      { apply busy_prefix_is_bounded_case2=> //.
+        move=> NP; apply: NOPREF.
+        by apply instantiated_busy_interval_prefix_equivalent_busy_interval_prefix => //.
+      }
+    }
+  Qed.
+
+End BoundedBusyIntervals.
-- 
GitLab