PPS - of Yury Chebiryak

University of Saarland
Department of Computer Science
Formal
Specification and Verification of
Functions of the
VAMOS Scheduler
Master’s Seminar
Yury Chebiryak
[email protected]
19.07.2005
Overview
 VAMOS
configuration
Assumptions
 Functional Verification

 Specification
 Proof

Sketch
Invariants
VAMOS Configuration
cVAMOS
dVAMOS
cCVM
PrcsConf
P:PIDPrcsConf
gd
cup
up
tsl
time
ca
ctsl
wkp
cp
pid
...
...
VAMOS configuration: gd
cVAMOS.dVAMOS.gd
...
cup : PID
rdy : list (listPID)
wkp : listPID
inactive : listPID
current_max_prio : PRIO
...
currently running process
array of ready lists
list of PIDs, waiting for IPC
…, not yet activated
current maximum priority,
PRIO={0, …, MAX_PRIO - 1}
PID={0, …, PID_MAX - 1}
VAMOS configuration: PrcsConf
PrcsConf
...
pid : PID
process ID
pri : PRIO
priority (higher is better)
state : nat
current status={READY, INACTIVE ...}
tsl : nat
amount of CPU clock ticks to use
ctsl : nat
...
already consumed timeslice
VAMOS Scheduler
rdy
2
…
1
…
ctsl
tsl
Pi
cup
current_max_prio
0
wkp
inactive
…
idle
…
…
MAX_PRIO=3
Priorized
Preemptive
With IDLE process
Overview

VAMOS configuration
 Assumptions

Functional Verification
 Specification
 Proof

Sketch
Invariants
vamosData
cVAMOS
global
computation
c'VAMOS
VamosData ( SVAMOS , dVAMOS )
VamosData ( S'VAMOS , d'VAMOS )
SVAMOS
concrete
computation
S’VAMOS
vamosData

Disjointness of lists of VAMOS
i  PID .
(dVAMOS .gd.P(i).state  INACTIVE  i  dVAMOS .gd.inactive) 
(dVAMOS .gd.P(i).state  READY
 i  (dVAMOS .gd.rdy [P(i).pri]) 
(dVAMOS .gd.P(i).state  INACTIVE  dVAMOS .gd .P ( i).state  READY
 i  dVAMOS .gd.wkp)

Current process is always ready
dVAMOS .gd.P(cup).state  READY
vamosData

Always exist at least one ready process (IDLE)
dVAMOS .gd.rdy [0]  []

Length of ReadyListsArray
length ( dVAMOS .gd .rdy )  MAX_PRIO

Priority is in correct range
i  PID . dVAMOS .gd.P(i).pri  MAX_PRIO
vamosData

Current Maximum Priority (CMP) is in correct range
dVAMOS .gd .current _ max_ prio  MAX_PRIO

Ready List indexed by CMP is not empty
dVAMOS .gd .rdy [ dVAMOS .gd .current _ max_ prio ]  []

Current maximum priority is correct
cmp _ correct (dVAMOS ) 
Max {i | i  MAX_PRIO  dVAMOS .gd .rdy [ i ]  [] }
Overview
VAMOS configuration
 Assumptions

 Functional
Verification
Specification
 Proof

Sketch
Invariants
Specification: search_next_process
search_next_process : DVAMOS  DVAMOS
Signature:
Assumptions:
VamosData ( SVAMOS , dVAMOS )  cmp _ correct ( dVAMOS )
Let
d'VAMOS  search_next_process dVAMOS
Result:
cmp _ correct ( d'VAMOS ) VamosData(S'VAMOS , d'VAMOS ) 
d'VAMOS .gd'.cup'  dVAMOS .gd.rdy[dVAMOS .gd.current_max_prio[0]]
Specification: compute_max_prio
Signature:
Assumptions:
compute_max_prio : DVAMOS  nat
VamosData ( SVAMOS , dVAMOS )
Let
res  compute_max_prio (dVAMOS )
Result:
res  Max {i | i  MAX_PRIO  dVAMOS .gd .rdy [ i ]  [] }
Specification: wake_up
Case P(p).pri  current_max_prio
2
1
P2
0
idle
wkp
P0
dVAMOS.gd.current_max_prio = 1
pid
pri=1
P1
Specification: wake_up
Case P(p).pri  current_max_prio
2
1
P2
0
idle
wkp
P0
dVAMOS.gd.current_max_prio = 1
pid
prio=1
P1
Delete
Specification: wake_up
Case P(p).pri  current_max_prio
2
1
P2
InsertTail
pid
prio=1
state=READY
0
wkp
idle
P0
dVAMOS.gd.current_max_prio = 1
P1
Specification: wake_up
Case P(p).pri  current_max_prio
cup
2
pid
prio=2
state=READY
1
P2
0
idle
wkp
P0
change
current_max_prio,
call
search_next_process
d´VAMOS.gd´.current_max_prio´=2
d´VAMOS.gd´.cup´= pid
P1
Specification: wake_up
Signature:
wake _ up : DVAMOS  PID  DVAMOS
Let
d'VAMOS  wake_up dVAMOS pid
Assumptions:
pid  dVAMOS .gd .wkp 
VamosData ( SVAMOS , dVAMOS ) 
cmp _ correct ( dVAMOS )
Let
pid_pri  dVAMOS .gd.P(pid).pri
Specification: wake_up
Result:
d'VAMOS .gd'.wkp'  dVAMOS .gd.wkp \ {pid}

d'VAMOS .gd'.rdy'  dVAMOS .gd.rdy [
pid_pri:  ( dVAMOS .gd.rdy [ pid_pri ] ) @ ( pid ) ]

d'VAMOS .gd'.P' (pid).state'  READY

( dVAMOS .gd .current_max_prio  pid_pri 
d'VAMOS .gd'.current_max_prio'  pid_pri 
d'VAMOS .gd'.cup'  pid )

VamosData(S'VAMOS , d'VAMOS )  cmp _ correct ( d'VAMOS )
Specification: process_get_mypid
Signature:
process _ get _ mypid : DVAMOS  PID
Assumptions:
VamosData ( SVAMOS , dVAMOS )  cmp _ correct ( dVAMOS )
Result:
process_get_mypid ( dVAMOS )  dVAMOS .gd .cup
Specification: process_switch_to
P2
cup
2
P2
P3
pid
1
pid
0
idle
ctsl
tsl
Specification: process_switch_to
P2
cup
2
P2
P3
pid
1
pid
0
idle
donate timeslice
donated timeslice
ctsl
tsl
Specification: process_switch_to
cup
2
P3
P2
P2
pid
1
pid
0
idle
Delete, then InsertTail
donated timeslice
ctsl
tsl
Specification: process_switch_to
P2
2
P3
P2
cup
1
pid
0
idle
change cup
pid
donated timeslice
ctsl
tsl
Specification: process_switch_to
Signature:
process_sw itch_to : DVAMOS  PID  DVAMOS
Assumptions:
VamosData(SVAMOS , dVAMOS )  cmp_correct(dVAMOS )
Let
d'VAMOS  process_sw itch_to dVAMOS pid,
pid_is_val id  (pid  0  pid  PID_MAX),
pid_is_rea dy  (dVAMOS .P(pid).state  READY),
precond  pid_is_val id  pid_is_rea dy
Specification: process_switch_to
Abbreviations:
CUP
CUP'
cup_pid
pid_ctsl
pid_ctsl'
cup_tsl
cup_ctsl
 dVAMOS .gd.cup,
 d'VAMOS .gd'.cup',
 dVAMOS .gd.P(CUP).pid,
 dVAMOS .gd.P(pid).ctsl,
 d'VAMOS .gd'.P' (pid).ctsl',
 dVAMOS .gd.P(CUP).tsl,
 dVAMOS .gd.P(CUP).ctsl
Specification: process_switch_to
Result(1):
precond  (pid  CUP) 
CUP'  pid  d'VAMOS .gd'.P' (CUP).ctsl'  0

d'VAMOS .gd'.rdy' [
cup_pid :  (dVAMOS .gd.rdy \ {CUP}) @ [CUP] ]

(pid_ctsl  ( cup_tsl  cup_ctsl)  pid_ctsl'  0)

( (pid_ctsl  (cup_tsl  cup_ctsl) ) 
pid_ctsl'  pid _ ctsl  ( cup_tsl  cup_ctsl))

(VamosData (S'VAMOS , d'VAMOS )  cmp_correct(d'VAMOS )
Specification: process_switch_to
Result(2):
precond  (pid  cVAMOS .dVAMOS .gd.cup)  d'VAMOS  dVAMOS
Error Result:
precond  d'VAMOS  dVAMOS
Specification: prcs_ch_sch_p
Signature:
prcs_ch_sc h_p : DVAMOS  pid  pri  tsl  DVAMOS
Assumptions:
VamosData ( SVAMOS , dVAMOS )  cmp _ correct ( dVAMOS )
Specification: prcs_ch_sch_p
Let
d'VAMOS
pid_is_val id
pid_is_ina ctive
pid_is_rea dy
pri_is_val id
pid_tsl
pid_pri
 prcs_ch_sc h_p dVAMOS
pid
pri tsl,
 (p  0  pid  PID_MAX),
 (dVAMOS .gd.P(pid).state  INACTIVE),
 (dVAMOS .gd.P(pid).state  READY),
 pri  MAX_PRIO,
 dVAMOS .gd.P(pid).tsl,
 dVAMOS .gd.P(pid).pri
Specification: prcs_ch_sch_p
Let
precond  pid_is_val id  pid_is_ina ctive  pri_is_val id
rdy'  dVAMOS .gd.rdy[
pid_pri :  dVAMOS .gd.rdy[pid_pri] \ {pid},
pri
:  dVAMOS .gd .rdy [ pri ] @ [pid]
]
Error Result:
precond  d'VAMOS  dVAMOS
Specification: prcs_ch_sch_p
Result:
precond  (VamosData (S'VAMOS , d'VAMOS )  cmp_correct(d'VAMOS ) 
d'VAMOS .gd'.P'(pid).tsl'  tsl

d'VAMOS .gd'.P'(pid).pri'  pid _ pri

(pid_is _ready  pri  pid_pri 
d'VAMOS .gd'.rdy'  rdy'

d'VAMOS .gd'.current_ max _prio' 
Max {i | i  MAX_PRIO  rdy' [ i ]  [] } )
Overview
VAMOS configuration
 Assumptions

 Functional
Verification
 Specification
Proof
Sketch
 Invariants
Proof Sketch: wake_up
int wake_up(pib_p p)
{
pib_p dummy;
int dummy_int;
wakeup_list =
dlist_pib_t_queue_Delete(wakeup_list,p);
ready_lists[p->priority] =
queue_InsertTail(ready_lists[p->priority],p);
p->state = VAMOS_PROCESS_READY;
if (p->priority > current_max_prio)
{
current_max_prio = p->priority;
dummy_int = search_next_process();
}
return 0;
}
Proof Sketch: wake_up
cVAMOS
Pre(wake_up)
Pre(Delete)
dList wakeup _ list
p  dList wakeup_lis t
int wake_up(pib_p p)
{
pib_p dummy;
int dummy_int;
Post(Delete)
dList wakeup_list \ {p}
wakeup_list =
dlist_pib_t_queue_Delete(wakeup_list,p);
Pre(InsertTail)
Post(InsertTail)
dList ready_lists
dList ready_list @ [p]
Pre(search_next_process) VC1
Post(search_next_process) VC2
Post(wake_up)
c'VAMOS
ready_lists[p->priority] =
queue_InsertTail(ready_lists[p->priority],p);
p->state = VAMOS_PROCESS_READY;
if (p->priority > current_max_prio)
{
current_max_prio = p->priority;
dummy_int = search_next_process();
}
return 0;
}
Proof Sketch: wake_up
cVAMOS
Pre(wake_up)
Pre(Delete)
dList wakeup _ list
p  dList wakeup_lis t
int wake_up(pib_p p)
{
pib_p dummy;
int dummy_int;
Post(Delete)
dList wakeup_list \ {p}
wakeup_list =
dlist_pib_t_queue_Delete(wakeup_list,p);
Pre(InsertTail)
Post(InsertTail)
dList ready_lists
dList ready_list @ [p]
Pre(search_next_process) VC1
Post(search_next_process) VC2
Post(wake_up)
c'VAMOS
ready_lists[p->priority] =
queue_InsertTail(ready_lists[p->priority],p);
p->state = VAMOS_PROCESS_READY;
if (p->priority > current_max_prio)
{
current_max_prio = p->priority;
dummy_int = search_next_process();
}
return 0;
}
Overview
VAMOS configuration
 Assumptions
 Functional Verification

 Specification
 Proof
Sketch
 Invariants
Invariants: Safety properties

Proceses from wakeup_list are not scheduled

After call of search_next_process current
process has priority current_max_prio

If process i has priority less than current_max_prio
it can only be scheduled if switch_to(i) is invoked
(not by handler_clock)
Invariants: Safety properties

If during execution of process i there was no call
of wake_up of process with priority higher than
current_max_prio, then process i consumes its
whole timeslice (it will not be interrupted)

If there is only one process with priority
current_max_prio, then it will run until
 call
of switch_to() or
 call of process_kill performing suicide or
 wake_up of process with higher priority.
Invariants: Liveness properties

Processes with current_max_prio share CPU
time with respect to their timeslices
Summary
Function call
InsertTail
Specification
Implementation Verification
search_next_process
+
+
+
+
+
+
+
+
+
compute_max_prio
+
+
+
wake_up
+
+
+
+
+
+
+
+
+
-
Rotate
process_get_mypid
process_switch_to
prcs_ch_sch_param
Thank you.
Questions?