Theory Round_Robin
section ‹Round robin scheduler›
theory Round_Robin
imports
Scheduler
begin
text ‹
A concrete scheduler must pick one possible reduction step from the small-step semantics for invidivual threads.
Currently, this is only possible if there is only one such by using @{term Predicate.the}.
›
subsection ‹Concrete schedulers›
subsection ‹Round-robin schedulers›
type_synonym 'queue round_robin = "'queue × nat"
primrec enqueue_new_thread :: "'t list ⇒ ('t,'x,'m) new_thread_action ⇒ 't list"
where
"enqueue_new_thread queue (NewThread t x m) = queue @ [t]"
| "enqueue_new_thread queue (ThreadExists t b) = queue"
definition enqueue_new_threads :: "'t list ⇒ ('t,'x,'m) new_thread_action list ⇒ 't list"
where
"enqueue_new_threads = foldl enqueue_new_thread"
primrec round_robin_update_state :: "nat ⇒ 't list round_robin ⇒ 't ⇒ ('l,'t,'x,'m,'w,'o) thread_action ⇒ 't list round_robin"
where
"round_robin_update_state n0 (queue, n) t ta =
(let queue' = enqueue_new_threads queue ⦃ta⦄⇘t⇙
in if n = 0 ∨ Yield ∈ set ⦃ta⦄⇘c⇙ then (rotate1 queue', n0) else (queue', n - 1))"
context multithreaded_base begin
abbreviation round_robin_step :: "nat ⇒ 't list round_robin ⇒ ('l,'t,'x,'m,'w) state ⇒ 't ⇒ ('t × (('l,'t,'x,'m,'w,'o) thread_action × 'x × 'm) option × 't list round_robin) option"
where
"round_robin_step n0 σ s t ≡ step_thread (round_robin_update_state n0 σ t) s t"
partial_function (option) round_robin_reschedule :: "'t ⇒
't list ⇒ nat ⇒ ('l,'t,'x,'m,'w) state ⇒ ('t × (('l,'t,'x,'m,'w,'o) thread_action × 'x × 'm) option × 't list round_robin) option"
where
"round_robin_reschedule t0 queue n0 s =
(let
t = hd queue;
queue' = tl queue
in
if t = t0 then
None
else
case round_robin_step n0 (t # queue', n0) s t of
None ⇒ round_robin_reschedule t0 (queue' @ [t]) n0 s
| ⌊ttaxmσ⌋ ⇒ ⌊ttaxmσ⌋)"
fun round_robin :: "nat ⇒ 't list round_robin ⇒ ('l,'t,'x,'m,'w) state ⇒ ('t × (('l,'t,'x,'m,'w,'o) thread_action × 'x × 'm) option × 't list round_robin) option"
where
"round_robin n0 ([], n) s = None"
| "round_robin n0 (t # queue, n) s =
(case round_robin_step n0 (t # queue, n) s t of
⌊ttaxmσ⌋ ⇒ ⌊ttaxmσ⌋
| None ⇒ round_robin_reschedule t (queue @ [t]) n0 s)"
end
primrec round_robin_invar :: "'t list round_robin ⇒ 't set ⇒ bool"
where "round_robin_invar (queue, n) T ⟷ set queue = T ∧ distinct queue"
lemma set_enqueue_new_thread:
"set (enqueue_new_thread queue nta) = set queue ∪ {t. ∃x m. nta = NewThread t x m}"
by(cases nta) auto
lemma set_enqueue_new_threads:
"set (enqueue_new_threads queue ntas) = set queue ∪ {t. ∃x m. NewThread t x m ∈ set ntas}"
apply(induct ntas arbitrary: queue)
apply(auto simp add: enqueue_new_threads_def set_enqueue_new_thread)
done
lemma enqueue_new_thread_eq_Nil [simp]:
"enqueue_new_thread queue nta = [] ⟷ queue = [] ∧ (∃t b. nta = ThreadExists t b)"
by(cases nta) simp_all
lemma enqueue_new_threads_eq_Nil [simp]:
"enqueue_new_threads queue ntas = [] ⟷ queue = [] ∧ set ntas ⊆ {ThreadExists t b|t b. True}"
apply(induct ntas arbitrary: queue)
apply(auto simp add: enqueue_new_threads_def)
done
lemma distinct_enqueue_new_threads:
fixes ts :: "('l,'t,'x) thread_info"
and ntas :: "('t,'x,'m) new_thread_action list"
assumes "thread_oks ts ntas" "set queue = dom ts" "distinct queue"
shows "distinct (enqueue_new_threads queue ntas)"
using assms
proof(induct ntas arbitrary: ts queue)
case Nil thus ?case by(simp add: enqueue_new_threads_def)
next
case (Cons nt ntas)
from ‹thread_oks ts (nt # ntas)›
have "thread_ok ts nt" and "thread_oks (redT_updT ts nt) ntas" by simp_all
from ‹thread_ok ts nt› ‹set queue = dom ts› ‹distinct queue›
have "set (enqueue_new_thread queue nt) = dom (redT_updT ts nt) ∧ distinct (enqueue_new_thread queue nt)"
by(cases nt)(auto)
with ‹thread_oks (redT_updT ts nt) ntas›
have "distinct (enqueue_new_threads (enqueue_new_thread queue nt) ntas)"
by(blast intro: Cons.hyps)
thus ?case by(simp add: enqueue_new_threads_def)
qed
lemma round_robin_reschedule_induct [consumes 1, case_names head rotate]:
assumes major: "t0 ∈ set queue"
and head: "⋀queue. P (t0 # queue)"
and rotate: "⋀queue t. ⟦ t ≠ t0; t0 ∈ set queue; P (queue @ [t]) ⟧ ⟹ P (t # queue)"
shows "P queue"
using major
proof(induct n≡"length (takeWhile (λx. x≠t0) queue)" arbitrary: queue)
case 0
then obtain queue' where "queue = t0 # queue'"
by(cases queue)(auto split: if_split_asm)
thus ?case by(simp add: head)
next
case (Suc n)
then obtain t queue' where [simp]: "queue = t # queue'"
and t: "t ≠ t0" and n: "n = length (takeWhile (λx. x ≠ t0) queue')"
and t0: "t0 ∈ set queue'"
by(cases queue)(auto split: if_split_asm)
from n t0 have "n = length (takeWhile (λx. x ≠ t0) (queue' @ [t]))" by(simp)
moreover from t0 have "t0 ∈ set (queue' @ [t])" by simp
ultimately have "P (queue' @ [t])" by(rule Suc.hyps)
with t t0 show ?case by(simp add: rotate)
qed
context multithreaded_base begin
declare actions_ok_iff [simp del]
declare actions_ok.cases [rule del]
lemma round_robin_step_invar_None:
"⟦ round_robin_step n0 σ s t' = ⌊(t, None, σ')⌋; round_robin_invar σ (dom (thr s)) ⟧
⟹ round_robin_invar σ' (dom (thr s))"
by(cases σ)(auto dest: step_thread_Some_NoneD simp add: set_enqueue_new_threads distinct_enqueue_new_threads)
lemma round_robin_step_invar_Some:
"⟦ deterministic I; round_robin_step n0 σ s t' = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋; round_robin_invar σ (dom (thr s)); s ∈ I ⟧
⟹ round_robin_invar σ' (dom (thr s) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})"
apply(cases σ)
apply clarsimp
apply(frule (1) step_thread_Some_SomeD)
apply(auto split: if_split_asm simp add: split_beta set_enqueue_new_threads deterministic_THE)
apply(auto simp add: actions_ok_iff distinct_enqueue_new_threads)
done
lemma round_robin_reschedule_Cons:
"round_robin_reschedule t0 (t0 # queue) n0 s = None"
"t ≠ t0 ⟹ round_robin_reschedule t0 (t # queue) n0 s =
(case round_robin_step n0 (t # queue, n0) s t of
None ⇒ round_robin_reschedule t0 (queue @ [t]) n0 s
| Some ttaxmσ ⇒ Some ttaxmσ)"
by(simp_all add: round_robin_reschedule.simps)
lemma round_robin_reschedule_NoneD:
assumes rrr: "round_robin_reschedule t0 queue n0 s = None"
and t0: "t0 ∈ set queue"
shows "set (takeWhile (λt'. t' ≠ t0) queue) ∩ active_threads s = {}"
using t0 rrr
proof(induct queue rule: round_robin_reschedule_induct)
case (head queue)
thus ?case by simp
next
case (rotate queue t)
from ‹round_robin_reschedule t0 (t # queue) n0 s = None› ‹t ≠ t0›
have "round_robin_step n0 (t # queue, n0) s t = None"
and "round_robin_reschedule t0 (queue @ [t]) n0 s = None"
by(simp_all add: round_robin_reschedule_Cons)
from this(1) have "t ∉ active_threads s" by(rule step_thread_NoneD)
moreover from ‹round_robin_reschedule t0 (queue @ [t]) n0 s = None›
have "set (takeWhile (λt'. t' ≠ t0) (queue @ [t])) ∩ active_threads s = {}"
by(rule rotate.hyps)
moreover have "takeWhile (λt'. t' ≠ t0) (queue @ [t]) = takeWhile (λt'. t' ≠ t0) queue"
using ‹t0 ∈ set queue› by simp
ultimately show ?case using ‹t ≠ t0› by simp
qed
lemma round_robin_reschedule_Some_NoneD:
assumes rrr: "round_robin_reschedule t0 queue n0 s = ⌊(t, None, σ')⌋"
and t0: "t0 ∈ set queue"
shows "∃x ln n. thr s t = ⌊(x, ln)⌋ ∧ ln $ n > 0 ∧ ¬ waiting (wset s t) ∧ may_acquire_all (locks s) t ln"
using t0 rrr
proof(induct queue rule: round_robin_reschedule_induct)
case head thus ?case by(simp add: round_robin_reschedule_Cons)
next
case (rotate queue t')
show ?case
proof(cases "round_robin_step n0 (t' # queue, n0) s t'")
case None
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, None, σ')⌋› ‹t' ≠ t0›
have "round_robin_reschedule t0 (queue @ [t']) n0 s = ⌊(t, None, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
thus ?thesis by(rule rotate.hyps)
next
case (Some a)
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, None, σ')⌋› ‹t' ≠ t0›
have "round_robin_step n0 (t' # queue, n0) s t' = ⌊(t, None, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
thus ?thesis by(blast dest: step_thread_Some_NoneD)
qed
qed
lemma round_robin_reschedule_Some_SomeD:
assumes "deterministic I"
and rrr: "round_robin_reschedule t0 queue n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
and t0: "t0 ∈ set queue"
and I: "s ∈ I"
shows "∃x. thr s t = ⌊(x, no_wait_locks)⌋ ∧ t ⊢ ⟨x, shr s⟩ -ta→ ⟨x', m'⟩ ∧ actions_ok s t ta"
using t0 rrr
proof(induct queue rule: round_robin_reschedule_induct)
case head thus ?case by(simp add: round_robin_reschedule_Cons)
next
case (rotate queue t')
show ?case
proof(cases "round_robin_step n0 (t' # queue, n0) s t'")
case None
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋› ‹t' ≠ t0›
have "round_robin_reschedule t0 (queue @ [t']) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
thus ?thesis by(rule rotate.hyps)
next
case (Some a)
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋› ‹t' ≠ t0›
have "round_robin_step n0 (t' # queue, n0) s t' = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
thus ?thesis using I by(blast dest: step_thread_Some_SomeD[OF ‹deterministic I›])
qed
qed
lemma round_robin_reschedule_invar_None:
assumes rrr: "round_robin_reschedule t0 queue n0 s = ⌊(t, None, σ')⌋"
and invar: "round_robin_invar (queue, n0) (dom (thr s))"
and t0: "t0 ∈ set queue"
shows "round_robin_invar σ' (dom (thr s))"
using t0 rrr invar
proof(induct queue rule: round_robin_reschedule_induct)
case head thus ?case by(simp add: round_robin_reschedule_Cons)
next
case (rotate queue t')
show ?case
proof(cases "round_robin_step n0 (t' # queue, n0) s t'")
case None
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, None, σ')⌋› ‹t' ≠ t0›
have "round_robin_reschedule t0 (queue @ [t']) n0 s = ⌊(t, None, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
moreover from ‹round_robin_invar (t' # queue, n0) (dom (thr s))›
have "round_robin_invar (queue @ [t'], n0) (dom (thr s))" by simp
ultimately show ?thesis by(rule rotate.hyps)
next
case (Some a)
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, None, σ')⌋› ‹t' ≠ t0›
have "round_robin_step n0 (t' # queue, n0) s t' = ⌊(t, None, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
thus ?thesis using ‹round_robin_invar (t' # queue, n0) (dom (thr s))›
by(rule round_robin_step_invar_None)
qed
qed
lemma round_robin_reschedule_invar_Some:
assumes "deterministic I"
and rrr: "round_robin_reschedule t0 queue n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
and invar: "round_robin_invar (queue, n0) (dom (thr s))"
and t0: "t0 ∈ set queue"
and "s ∈ I"
shows "round_robin_invar σ' (dom (thr s) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})"
using t0 rrr invar
proof(induct queue rule: round_robin_reschedule_induct)
case head thus ?case by(simp add: round_robin_reschedule_Cons)
next
case (rotate queue t')
show ?case
proof(cases "round_robin_step n0 (t' # queue, n0) s t'")
case None
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋› ‹t' ≠ t0›
have "round_robin_reschedule t0 (queue @ [t']) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
moreover from ‹round_robin_invar (t' # queue, n0) (dom (thr s))›
have "round_robin_invar (queue @ [t'], n0) (dom (thr s))" by simp
ultimately show ?thesis by(rule rotate.hyps)
next
case (Some a)
with ‹round_robin_reschedule t0 (t' # queue) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋› ‹t' ≠ t0›
have "round_robin_step n0 (t' # queue, n0) s t' = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
by(simp add: round_robin_reschedule_Cons)
thus ?thesis using ‹round_robin_invar (t' # queue, n0) (dom (thr s))› ‹s ∈ I›
by(rule round_robin_step_invar_Some[OF ‹deterministic I›])
qed
qed
lemma round_robin_NoneD:
assumes rr: "round_robin n0 σ s = None"
and invar: "round_robin_invar σ (dom (thr s))"
shows "active_threads s = {}"
proof -
obtain queue n where σ: "σ = (queue, n)" by(cases σ)
show ?thesis
proof(cases queue)
case Nil
thus ?thesis using invar σ by(fastforce elim: active_threads.cases)
next
case (Cons t queue')
with rr σ have "round_robin_step n0 (t # queue', n) s t = None"
and "round_robin_reschedule t (queue' @ [t]) n0 s = None" by simp_all
from ‹round_robin_step n0 (t # queue', n) s t = None›
have "t ∉ active_threads s" by(rule step_thread_NoneD)
moreover from ‹round_robin_reschedule t (queue' @ [t]) n0 s = None›
have "set (takeWhile (λx. x ≠ t) (queue' @ [t])) ∩ active_threads s = {}"
by(rule round_robin_reschedule_NoneD) simp
moreover from invar σ Cons
have "takeWhile (λx. x ≠ t) (queue' @ [t]) = queue'"
by(subst takeWhile_append2) auto
moreover from invar have "active_threads s ⊆ set queue"
using σ by(auto elim: active_threads.cases)
ultimately show ?thesis using Cons by auto
qed
qed
lemma round_robin_Some_NoneD:
assumes rr: "round_robin n0 σ s = ⌊(t, None, σ')⌋"
shows "∃x ln n. thr s t = ⌊(x, ln)⌋ ∧ ln $ n > 0 ∧ ¬ waiting (wset s t) ∧ may_acquire_all (locks s) t ln"
proof -
obtain queue n where σ: "σ = (queue, n)" by(cases σ)
with rr have "queue ≠ []" by clarsimp
then obtain t' queue' where queue: "queue = t' # queue'"
by(auto simp add: neq_Nil_conv)
show ?thesis
proof(cases "round_robin_step n0 (t' # queue', n) s t'")
case (Some a)
with rr queue σ have "round_robin_step n0 (t' # queue', n) s t' = ⌊(t, None, σ')⌋" by simp
thus ?thesis by(blast dest: step_thread_Some_NoneD)
next
case None
with rr queue σ have "round_robin_reschedule t' (queue' @ [t']) n0 s = ⌊(t, None, σ')⌋" by simp
thus ?thesis by(rule round_robin_reschedule_Some_NoneD)simp
qed
qed
lemma round_robin_Some_SomeD:
assumes "deterministic I"
and rr: "round_robin n0 σ s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
and "s ∈ I"
shows "∃x. thr s t = ⌊(x, no_wait_locks)⌋ ∧ t ⊢ ⟨x, shr s⟩ -ta→ ⟨x', m'⟩ ∧ actions_ok s t ta"
proof -
obtain queue n where σ: "σ = (queue, n)" by(cases σ)
with rr have "queue ≠ []" by clarsimp
then obtain t' queue' where queue: "queue = t' # queue'"
by(auto simp add: neq_Nil_conv)
show ?thesis
proof(cases "round_robin_step n0 (t' # queue', n) s t'")
case (Some a)
with rr queue σ have "round_robin_step n0 (t' # queue', n) s t' = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋" by simp
thus ?thesis using ‹s ∈ I› by(blast dest: step_thread_Some_SomeD[OF ‹deterministic I›])
next
case None
with rr queue σ have "round_robin_reschedule t' (queue' @ [t']) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋" by simp
thus ?thesis by(rule round_robin_reschedule_Some_SomeD[OF ‹deterministic I›])(simp_all add: ‹s ∈ I›)
qed
qed
lemma round_robin_invar_None:
assumes rr: "round_robin n0 σ s = ⌊(t, None, σ')⌋"
and invar: "round_robin_invar σ (dom (thr s))"
shows "round_robin_invar σ' (dom (thr s))"
proof -
obtain queue n where σ: "σ = (queue, n)" by(cases σ)
with rr have "queue ≠ []" by clarsimp
then obtain t' queue' where queue: "queue = t' # queue'"
by(auto simp add: neq_Nil_conv)
show ?thesis
proof(cases "round_robin_step n0 (t' # queue', n) s t'")
case (Some a)
with rr queue σ have "round_robin_step n0 (t' # queue', n) s t' = ⌊(t, None, σ')⌋" by simp
thus ?thesis using invar unfolding σ queue by(rule round_robin_step_invar_None)
next
case None
with rr queue σ have "round_robin_reschedule t' (queue' @ [t']) n0 s = ⌊(t, None, σ')⌋" by simp
moreover from invar queue σ have "round_robin_invar (queue' @ [t'], n0) (dom (thr s))" by simp
ultimately show ?thesis by(rule round_robin_reschedule_invar_None) simp
qed
qed
lemma round_robin_invar_Some:
assumes "deterministic I"
and rr: "round_robin n0 σ s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
and invar: "round_robin_invar σ (dom (thr s))" "s ∈ I"
shows "round_robin_invar σ' (dom (thr s) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})"
proof -
obtain queue n where σ: "σ = (queue, n)" by(cases σ)
with rr have "queue ≠ []" by clarsimp
then obtain t' queue' where queue: "queue = t' # queue'"
by(auto simp add: neq_Nil_conv)
show ?thesis
proof(cases "round_robin_step n0 (t' # queue', n) s t'")
case (Some a)
with rr queue σ have "round_robin_step n0 (t' # queue', n) s t' = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋" by simp
thus ?thesis using invar unfolding σ queue by(rule round_robin_step_invar_Some[OF ‹deterministic I›])
next
case None
with rr queue σ have "round_robin_reschedule t' (queue' @ [t']) n0 s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋" by simp
moreover from invar queue σ
have "round_robin_invar (queue' @ [t'], n0) (dom (thr s))" by simp
ultimately show ?thesis by(rule round_robin_reschedule_invar_Some[OF ‹deterministic I›])(simp_all add: ‹s ∈ I›)
qed
qed
end
locale round_robin_base =
scheduler_base_aux
final r convert_RA
thr_α thr_invar thr_lookup thr_update
ws_α ws_invar ws_lookup
is_α is_invar is_memb is_ins is_delete
for final :: "'x ⇒ bool"
and r :: "'t ⇒ ('x × 'm) ⇒ (('l,'t,'x,'m,'w,'o) thread_action × 'x × 'm) Predicate.pred"
and convert_RA :: "'l released_locks ⇒ 'o list"
and "output" :: "'queue round_robin ⇒ 't ⇒ ('l,'t,'x,'m,'w,'o) thread_action ⇒ 'q option"
and thr_α :: "'m_t ⇒ ('l,'t,'x) thread_info"
and thr_invar :: "'m_t ⇒ bool"
and thr_lookup :: "'t ⇒ 'm_t ⇀ ('x × 'l released_locks)"
and thr_update :: "'t ⇒ 'x × 'l released_locks ⇒ 'm_t ⇒ 'm_t"
and ws_α :: "'m_w ⇒ ('w,'t) wait_sets"
and ws_invar :: "'m_w ⇒ bool"
and ws_lookup :: "'t ⇒ 'm_w ⇀ 'w wait_set_status"
and ws_update :: "'t ⇒ 'w wait_set_status ⇒ 'm_w ⇒ 'm_w"
and ws_delete :: "'t ⇒ 'm_w ⇒ 'm_w"
and ws_iterate :: "'m_w ⇒ ('t × 'w wait_set_status, 'm_w) set_iterator"
and ws_sel :: "'m_w ⇒ ('t × 'w wait_set_status ⇒ bool) ⇀ ('t × 'w wait_set_status)"
and is_α :: "'s_i ⇒ 't interrupts"
and is_invar :: "'s_i ⇒ bool"
and is_memb :: "'t ⇒ 's_i ⇒ bool"
and is_ins :: "'t ⇒ 's_i ⇒ 's_i"
and is_delete :: "'t ⇒ 's_i ⇒ 's_i"
+
fixes queue_α :: "'queue ⇒ 't list"
and queue_invar :: "'queue ⇒ bool"
and queue_empty :: "unit ⇒ 'queue"
and queue_isEmpty :: "'queue ⇒ bool"
and queue_enqueue :: "'t ⇒ 'queue ⇒ 'queue"
and queue_dequeue :: "'queue ⇒ 't × 'queue"
and queue_push :: "'t ⇒ 'queue ⇒ 'queue"
begin
definition queue_rotate1 :: "'queue ⇒ 'queue"
where "queue_rotate1 = case_prod queue_enqueue ∘ queue_dequeue"
primrec enqueue_new_thread :: "'queue ⇒ ('t,'x,'m) new_thread_action ⇒ 'queue"
where
"enqueue_new_thread ts (NewThread t x m) = queue_enqueue t ts"
| "enqueue_new_thread ts (ThreadExists t b) = ts"
definition enqueue_new_threads :: "'queue ⇒ ('t,'x,'m) new_thread_action list ⇒ 'queue"
where
"enqueue_new_threads = foldl enqueue_new_thread"
primrec round_robin_update_state :: "nat ⇒ 'queue round_robin ⇒ 't ⇒ ('l,'t,'x,'m,'w,'o) thread_action ⇒ 'queue round_robin"
where
"round_robin_update_state n0 (queue, n) t ta =
(let queue' = enqueue_new_threads queue ⦃ta⦄⇘t⇙
in if n = 0 ∨ Yield ∈ set ⦃ta⦄⇘c⇙ then (queue_rotate1 queue', n0) else (queue', n - 1))"
abbreviation round_robin_step ::
"nat ⇒ 'queue round_robin ⇒ ('l,'t,'m,'m_t,'m_w,'s_i) state_refine ⇒ 't
⇒ ('t × (('l,'t,'x,'m,'w,'o) thread_action × 'x × 'm) option × 'queue round_robin) option"
where
"round_robin_step n0 σ s t ≡ step_thread (round_robin_update_state n0 σ t) s t"
partial_function (option) round_robin_reschedule ::
"'t ⇒ 'queue ⇒ nat ⇒ ('l,'t,'m,'m_t,'m_w,'s_i) state_refine
⇒ ('t × (('l,'t,'x,'m,'w,'o) thread_action × 'x × 'm) option × 'queue round_robin) option"
where
"round_robin_reschedule t0 queue n0 s =
(let
(t, queue') = queue_dequeue queue
in
if t = t0 then
None
else
case round_robin_step n0 (queue_push t queue', n0) s t of
None ⇒ round_robin_reschedule t0 (queue_enqueue t queue') n0 s
| ⌊ttaxmσ⌋ ⇒ ⌊ttaxmσ⌋)"
primrec round_robin :: "nat ⇒ ('l,'t,'x,'m,'w,'o,'m_t,'m_w,'s_i,'queue round_robin) scheduler"
where
"round_robin n0 (queue, n) s =
(if queue_isEmpty queue then None
else
let
(t, queue') = queue_dequeue queue
in
(case round_robin_step n0 (queue_push t queue', n) s t of
⌊ttaxmσ⌋ ⇒ ⌊ttaxmσ⌋
| None ⇒ round_robin_reschedule t (queue_enqueue t queue') n0 s))"
primrec round_robin_invar :: "'queue round_robin ⇒ 't set ⇒ bool"
where "round_robin_invar (queue, n) T ⟷ queue_invar queue ∧ Round_Robin.round_robin_invar (queue_α queue, n) T"
definition round_robin_α :: "'queue round_robin ⇒ 't list round_robin"
where "round_robin_α = apfst queue_α"
definition round_robin_start :: "nat ⇒ 't ⇒ 'queue round_robin"
where "round_robin_start n0 t = (queue_enqueue t (queue_empty ()), n0)"
lemma round_robin_invar_correct:
"round_robin_invar σ T ⟹ Round_Robin.round_robin_invar (round_robin_α σ) T"
by(cases σ)(simp add: round_robin_α_def)
end
locale round_robin =
round_robin_base
final r convert_RA "output"
thr_α thr_invar thr_lookup thr_update
ws_α ws_invar ws_lookup ws_update ws_delete ws_iterate ws_sel
is_α is_invar is_memb is_ins is_delete
queue_α queue_invar queue_empty queue_isEmpty queue_enqueue queue_dequeue queue_push
+
scheduler_aux
final r convert_RA
thr_α thr_invar thr_lookup thr_update
ws_α ws_invar ws_lookup
is_α is_invar is_memb is_ins is_delete
+
ws: map_update ws_α ws_invar ws_update +
ws: map_delete ws_α ws_invar ws_delete +
ws: map_iteratei ws_α ws_invar ws_iterate +
ws: map_sel' ws_α ws_invar ws_sel +
queue: list queue_α queue_invar +
queue: list_empty queue_α queue_invar queue_empty +
queue: list_isEmpty queue_α queue_invar queue_isEmpty +
queue: list_enqueue queue_α queue_invar queue_enqueue +
queue: list_dequeue queue_α queue_invar queue_dequeue +
queue: list_push queue_α queue_invar queue_push
for final :: "'x ⇒ bool"
and r :: "'t ⇒ ('x × 'm) ⇒ (('l,'t,'x,'m,'w,'o) thread_action × 'x × 'm) Predicate.pred"
and convert_RA :: "'l released_locks ⇒ 'o list"
and "output" :: "'queue round_robin ⇒ 't ⇒ ('l,'t,'x,'m,'w,'o) thread_action ⇒ 'q option"
and thr_α :: "'m_t ⇒ ('l,'t,'x) thread_info"
and thr_invar :: "'m_t ⇒ bool"
and thr_lookup :: "'t ⇒ 'm_t ⇀ ('x × 'l released_locks)"
and thr_update :: "'t ⇒ 'x × 'l released_locks ⇒ 'm_t ⇒ 'm_t"
and ws_α :: "'m_w ⇒ ('w,'t) wait_sets"
and ws_invar :: "'m_w ⇒ bool"
and ws_lookup :: "'t ⇒ 'm_w ⇀ 'w wait_set_status"
and ws_update :: "'t ⇒ 'w wait_set_status ⇒ 'm_w ⇒ 'm_w"
and ws_delete :: "'t ⇒ 'm_w ⇒ 'm_w"
and ws_iterate :: "'m_w ⇒ ('t × 'w wait_set_status, 'm_w) set_iterator"
and ws_sel :: "'m_w ⇒ ('t × 'w wait_set_status ⇒ bool) ⇀ ('t × 'w wait_set_status)"
and is_α :: "'s_i ⇒ 't interrupts"
and is_invar :: "'s_i ⇒ bool"
and is_memb :: "'t ⇒ 's_i ⇒ bool"
and is_ins :: "'t ⇒ 's_i ⇒ 's_i"
and is_delete :: "'t ⇒ 's_i ⇒ 's_i"
and queue_α :: "'queue ⇒ 't list"
and queue_invar :: "'queue ⇒ bool"
and queue_empty :: "unit ⇒ 'queue"
and queue_isEmpty :: "'queue ⇒ bool"
and queue_enqueue :: "'t ⇒ 'queue ⇒ 'queue"
and queue_dequeue :: "'queue ⇒ 't × 'queue"
and queue_push :: "'t ⇒ 'queue ⇒ 'queue"
begin
lemma queue_rotate1_correct:
assumes "queue_invar queue" "queue_α queue ≠ []"
shows "queue_α (queue_rotate1 queue) = rotate1 (queue_α queue)"
and "queue_invar (queue_rotate1 queue)"
using assms
apply(auto simp add: queue_rotate1_def split_beta queue.dequeue_correct queue.enqueue_correct)
by(cases "queue_α queue") simp_all
lemma enqueue_thread_correct:
assumes "queue_invar queue"
shows "queue_α (enqueue_new_thread queue nta) = Round_Robin.enqueue_new_thread (queue_α queue) nta"
and "queue_invar (enqueue_new_thread queue nta)"
using assms
by(case_tac [!] nta)(simp_all add: queue.enqueue_correct)
lemma enqueue_threads_correct:
assumes "queue_invar queue"
shows "queue_α (enqueue_new_threads queue ntas) = Round_Robin.enqueue_new_threads (queue_α queue) ntas"
and "queue_invar (enqueue_new_threads queue ntas)"
using assms
apply(induct ntas arbitrary: queue)
apply(simp_all add: enqueue_new_threads_def Round_Robin.enqueue_new_threads_def enqueue_thread_correct)
done
lemma round_robin_update_thread_correct:
assumes "round_robin_invar σ T" "t' ∈ T"
shows "round_robin_α (round_robin_update_state n0 σ t ta) = Round_Robin.round_robin_update_state n0 (round_robin_α σ) t ta"
using assms
apply(cases σ)
apply(auto simp add: round_robin_α_def queue_rotate1_correct enqueue_threads_correct del: conjI)
apply(subst (1 2) queue_rotate1_correct)
apply(auto simp add: enqueue_threads_correct)
done
lemma round_robin_step_correct:
assumes det: "α.deterministic I"
and invar: "round_robin_invar σ (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
shows
"map_option (apsnd (apsnd round_robin_α)) (round_robin_step n0 σ s t) =
α.round_robin_step n0 (round_robin_α σ) (state_α s) t" (is ?thesis1)
and "case_option True (λ(t, taxm, σ). round_robin_invar σ (case taxm of None ⇒ dom (thr_α (thr s)) | Some (ta, x', m') ⇒ dom (thr_α (thr s)) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})) (round_robin_step n0 σ s t)"
(is ?thesis2)
proof -
have "?thesis1 ∧ ?thesis2"
proof(cases "dom (thr_α (thr s)) = {}")
case True
thus ?thesis using invar
apply(cases σ)
apply(auto dest: step_thread_Some_NoneD[OF det] step_thread_Some_SomeD[OF det])
apply(fastforce simp add: α.step_thread_eq_None_conv elim: α.active_threads.cases intro: sym)
done
next
case False
then obtain t' where t': "t' ∈ dom (thr_α (thr s))" by blast
hence ?thesis1
using step_thread_correct(1)[of I round_robin_invar σ s round_robin_α "round_robin_update_state n0 σ t" t, OF det invar]
unfolding o_def using invar
by(subst (asm) round_robin_update_thread_correct) auto
moreover
{ fix ta :: "('l, 't, 'x, 'm, 'w, 'o) thread_action"
assume "FWThread.thread_oks (thr_α (thr s)) ⦃ta⦄⇘t⇙"
moreover from t' invar have "queue_α (fst σ) ≠ []" by(cases σ) auto
ultimately have "round_robin_invar (round_robin_update_state n0 σ t ta) (dom (thr_α (thr s)) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})"
using invar t' by(cases σ)(auto simp add: queue_rotate1_correct enqueue_threads_correct set_enqueue_new_threads iff del: domIff intro: distinct_enqueue_new_threads) }
from step_thread_correct(2)[OF det, of round_robin_invar σ s "round_robin_update_state n0 σ t" t, OF invar this]
have ?thesis2 using t' invar by simp
ultimately show ?thesis by blast
qed
thus ?thesis1 ?thesis2 by blast+
qed
lemma round_robin_reschedule_correct:
assumes det: "α.deterministic I"
and invar: "round_robin_invar (queue, n) (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
and t0: "t0 ∈ set (queue_α queue)"
shows "map_option (apsnd (apsnd round_robin_α)) (round_robin_reschedule t0 queue n0 s) =
α.round_robin_reschedule t0 (queue_α queue) n0 (state_α s)"
and "case_option True (λ(t, taxm, σ). round_robin_invar σ (case taxm of None ⇒ dom (thr_α (thr s)) | Some (ta, x', m') ⇒ dom (thr_α (thr s)) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})) (round_robin_reschedule t0 queue n0 s)"
using t0 invar
proof(induct "queue_α queue" arbitrary: queue n rule: round_robin_reschedule_induct)
case head
{ case 1 thus ?case using head[symmetric]
by(subst round_robin_reschedule.simps)(subst α.round_robin_reschedule.simps, clarsimp simp add: split_beta queue.dequeue_correct)
next
case 2 thus ?case using head[symmetric]
by(subst round_robin_reschedule.simps)(clarsimp simp add: split_beta queue.dequeue_correct) }
next
case (rotate αqueue' t)
obtain t' queue' where queue': "queue_dequeue queue = (t', queue')" by(cases "queue_dequeue queue")
note [simp] = ‹t # αqueue' = queue_α queue›[symmetric]
{ case 1
with queue' have [simp]: "t' = t" "αqueue' = queue_α queue'" "queue_invar queue'" by(auto elim: queue.removelE)
from 1 queue' have invar': "round_robin_invar (queue_push t queue', n0) (dom (thr_α (thr s)))"
by(auto simp add: queue.push_correct)
show ?case
proof(cases "round_robin_step n0 (queue_push t queue', n0) s t")
case Some thus ?thesis
using queue' ‹t ≠ t0› round_robin_step_correct[OF det invar' ‹state_invar s›, of n0 t] invar' ‹state_α s ∈ I›
by(subst round_robin_reschedule.simps)(subst α.round_robin_reschedule.simps, auto simp add: round_robin_α_def queue.push_correct)
next
case None
hence αNone: "α.round_robin_step n0 (queue_α (queue_push t queue'), n0) (state_α s) t = None"
using round_robin_step_correct[OF det invar' ‹state_invar s›, of n0 t] invar' ‹state_α s ∈ I›
by(auto simp add: queue.push_correct round_robin_α_def)
have "αqueue' @ [t] = queue_α (queue_enqueue t queue')" by(simp add: queue.enqueue_correct)
moreover from invar'
have "round_robin_invar (queue_enqueue t queue', n0) (dom (thr_α (thr s)))"
by(auto simp add: queue.enqueue_correct queue.push_correct)
ultimately
have "map_option (apsnd (apsnd round_robin_α)) (round_robin_reschedule t0 (queue_enqueue t queue') n0 s) =
α.round_robin_reschedule t0 (queue_α (queue_enqueue t queue')) n0 (state_α s)"
using ‹state_invar s› ‹state_α s ∈ I› by(rule rotate.hyps)
thus ?thesis using None αNone ‹t ≠ t0› invar' queue'
by(subst round_robin_reschedule.simps)(subst α.round_robin_reschedule.simps, auto simp add: queue.enqueue_correct queue.push_correct)
qed
next
case 2
with queue' have [simp]: "t' = t" "αqueue' = queue_α queue'" "queue_invar queue'" by(auto elim: queue.removelE)
from 2 queue' have invar': "round_robin_invar (queue_push t queue', n0) (dom (thr_α (thr s)))"
by(auto simp add: queue.push_correct)
show ?case
proof(cases "round_robin_step n0 (queue_push t queue', n0) s t")
case Some thus ?thesis
using queue' ‹t ≠ t0› round_robin_step_correct[OF det invar' ‹state_invar s›, of n0 t] invar' ‹state_α s ∈ I›
by(subst round_robin_reschedule.simps)(auto simp add: round_robin_α_def queue.push_correct)
next
case None
have "αqueue' @ [t] = queue_α (queue_enqueue t queue')" by(simp add: queue.enqueue_correct)
moreover from invar'
have "round_robin_invar (queue_enqueue t queue', n0) (dom (thr_α (thr s)))"
by(auto simp add: queue.enqueue_correct queue.push_correct)
ultimately
have "case_option True (λ(t, taxm, σ). round_robin_invar σ (case_option (dom (thr_α (thr s))) (λ(ta, x', m'). dom (thr_α (thr s)) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙}) taxm)) (round_robin_reschedule t0 (queue_enqueue t queue') n0 s)"
using ‹state_invar s› ‹state_α s ∈ I› by(rule rotate.hyps)
thus ?thesis using None ‹t ≠ t0› invar' queue'
by(subst round_robin_reschedule.simps)(auto simp add: queue.enqueue_correct queue.push_correct)
qed
}
qed
lemma round_robin_correct:
assumes det: "α.deterministic I"
and invar: "round_robin_invar σ (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
shows "map_option (apsnd (apsnd round_robin_α)) (round_robin n0 σ s) =
α.round_robin n0 (round_robin_α σ) (state_α s)"
(is ?thesis1)
and "case_option True (λ(t, taxm, σ). round_robin_invar σ (case taxm of None ⇒ dom (thr_α (thr s)) | Some (ta, x', m') ⇒ dom (thr_α (thr s)) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})) (round_robin n0 σ s)"
(is ?thesis2)
proof -
obtain queue n where σ: "σ = (queue, n)" by(cases σ)
have "?thesis1 ∧ ?thesis2"
proof(cases "queue_α queue")
case Nil thus ?thesis using invar σ
by(auto simp add: split_beta queue.isEmpty_correct round_robin_α_def)
next
case (Cons t αqueue')
with invar σ obtain queue'
where [simp]: "queue_dequeue queue = (t, queue')" "αqueue' = queue_α queue'" "queue_invar queue'"
by(auto elim: queue.removelE)
from invar σ Cons have invar': "round_robin_invar (queue_push t queue', n) (dom (thr_α (thr s)))"
by(auto simp add: queue.push_correct)
from invar σ Cons have invar'': "round_robin_invar (queue_enqueue t queue', n0) (dom (thr_α (thr s)))"
by(auto simp add: queue.enqueue_correct)
show ?thesis
proof(cases "round_robin_step n0 (queue_push t queue', n) s t")
case Some
with σ Cons invar show ?thesis
using round_robin_step_correct[OF det invar' ‹state_invar s›, of n0 t]
by(auto simp add: queue.isEmpty_correct queue.push_correct round_robin_α_def)
next
case None
from invar σ Cons have "t ∈ set (queue_α (queue_enqueue t queue'))"
by(auto simp add: queue.enqueue_correct)
from round_robin_reschedule_correct[OF det invar'' ‹state_invar s›, OF ‹state_α s ∈ I› this, of n0] None σ Cons invar
round_robin_step_correct[OF det invar' ‹state_invar s›, of n0 t]
show ?thesis by(auto simp add: queue.isEmpty_correct queue.push_correct round_robin_α_def queue.enqueue_correct)
qed
qed
thus ?thesis1 ?thesis2 by simp_all
qed
lemma round_robin_scheduler_spec:
assumes det: "α.deterministic I"
shows "scheduler_spec final r (round_robin n0) round_robin_invar thr_α thr_invar ws_α ws_invar is_α is_invar I"
proof
fix σ s
assume rr: "round_robin n0 σ s = None"
and invar: "round_robin_invar σ (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
from round_robin_correct[OF det, OF invar, of n0] rr
have "α.round_robin n0 (round_robin_α σ) (state_α s) = None" by simp
moreover from invar have "Round_Robin.round_robin_invar (round_robin_α σ) (dom (thr (state_α s)))"
by(simp add: round_robin_invar_correct)
ultimately show "α.active_threads (state_α s) = {}" by(rule α.round_robin_NoneD)
next
fix σ s t σ'
assume rr: "round_robin n0 σ s = ⌊(t, None, σ')⌋"
and invar: "round_robin_invar σ (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
from round_robin_correct[OF det, OF invar, of n0] rr
have rr': "α.round_robin n0 (round_robin_α σ) (state_α s) = ⌊(t, None, round_robin_α σ')⌋" by simp
then show "∃x ln n. thr_α (thr s) t = ⌊(x, ln)⌋ ∧ 0 < ln $ n ∧ ¬ waiting (ws_α (wset s) t) ∧ may_acquire_all (locks s) t ln"
by(rule α.round_robin_Some_NoneD[where s="state_α s", unfolded state_α_conv])
next
fix σ s t ta x' m' σ'
assume rr: "round_robin n0 σ s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
and invar: "round_robin_invar σ (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
from round_robin_correct[OF det, OF invar, of n0] rr
have rr': "α.round_robin n0 (round_robin_α σ) (state_α s) = ⌊(t, ⌊(ta, x', m')⌋, round_robin_α σ')⌋" by simp
thus "∃x. thr_α (thr s) t = ⌊(x, no_wait_locks)⌋ ∧ Predicate.eval (r t (x, shr s)) (ta, x', m') ∧ α.actions_ok (state_α s) t ta"
using ‹state_α s ∈ I› by(rule α.round_robin_Some_SomeD[OF det, where s="state_α s", unfolded state_α_conv])
next
fix σ s t σ'
assume rr: "round_robin n0 σ s = ⌊(t, None, σ')⌋"
and invar: "round_robin_invar σ (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
from round_robin_correct[OF det, OF invar, of n0] rr
show "round_robin_invar σ' (dom (thr_α (thr s)))" by simp
next
fix σ s t ta x' m' σ'
assume rr: "round_robin n0 σ s = ⌊(t, ⌊(ta, x', m')⌋, σ')⌋"
and invar: "round_robin_invar σ (dom (thr_α (thr s)))" "state_invar s" "state_α s ∈ I"
from round_robin_correct[OF det, OF invar, of n0] rr
show "round_robin_invar σ' (dom (thr_α (thr s)) ∪ {t. ∃x m. NewThread t x m ∈ set ⦃ta⦄⇘t⇙})" by simp
qed
lemma round_robin_start_invar:
"round_robin_invar (round_robin_start n0 t0) {t0}"
by(simp add: round_robin_start_def queue.empty_correct queue.enqueue_correct)
end
sublocale round_robin_base <
scheduler_base
final r convert_RA
"round_robin n0" "output" "pick_wakeup_via_sel (λs P. ws_sel s (λ(k,v). P k v))" round_robin_invar
thr_α thr_invar thr_lookup thr_update
ws_α ws_invar ws_lookup ws_update ws_delete ws_iterate
is_α is_invar is_memb is_ins is_delete
for n0 .
sublocale round_robin <
pick_wakeup_spec
final r convert_RA
"pick_wakeup_via_sel (λs P. ws_sel s (λ(k,v). P k v))" round_robin_invar
thr_α thr_invar
ws_α ws_invar
is_α is_invar
by(rule pick_wakeup_spec_via_sel)(unfold_locales)
context round_robin begin
lemma round_robin_scheduler:
assumes det: "α.deterministic I"
shows
"scheduler
final r convert_RA
(round_robin n0) (pick_wakeup_via_sel (λs P. ws_sel s (λ(k,v). P k v))) round_robin_invar
thr_α thr_invar thr_lookup thr_update
ws_α ws_invar ws_lookup ws_update ws_delete ws_iterate
is_α is_invar is_memb is_ins is_delete
I"
proof -
interpret scheduler_spec
final r convert_RA
"round_robin n0" round_robin_invar
thr_α thr_invar
ws_α ws_invar
is_α is_invar
I
using det by(rule round_robin_scheduler_spec)
show ?thesis by(unfold_locales)(rule α.deterministic_invariant3p[OF det])
qed
end
lemmas [code] =
round_robin_base.queue_rotate1_def
round_robin_base.enqueue_new_thread.simps
round_robin_base.enqueue_new_threads_def
round_robin_base.round_robin_update_state.simps
round_robin_base.round_robin_reschedule.simps
round_robin_base.round_robin.simps
round_robin_base.round_robin_start_def
end