Separation Logic and Concurrency Verification

Slides:



Advertisements
Similar presentations
Operating Systems ECE344 Midterm review Ding Yuan
Advertisements

Background Concurrent access to shared data can lead to inconsistencies Maintaining data consistency among cooperating processes is critical What is wrong.
CS533 Concepts of Operating Systems Class 3 Monitors.
Certifying Low-Level Programs with Hardware Interrupts and Preemptive Threads Xinyu Feng Toyota Technological Institute at Chicago Joint work with Zhong.
10/19/2007TTI-C PL-Lunch Certified Concurrent Code with Interrupts Xinyu Feng Joint work with Zhong Shao (Yale University) and Yuan Dong (Tsinghua University)
Home: Phones OFF Please Unix Kernel Parminder Singh Kang Home:
Modular Verification of Assembly Code with Stack-Based Control Abstractions Xinyu Feng Yale University Joint work with Zhong Shao, Alexander Vaynberg,
On the Relationship Between Concurrent Separation Logic and Assume-Guarantee Reasoning Xinyu Feng Yale University Joint work with Rodrigo Ferreira and.
CS533 - Concepts of Operating Systems 1 Class Discussion.
CPS110: Implementing threads/locks on a uni-processor Landon Cox.
Threads CS 416: Operating Systems Design, Spring 2001 Department of Computer Science Rutgers University
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Operating Systems CMPSCI 377 Lecture.
Synchronization CSCI 444/544 Operating Systems Fall 2008.
CS510 Concurrent Systems Introduction to Concurrency.
Threads and Concurrency. A First Look at Some Key Concepts kernel The software component that controls the hardware directly, and implements the core.
Concurrency Verification. Why concurrency verification Concurrent programs show in many systems –Multi-task support in OS kernels –Handling interrupts.
Hardware process When the computer is powered up, it begins to execute fetch-execute cycle for the program that is stored in memory at the boot strap entry.
CPS110: Implementing threads Landon Cox. Recap and looking ahead Hardware OS Applications Where we’ve been Where we’re going.
CS399 New Beginnings Jonathan Walpole. 2 Concurrent Programming & Synchronization Primitives.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Computer Systems Principles Synchronization Emery Berger and Mark Corner University.
Hardware process When the computer is powered up, it begins to execute fetch-execute cycle for the program that is stored in memory at the boot strap entry.
CSE 153 Design of Operating Systems Winter 2015 Midterm Review.
COT 4600 Operating Systems Fall 2009 Dan C. Marinescu Office: HEC 439 B Office hours: Tu-Th 3:00-4:00 PM.
Managing Processors Jeff Chase Duke University. The story so far: protected CPU mode user mode kernel mode kernel “top half” kernel “bottom half” (interrupt.
CHAPTER 7 CONCURRENT SOFTWARE Copyright © 2000, Daniel W. Lewis. All Rights Reserved.
Implementing Lock. From the Previous Lecture  The “too much milk” example shows that writing concurrent programs directly with load and store instructions.
CS510 Concurrent Systems Jonathan Walpole. Introduction to Concurrency.
Implementing Mutual Exclusion Andy Wang Operating Systems COP 4610 / CGS 5765.
CS162 Section 2. True/False A thread needs to own a semaphore, meaning the thread has called semaphore.P(), before it can call semaphore.V() False: Any.
Scheduler activations Landon Cox March 23, What is a process? Informal A program in execution Running code + things it can read/write Process ≠
Tutorial 2: Homework 1 and Project 1
CSE 120 Principles of Operating
Multi-processor Scheduling
A Practical Verification Framework for Preemptive OS Kernels
CS 6560: Operating Systems Design
CS703 – Advanced Operating Systems
Synchronization.
Low-Level Program Verification
Scheduler activations
Memory Consistency Models
Memory Consistency Models
Joint work with Yong Li, Xinyu Feng, Zhong Shao and Yu Zhang
Concurrency Verification
Concurrent Separation Logic
COT 5611 Operating Systems Design Principles Spring 2014
Thread Implementation Issues
Lecture Topics: 11/1 General Operating System Concepts Processes
Lecture 2 Part 2 Process Synchronization
Implementing Mutual Exclusion
Kernel Synchronization I
Process Description and Control
Implementing Mutual Exclusion
CSE 451: Operating Systems Winter 2007 Module 6 Synchronization
Concurrent Separation Logic
Concurrent Separation Logic
October 9, 2002 Gary Kimura Lecture #5 October 9, 2002
CSE 451: Operating Systems Autumn 2004 Module 6 Synchronization
CSE 451: Operating Systems Autumn 2003 Lecture 7 Synchronization
CSE 451: Operating Systems Autumn 2005 Lecture 7 Synchronization
CSE 451: Operating Systems Winter 2004 Module 6 Synchronization
CSE 451: Operating Systems Winter 2003 Lecture 7 Synchronization
CSE 153 Design of Operating Systems Winter 19
CS333 Intro to Operating Systems
Chapter 6: Synchronization Tools
CSE 451: Operating Systems Spring 2008 Module 7 Synchronization
CSE 451: Operating Systems Winter 2007 Module 6 Synchronization
CSE 451: Operating Systems Autumn 2009 Module 7 Synchronization
CS703 – Advanced Operating Systems
CSE 451: Operating Systems Spring 2007 Module 7 Synchronization
Presentation transcript:

Separation Logic and Concurrency Verification Xinyu Feng (冯新宇) University of Science and Technology of China

Why concurrency verification Concurrent programs show in many systems Multi-task support in OS kernels Handling interrupts from external devices … Will be more common Multi-core processors Intellectually interesting Correctness/incorrectness are not obvious

Shared-State Concurrency Model B Memory

Execution Model: Simple Examples [ 100 ] := 3 [ 100 ] := 5 [ 100 ] := 3 [ 101 ] := 5 100 101 3 5 100 3/5 Don’t know which one is written first, but order doesn’t matter. Order may affect the result if threads share resources.

Execution Model: Simple Examples It is difficult to discuss resource sharing with memory pointer aliasing. T1: T2: [ x ] := 3 [ y ] := 5 x x y y 3/5 3 5

Execution Model: Simple Examples C1n C21; C22; C2n T1 T2 Non-deterministic interleaving may produce exponential num. of execution traces; Different traces may lead to different results (depends on the resource sharing).

Challenges to reason about concurrent programs Sharing of resources makes the result dependent on the ordering of execution Non-deterministic interleaving produces exponential num. of possible ordering Memory pointer aliasing makes it difficult to tell how resources are shared

Outline of this Lecture Separation Logic Concurrent Separation Logic (CSL) Extension of CSL to handle Interrupts

Separation Logic A Hoare-style program logic: { p } C { q } [Ishtiaq&O’Hearn’01,Reynolds’02] A Hoare-style program logic: { p } C { q } What’s new here is the assertion language.

Separation Logic Assertions emp empty heap l  n n l p  q p q p  q

Separation Logic Assertions emp empty heap l  n n l p  q p q l_ defined as n. l  n ln defined as (ln)  true n l

Properties   pemp  p pq  qp pp  p ptrue  p pp  p (l_)(l_)  false p  ptrue ptrue  p 

Assertions Model Ownership [l] := m; {(l  m)} {emp} [l] := m; {???}   Ownership cannot be duplicated: (l_)  (l_)(l_)

Strength of Separation {(xn)  (yn)} [x] := m; {(xm)  (yn)} {(xn)  (yn)} [x] := m; {(xm)  (yn)}   what if x=y ?

A Frame Rule for Modularity C p q r { p } C { q } { p  r } C { q  r } r Another example showing the strength of separation!

Specification of a List top … List (top)  (top = null)  emp  next. top  (_, next)  List ( next ).

Example: getNode getNode() if (top <> null){ { List (top) } r1 = top; r2 = top.next; top = r2; } else {r1 = null } { List (top) } { List (top)  top  null } { next. top  (_, next)  List ( next ) } { r1 = top  next. top  (_, next)  List ( next )  r2 = next } { r1  (_, _)  List ( r2 ) } { r1  (_, _)  List ( top ) } { List ( top ) * (top = r1 = null  emp  r1  (_, _) ) }

Reading Materials See the miniCourse webpage of John Reynolds: http://www.cs.cmu.edu/~jcr/

Outline of This Lecture Separation Logic Concurrent Separation Logic (CSL) Extension of CSL to handle Interrupts

Separation Logic for Concurrency [ 100 ] := 3 [ 100 ] := 5 [ 100 ] := 3 [ 101 ] := 5 100 101 3 5 100 3/5 Separation is an effective way to control interference.

Concurrent Separation Logic (CSL) [O’Hearn 2004] Key ideas: Threads can only access disjoint resources at the same time. p  q {p} C1 {p'} {q} C2 {q'} p q Transfer is logical: no memory copying {p  q} C1 || C2 {p'  q'} C1 and C2 are verified as sequential programs But how to allow threads to share resources?

Locks and Critical Regions Lock-based critical regions (CR): l.acq(); … l.rel() Invariants about memory protected by locks:  = {l1  r1, …, ln  rn} r1, …, rn disjoint l1 ln r1   rn Note: different locks protect disjoint resources.

Concurrent Separation Logic (CSL) ┝ {p} C1 {p'} ┝ {q} C2 {q'} ┝ {p  q} C1 || C2 {p'  q'} l1 ln Memory Model: p q r1   rn

CSL (cont’d) p1 r p2 p2 p1  r  p2 p1’ p1’  r  p2 r p2 p2 Each thread can freely access to its local resource.

CSL (cont’d) p1 r p2 p2 p1  r  p2 p1  r  p2 l.acq(); C l.rel(); Suppose (l) = r

CSL (cont’d) p1 r p2 p2 p1  r  p2 p1  r  p2 p1’  r  p2 l.acq(); l.rel()

CSL (cont’d) p1 r p2 p2 p1  r  p2 p1  r  p2 p1’  r  p2 l.acq(); p1  r  p2 C p1’  r  p2 l.rel(); p1’  r  p2

CSL (cont’d) Reasoning about lock acquire/release: ┝ {emp} l.acq() { (l) } Acquiring the lock means getting the ownership of the lock-protected resource. (l) is transferred from shared to local.

CSL (cont’d) The rule does not support reentrant locks: ┝ {emp} l.acq() { (l) } {emp} l.acq() {(l) } {(l)  (l) }

CSL (cont’d) Reasoning about lock acquire/release: ┝ { (l) } l.rel() { emp } Before releasing the lock, the corresponding resource needs to be well-formed. Releasing the lock means losing the ownership of the resource (which is transferred from local to shared).

CSL (cont’d) Reasoning about lock acquire/release: ┝ {emp} l.acq() { (l) } ┝ { (l) } l.rel() { emp } We call this ownership-transfer axiomatic semantics of locks

Example: List  = { l  List(top) } getNode(): l.acq(); -{emp} … l.rel(); -{emp} top … r -{emp * List(top)}; -{r(_,_) * List(top)} -{r(_,_) } Sequential verification

Outline of This Lecture Separation Logic Concurrent Separation Logic (CSL) Extension of CSL to handle Interrupts

Layering of OS Code B: concurrent code with explicit interrupts How to certify ???

Example: Spinlocks (uniprocessor) 0/1 acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; // disable Interrupt timer_0: ... switch iret // lock is taken by others … [l] :=1; …

Example: Spinlocks (uniprocessor) 0/1 acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; // lock available // acquire lock // enable Interrupt

Concurrency with Interrupts: Challenges IR0 IR1 Asymmetric preemption between handlers and non-handler code Intertwining between threads and handlers Asymmetric synchronization: cli/sti are different from locks

Study the problem in 3 steps Interrupts with Sequential Programs Interrupts with Multi-threaded Programs Adding block/unblock primitives

AIM – I : The Machine (program) P ::=(C,S,pc) (data heap) H f1: I1 pc addu … cli sti iret … j f 1 2 … f2: I2 r1 r2 r3 … rn ih: ISR (register file) R ie … (code heap) C (state) S ::=(H,R,ie) ::={f  I}* (program) P ::=(C,S,pc)

Example: Teeter-Totter left right 50 50 timer: if([left] == 0){ print(“right wins!”); iret; } [left] := [left]-1; [right] := [right]+1; while([right] != 0){ cli; [right] := [right]-1; [left] := [left]+1; sti; } print(“left wins!”); Which side wins depends on how frequently the timer interrupt comes.

AIM – I : The Memory Model INV Wellformedness of A; Protocol for sharing B A Memory sti … iret cli … Non-handler Handler

AIM – I : cli/sti B cli B A critical region B sti B A B ie = 1 ie = 0 INV B INV cli B A critical region B Explain memory models: add animation sti B A INV B INV ie = 1 ie = 0

Ownership Transfer Semantics for cli/sti ┝ {ie=1} cli {ie=0  INV } ┝ {ie=0  INV} sti {ie=1}

AIM – I : handler B A irq B A iret B A B A ie = 1 ie = 0 INV INV INV Explain memory models: add animation iret B A INV B A INV ie = 1 ie = 0

Example: Teeter-Totter left right INV: m, n. (left  m)  (right  n)  (m+n = 100) m n while(!done){ -{ie=1} cli; -{ie=0  INV} [right] := [right]-1; [left] := [left]+1; done := ([right] == 0); sti; } timer: -{INV} if([left] == 0){ print(“right wins!”); iret; } [left] := [left]-1; [right] := [right]+1; INV is broken in the middle

Step 2: Interrupts with Multi-threaded Programs

AIM – II : The Machine (program) P ::=(C,S,Q,pc) … (ready. queue) Q (data heap) H f1: I1 1 2 … f2: I2 pc cli sti … switch j f r1 r2 r3 … rn ih: ISR (register file) R ie … (code heap) C (state) S ::=(H,R,ie) ::={f  I}* (program) P ::=(C,S,Q,pc)

AIM – II : switch A primitive implemented at layer C Interrupt must be disabled before executing switch Operational semantics: Put the current thread into ready Q Resume a thread in Q (non-deterministic op) Explain where does switch come from

Example: spin locks acquire (l): cli; while([l] == 0){ sti; } return; switch release (l): cli; [l] := 1; sti; return;

Examples Layer A: timer_0: ... switch iret yield: cli switch sti ret ie = 0: non-preemptive threads ie = 1 & timer_1: non-preemptive threads ie = 1 & timer_0: preemptive threads timer_1: ... iret

T1/T2: threads’ private memory AIM – II : Memory Model INV B A A T1/T2: threads’ private memory C T1 T2 INV1 C: Shared by threads A INV

cli/sti t1: C t1: A T1 T2 T1 T2 C A critical region t1: C' t1: A' T1' INV T1 T2 INV1 T1 T2 t1: cli C A INV1 INV critical region t1: C' t1: A' INV T1' T2 INV1 C' A' INV T1' T2 INV1 t1: sti ie = 1 ie = 0

Example: Spinlocks (uniprocessor) 0/1 R  -{ emp } -{ R } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; Lock l protects the resource R release (l): cli; [l] := 1; sti; return; Don’t talk about the details of abstract specifications

Example: Spinlocks (uniprocessor) 0/1 R  -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; INV1: b. (l  b)  (b=0emp  b=1R) Lock and resource R are available Lock is taken; no R for share. A INV C T1 T2 INV1 The lock and the resource R are shared between threads (part of block C). -{ R }

Example: Spinlocks (uniprocessor) 0/1 R  INV1: b. (l  b)  (b=0emp  b=1R) -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; -{ emp  INV1  INV}

Example: Spinlocks (uniprocessor) 0/1 R  INV1: b. (l  b)  (b=0emp  b=1R) -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; -{ emp  INV1  INV} -{ emp  INV1  INV} -{ emp }

Example: Spinlocks (uniprocessor) 0/1 R  INV1: b. (l  b)  (b=0emp  b=1R) -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; -{ emp  INV1  INV} -{ emp  INV1  INV} maybe different state -{ emp } -{ emp  INV1  INV} -{ (l  1)  R  INV} emp  INV1

Example: Spinlocks (uniprocessor) 0/1 R  INV1: b. (l  b)  (b=0emp  b=1R) -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; -{ emp  INV1  INV} -{ emp  INV1  INV} -{ emp } -{ emp  INV1  INV} -{ (l  1)  R  INV} emp  INV1 -{ (l  0)  R  INV}

Example: Spinlocks (uniprocessor) 0/1 R  INV1: b. (l  b)  (b=0emp  b=1R) -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; -{ emp  INV1  INV } -{ emp  INV1  INV } -{ emp } -{ emp  INV1  INV } Verification is the same as sequential reasoning -{ (l  1)  R  INV } -{ (l  0)  R  INV } INV1 -{ R } -{ R } The verification is sequential!

Example: Spinlocks (uniprocessor) 0/1 R  INV1: b. (l  b)  (b=0emp  b=1R) -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; -{ emp  INV1  INV } timer_0: ... switch iret … [l] :=1; … -{ emp  INV1  INV } -{ emp } -{ emp  INV1  INV } Verification is the same as sequential reasoning -{ (l  1)  R  INV } -{ (l  0)  R  INV } INV1 -{ R } -{ R } The verification is sequential!

switch Thread t1 Thread t2 t2: C t2: A T1 T2 T1 T2 untouched t1: C INV T1 T2 INV1 T1 T2 untouched t1: switch t1: C t1: A INV1 * INV preserved INV1 INV … sti … cli … switch t1: C' t1: A' INV T1 T2' INV1 t2: C' t2: A' INV T1 T2' INV1 t2: switch Thread t1 Thread t2 ie = 0

Local Semantics for switch ┝ {ie = 0  INV1  INV } switch {ie = 0  INV1  INV }

Example: Spinlocks (uniprocessor) 0/1 R  INV1: b. (l  b)  (b=0emp  b=1R) -{ emp } acquire (l): cli; while([l] == 0){ sti; } [l] := 0; return; -{ emp  INV1  INV } -{ emp  INV1  INV } switch INV1  INV preserved -{ emp } -{ emp  INV1  INV } Verification is the same as sequential reasoning -{ (l  1)  R  INV } -{ (l  0)  R  INV } INV1 -{ R } -{ R } The verification is sequential!

Step 3: Adding block/unblock primitives

AIM – III : The Machine (program) P ::=(C,S,B,Q,pc) … (ready. queue) Q f1: f2: ih: r1 1 2 … r2 r3 rn (data heap) H (register file) R ie pc R … (ready. queue) Q w1 w2 (code heap) C (state) S ::=(H,R,ie) … block unblock … pc wn B (program) P ::=(C,S,B,Q,pc)

AIM – III : block and unblock block rs put current thread into the block queue B(rs) pick a thread from ready queue to execute unblock rs, rd move a thread from B(rs) to the ready queue put the thread id into rd, put 0 if B(rs) empty no context switching!

Examples: locks  l 0/1 R B(l) = Ql acquire_0(l): cli; if ([l] == 0) block l; else [l] := 0; sti; return; acquire_1(l): cli; while ([l] == 0) block l; [l] := 0; sti; return; release_0(l): local x; cli; unblock l x; if (x == 0) [l] := 1; sti; return; release_1(l): local x; cli; unblock l x; [l] := 1; sti; return;

How to interpret block/unblock Threads block themselves to wait for resources. locks: wait for resources protected by locks condition variables: wait for resources over which the condition holds w1 R1 R2 Rn  ::= {w0  R0, … , wn  Rn} Ri can be emp ! w2 … wn B

How to interpret block/unblock INV T1 INV1 ! T1 ? T2 T2 block T1 T1 INV1 INV block unblock T1 INV INV1 T2 ! T2 INV INV1 T1 ! ! switch Thread 1 Thread 2

Local Semantics for block/unblock p  (ie = 0)  INV1  INV0  ┝ { p } block l {p  (l)} p  ie = 0  ┝ {p  (l)} unblock l x {p  (x  0  emp  x = 0  (l))} Blocked thread is released: ownership of (l) is transferred No threads waiting and no ownership transfer

Examples: locks  l 0/1 R B(l) = Ql (l) = R INV1: b, (l  b)  (b=0emp  b=1R) -{ emp } acquire_0(l): cli; if ([l] == 0) block l; else [l] := 0; sti; return; -{ emp } -{ emp  INV1  INV} -{ emp  INV1  INV} -{ emp  INV1  INV  (l) } -{ emp  INV1  INV  R} -{ emp  R} -{ R }

Examples: locks  l 0/1 R B(l) = Ql (l) = R INV1: b, (l  b)  (b=0emp  b=1R) -{ R } release_0(l): local x; cli; unblock l x; if (x == 0) [l] := 1; sti; return; -{ R } -{ R  INV1  INV} -{(x=0  R  x 0  emp)  INV1  INV} -{ R  INV1  INV0} -{ (l  0)  R  INV} -{ (l  1)  R  INV} -{ INV1  INV} -{ emp } -{ emp }

Examples: locks  l 0/1 R B(l) = Ql (l) = R (l) = emp INV1: b, (l  b)  (b=0emp  b=1R) -{ emp } -{ R } acquire_1(l): cli; while ([l] == 0) block l; [l] := 0; sti; return; release_1(l): local x; cli; unblock l x; [l] := 1; sti; return; -{ R } -{ emp }

Examples : Condition Variables wait()/notify() Hoare Style / Brinch-Hanson Style Mesa style Reading material: Feng et al. “Certifying Low-Level Programs with Hardware Interrupts and Preemptive Threads”.

Summary Separation logic Concurrent Separation Logic (CSL) Ownership transfer semantics to thread primitives and interrupt primitives Can be further extended

Thank you