# Library prosa.analysis.facts.busy_interval.priority_inversion

Require Export prosa.model.task.preemption.parameters.

Require Export prosa.model.schedule.priority_driven.

Require Export prosa.model.schedule.work_conserving.

Require Export prosa.analysis.definitions.job_properties.

Require Export prosa.analysis.definitions.busy_interval.

Require Export prosa.analysis.facts.model.ideal.schedule.

Require Export prosa.analysis.facts.busy_interval.busy_interval.

Require Export prosa.analysis.facts.model.preemption.

Require Export prosa.analysis.facts.behavior.completion.

Require Export prosa.model.schedule.priority_driven.

Require Export prosa.model.schedule.work_conserving.

Require Export prosa.analysis.definitions.job_properties.

Require Export prosa.analysis.definitions.busy_interval.

Require Export prosa.analysis.facts.model.ideal.schedule.

Require Export prosa.analysis.facts.busy_interval.busy_interval.

Require Export prosa.analysis.facts.model.preemption.

Require Export prosa.analysis.facts.behavior.completion.

Throughout this file, we assume ideal uni-processor schedules.

# Priority inversion is bounded

In this module we prove that any priority inversion that occurs in the model with bounded nonpreemptive segments defined in module prosa.model.schedule.uni.limited.platform.definitions is bounded.
Consider any type of tasks ...

... and any type of jobs associated with these tasks.

Context {Job : JobType}.

Context `{JobTask Job Task}.

Context `{Arrival : JobArrival Job}.

Context `{Cost : JobCost Job}.

Context `{JobTask Job Task}.

Context `{Arrival : JobArrival Job}.

Context `{Cost : JobCost Job}.

Consider any arrival sequence with consistent arrivals ...

Variable arr_seq : arrival_sequence Job.

Hypothesis H_arrival_times_are_consistent : consistent_arrival_times arr_seq.

Hypothesis H_arrival_times_are_consistent : consistent_arrival_times arr_seq.

... and any ideal uniprocessor schedule of this arrival sequence.

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_priorities.

Hypothesis H_priority_is_transitive: transitive_priorities.

Hypothesis H_priority_is_reflexive: reflexive_priorities.

Hypothesis H_priority_is_transitive: transitive_priorities.

In addition, we assume the existence of a function mapping a
task to its maximal non-preemptive segment ...

... and the existence of a function mapping a job and its
progress to a boolean value saying whether this job is
preemptable at its current point of execution.

And assume that they define a valid preemption model with
bounded nonpreemptive segments.

Hypothesis H_valid_model_with_bounded_nonpreemptive_segments:

valid_model_with_bounded_nonpreemptive_segments arr_seq sched.

valid_model_with_bounded_nonpreemptive_segments arr_seq sched.

Further, allow for any work-bearing notion of job readiness.

Context `{@JobReady Job (ideal.processor_state Job) Cost Arrival}.

Hypothesis H_job_ready : work_bearing_readiness arr_seq sched.

Hypothesis H_job_ready : work_bearing_readiness arr_seq sched.

We assume that the schedule is valid and that all jobs come from the arrival sequence.

Hypothesis H_sched_valid : valid_schedule sched arr_seq.

Hypothesis H_jobs_come_from_arrival_sequence: jobs_come_from_arrival_sequence sched arr_seq.

Hypothesis H_jobs_come_from_arrival_sequence: jobs_come_from_arrival_sequence sched arr_seq.

Next, we assume that the schedule is a work-conserving schedule...

... and the schedule respects the policy defined by the
predicate job_preemptable (i.e., bounded nonpreemptive
segments).

Let's define some local names for clarity.

Finally, we introduce the notion of the maximal length of
(potential) priority inversion at a time instant t, which is
defined as the maximum length of nonpreemptive segments among
all jobs that arrived so far.

Definition max_length_of_priority_inversion (j : Job) (t : instant) :=

\max_(j_lp <- arrivals_before arr_seq t | (~~ hep_job j_lp j) && (job_cost j_lp > 0))

(job_max_nonpreemptive_segment j_lp - ε).

\max_(j_lp <- arrivals_before arr_seq t | (~~ hep_job j_lp j) && (job_cost j_lp > 0))

(job_max_nonpreemptive_segment j_lp - ε).

Next we prove that a priority inversion of a job is bounded by
function max_length_of_priority_inversion.
Note that any bound on function
max_length_of_priority_inversion will also be a bound on the
maximal priority inversion. This bound may be different for
different scheduler and/or task models. Thus, we don't define
such a bound in this module.
Consider any job j of tsk with positive job cost.

Variable j : Job.

Hypothesis H_j_arrives : arrives_in arr_seq j.

Hypothesis H_job_cost_positive : job_cost_positive j.

Hypothesis H_j_arrives : arrives_in arr_seq j.

Hypothesis H_job_cost_positive : job_cost_positive j.

Consider any busy interval prefix

`[t1, t2)`

of job j.
Variable t1 t2 : instant.

Hypothesis H_busy_interval_prefix:

busy_interval_prefix arr_seq sched j t1 t2.

Hypothesis H_busy_interval_prefix:

busy_interval_prefix arr_seq sched j t1 t2.

# Processor Executes HEP jobs after Preemption Point

In this section, we prove that at any time instant after any preemption point (inside the busy interval), the processor is always busy scheduling a job with higher or equal priority.
First, we show that the processor at any preemptive point is always
busy scheduling a job with higher or equal priority.

Consider an arbitrary preemption time t ∈

`[t1,t2)`

.
Variable t : instant.

Hypothesis H_t_in_busy_interval : t1 ≤ t < t2.

Hypothesis H_t_preemption_time : preemption_time sched t.

Hypothesis H_t_in_busy_interval : t1 ≤ t < t2.

Hypothesis H_t_preemption_time : preemption_time sched t.

In case when t < t2 - 1, we use the fact that time instant
t+1 is not a quiet time. The later implies that there is a
pending higher-or-equal priority job at time t. Thus, the
assumption that the schedule respects priority policy at
preemption points implies that the scheduled job must have a
higher-or-equal priority.

Lemma scheduled_at_preemption_time_implies_higher_or_equal_priority_lt:

t < t2.-1 →

∀ jhp,

scheduled_at sched jhp t →

hep_job jhp j.

t < t2.-1 →

∀ jhp,

scheduled_at sched jhp t →

hep_job jhp j.

In case when t = t2 - 1, we cannot use the same proof
since t+1 = t2, but t2 is a quiet time. So we do a
similar case analysis on the fact that t1 = t ∨ t1 < t.

Lemma scheduled_at_preemption_time_implies_higher_or_equal_priority_eq:

t = t2.-1 →

∀ jhp,

scheduled_at sched jhp t →

hep_job jhp j.

t = t2.-1 →

∀ jhp,

scheduled_at sched jhp t →

hep_job jhp j.

By combining the above facts we conclude that a job that is
scheduled at time t has higher-or-equal priority.

Corollary scheduled_at_preemption_time_implies_higher_or_equal_priority:

∀ jhp,

scheduled_at sched jhp t →

hep_job jhp j.

∀ jhp,

scheduled_at sched jhp t →

hep_job jhp j.

Since a job that is scheduled at time t has higher-or-equal priority,
by properties of a busy interval it cannot arrive before time instant t1.

Lemma scheduled_at_preemption_time_implies_arrived_between_within_busy_interval:

∀ jhp,

scheduled_at sched jhp t →

arrived_between jhp t1 t2.

∀ jhp,

scheduled_at sched jhp t →

arrived_between jhp t1 t2.

From the above lemmas we prove that there is a job jhp that is (1) scheduled at time t,
(2) has higher-or-equal priority, and (3) arrived between t1 and t2.

Corollary not_quiet_implies_exists_scheduled_hp_job_at_preemption_point:

∃ j_hp,

arrived_between j_hp t1 t2 ∧

hep_job j_hp j ∧

job_scheduled_at j_hp t.

End ProcessorBusyWithHEPJobAtPreemptionPoints.

∃ j_hp,

arrived_between j_hp t1 t2 ∧

hep_job j_hp j ∧

job_scheduled_at j_hp t.

End ProcessorBusyWithHEPJobAtPreemptionPoints.

... and the fact that at any time instant after a preemption point the
processor is always busy with a job with higher or equal priority.

Lemma not_quiet_implies_exists_scheduled_hp_job_after_preemption_point:

∀ tp t,

preemption_time sched tp →

t1 ≤ tp < t2 →

tp ≤ t < t2 →

∃ j_hp,

arrived_between j_hp t1 t.+1 ∧

hep_job j_hp j ∧

job_scheduled_at j_hp t.

∀ tp t,

preemption_time sched tp →

t1 ≤ tp < t2 →

tp ≤ t < t2 →

∃ j_hp,

arrived_between j_hp t1 t.+1 ∧

hep_job j_hp j ∧

job_scheduled_at j_hp t.

Now, suppose there exists some constant K that bounds the distance to
a preemption time from the beginning of the busy interval.

Variable K : duration.

Hypothesis H_preemption_time_exists:

∃ pr_t, preemption_time sched pr_t ∧ t1 ≤ pr_t ≤ t1 + K.

Hypothesis H_preemption_time_exists:

∃ pr_t, preemption_time sched pr_t ∧ t1 ≤ pr_t ≤ t1 + K.

Then we prove that the processor is always busy with a job with
higher-or-equal priority after time instant t1 + K.

Lemma not_quiet_implies_exists_scheduled_hp_job:

∀ t,

t1 + K ≤ t < t2 →

∃ j_hp,

arrived_between j_hp t1 t.+1 ∧

hep_job j_hp j ∧

job_scheduled_at j_hp t.

End PreemptionTimeAndPriorityInversion.

∀ t,

t1 + K ≤ t < t2 →

∃ j_hp,

arrived_between j_hp t1 t.+1 ∧

hep_job j_hp j ∧

job_scheduled_at j_hp t.

End PreemptionTimeAndPriorityInversion.

# Preemption Time Exists

In this section we prove that the function max_length_of_priority_inversion indeed upper bounds the priority inversion length.
First we prove that if a job with higher-or-equal priority is scheduled at
a quiet time t+1 then this is the first time when this job is scheduled.

Lemma hp_job_not_scheduled_before_quiet_time:

∀ jhp t,

quiet_time arr_seq sched j t.+1 →

job_scheduled_at jhp t.+1 →

hep_job jhp j →

~~ job_scheduled_at jhp t.

∀ jhp t,

quiet_time arr_seq sched j t.+1 →

job_scheduled_at jhp t.+1 →

hep_job jhp j →

~~ job_scheduled_at jhp t.

Also, we show that lower-priority jobs that are scheduled inside the
busy-interval prefix

`[t1,t2)`

must arrive before that interval.
Lemma low_priority_job_arrives_before_busy_interval_prefix:

∀ jlp t,

t1 ≤ t < t2 →

job_scheduled_at jlp t →

~~ hep_job jlp j →

job_arrival jlp < t1.

∀ jlp t,

t1 ≤ t < t2 →

job_scheduled_at jlp t →

~~ hep_job jlp j →

job_arrival jlp < t1.

Moreover, we show that lower-priority jobs that are scheduled
inside the busy-interval prefix

`[t1,t2)`

must be scheduled
before that interval.
Lemma low_priority_job_scheduled_before_busy_interval_prefix:

∀ jlp t,

t1 ≤ t < t2 →

job_scheduled_at jlp t →

~~ hep_job jlp j →

∃ t', t' < t1 ∧ job_scheduled_at jlp t'.

∀ jlp t,

t1 ≤ t < t2 →

job_scheduled_at jlp t →

~~ hep_job jlp j →

∃ t', t' < t1 ∧ job_scheduled_at jlp t'.

Thus, there must be a preemption time in the interval t1, t1
+ max_priority_inversion t1. That is, if a job with
higher-or-equal priority is scheduled at time instant t1, then
t1 is a preemption time. Otherwise, if a job with lower
priority is scheduled at time t1, then this jobs also should
be scheduled before the beginning of the busy interval. So,
the next preemption time will be no more than
max_priority_inversion t1 time units later.
We proceed by doing a case analysis.

(1) Case when the schedule is idle at time t1.

Assume that the schedule is idle at time t1.

Then time instant t1 is a preemption time.

Lemma preemption_time_exists_case1:

∃ pr_t,

preemption_time sched pr_t ∧

t1 ≤ pr_t ≤ t1 + max_length_of_priority_inversion j t1.

End Case1.

∃ pr_t,

preemption_time sched pr_t ∧

t1 ≤ pr_t ≤ t1 + max_length_of_priority_inversion j t1.

End Case1.

(2) Case when a job with higher-or-equal priority is scheduled at time t1.

Variable jhp : Job.

Hypothesis H_jhp_is_scheduled : scheduled_at sched jhp t1.

Hypothesis H_jhp_hep_priority : hep_job jhp j.

Hypothesis H_jhp_is_scheduled : scheduled_at sched jhp t1.

Hypothesis H_jhp_hep_priority : hep_job jhp j.

Then time instant t1 is a preemption time.

Lemma preemption_time_exists_case2:

∃ pr_t,

preemption_time sched pr_t ∧

t1 ≤ pr_t ≤ t1 + max_length_of_priority_inversion j t1.

End Case2.

∃ pr_t,

preemption_time sched pr_t ∧

t1 ≤ pr_t ≤ t1 + max_length_of_priority_inversion j t1.

End Case2.

(3) Case when a job with lower priority is scheduled at time t1.

Variable jlp : Job.

Hypothesis H_jlp_is_scheduled : scheduled_at sched jlp t1.

Hypothesis H_jlp_low_priority : ~~ hep_job jlp j.

Hypothesis H_jlp_is_scheduled : scheduled_at sched jlp t1.

Hypothesis H_jlp_low_priority : ~~ hep_job jlp j.

To prove the lemma in this case we need a few auxiliary
facts about the first preemption point of job jlp.

Variable fpt : instant.

Hypothesis H_fpt_is_preemptio_point : job_preemptable jlp (progr_t1 + fpt).

Hypothesis H_fpt_is_first_preemption_point:

∀ ρ,

progr_t1 ≤ ρ ≤ progr_t1 + (job_max_nonpreemptive_segment jlp - ε) →

job_preemptable jlp ρ →

service sched jlp t1 + fpt ≤ ρ.

Hypothesis H_fpt_is_preemptio_point : job_preemptable jlp (progr_t1 + fpt).

Hypothesis H_fpt_is_first_preemption_point:

∀ ρ,

progr_t1 ≤ ρ ≤ progr_t1 + (job_max_nonpreemptive_segment jlp - ε) →

job_preemptable jlp ρ →

service sched jlp t1 + fpt ≤ ρ.

For convenience we also assume the following inequality holds.

Hypothesis H_progr_le_max_nonp_segment:

progr_t1 ≤ progr_t1 + fpt ≤ progr_t1 + (job_max_nonpreemptive_segment jlp - ε).

progr_t1 ≤ progr_t1 + fpt ≤ progr_t1 + (job_max_nonpreemptive_segment jlp - ε).

Lemma no_intermediate_preemption_point:

∀ ρ,

progr_t1 ≤ ρ < progr_t1 + fpt →

~~ job_preemptable jlp ρ.

∀ ρ,

progr_t1 ≤ ρ < progr_t1 + fpt →

~~ job_preemptable jlp ρ.

Thanks to the fact that the scheduler respects the notion of preemption points
we show that jlp is continuously scheduled in time interval

`[t1, t1 + fpt)`

.
Lemma continuously_scheduled_between_preemption_points:

∀ t',

t1 ≤ t' < t1 + fpt →

job_scheduled_at jlp t'.

∀ t',

t1 ≤ t' < t1 + fpt →

job_scheduled_at jlp t'.

Thus, job jlp reaches its preemption point at time instant t1 + fpt,
which implies that time instant t1 + fpt is a preemption time.

And since fpt ≤ max_length_of_priority_inversion j t1,
t1 ≤ t1 + fpt ≤ t1 + max_length_of_priority_inversion j t1.

Lemma preemption_time_le_max_len_of_priority_inversion:

t1 ≤ t1 + fpt ≤ t1 + max_length_of_priority_inversion j t1.

End FirstPreemptionPointOfjlp.

t1 ≤ t1 + fpt ≤ t1 + max_length_of_priority_inversion j t1.

End FirstPreemptionPointOfjlp.

Next we combine the facts above to conclude the lemma.

Lemma preemption_time_exists_case3:

∃ pr_t,

preemption_time sched pr_t ∧

t1 ≤ pr_t ≤ t1 + max_length_of_priority_inversion j t1.

End Case3.

End CaseAnalysis.

∃ pr_t,

preemption_time sched pr_t ∧

t1 ≤ pr_t ≤ t1 + max_length_of_priority_inversion j t1.

End Case3.

End CaseAnalysis.

By doing the case analysis, we show that indeed there is a
preemption time in time interval [t1, t1 +
max_length_of_priority_inversion j t1].