Presentation is loading. Please wait.

Presentation is loading. Please wait.

A Program Logic for Concurrent Objects under Fair Scheduling Hongjin Liang and Xinyu Feng University of Science and Technology of China (USTC) To appear.

Similar presentations


Presentation on theme: "A Program Logic for Concurrent Objects under Fair Scheduling Hongjin Liang and Xinyu Feng University of Science and Technology of China (USTC) To appear."— Presentation transcript:

1 A Program Logic for Concurrent Objects under Fair Scheduling Hongjin Liang and Xinyu Feng University of Science and Technology of China (USTC) To appear at POPL 2016

2 … push(7); x = pop(); … push(6); … Client code C java.util.concurrent void push(int v) { … } … int pop() { … } Concurrent Object O Whole program C[O]

3 Correctness of O Linearizability Correctness w.r.t. functionality Not talk about termination/liveness properties Progress properties Lock-freedom (LF) Wait-freedom (WF) Obstruction-freedom (OF) Deadlock-freedom (DF) Starvation-freedom (SF) Non-blocking synchronization - Program Logics: Gotsman et al. POPL’09, Hoffmann et al. LICS’13, … Blocking synchronization - Program Logics: ???

4 DF and SF as Progress Properties DF: in each fair execution, there always exists some method call that can finish Fair sched: every active thread gets eventually executed Disallow non-termination of critical section f() { lock L; while (true) {}; unlock L; }  [Herlihy and Shavit 2011]

5 DF and SF as Progress Properties DF: in each fair execution, there always exists some method call that can finish Fair sched: every active thread gets eventually executed Disallow non-termination of critical section Disallow live-lock g1() { lock L1; while (!available(L2)) { unlock L1; lock L1; } unlock L1; } g2() { lock L2; while (!available(L1)) { unlock L2; lock L2; } unlock L2; }  [Herlihy and Shavit 2011]

6 DF and SF as Progress Properties DF: in each fair execution, there always exists some method call that can finish Fair sched: every active thread gets eventually executed Disallow non-termination of critical section Disallow live-lock Possible ad-hoc synchronization h1() { x := 1; while (y != 0) {}; x := 0; } h2() { y := 1; while (x != 0) {}; y := 0; }  [Herlihy and Shavit 2011]

7 DF and SF as Progress Properties DF: in each fair execution, there always exists some method call that can finish Disallow non-termination of critical section Disallow live-lock Possible ad-hoc synchronization  Not verified in existing work which views DF as a safety property SF: in each fair execution, every method call can finish [Herlihy and Shavit 2011]

8 Our Contributions Program Logic LiLi for Linearizability & Liveness Identify two challenges in progress verification, addressed by separate mechanisms Unify thread-local reasoning about DF and SF One set of inference rules (also applied to verifying LF and WF) Examples: Ticket locks, queue locks, TAS locks, two-lock queues, … We’re the first to verify SF of lock-coupling lists and DF of optimistic lists and lazy lists

9 Challenges in Progress Verification In sequential settings, no infinite loops  termination In concurrent settings, env interference may affect termination of a method Blocking Delay

10 Challenge 1: Blocking Caused by absence of env’s certain actions (e.g. unlock) f() { lock L; unlock L; } g() { lock L; } f(); || g(); f may never terminate because it keeps waiting for env’s unlock action Not acceptable.

11 Challenge 1: Blocking Caused by absence of env’s certain actions (e.g. unlock) Sometimes bad: the certain action never happens Sometimes acceptable: the certain action eventually happens under fair scheduling SF and DF assume fair scheduling f() { lock L; unlock L; } f(); || f(); Left f may wait for env’s unlock. But it will terminate under fair scheduling.

12 Challenge 1: Blocking Caused by absence of env’s certain actions (e.g. unlock) Sometimes bad: the certain action never happens Sometimes acceptable: the certain action eventually happens under fair scheduling How to support “acceptable” blocking but prevent “bad” blocking? Our idea: introduce definite actions D to specify the certain actions that eventually happen

13 Our idea: definite actions D D is a special action in the form of P  Q Enabled(D) is defined as P D should be “definite”: Q should eventually be reached (regardless of env) once P holds the thread has released lock the thread has acquired lock D Enabled assume fair scheduling P Q

14 Queue management in banks Using D to verify counter with ticket lock inc() { local i, r; i := getAndInc( next ); while( i != owner ) {} ; // acquire lock r := cnt; cnt := r + 1; // critical section owner := i + 1; // release lock } the next available ticket currently being served next owner i

15 Using D to verify counter with ticket lock inc() { local i, r; i := getAndInc( next ); while( i != owner ) {} ; // acquire lock r := cnt; cnt := r + 1; // critical section owner := i + 1; // release lock } 0123 T1: request lock T2: request lock T1: release lock T3: request lock owner next Lock acquired It’s SF, because critical section is straight-line code threads requesting the lock form a queue Lock acquired

16 Using D to verify counter with ticket lock T is blocked: it is waiting for env threads ahead of it in the queue to finish D next owner 0123 TT2 T1 T is blocked Lock acquired the thread has released lock the thread acquires lock D How to establish D (prove D is indeed “definite”) ? Prove critical section terminates no matter what env does

17 T will get lockT2 releases lock T2 gets lock D T1 releases lock T1 gets lock D Enabled initially next owner 0123 TT2 T1 DProgress: T will be unblocked after env finishes a finite number of Ds Enable fair sched T is blocked Lock acquired which form a queue to ensure SF Queue length is a decreasing metric

18 Summary of the definite action idea Support “good” blocking D will definitely happen under fair sched, regardless of env DProgress: any blocked thread will be unblocked after env finishes a finite queue of Ds SF: every method can finish in any fair execution More examples: queue locks, lock-coupling lists  DF: blocking and delay are intertwined

19 Challenge 2: Delay Caused by occurrence of env’s certain actions (e.g. object state updates via cas) incDF() { local b, r; b := false; while( !b ) { b := cas(&L, 0, T); } r := cnt; cnt := r + 1; // critical section L := 0; } current thread ID Example: counter with cas lock incDF(); while(true) incDF(); Left incDF may never terminate due to env’s infinite num of successful cases. Acceptable, since DF requires only whole-system progress. Delay!

20 D & DProgress idea for blocking does not allow delay in the DF counter T will get lockT1 releases lock T1 is holding lock D T2 gets lock ? T is blocked Queue jumps! DProgress: T will be unblocked after env finishes a finite queue of Ds, where queue length is a decreasing metric  Queue jumps delay the progress of the unblocked T. Allowed, since DF requires only whole-system progress.

21 Relax DProgress to allow queue jumps DProgress: T will be unblocked after env finishes a finite queue of Ds, where queue length can be increased when delayed by env. T will get lockT1 releases lock T1 is holding lock T2 gets lock ? D Queue jumps! Problem: How to prevent infinite delays without whole-system progress?

22 Tokens ensure no infinite delays before whole-system progress Our idea: assign tokens Consume a token for a delaying action Similar ideas have been used to verify LF (i.e. whole-system progress under any scheduling) [Hoffmann et al LICS’13, Liang et al CSL-LICS’14]

23 Tokens ensure no infinite delays before whole-system progress inc() { { p *  } local b, r; b := false; while( !b ) { b := cas(&L, 0, T); } r := cnt; cnt := r + 1; L := 0; { q } } pay  at successful cas (the only action that can jump other threads’ queues)

24 Summary for DF verification Blocking and delay are intertwined Blocking: D will definitely happen under fair sched, regardless of env DProgress: a blocked thread waits for env to finish a finite queue of Ds Allow queue jumps (queue length increases) when delayed by env Delay: Each method is assigned a finite number of tokens Delaying action: pay one token DF: whole system progress under fair scheduling

25 By turning on/off mechanisms for blocking & delay, we can support all the four progress properties. non-delaydelay non-blockingwait-freedom  lock-freedom  blockingstarvation-freedom  deadlock-freedom

26 Trickier: Blocking + Delay + Rollback add(e) { // all locks are CAS locks local b := false, p, c; while (!b) { (p, c) := find(e); lock p; lock c; b := validate(p, c); if (!b) { unlock c; unlock p; } } … // insert e between p and c unlock c; unlock p; } Examples: optimistic lists and lazy lists It’s deadlock-free. Problem: A thread may lock a node for an unbounded num of times. Need infinite tokens? Our solution: stratify tokens (see the paper)

27 Our logic LiLi Judgment O : concrete method impl (e.g. cas-lock counter) A : abstract atomic spec (e.g. ) D : definite actions R, G : rely/guarantee to describe env interference (also label delaying actions) p : concrete & abstract states & tokens D, R, G { p } O : A

28 Soundness Theorem for LiLi a) O is linearizable w.r.t. A If, then we have: {p} O : A D, R, G b) O is deadlock-free c)if R & G do not have delaying actions, then O is starvation-free d)if D is not used, then O is lock-free e)if D is not used and R & G do not have delaying actions, then O is wait-free non-delaydelay non-blockingWF  LF  blockingSF  DF

29 Summary: LiLi for Linearzability & Liveness Blocking: definite actions Delay: tokens Unified: By ignoring either or both features, LiLi can be instantiated to verify all the four progress properties non-delaydelay non-blockingwait-freedom  lock-freedom  blockingstarvation-freedom  deadlock-freedom

30 Backup Slides

31 Obstruction-Freedom Progress when the thread executes in isolation (without interference from env) non-delay“good” delay unlimited delay non- blocking wait- freedom  lock- freedom  obstruction- freedom  “good” blocking starvation- freedom  deadlock- freedom

32 Obstruction-Freedom Progress when the thread executes in isolation (without interference from env) g1() { while (x > 0) { x--; } g2() { while (x < 10) { x++; }

33 Comparisons with earlier token-based work for LF verification We all assign  -tokens to loops (pay  at each round) But LiLi also assigns  -tokens for delaying actions Earlier work assumes each method has only one delaying action, which is at the linearization point (LP) [Hoffmann et al LICS’13, Liang et al CSL-LICS’14] incLF(){ local done, r; done := false; while (!done) { r := cnt; done := cas(cnt, r, r + 1); // LP }

34 Stratify tokens and delaying actions add(e) { {  (1, 2)  … } local b := false, p, c; while (!b) { (p, c) := find(e); { valid(p, c)   (1, 2)  …  … } lock p; lock c; { valid(p, c)   (1, 0)  …  invalid(p, c)   (1, 2)  … } b := validate(p, c); if (!b) { unlock c; unlock p; } } … // insert e between p and c unlock c; unlock p; } invalid(p, c)   (1, 4)  … } Could reset level-1 tokens when delayed by env’s level-2 action Level 2: for add/remove Level 1: for lock p & lock c

35 Prevent Live-Lock by stratification of  -tokens & delaying actions Level 2: lock L2 Level 1: lock L1 When g2 locks L2, g1 gets more 1-level  -tokens But 2-level  -tokens do not increase! g1() { lock L1; while (available(L2)) { unlock L1; lock L1; } unlock L1; } g2() { lock L2; while (available(L1)) { unlock L2; lock L2; } unlock L2; } g1(); || g2();

36 Establish D Termination of loop (“critical section”) when D is enabled p’ has one less  -token than p one token is consumed to start the new iteration  -tokens do not increase, unless delayed by env {p’} C {p}D, R, G {p} while B do C {p   B} D, R, G p  B  Enabled(D)  p’ *  …

37 Establish D Termination of loop (“critical section”) when D is enabled Global constraints (at TOP rule) {p’} C {p}D, R, G {p} while B do C {p   B} D, R, G p  B  Enabled(D)  p’ *  … {p  arem(A)   (E)} C {p  arem(skip)} D, R, G {p} C : AD, R, G p   Enabled(D) G  D  (Enabled(D)  Enabled(D)) …

38 DProgress queue for blocking {p’} C {p}D, R, G {p} while B do C {p   B} D, R, G p  B  (Enabled(D)  Q)  p’ *  p  DProgress( n, D, Q)DProgress( n, D, Q) stable

39 The full rule for while {p’} C {p}D, R, G {p} while B do C {p   B} D, R, G p  B  (Enabled(D)  Q)  p’ *  p  DProgress( n, D, Q)DProgress( n, D, Q) stable

40 Tokens for delay ATOM rule: Consume  -tokens q’  k q : k-level  -tokens decrease Stable(p, R) Reset j-level  -tokens for k-level env actions where j < k Reset  -tokens to loop more rounds {p} C {q’} SL {p} atomic{C} {q}D, R, G q’  k q (p  k q)  G

41 Why linearizability and progress together? Progress-aware abstractions for concurrent objects Contextual refinement O  A P Linearizability O  lin A  Progress P(O)  D, R, G { p } O : A  Progress-aware spec

42 Progress-aware specs A SF and A DF O  A P : Assume fair scheduling Preserve termination behaviors A SF : atomic spec A A DF : wrap A with delaying code O  APO  AP O  lin A  P(O)P(O)  D, R, G { p } O : A 

43 DF-aware spec O  wr(A) O  lin A  DF(O)  D, R, G { p } O : A 


Download ppt "A Program Logic for Concurrent Objects under Fair Scheduling Hongjin Liang and Xinyu Feng University of Science and Technology of China (USTC) To appear."

Similar presentations


Ads by Google