Skip to content

Commit 464e2c4

Browse files
committed
Trace element ≝ process
1 parent e9d3ed5 commit 464e2c4

2 files changed

Lines changed: 131 additions & 43 deletions

File tree

theories/Handlers/Mailbox.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ Section defn.
2929
Let t := Pid.FMap.M.t Mailbox.
3030

3131
(** "Address" of the mailbox *)
32-
Record Address {mba_t : Set} := {
32+
Record Address {mba_t : Set} :=
33+
mkAddress
34+
{
3335
mba_pid : PID
3436
}.
3537

theories/VM.v

Lines changed: 128 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,22 @@ Section VM.
3030
Let World := @h_state _ _ IOH.
3131

3232
CoInductive Program (Mailbox : Set) : Type :=
33-
| p_dead : (* Program terminted *)
33+
| die : (* Program termintes *)
3434
Program Mailbox
3535
| p_yield :
36-
(* Interrupt the computation without producing any side effects.
37-
This primitive is used to softly introduce the concept of
38-
Erlang's "reductions", and to side-step termination checker,
39-
making programs non-Turing in a practically useful, as opposed
40-
to forced, way.
41-
42-
In Erlang, reduction counting improves responsiveness of the
43-
system, in SLOT it *additionally* gives a structural argument
44-
"for free". *)
45-
forall {CTX : Type}
46-
(ctx : CTX)
47-
(continuation : CTX -> Program Mailbox),
48-
Program Mailbox
49-
| p_cont : (* Program is doing I/O *)
36+
(** Interrupt the computation without producing any side effects.
37+
38+
This primitive is used to softly introduce the concept of
39+
Erlang's "reductions", and to side-step termination checker,
40+
making programs non-Turing in a practically useful, as opposed
41+
to forced, way.
42+
43+
In Erlang, reduction counting improves responsiveness of the
44+
system, in SLOT it *additionally* gives a structural argument
45+
"for free". *)
46+
forall (continuation : Program Mailbox),
47+
Program Mailbox
48+
| p_io : (* Program is doing I/O *)
5049
forall (pending_req : Request)
5150
(continuation : Reply pending_req -> Program Mailbox),
5251
Program Mailbox
@@ -57,34 +56,35 @@ Section VM.
5756
Program Mailbox.
5857

5958
Record Process :=
60-
{ proc_mb_t : Set;
61-
proc_prog : @Program proc_mb_t;
62-
}.
59+
mkProcess
60+
{ pid : PID;
61+
proc_mb_t : Set;
62+
cont : @Program proc_mb_t;
63+
}.
64+
65+
#[export] Instance etaProc : Settable _ := settable! mkProcess <pid; proc_mb_t; cont>.
6366

6467
Record VM :=
6568
mkVM
6669
{ (* State of the I/O handler *)
6770
world : World;
6871
(* Set of runnable processes *)
69-
runq : list (PID * Process);
70-
(* Set of sleeping processes *)
71-
sleepq : list (PID * Process);
72+
runq : list Process;
7273
(* Counter that gets incremented when process spawns a child.
7374
This counter is used as a suffix of the child's pid *)
7475
child_ctr : Pid.FMap.t positive;
7576
}.
7677

77-
#[export] Instance etaX : Settable _ := settable! mkVM <world; runq; sleepq; child_ctr>.
78+
#[export] Instance etaVM : Settable _ := settable! mkVM <world; runq; child_ctr>.
7879

79-
Program Definition vm_setoid : Setoid VM :=
80+
Global Program Definition vm_setoid : Setoid VM :=
8081
{| equiv a b :=
81-
let (w1, rq1, sq1, cc1) := a in
82-
let (w2, rq2, sq2, cc2) := b in
82+
let (w1, rq1, cc1) := a in
83+
let (w2, rq2, cc2) := b in
8384
let w_eq := @equiv _ h_setoid in
8485
let p_eq := @equiv _ (setoid_permutation _) in
8586
w_eq w1 w2 /\
8687
p_eq rq1 rq2 /\
87-
p_eq sq1 sq2 /\
8888
@equiv _ (eq_setoid _) cc1 cc2;
8989
|}.
9090
Next Obligation.
@@ -103,38 +103,118 @@ Section VM.
103103
end in
104104
(v<| child_ctr := cc |>, ctr).
105105

106-
Definition do_spawn {Mailbox : Set} (parent : PID) (prog : @Program Mailbox) (v : VM) : VM :=
106+
Definition do_spawn {Mailbox : Set} (parent : PID) (prog : @Program Mailbox) (v : VM) : (PID * VM) :=
107107
let (v, child_pid_suffix) := new_child_id parent v in
108108
let rq := runq v in
109109
let new_pid := parent ++ [child_pid_suffix] in
110-
let new_process := {| proc_mb_t := Mailbox; proc_prog := prog |} in
110+
let new_process := {|
111+
pid := new_pid;
112+
proc_mb_t := Mailbox;
113+
cont := prog
114+
|} in
111115
let w' := h_spawn new_pid Mailbox (world v) in
112-
v<| runq := (new_pid, new_process) :: rq|> <|world := w'|>.
116+
(new_pid, v<| runq := new_process :: rq|> <|world := w'|>).
113117

114118
Definition initVm {Mailbox : Set} (w : World) (p : @Program Mailbox) :=
115119
let vm :=
116120
{|
117121
world := w;
118122
runq := [];
119-
sleepq := [];
120123
child_ctr := Pid.FMap.empty _;
121124
|} in
122-
do_spawn [] p vm.
125+
let (_, vm) := do_spawn [] p vm in
126+
vm.
127+
128+
Definition vmte_canon_rel (a b : Process) :=
129+
(* Order of events is canonical when pid a =< pid b: *)
130+
match PIDOrd.compare_ (pid a) (pid b) with
131+
| Gt => False
132+
| _ => True
133+
end.
134+
135+
Lemma vmte_canon_rel_dec a b : Decidable.decidable (vmte_canon_rel a b).
136+
Proof.
137+
unfold Decidable.decidable, vmte_canon_rel.
138+
sauto.
139+
Qed.
140+
141+
Lemma vmte_canon_rel_total a b : vmte_canon_rel a b \/ vmte_canon_rel b a.
142+
Proof.
143+
unfold Decidable.decidable, vmte_canon_rel.
144+
sauto use:PIDOrd.compare_asymm.
145+
Qed.
146+
147+
Global Instance vmevCanonOrder : CanonicalOrder vmte_canon_rel :=
148+
{ canon_rel_dec := vmte_canon_rel_dec;
149+
canon_rel_total := vmte_canon_rel_total;
150+
}.
151+
152+
Definition exec_proc (proc : Process) (vm vm' : VM) : Prop :=
153+
match proc with
154+
{| pid := pid; proc_mb_t := mb_t; cont := prog |} =>
155+
match prog with
156+
| die _ =>
157+
vm' = vm <| world := h_terminate pid (world vm) |>
158+
| p_yield _ next =>
159+
let proc := {| pid := pid; proc_mb_t := mb_t; cont := next |} in
160+
vm' = vm <| runq := proc :: (runq vm) |>
161+
| p_io _ req next =>
162+
exists w' io_reply,
163+
let proc := {| pid := pid; proc_mb_t := mb_t; cont := next io_reply |} in
164+
morphism (h_handler pid req) (world vm) (io_reply, w') /\
165+
vm' = vm <| runq := proc :: (runq vm) |> <| world := w' |>
166+
| @p_spawn _ child_mb_t child_prog next =>
167+
let (child_pid, vm) := do_spawn pid child_prog vm in
168+
let addr := mkAddress child_mb_t child_pid in
169+
let proc := {| pid := pid; proc_mb_t := mb_t; cont := next addr |} in
170+
vm' = vm <| runq := proc :: (runq vm) |>
171+
end
172+
end.
173+
174+
Program Definition vm_state_trans : MFun VM (@ts_ret VM Process) :=
175+
{|
176+
morphism vm ret :=
177+
match runq vm, ret with
178+
| [], None =>
179+
(* No runnable processes: *)
180+
True
181+
| rq, Some (te, vm') =>
182+
exists proc rq',
183+
Pick rq proc rq' /\ exec_proc proc (vm <|runq := rq'|>) vm'
184+
| _, _ =>
185+
False
186+
end
187+
|}.
188+
Next Obligation.
189+
sauto.
190+
Qed.
191+
Next Obligation.
192+
destruct x' as [w rq sq cctr].
193+
destruct rq as [|firstproc rq_].
194+
- exists None. sauto.
195+
- simpl in *.
196+
destruct y as [[te vm']|].
197+
+ destruct H0 as [proc [rq' [Hrq' Hexec]]].
198+
destruct proc as [pid mb_t prog].
199+
destruct prog.
200+
* simpl in Hexec.
201+
Admitted.
202+
203+
Global Instance vmTS : @TransitionSystem VM Process :=
204+
{ ts_state_trans := vm_state_trans;
205+
}.
123206
End VM.
124207

125208
Global Arguments VM {_ _} _.
126-
Global Arguments p_dead {_ _ _}.
209+
Global Arguments die {_ _ _}.
127210
Global Arguments p_yield {_ _ _}.
128-
Global Arguments p_cont {_ _ _}.
211+
Global Arguments p_io {_ _ _}.
129212
Global Arguments p_spawn {_ _ _ _}.
130213

131214
(* begin details *)
132-
Notation "'do' V '<-' I ; C" := (p_cont (I) (fun V => C))
215+
Notation "'do' V '<-' I ; C" := (p_io (I) (fun V => C))
133216
(at level 100, C at next level, V name, right associativity) : slot_scope.
134217

135-
Notation "'done'" := (p_cont (fun _ => p_dead))
136-
(at level 100, right associativity) : slot_scope.
137-
138218
Notation "'call' V '<-' I ; C" := (I (fun V => C))
139219
(at level 100, C at next level, V ident,
140220
right associativity) : slot_scope.
@@ -143,9 +223,8 @@ Notation "'spawn' V '<-' I ; C" := (p_spawn (I) (fun V => C))
143223
(at level 100, C at next level, V ident,
144224
right associativity) : slot_scope.
145225

146-
Notation "P '!' M ; C" := (p_cont (send P (appmsg M)) (fun _ => C))
226+
Notation "P '!' M ; C" := (p_io (send P (appmsg M)) (fun _ => C))
147227
(at level 99, C at next level, right associativity) : slot_scope.
148-
149228
(* end details *)
150229

151230
Definition prog_t `(IOHandler) mb_t :=
@@ -155,14 +234,21 @@ Section test.
155234
Let h := mailboxHandler.
156235
Let VM := VM h.
157236

158-
Let child1 : prog_t h positive := p_dead.
237+
Let child1 : prog_t h positive := die.
159238

160-
Let child2 : prog_t h bool := p_dead.
239+
Let child2 : prog_t h bool := die.
161240

162241
Let prog : prog_t h True :=
163242
spawn c1 <- child1;
164243
c1 ! 1;
165244
spawn c2 <- child2;
166245
c2 ! false;
167-
p_dead.
246+
die.
247+
248+
Fail Let prog' : prog_t h True :=
249+
spawn c1 <- child1;
250+
c1 ! 1;
251+
spawn c2 <- child2;
252+
c2 ! 1;
253+
die.
168254
End test.

0 commit comments

Comments
 (0)