/
K. Rustan M. Leino RiSE , K. Rustan M. Leino RiSE ,

K. Rustan M. Leino RiSE , - PowerPoint Presentation

DynamicDiva
DynamicDiva . @DynamicDiva
Follow
342 views
Uploaded On 2022-08-04

K. Rustan M. Leino RiSE , - PPT Presentation

Joint work with Peter Müller ETH Zurich Jan Smans KU Leuven Special thanks to Mike Barnett VMCAI Madrid Spain 18 January 2010 Verifying Concurrent Programs with Chalice Concurrent programs ID: 935483

amp acc requires method acc amp method requires var int valid ensures mask cell square fork permissions myclass permission

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "K. Rustan M. Leino RiSE ," is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

K. Rustan M. Leino

RiSE, Joint work with:Peter Müller (ETH Zurich)Jan Smans (KU Leuven)Special thanks to Mike Barnett

VMCAI, Madrid, Spain, 18 January 2010

Verifying Concurrent Programs with Chalice

Slide2

Concurrent programsInterleaving of thread executionsUnbounded number of: threads, locks, …We need some basis for doing the reasoningA way of thinking!

Slide3

ChaliceExperimental language with focus on:Shared-memory concurrencyStatic verificationKey featuresMemory access governed by a model of permissionsSharing via locks with monitor invariantsCopy-free non-blocking channelsDeadlock checking, dynamic lock re-orderingOther featuresClasses; Mutual exclusion and readers/writers locks; Fractional permissions; Two-state monitor invariants; Asynchronous method calls; Memory leak checking; Logic predicates and functions; Ghost and prophecy variables

Slide4

Dealing with memory (the heap)Access to a memory location requires permissionPermissions are held by activation recordsSyntax for talking about permission to y: acc(y)

Slide5

Incdemo

Slide6

Transfer of permissionsmethod Main(){

var c := new Counter; call c.Inc();

}

method

Inc()

requires acc

(y);

ensures

acc

(y);

{

y := y + 1;

}

acc

(

c.y

)

Slide7

The two halves of a callcall == fork + join is semantically like … but is compiled to more efficient codecall

x,y := o.M(E, F);fork tk

:= o.M

(E, F);

join

x,y :=

tk;

Slide8

Parallel Incdemo

Slide9

Passing permissions to threadsclass XYZ {

var x: int; var y:

int

;

var

z: int

;

method Main()

{

var

c :=

new

XYZ;

fork

c.A

();

fork

c.B

();

}

}

method

A()

requires

acc(x);{ x := x + 1;}

method

B()

requires

acc

(y) &&

acc

(z);

{

y := y + z;

}

Slide10

Read permissionsacc(y) write permission to yrd(y) read permission to yAt any one time, at most one thread can have write permission to a location

Slide11

Passing permissions to threadsclass Fib {

var x: int; var y:

int

;

var

z: int

;

method Main()

{

var

c :=

new

Fib;

fork

c.A

();

fork

c.B

();

}

}

method

A()

requires

rd(x) && acc(y){

y := x + 21;

}

method

B()

requires

rd

(x) &&

acc

(z)

{

z := x + 34;

}

Slide12

Fractional permissionsacc(y) 100% permission to yacc(y, p) p% permission to yrd(y) read permission to yWrite access requires 100%Read access requires >0% = +

acc(y)

acc

(y,69)

acc

(y,31)

rd

(y)

acc

(y,

)

Slide13

Shared stateWhat if two threads want write access to the same location?method A() …{

y := y + 21;}method B() …{

y := y + 34;}

class

Fib

{

var y:

int;

method

Main()

{

var

c :=

new

Fib;

fork

c.A

();

fork

c.B

();

}

}

acc

(

c.y

)

?

Slide14

Monitorsmethod A() …{

acquire this; y := y + 21; release

this

;}

method

B() …

{

acquire

this;

y := y + 34;

release

this

;

}

class

Fib

{

var

y:

int

;

invariant

acc

(y

);

method

Main()

{ var c := new Fib;

share

c;

fork

c.A

();

fork

c.B

();

}

}

acc

(

c.y

)

acc

(y)

Slide15

Locks and permissionsThe conceptsholding a lock, andhaving permissions are orthogonal to one anotherIn particular:Holding a lock does not imply any right to read or modify shared variablesTheir connection is:Acquiring a lock obtains some permissionsReleasing a lock gives up some permissions

Slide16

Monitor invariantsLike other specifications, monitors can hold both permissions and conditionsExample: invariant acc(y) && 0 ≤ y

acc

(y)

Slide17

Owicki Gries counter[Chalice encoding by Bart Jacobs]demo

Slide18

Abstractionclass MyClass {

var x,y: int; predicate

Valid {

acc(

c.x) &&

acc(

c.y) && x ≤

y }

}

Slide19

Abstractionclass MyClass {

var x,y: int; predicate

Valid {

acc(

c.x) &&

acc(

c.y) && x ≤

y }

method New()

returns

(c:

MyClass

)

ensures

c.Valid

;

{

}

method

Mutate()

requires

c.Valid

;

ensures

c.Valid

; { … }}

Slide20

Abstractionclass MyClass {

var x,y: int; predicate

Valid {

acc(

c.x) &&

acc(

c.y) && x ≤

y } method

New() returns

(c:

MyClass

)

ensures

c.Valid

;

{

var

c :=

new

MyClass

{ x := 3, y := 5 };

fold

c.Valid

;

}

method Mutate() requires c.Valid; ensures

c.Valid

;

{

unfold

c.Valid

;

c.y

:=

c.y

+ 3;

fold

c.Valid

;

}

}

acc

(

c.x

)

acc

(

c.y

)

x ≤ y

c.Valid

Slide21

Abstractionclass MyClass {

var x,y: int; predicate

Valid {

acc(

c.x) &&

acc(

c.y) && x ≤

y } method

New() returns

(c:

MyClass

)

ensures

c.Valid

;

{

var

c :=

new

MyClass

{ x := 3, y := 5 };

fold

c.Valid

;

}

method Mutate() requires c.Valid; ensures

c.Valid

;

{

unfold

c.Valid

;

c.y

:=

c.y

+ 3;

fold

c.Valid

;

}

}

acc

(

c.x

)

acc

(

c.y

)

x ≤ y

c.Valid

c.Valid

Slide22

Channelschannel Ch(c: Cell, z: int

) where acc(c.y) && c.y ≤ z;

Slide23

Channelschannel Ch(c: Cell, z: int

) where acc(c.y) && c.y ≤ z;

class Cell {

var

x,y:

int;

method Producer(

ch: Ch

)

{

var

c :=

new

C { x := 0, y := 0 };

send

ch

(c, 5);

}

method

Consumer(

ch

:

Ch

)

{

receive

c,z

:= ch; … }}

acc

(

c.y

)

acc

(

c.x

)

Slide24

Channelschannel Ch(c: Cell, z: int

) where acc(c.y) && c.y ≤ z;

class Cell {

var

x,y:

int;

method Producer(

ch: Ch

)

{

var

c :=

new

C { x := 0, y := 0 };

send

ch

(c, 5);

}

method

Consumer(

ch

:

Ch

)

{

receive

c,z

:= ch; … }}

acc

(

c.y

)

c.y

≤ z

Slide25

Preventing deadlocksDeadlocks are prevented by making sure no such cycle can ever occurThe program partially order locksThe program is checked to acquire locks in strict ascending orderA deadlock is the situation where a nonempty set (cycle) of threads each waits for a resource (e.g., lock) that is held by another thread in the set

Slide26

Wait orderWait order is a dense partial order(Mu, <<) with a bottom element << is the strict version of <<The wait level of an object o is stored in a mutable ghost field o.muAccessing o.mu requires appropriate permissions, as for other fields

Slide27

Example: Avoiding deadlocksWith these preconditions, both methods verifyThe conjunction of the preconditions is false, so the methods can never be invoked at the same timemethod

M(){ acquire

a;

acquire

b;

…}

method

N()

{

acquire

b;

acquire

a;

}

requires

rd

(a.mu

);

requires

rd

(b.mu);

requires

rd

(a.mu)

requires

rd

(b.mu)

requires

waitlevel

<<

b.mu;

requires

b.mu << a.mu;

requires

waitlevel

<<

a.mu;

requires

a.mu << b.mu;

Slide28

Setting the wait orderRecall, the wait level of an object o is stored in the ghost field o.muInitially, the .mu field is The .mu field is set by the share statement: picks some wait level strictly between

L and H, and sets o.mu to that levelProvided L << H and neither denotes an extreme element, such a wait level exists, since the order is denseChanging o.mu requires acc(o.mu), as usual

share

o

between L

and H;

Slide29

Formal semantics of ChaliceGiven as translation to BoogieChalice

Z3

Boogie

Boogie is an intermediate verification language

Slide30

Encoding the heapChalice: o.fBoogie: Heap[ o, f ]where Heap is declared to be a map fromobjects and field names to valuesTo encode permissions, use another map: Mask

Slide31

Encoding a call call M() = Exhale[[ P ]]; Inhale[[ Q ]]

method M() requires P; ensures Q;

Slide32

Exhale and InhaleDefined by structural inductionFor expression P without permission predicatesExhale P ≡ assert PInhale P ≡ assume PExhale acc(o.f, p)

≡ assert p ≤ Mask[o,f]; Mask[o,f] := Mask[o,f] – p;Inhale acc(o.f, p) ≡ if (Mask[o,f] == 0) {

havoc Heap[o,f]; }

Mask[o,f] := Mask[o,f] + p;

Slide33

Examplecall M()=

assert 100 ≤ Mask[this,y];Mask[this,y] := Mask[this,y] – 100;oldH := Heap;if (Mask[this,y] = 0) { havoc Heap[this,y]; }Mask[this,y] := Mask[this,y] + 100;

assume Heap[this,y] = oldH

[this,y] * oldH [this,y

];

class

Cell {

var y:

int;

method

Square()

requires

acc

(y);

ensures

acc

(y) && y =

old

(y*y

);

Slide34

Boogie translation demodemo

Slide35

An alternative to oldLogical constant: Let the verifier figure out K!method

Square(c: Cell) requires acc(c.y);

ensures

acc(

c.y) &&

c.y ==

old(c.y

*c.y);

method

Square(c: Cell,

ghost

K:

int

)

requires

acc

(

c.y

) && K ==

c.y

;

ensures

acc

(

c.y

) &&

c.y

== K*K;

call

Square(c,

c.y);call Square(c, *);

Slide36

Square only reads c.ymethod Square(c: Cell

) returns (r: int) requires

acc(

c.y, ε

);

ensures

acc(

c.y, ε

) && r == c.y

*

c.y

;

method

Square(c: Cell)

returns

(r:

int

)

requires

acc

(

c.y

);

ensures

acc

(

c.y

) && r ==

c.y

*

c.y;method Square(c: Cell, ghost K: perm

)

returns

(r:

int

)

requires

acc

(

c.y

, K);

ensures

acc

(

c.y

, K) && r ==

c.y

*

c.y

;

ε

loses procedural abstraction

Slide37

Language questionsA better notation? rd(c.y)? Does that pick one K for each method activation?Can these 3 kinds of “parameters” (real, ghost, permission) be treated more uniformly?

Which kinds should be indicated explicitly by the programmer and which should be figured out by the compiler?method Square(c: Cell, ghost K: perm

)

returns

(r:

int)

requires

acc(c.y

, K);

ensures

acc

(

c.y

, K) && r ==

c.y

*

c.y

;

Slide38

Chalice summaryPermissions guide what memory locations are allowed to be accessedActivation records can hold permissionsPermissions can also be stored in various “boxes” (monitors, predicates, channels)Permissions can be transferred between activation records and boxesLocks grant mutually exclusive access to monitors

Slide39

Try it for yourselfChalice (and Boogie) available as open source:http://boogie.codeplex.com Tutorial and other papers available from:http://research.microsoft.com/~leino