Automated and Modular Refinement Reasoning for Concurrent Programs Shaz Qadeer.

Slides:



Advertisements
Similar presentations
Technologies for finding errors in object-oriented software K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 1 Summer school on Formal Models.
Advertisements

Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Garbage collection David Walker CS 320. Where are we? Last time: A survey of common garbage collection techniques –Manual memory management –Reference.
QED: A Simplifier for Concurrent Programs Shaz Qadeer Microsoft Research Joint work with Tayfun ElmasAli SezginSerdar Tasiran.
Semantics Static semantics Dynamic semantics attribute grammars
1 Write Barrier Elision for Concurrent Garbage Collectors Martin T. Vechev Cambridge University David F. Bacon IBM T.J.Watson Research Center.
A Program Transformation For Faster Goal-Directed Search Akash Lal, Shaz Qadeer Microsoft Research.
Abstraction and Modular Reasoning for the Verification of Software Corina Pasareanu NASA Ames Research Center.
Reduction, abstraction, and atomicity: How much can we prove about concurrent programs using them? Serdar Tasiran Koç University Istanbul, Turkey Tayfun.
Automated Software Verification with a Permission-Based Logic 20 th June 2014, Zürich Malte Schwerhoff, ETH Zürich.
1 1 Regression Verification for Multi-Threaded Programs Sagar Chaki, SEI-Pittsburgh Arie Gurfinkel, SEI-Pittsburgh Ofer Strichman, Technion-Haifa Originally.
A Rely-Guarantee-Based Simulation for Verifying Concurrent Program Transformations Hongjin Liang, Xinyu Feng & Ming Fu Univ. of Science and Technology.
Automated and Modular Refinement Reasoning for Concurrent Programs Collaborators: Chris Hawblitzel (Microsoft) Erez Petrank (Technion) Serdar Tasiran (Koc.
David Evans CS655: Programming Languages University of Virginia Computer Science Lecture 19: Minding Ps & Qs: Axiomatic.
On-the-Fly Garbage Collection: An Exercise in Cooperation Edsget W. Dijkstra, Leslie Lamport, A.J. Martin and E.F.M. Steffens Communications of the ACM,
Symmetry-Aware Predicate Abstraction for Shared-Variable Concurrent Programs Alastair Donaldson, Alexander Kaiser, Daniel Kroening, and Thomas Wahl Computer.
1 Beyond Reduction Busy Acquire atomic void busy_acquire() { while (true) { if (CAS(m,0,1)) break; } } if (m == 0) { m = 1; return true; } else.
/ PSWLAB Atomizer: A Dynamic Atomicity Checker For Multithreaded Programs By Cormac Flanagan, Stephen N. Freund 24 th April, 2008 Hong,Shin.
Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach Shaz Qadeer Microsoft Research Redmond, WA Serdar Taşıran Serdar.
VIDE Integrated Environment for Development and Verification of Programs.
Modular Verification of Multithreaded Software Shaz Qadeer Compaq Systems Research Center Shaz Qadeer Compaq Systems Research Center Joint work with Cormac.
On the Relationship Between Concurrent Separation Logic and Assume-Guarantee Reasoning Xinyu Feng Yale University Joint work with Rodrigo Ferreira and.
Houdini: An Annotation Assistant for ESC/Java Cormac Flanagan and K. Rustan M. Leino Compaq Systems Research Center.
1 A Modular Checker for Multithreaded Programs Cormac Flanagan HP Systems Research Center Joint work with Shaz Qadeer Sanjit A. Seshia.
Thread-Modular Verification Shaz Qadeer Joint work with Cormac Flanagan Stephen Freund Shaz Qadeer Joint work with Cormac Flanagan Stephen Freund.
Damien Doligez Georges Gonthier POPL 1994 Presented by Eran Yahav Portable, Unobtrusive Garbage Collection for Multiprocessor Systems.
Chair of Software Engineering Automatic Verification of Computer Programs.
Programming Language Semantics Axiomatic Semantics of Parallel Programs.
Comparison Under Abstraction for Verifying Linearizability Daphna Amit Noam Rinetzky Mooly Sagiv Tom RepsEran Yahav Tel Aviv UniversityUniversity of Wisconsin.
K. Rustan M. Leino RiSE, Microsoft Research, Redmond joint work with Peter Müller and Jan Smans Lecture 0 1 September 2009 FOSAD 2009, Bertinoro, Italy.
Maria-Cristina Marinescu Martin Rinard Laboratory for Computer Science Massachusetts Institute of Technology A Synthesis Algorithm for Modular Design of.
Aquinas Hobor and Cristian Gherghina (National University of Singapore) TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.:
Runtime Refinement Checking of Concurrent Data Structures (the VYRD project) Serdar Tasiran Koç University, Istanbul, Turkey Shaz Qadeer Microsoft Research,
Eran Yahav 1. Previously…  An algorithmic view  Abstract data types (ADT)  Correctness Conditions  Sequential consistency  Linearizability  Treiber’s.
Verification of obstruction-free algorithm with contention management Niloufar Shafiei.
Reasoning about programs March CSE 403, Winter 2011, Brun.
Formal verification of skiplist algorithms Student: Trinh Cong Quy Supervisor: Bengt Jonsson Reviewer: Parosh Abdulla.
Symbolic Execution with Abstract Subsumption Checking Saswat Anand College of Computing, Georgia Institute of Technology Corina Păsăreanu QSS, NASA Ames.
Chapter 3 Part II Describing Syntax and Semantics.
Consider the program fragment below left. Assume that the program containing this fragment executes t1() and t2() on separate threads running on separate.
Motivation  Parallel programming is difficult  Culprit: Non-determinism Interleaving of parallel threads But required to harness parallelism  Sequential.
ICFEM 2002, Shanghai Reasoning about Hardware and Software Memory Models Abhik Roychoudhury School of Computing National University of Singapore.
Lightweight Support for Magic Wands in an Automatic Verifier Malte Schwerhoff and Alexander J. Summers 10 th July 2015, ECOOP, Prague.
Compositionality Entails Sequentializability Pranav Garg, P. Madhusudan University of Illinois at Urbana-Champaign.
Formal Verification. Background Information Formal verification methods based on theorem proving techniques and model­checking –To prove the absence of.
/ PSWLAB Thread Modular Model Checking by Cormac Flanagan and Shaz Qadeer (published in Spin’03) Hong,Shin Thread Modular Model.
Specifying Multithreaded Java semantics for Program Verification Abhik Roychoudhury National University of Singapore (Joint work with Tulika Mitra)
A Calculus of Atomic Actions Tayfun Elmas, Shaz Qadeer and Serdar Tasiran POPL ‘ – Seminar in Distributed Algorithms Cynthia Disenfeld 27/05/2013.
Program Analysis and Verification
Overview of Compilation Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Programming Language Principles Lecture 2.
Simplifying Linearizability Proofs Using Reduction and Abstraction Serdar Tasiran Koc University, Istanbul, Turkey Tayfun Elmas, Ali Sezgin, Omer Subasi.
A Calculus of Atomic Actions Serdar Tasiran Koc University, Istanbul, Turkey Tayfun ElmasShaz Qadeer Koc University Microsoft Research.
NIRICT RECONNAISSANCE TOPIC PERFORMANCE AND CORRECTNESS OF GPGPU MARIEKE HUISMAN ALEXANDRU IOSUP ANA LUCIA VARBANESCU ANTON WIJS.
Spring 2017 Program Analysis and Verification
Formal methods: Lecture
The Relationship Between Separation Logic and Implicit Dynamic Frames
Threads Cannot Be Implemented As a Library
Reasoning About Code.
Reasoning about code CSE 331 University of Washington.
Graph-Based Operational Semantics
Modular verification of multithreaded shared-memory programs
Joint work with Yong Li, Xinyu Feng, Zhong Shao and Yu Zhang
Formal Methods in Software Engineering 1
Specifying Multithreaded Java semantics for Program Verification
Verification of Concurrent Programs
Hongjin Liang, Xinyu Feng & Ming Fu
Programming Languages 2nd edition Tucker and Noonan
Over-Approximating Boolean Programs with Unbounded Thread Creation
Programming Languages 2nd edition Tucker and Noonan
Presentation transcript:

Automated and Modular Refinement Reasoning for Concurrent Programs Shaz Qadeer

The refinement approach P is safe P = P 0 refines P 1 … P k-1 refines P k is safe Abstraction Refinement Layered proof could be simpler both for human and computer The most natural specification of a program might be another program

Concurrent program primitive action Acquire(linear tid: int) [ assert tid != 0; assume lock == 0; lock := tid ] primitive action Release(linear tid: int) [ assert tid != 0  lock == tid; lock := 0 ] call A S1; S2 if (e) S1 else S2 while (e) S procedure P(…) { … } call P async call P call P1 || P2 gateaction

Safety Preemptive interleaved semantics Program must not fail gate of primitive atomic actions

Refines In general, any relation that preserves safety If X refines Y and Y is safe, then X is safe In our work, (non-primitive) actions are refined by procedures A partial map RS from procedures to actions for each P in dom(RS), replace every occurrence of call P with call RS(P)

Establishing refinement in two steps Reduce preemptive to cooperative semantics “yield e” for annotating cooperative semantics Check that for each P in dom(RS), body of P is simulated by skip*; RS(P); skip*

Preemptive to cooperative semantics primitive action Acquire(linear tid: int) right [ assert tid != 0; assume lock == 0; lock := tid ] primitive action Release(linear tid: int) left [ assert tid != 0; assert lock == tid; lock := 0 ] RM LM N,  Y B,L L B,R Right mover R Left moverL Both mover B Non moverN Yield Y Pairwise commutativity checks Gate 1  Gate 2 |- Act 1  Act 2  Act 2  Act 1

  R L Y RM LM N,  Y B,L L B,R procedure P(linear tid: int) requires tid != 0; { while (*) { call Acquire(tid); call Release(tid); yield true; }

Checking simulation by skip*; RS(P); skip* The sequence of yield-to-yield execution fragments from beginning to end of P must look like skip*; RS(P); skip* This check is compiled to an assertion Instrument body of P with a bit indicating whether RS(P) has occurred Save global variables at last yield in snapshot variables

Modular reasoning (in the large) A module has procedures and owns a subset of shared variables Atomic actions and yield invariants in a module cannot refer to variables owned by another module Each module is verified separately Ownership is allowed to change across refinement layers Procedures in a module verified together atomic actions, yield invariants, preconditions, postconditions, loop invariants verification conditions conjunctively decomposed for scalable parallel verification

Refinement requires invariants Ghost variables Linear variables for free invariants thread identifiers, permissions, disjoint memory Explicit non-interference reasoning yield e (location invariants ala Owicki-Gries) rely specifications via procedures that abstract over yield statements

Implementation Boogie extension for concurrency and intra-module reasoning BoogieAsm for module system and X86 code generation Summary of verification techniques Linear variables (types) Yield sufficiency (automata) Commutativity (logic) Atomicity refinement (logic) Non-interference (logic) Sequential correctness (logic)

Garbage Collector specification // y = x.f ReadField(linear tid: int, x: idx, f: fld, y: idx) atomic [ Root[y] := Mem[Root[x]][f] ] // x.f = y WriteField(linear tid: int, x: idx, f: fld, y: idx) atomic [ Mem[Root[x]][f] := Root[y] ] // x = new object Alloc(linear tid: int, x: idx) atomic [ var o: obj; assume  Alloc[o]; Alloc[o] := true; Root[x] := o ] Mem: [obj][fld]obj Root: [idx]obj Alloc: [obj]bool // Initialize data structures and start GC thread Initialize(consume gcTid: int, linear mutatorTids:[int]bool) atomic [ ]

Garbage Collector implementation A mark-sweep collector that extends Dijkstra et al. 78 Multiple parallel mutators Fast write barrier No read barrier Performance-related features that make verification difficult Mutator cooperates with collector during the mark phase Mark/Sweep/Idle phases separated by barriers Barrier for atomic root scan

Garbage Collector verification Simple high-level specification refined down to primitive operations (load, store, CAS) Six levels of refinement 2100 lines of code and specification Verifies in ~60s on my 4-core laptop Simplifying assumptions Naïve allocator (sequential search for free space) Logical objects each with the same number of fields Sequentially consistent execution

MarkAllGrays(linear tid:Tid) { while (true) { var isEmpty:bool, node:int := GraySetChoose(tid); if (isEmpty) { break; } for (var f:int := 0; f < numFields; f++) { var child:int := ReadFieldInMark(tid, node, f); if (memAddr(child)) { call GraySetInsertChildIfWhite(tid, node, child); } } call GraySetRemove(tid, node); } } WriteBarrier(linear tid:Tid, y:idx) { var rootVal:int := ReadRoot(tid, y); if (memAddr(rootVal)) { if (ReadMutatorPhase(tid) == MARK) { call GraySetInsertIfWhite(tid, rootVal); } } } Mark(linear tid:Tid) { call ResetSweepPtr(tid); while (true) { if (ScanRoots(tid)) { return; } call MarkAllGrays(tid); } } Alloc(consume tid_in:Tid, y:idx) returns(linear tid:Tid) { call tid := TestRootScanBarrier(tid_in); call UpdateMutatorPhase(tid); var ptr:int, absPtr:obj := AllocRaw(tid, y); } assert mutatorTidWhole(tid_in) && rootAddr(y) && tidOwns(tid_in, y); var o:obj; assume (memAddrAbs(o) && !allocSet[o]); allocSet[o] := true; rootAbs[y] := o; memAbs[o] :=...initial fields...; tid := tid_in; // x.f := y WriteField(linear tid:Tid, x:idx, f:fld, y:idx) { call WriteBarrier(tid, y); call WriteFieldRaw(tid, x, f, y); } assert mutatorTidWhole(tid) && fieldIndex(f) && rootAddr(x) && tidOwns(tid, x) && rootAddr(y) && tidOwns(tid, y) && memAddrAbs(rootAbs[x]); memAbs[rootAbs[x]][f] := rootAbs[y]; // y := x.f ReadField(linear tid:Tid, x:idx, f:fld, y:idx) { call ReadFieldRaw(tid, x, f, y); } assert mutatorTidWhole(tid) && fieldIndex(f) && rootAddr(x) && tidOwns(tid, x) && rootAddr(y) && tidOwns(tid, y) && memAddrAbs(rootAbs[x]); rootAbs[y] := memAbs[rootAbs[x]][f]; Initialize(consume gcTid:Tid, linear mutatorTids:[int]bool) {... async call GarbageCollect(gcTid); } Eq(linear tid:Tid, x:idx, y:idx) // x == y returns (eq:bool) {...} assert... eq := rootAbs[x] == rootAbs[y]; GarbageCollect(linear tid:Tid) { while (true) { call WaitForMutators(tid, Handshake(tid)); call Mark(tid); call WaitForMutators(tid, Handshake(tid)); call Sweep(tid); call Handshake(tid); } } ScanRoots(linear tid:Tid) returns (done:bool) { call CollectorRootScanBarrierStart(tid); call CollectorRootScanBarrierWait(tid); for (var i:int := 0; i < numRoots; i++) { var obj:int := ReadRootInRootScanBarrier(tid, i); if (memAddr(obj)) { call GraySetInsertIfWhite(tid, obj); } } call done := IsGraySetEmpty(tid); call CollectorRootScanBarrierEnd(tid); } WriteFieldRaw(linear tid:Tid, x:idx, f:fld, y:idx) { var valx:int := ReadRoot(tid, x); var valy:int := ReadRoot(tid, y); call WriteFieldGeneral(tid, valx, f, valy); } assert tid == GcTid; Color :=...; done := (forall v:int :: memAddr(v) ==> Color[v] != GRAY); assert mutatorTidWhole(tid) && rootAddr(x) && tidOwns(tid, x) && rootAddr(y) && tidOwns(tid, y) && fieldIndex(f) && memAddr(root[x]) && memAddrAbs(rootAbs[x]); memAbs[rootAbs[x]][f] := rootAbs[y]; mem[root[x]][f] := root[y]; assert mutatorTidWhole(tid) && rootAddr(y) && tidOwns(tid, y); if ( memAddr(root[y]) && Color[root[y]] == WHITE && mutatorPhase[tid] == MARK) { Color[val] := GRAY; } Sweep(linear tid:Tid) {... for (var i:int:= memLo; i < memHi; i++) { call SweepOneObject(tid); } }