reasoning about optimistic concurrency using a program logic for history
DESCRIPTION
Reasoning about Optimistic Concurrency Using a Program Logic for History. Ming Fu USTC & Yale Joint work with Yong Li, Xinyu Feng , Zhong Shao and Yu Zhang. What is Optimistic Concurrency? . Increments the shared variable x atomically: Optimistic Concurrency - PowerPoint PPT PresentationTRANSCRIPT
Reasoning about Optimistic Concurrency Using a Program Logic for History
Ming FuUSTC & Yale
Joint work with Yong Li, Xinyu Feng, Zhong Shao 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
Pessimistic Optimistic
lock x; x++; unlock x;
int t; do { t = x; }while (!CAS(&x, t,
t+1))
An Optimistic Non-blocking Stack
pop( ){1 local done, next, t;2 done = false;3 while (!done) {4 t = Top; 5 if (t==null) return
null;6 next = t.Next;7 done = CAS(&Top, t,
next);8 }9 return t;
push(x){10 local done, t;
11 done = false;12 while(!done) {13 t = Top;14 x.Next = t;15 done = CAS(&Top,
t, x);16 }17 return true;
Bug#1: t might be a dangling pointerBug#2: ABA problem leads to corrupted stacks
…n Next n Next
Top
ABA ProblemT1 and T2 do pops and pushes, interleaved as follows:
A
C
B
Top
t
next
B
Cnext(removed)
Top
A
B
t
Top
Cnext(removed)
Timeline
T1:pop(){ read t read next interrupt
resume CAS succeedsstack corrupted
T2: a = pop(); c = pop(); push(a);
Fix Bugs with Hazard Pointers [Michael04]
pop( ){1 local done, next, t, t1; 2 done = false;3 while (!done) {4 t = Top;5 if (t==null) return null;6 HP[tid] = t;7 t1 := Top;8 if (t == t1){ 9 next = t.Next;10 done = CAS(&Top, t,
next);11 }12 }13 retireNode(t);14 HP[tid] = null;15 return t;
push(x)16 local done, t;
17 done = false;18 while(!done) {19 t = Top;20 x.Next := t;21 done = CAS(&Top, t,
x);22 }23 return true;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; }
hazard to 3
pop( ){1 local done, next, t, t1; 2 done = false;3 while (!done) {4 t = Top;5 if (t==null) return null;6 HP[tid] = t;7 t1 := Top;8 if (t == t1){ 9 next = t.Next;10 done = CAS(&Top, t,
next);11 }12 }13 retireNode(t);14 HP[tid] = null;15 return t;
A
C
Top
B
0
1
2
3
4
HP
5
6
7
tid
reclaimable nodesremoved nodes pointed by hazard pointers
AA
nodes on stack
removed by 3hazard to 5hazard to 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)
Introduces past tense temporal operators into Rely-Guarantee Reasoning!
No history variables
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
s0 s1 s2 s3 s4 s5 s6
Time
p
p holds over the historical trace
q holds ever since
s0 s1 s2 s3 s4 s5 s6
Time
p
p = (p true) \/ p
p was once true in the history, including the current trace.
p holds at every step in the history
p = ( p)Time
s0 s1 s2 s3 s4 s5 s6
pp
p
...
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
R/G, p, q are trace assertions
(R, G) {p ┝ r} C {q r}(FrameT)
(R, G) {p} ┝ C {q}
(R, G) {p} ┝ C {q I’}(Inv)
(R, G) {p ┝ I} C {q} (R G) (I I’)
Knowledge about history can be added when necessary!
Derived invariants I and I’ can be used for free!
Basic judgment: R,G {p} ┝ C {q}
Verification of pop
reclaimable nodesremoved nodes pointed by hazard pointers
nodes on stack
Shared = Top * Stack * RN*HP
Removed by a thread t in the historyand pointed by the hazard pointer of thread tid ever since
HP[tid] & Top point to A and CAS succeeds
Temporal property for each node In RN
HP[tid] points to A
remove(A, tid) :removed by 3A
C
Top
B
0
1
2
3
4
HP
5
6
7
A Ishazard to 5Ishazard to 7
Shared Resources
Verification of pop
reclaimable nodesremoved nodes pointed by hazard pointersnodes on stack
Ishazard(A, tid) :
HP[tid] & Top point to A
(HP[tid] points to A) and not (tid updates Top)
hazardfree(A, tid) :
For all other tid’ , Ishazard(A, tid’) remove(A, tid)
removed by 3A
C
Top
B
0
1
2
3
4
HP
5
6
7
A Ishazard to 5Ishazard to 7
Shared Resources
retireNode(A)
Applying Inv Rule in the proof
pop( ){…8 if (t == t1){ {Ishazard(t,tid)}
{Ishazard(t,tid) * t |-> _, _} 9 next = t.Next;10 done = CAS(&Top, t,
next);11 }12 }13 retireNode(t);14 HP[tid] = null;15 return t;
Invariants INV1 for avoiding Bug#1: for all t, tid, ishazard(t, tid) /\ t ≠ null=> t Є Stack \/ t Є RN
Apply Inv rule with
(R \/ G)
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)
– Verifying the correctness of Michael’s non-blocking stacks
Thank you!
Questions?