diff --git a/analysis/facts/behavior/arrivals.v b/analysis/facts/behavior/arrivals.v index 64b99683907524336202a150b4d220666cc07321..31612165f0a8d3fbb4ceb8326fe2a307eed0a1f7 100644 --- a/analysis/facts/behavior/arrivals.v +++ b/analysis/facts/behavior/arrivals.v @@ -93,6 +93,19 @@ Section Arrived. now apply ready_implies_arrived. Qed. + (** Similarly, since backlogged jobs are by definition pending, any + backlogged job must be incomplete. *) + Lemma backlogged_implies_incomplete: + forall j t, + backlogged sched j t -> ~~ completed_by sched j t. + Proof. + move=> j t BACK. + have suff: pending sched j t. + - by move /andP => [_ INCOMP]. + - apply; move: BACK => /andP [READY _]. + by apply any_ready_job_is_pending. + Qed. + End Arrived. (** In this section, we establish useful facts about arrival sequence prefixes. *) diff --git a/analysis/facts/behavior/completion.v b/analysis/facts/behavior/completion.v index d7b3e2171b504b50292752bc84964805706b2028..eaf7c733f2dce11d445c371f5c05fc0c0c6bb018 100644 --- a/analysis/facts/behavior/completion.v +++ b/analysis/facts/behavior/completion.v @@ -1,12 +1,13 @@ Require Export prosa.analysis.facts.behavior.service. Require Export prosa.analysis.facts.behavior.arrivals. Require Export prosa.analysis.definitions.schedule_prefix. +Require Export prosa.analysis.definitions.job_properties. (** * Completion *) (** In this file, we establish basic facts about job completions. *) Section CompletionFacts. - + (** Consider any job type,...*) Context {Job: JobType}. Context `{JobCost Job}. @@ -18,10 +19,10 @@ Section CompletionFacts. (** ...and a given schedule. *) Variable sched: schedule PState. - (** Let j be any job that is to be scheduled. *) + (** Let [j] be any job that is to be scheduled. *) Variable j: Job. - (** We prove that after job j completes, it remains completed. *) + (** We prove that after job [j] completes, it remains completed. *) Lemma completion_monotonic: forall t t', t <= t' -> @@ -33,6 +34,19 @@ Section CompletionFacts. by apply service_monotonic. Qed. + (** We prove that if [j] is not completed by [t'], then it's also not + completed by any earlier instant. *) + Lemma incompletion_monotonic: + forall t t', + t <= t' -> + ~~ completed_by sched j t' -> + ~~ completed_by sched j t. + Proof. + move => t t' LE. + apply contra. + by apply completion_monotonic. + Qed. + (** We observe that being incomplete is the same as not having received sufficient service yet... *) Lemma less_service_than_cost_is_incomplete: @@ -52,6 +66,19 @@ Section CompletionFacts. move=> t. by split; rewrite /remaining_cost -less_service_than_cost_is_incomplete subn_gt0 //. Qed. + (** Trivially, it follows that an incomplete job has a positive cost. *) + Corollary incomplete_implies_positive_cost: + forall t, + ~~ completed_by sched j t -> + job_cost_positive j. + Proof. + move=> t INCOMP. + apply: (ltn_leq_trans _); + last by apply leq_subr. + apply incomplete_is_positive_remaining_cost. + exact INCOMP. + Qed. + (** Assume that completed jobs do not execute. *) Hypothesis H_completed_jobs: completed_jobs_dont_execute sched. diff --git a/analysis/facts/behavior/deadlines.v b/analysis/facts/behavior/deadlines.v index a657981925d24ea609c1f8bded4711ab2e35124b..4332b86b270b81f8b66efd2148c94b4f9e655be5 100644 --- a/analysis/facts/behavior/deadlines.v +++ b/analysis/facts/behavior/deadlines.v @@ -5,7 +5,7 @@ Require Export prosa.analysis.facts.behavior.completion. (** In this file, we observe basic properties of the behavioral job model w.r.t. deadlines. *) Section DeadlineFacts. - + (** Consider any given type of jobs with costs and deadlines... *) Context {Job : JobType} `{JobCost Job} `{JobDeadline Job}. @@ -13,8 +13,51 @@ Section DeadlineFacts. Context {PState: eqType}. Context `{ProcessorState Job PState}. - (** We begin with schedules / processor models in which scheduled jobs - always receive service. *) + (** First, we derive two properties from the fact that a job is incomplete at + some point in time. *) + Section Incompletion. + + (** Consider any given schedule. *) + Variable sched: schedule PState. + + (** Trivially, a job that both meets its deadline and is incomplete at a + time [t] must have a deadline later than [t]. *) + Lemma incomplete_implies_later_deadline: + forall j t, + job_meets_deadline sched j -> + ~~ completed_by sched j t -> + t < job_deadline j. + Proof. + move=> j t MET INCOMP. + apply contraT; rewrite -leqNgt => PAST_DL. + have DL_MISS: ~~ completed_by sched j (job_deadline j) + by apply incompletion_monotonic with (t' := t) => //. + by move: DL_MISS => /negP. + Qed. + + (** Furthermore, a job that both meets its deadline and is incomplete at a + time [t] must be scheduled at some point between [t] and its + deadline. *) + Lemma incomplete_implies_scheduled_later: + forall j t, + job_meets_deadline sched j -> + ~~ completed_by sched j t -> + exists t', t <= t' < job_deadline j /\ scheduled_at sched j t'. + Proof. + move=> j t MET INCOMP. + apply: cumulative_service_implies_scheduled. + rewrite -(ltn_add2l (service sched j t)) addn0. + rewrite service_cat; + last by (apply ltnW; apply incomplete_implies_later_deadline). + apply ltn_leq_trans with (n := job_cost j); + first by rewrite less_service_than_cost_is_incomplete. + by apply MET. + Qed. + + End Incompletion. + + (** Next, we look at schedules / processor models in which scheduled jobs + always receive service. *) Section IdealProgressSchedules. (** Consider a given reference schedule... *) @@ -26,26 +69,19 @@ Section DeadlineFacts. (** ...and scheduled jobs always receive service. *) Hypothesis H_scheduled_implies_serviced: ideal_progress_proc_model PState. - (** We observe that, if a job is known to meet its deadline, then - its deadline must be later than any point at which it is - scheduled. That is, if a job that meets its deadline is - scheduled at time t, we may conclude that its deadline is at a - time later than t. *) + (** We observe that if a job meets its deadline and is scheduled at time + [t], then then its deadline is at a time later than t. *) Lemma scheduled_at_implies_later_deadline: forall j t, job_meets_deadline sched j -> scheduled_at sched j t -> t < job_deadline j. Proof. - move=> j t. - rewrite /job_meets_deadline => COMP SCHED. - case: (boolP (t < job_deadline j)) => //. - rewrite -leqNgt => AFTER_DL. - apply completion_monotonic with (t' := t) in COMP => //. - apply scheduled_implies_not_completed in SCHED => //. - move/negP in SCHED. contradiction. + move=> j t MET SCHED_AT. + apply (incomplete_implies_later_deadline sched) => //. + by apply scheduled_implies_not_completed. Qed. - + End IdealProgressSchedules. (** In the following section, we observe that it is sufficient to diff --git a/analysis/facts/edf_definitions.v b/analysis/facts/edf_definitions.v new file mode 100644 index 0000000000000000000000000000000000000000..f7d992c2fdc738424fcb811f9bd6eda1a375f6a8 --- /dev/null +++ b/analysis/facts/edf_definitions.v @@ -0,0 +1,105 @@ +Require Export prosa.analysis.facts.model.ideal_schedule. +Require Export prosa.analysis.facts.behavior.deadlines. +Require Export prosa.analysis.definitions.schedulability. +Require Export prosa.model.priority.edf. +Require Export prosa.model.schedule.edf. +Require Export prosa.model.schedule.priority_driven. + +(** * Equivalence of EDF Definitions *) + +(** Recall that we have defined "EDF schedules" in two ways. + + The generic way to define an EDF schedule is by using the EDF priority + policy defined in [model.priority.edf] and the general notion of + priority-compliant schedules defined in [model.schedule.priority_driven]. + + Another, more straight-forward way to define an EDF schedule is the standalone + definition given in [model.schedule.edf], which is less general but simpler + and used in the EDF optimality proof. + + In this file, we show that both definitions are equivalent assuming: + + (1) ideal uniprocessor schedules, ... *) +Require Import prosa.model.processor.ideal. + +(** ... (2) the classic Liu & Layland model of readiness without jitter and + without self-suspensions, where pending jobs are always ready, and ... *) +Require Import prosa.model.readiness.basic. + +(** ... (3) that jobs are fully preemptive. *) +Require Import prosa.model.preemption.fully_preemptive. + +Section Equivalence. + + (** For any given type of jobs, each characterized by an arrival time, + an execution cost, and an absolute deadline, ... *) + Context {Job : JobType} `{JobCost Job} `{JobDeadline Job} `{JobArrival Job}. + + (** ...consider a given valid job arrival sequence ... *) + Variable arr_seq: arrival_sequence Job. + Hypothesis H_arr_seq_valid: valid_arrival_sequence arr_seq. + + (** ...and a corresponding schedule. *) + Variable sched : schedule (ideal.processor_state Job). + + (** Suppose jobs don't execute after their completion, ... *) + Hypothesis H_completed_jobs_dont_execute: completed_jobs_dont_execute sched. + + (** ...all jobs come from the arrival sequence [arr_seq], ...*) + Hypothesis H_from_arr_seq: jobs_come_from_arrival_sequence sched arr_seq. + + (** ...and jobs from [arr_seq] don't miss their deadlines. *) + Hypothesis H_no_deadline_misses: all_deadlines_of_arrivals_met arr_seq sched. + + (** We first show that a schedule that satisfies the standalone + [EDF_schedule] predicate is also compliant with the generic notion of EDF + policy defined in Prosa, namely the [respects_policy_at_preemption_point] + predicate. *) + Lemma EDF_schedule_implies_respects_policy_at_preemption_point : + EDF_schedule sched -> + respects_policy_at_preemption_point arr_seq sched. + Proof. + move=> EDF j' j t ARR PREEMPTION BL SCHED. + have suff: exists t' : nat, t <= t' < job_deadline j' /\ scheduled_at sched j' t'. + { move=> [t' [/andP [LE _] SCHED']]. + apply: (EDF t); [done | exact LE | exact SCHED' |]. + by apply: (backlogged_implies_arrived sched j' t). } + apply; apply: incomplete_implies_scheduled_later; + first by apply: H_no_deadline_misses => //. + by apply: (backlogged_implies_incomplete sched j' t). + Qed. + + (** Conversely, the reverse direction also holds: a schedule that satisfies + the [respects_policy_at_preemption_point] predicate is also an EDF + schedule in the sense of [EDF_schedule]. *) + Lemma respects_policy_at_preemption_point_implies_EDF_schedule : + respects_policy_at_preemption_point arr_seq sched -> + EDF_schedule sched. + Proof. + move=> H_priority_driven t j_hp SCHED t' j LEQ SCHED' EARLIER_ARR. + case (boolP (j == j_hp)); first by move /eqP => EQ; subst. + move /neqP => NEQ. + exploit (H_priority_driven j j_hp t) => //. + { by apply (H_from_arr_seq _ _ SCHED'). } + { by rewrite /preemption_time; destruct (sched t). } + { apply /andP; split => //. + - apply /andP; split => //. + apply (incompletion_monotonic _ j _ _ LEQ). + apply scheduled_implies_not_completed => //. + by apply ideal_proc_model_ensures_ideal_progress. + - apply /negP; move => SCHED''. + by exploit (ideal_proc_model_is_a_uniprocessor_model j j_hp sched t). } + Qed. + + (** From the two preceding lemmas, it follows immediately that the two EDF + definitions are indeed equivalent, which we note with the following + corollary. *) + Corollary EDF_schedule_equiv: + EDF_schedule sched <-> respects_policy_at_preemption_point arr_seq sched. + Proof. + split. + - by apply EDF_schedule_implies_respects_policy_at_preemption_point. + - by apply respects_policy_at_preemption_point_implies_EDF_schedule. + Qed. + +End Equivalence. diff --git a/results/edf/optimality.v b/results/edf/optimality.v index 4246df6ad7a96f1036a2d451bb80dd1eff776c9b..adaaf40f0e0027fe1d46f2ea5ca2e207c4414c38 100644 --- a/results/edf/optimality.v +++ b/results/edf/optimality.v @@ -1,5 +1,6 @@ Require Export prosa.analysis.facts.transform.edf_opt. Require Export prosa.analysis.facts.transform.edf_wc. +Require Export prosa.analysis.facts.edf_definitions. (** * Optimality of EDF on Ideal Uniprocessors *) @@ -8,11 +9,15 @@ Require Export prosa.analysis.facts.transform.edf_wc. schedule), then there is also an (ideal) EDF schedule in which all deadlines are met. *) -(** The following results assume ideal uniprocessor schedules... *) +(** The following results assume ideal uniprocessor schedules,... *) Require prosa.model.processor.ideal. -(** ... and the basic (i.e., Liu & Layland) readiness model under which any - pending job is always ready. *) +(** ... the basic (i.e., Liu & Layland) readiness model under which any + pending job is always ready, ... *) Require prosa.model.readiness.basic. +(** ... the EDF priority policy, ... *) +Require prosa.model.priority.edf. +(** ...and a fully preemptive job model. *) +Require prosa.model.preemption.fully_preemptive. (** ** Optimality Theorem *) @@ -26,7 +31,7 @@ Section Optimality. Hypothesis H_arr_seq_valid: valid_arrival_sequence arr_seq. (** We observe that EDF is optimal in the sense that, if there exists - any schedule in which all jobs of arr_seq meet their deadline, + any schedule in which all jobs of [arr_seq] meet their deadline, then there also exists an EDF schedule in which all deadlines are met. *) Theorem EDF_optimality: @@ -87,6 +92,33 @@ Section Optimality. [EDF_WC_optimality]. We nonetheless have two separate proofs for historic reasons as [EDF_optimality] predates [EDF_WC_optimality] (in Prosa). *) + (** Finally, we state the optimality theorem also in terms of a + policy-compliant schedule, which a more generic notion used in Prosa for + scheduling policies (rather than the simpler, but ad-hoc + [EDF_schedule] predicate used above). + + Given that we're considering the EDF priority policy and a fully + preemptive job model, satisfying the [EDF_schedule] predicate is + equivalent to satisfying the [respects_policy_at_preemption_point] + w.r.t. to the EDF policy predicate. The optimality of priority-compliant + schedules that are work-conserving follows hence directly from the above + [EDF_WC_optimality] theorem. *) + Corollary EDF_priority_compliant_WC_optimality: + (exists any_sched : schedule (ideal.processor_state Job), + valid_schedule any_sched arr_seq /\ + all_deadlines_of_arrivals_met arr_seq any_sched) -> + exists priority_compliant_sched : schedule (ideal.processor_state Job), + valid_schedule priority_compliant_sched arr_seq /\ + all_deadlines_of_arrivals_met arr_seq priority_compliant_sched /\ + work_conserving arr_seq priority_compliant_sched /\ + respects_policy_at_preemption_point arr_seq priority_compliant_sched. + Proof. + move /EDF_WC_optimality => [edf_sched [[ARR READY] [DL_MET [WC EDF]]]]. + exists edf_sched. + apply (EDF_schedule_equiv arr_seq _) in EDF => //. + now apply (completed_jobs_are_not_ready edf_sched READY). + Qed. + End Optimality. (** ** Weak Optimality Theorem *) diff --git a/scripts/wordlist.pws b/scripts/wordlist.pws index 3df9e5318c4eff68edc4a31cb98e17e613f9b830..70f856d506ea4753f224c4652ac205307ed82cb0 100644 --- a/scripts/wordlist.pws +++ b/scripts/wordlist.pws @@ -60,4 +60,7 @@ RTCT superadditivity superadditive subadditivity -subadditive \ No newline at end of file +subadditive +ad +hoc +