200 likes | 329 Views
This paper explores Optimistic Concurrency and its applications in ensuring data consistency through effective conflict detection mechanisms. It leverages a Program Logic for History (HLRG), which introduces temporal operators for reasoning about historical events without utilizing history variables. The study highlights the advantages of this approach over traditional locking mechanisms, particularly in the verification of non-blocking data structures like stacks, while addressing known issues such as dangling pointers and the ABA problem. This method offers a modular verification framework suitable for complex concurrent systems.
E N D
Reasoning about Optimistic Concurrency Using a Program Logic for History Ming Fu USTC & Yale Joint work with Yong Li, XinyuFeng, ZhongShao and Yu Zhang
What is Optimistic Concurrency? • Increments the shared variable x atomically: • Optimistic Concurrency • Ensuring data consistency by conflict detection • More efficient than coarse-grained lock-based synchronization • Complex, error-prone and hard to verify
An Optimistic Non-blocking Stack Top Next Next n n … • Bug#1: t might be a dangling pointer • Bug#2: ABA problem leads to corrupted stacks
ABA Problem T1 and T2 do pops and pushes, interleaved as follows: T2: a = pop(); c = pop(); push(a); Top Top Top T1: pop() { read t read next interrupt resume CAS succeeds stack corrupted t t A A next C B B B next next C C (removed) (removed) Timeline
Fix Bugs with Hazard Pointers [Michael04] retireNode(t): local i, t; i := 1; while(i<=th_num){ if (i != tid){ t’ := HP[i]; if (t’!= t) i:= i+1; }else i:= i+1; }
nodes on stack • pop( ){ • local done, next, t, t1; • done = false; • while (!done) { • t = Top; • if (t==null) return null; • HP[tid] = t; • t1 := Top; • if (t == t1){ • next = t.Next; • done = CAS(&Top, t, next); • } • } • retireNode(t); • HP[tid] = null; • return t; removed nodes pointed by hazard pointers reclaimable nodes 0 HP 1 2 Top hazard to 3 removed by 3 3 tid A A A 4 hazard to 5 5 C hazard to 7 6 B 7
Verifying Stacks with Hazard Pointers using CSL [Matthew POPL07] • pop(){ • 03 while (!done){ • . . . • 06 <HP[tid] = t; HP’[tid] = Req>; • 07 <if (Top != t) continue; else HP’[tid] = Tail(t.Next) >; • 08 <next = t.Next; if (HP’[tid] != Tail(next)) HP’[tid] = Left>; • 09 <done = CAS(&Top, t, next)>; • 10 } • 11 } • . . . • } History variables HP’[tid] and auxiliary codes are used for representing some temporal properties An indirect approach to specifying historical events
A Program Logic for History (HLRG) No history variables Introduces past tense temporal operators into Rely-Guarantee Reasoning! HLRG gives us the following benefit:
Extensions in HLRG • Program Traces • Trace-based Operational Semantics • Trace assertions p, q, R, G::= P | Id | p q | …
p q Time p holds over the historical trace p q q q q q holds ever since
Time p = (p true) \/ p p p was once true in the history, including the current trace.
Time ... p p = ( p) p p p holds at every step in the history
Rely-Guarantee Reasoning [Jones'83] • R: invariant of environment’s transitions • G: invariant of the thread’s transitions • p: precondition • q: postcondition Basic judgment: R,G┝ {p} C{q} R/G cannot express directly the temporal properties about the subtle interaction between threads !
Frame Time & Invariants Rules Basic judgment: R,G┝ {p} C{q} R/G, p, q are trace assertions Knowledge about history can be added when necessary! (R, G)┝ {p I} C{q} (R G) (II’) (Inv) (R, G)┝ {p} C{q} (R, G)┝ {p} C{q I’} (FrameT) (R, G)┝ {p r} C{q r} Derived invariants I and I’ can be used for free!
Verification of pop nodes on stack removed nodes pointed by hazard pointers reclaimable nodes Shared Resources Shared = Top*Stack* RN*HP 0 HP 1 Temporal property for each node In RN 2 remove(A, tid) : removed by 3 3 A A HP[tid] & Top point to A and CAS succeeds Top 4 Ishazard to 5 HP[tid] points to A 5 C Ishazard to 7 6 Removed by a thread t in the history and pointed by the hazard pointer of thread tid ever since B 7
Verification of pop nodes on stack removed nodes pointed by hazard pointers reclaimable nodes Shared Resources Ishazard(A, tid) : 0 HP HP[tid] & Top point to A (HP[tid] points to A) and not (tid updates Top) 1 2 removed by 3 3 retireNode(A) A A Top 4 Ishazard to 5 hazardfree(A, tid) : 5 Ishazard to 7 C For all other tid’ , Ishazard(A, tid’) 6 remove(A, tid) B 7
Applying Inv Rule in the proof pop( ){ … if (t == t1){ {Ishazard(t,tid)} {Ishazard(t,tid) * t |-> _, _} next = t.Next; done = CAS(&Top, t, next); } } retireNode(t); HP[tid] = null; return t; (R \/ G) Apply Inv rule with Invariants INV1 for avoiding Bug#1: for all t, tid, ishazard(t, tid) /\ t ≠ null => t Є Stack \/ t Є RN see CONCUR’10 paper for details!
Conclusion • A Program Logic for History (HLRG) • R-G reasoning + past tense temporal assertions • Specifying historical events directly without using history variables • modular verification (frame rules over space and time) • Verifyingthe correctness of Michael’s non-blocking stacks
Thank you! Questions?
p q Time s0 s1 s2 s3 s4 s5 s6 p q