! " I see a deadlock potential in that execution log file lock(T1,L1) lock(T1,L2) release(T1,L2) release(T1,L1) lock(T2,L2) lock(T2,L1) Page 1 RV Implemented system under test Page 2 dispatch input Implemented system event stream under test Specs reports Algorithms instrumentation runtime monitoring runtime checking runtime validation runtime analysis dynamic analysis Page 3 # $ # & # ) # " ' ' % ! $ ( ! % $ $ " # " # * (" % # " % # % " ! ! % +& , Page 4 ! " always newCommand s1 validate success s3 s2 execute fail execute s6 s8 customValidate s4 rejectCommand execute s7 customValidate s5 Page 5 # # $ ! ( 0 # . 1 # ) %/ ( / ! ( 1 % ( & ' / Page 6 $ ! ! ( ( ( 1 , % + ! / Page 7 ( ) *+ synchronized statements A basic scenario $ ' 2 3 *2 *3 T1: T2: synchronized(L1){ ... synchronized(L2){ ... synchronized(L2){ ... synchronized(L1){ ... } ... } } ... } Page 8 ( ) *+ synchronized methods Dynamic locks class Value{ int x = 1; synchronized void add(Value v){x = x + v.get();} synchronized int get(){return x;} } v1 = new Value(); v2 = new Value(); Thread T1 Thread T2 v1 v1.add(v2) v2.add(v1) v2 Page 9 ( ) *+ A challenge for static analysis dynamic locking N = number of philosophers class Main{ Fork[] forks = new Fork[N]; .. for(int i=0;i<N;i++){ new Phisosopher(forks[i],forks[(i+1)%N]; }; } $ ' while(count<10){ synchronized(salt_chaker) synchronized(left){ synchronized(right){count++} } } arithmetic Page 10 ( # " # ) %& ( ! 4 % # 0 , 1 % 4 % # % ' – 0 526 +7 3 – 0 538 +3/6 2 – 0 532 + ! # , ! – 0 57 +7 – 0 59 +3: , /, % , .! ' % ! # ) ,- ! # $ ! ' , ! ! ;$ /, ( 4 Page 11 Error report Error X in line Y … analyze model build model extract trace l(T1,G) l(T1,L1) l(T1,L2) u(T1,L2) u(T1,L1) l(T2,G) l(T2,L2) l(T2,L1) u(T2,L1) u(T2,L2) u(T2,G) l(T3,L1) l(T3,L2) u(T3,L2) u(T3,L1) l(T1,L2) l(T1,L1) u(T1,L1) u(T1,L2) Extracted events kinds: l(T,L) -- T locks L u(T,L) -- T unlocks L Page 12 " / % Hmm … looks pretty good to me. good run bad run Page 13 ( 0, 1 ( % Shoot … some foot prints of a bug! good run turn a hard to test property into a stronger easy to test property. bad run Page 14 , < < = ( 2 + , ! !$$ " % " % " = $ $ % % ! Page 15 # # >! - ( % $ / # >! / Page 16 $ Error report Error X in line Y … 2% / detect cycles compute graph extract trace Page 17 ( 3 # 45556 T1: T2: synchronized(L1){ ... synchronized(L2){ ... synchronized(L2){ ... synchronized(L1){ ... } ... } } ... } = % /7 /4 Page 18 ( Input: an execution trace GL : (Lock * , CL : [Thread Lock + 5 2//@ @, A? + , GL '5 GL CL := CL !+ , CL := CL +B ? { (o’,o) | o’ [ CL(t) [ ; CL(t) }; {o} ]; CL(t) \ {o} ]; + $ $ $ *, ' C < ,D Page 19 ( - , 3- % $ 8 % 6 9 T1: T2: T3: sync(G){ sync(L1){ sync(L2){} } }; T3 = new T3(); j3.start(); J3.join(); sync(L2){ sync(L1){} } sync(G){ sync(L2){ sync(L1){} } } sync(L1){ sync(L2){} } % % Page 20 *+ *+ T1: T2: T3: sync(G){ sync(L1){ sync(L2){} } }; T3 = new T3(); j3.start(); J3.join(); sync(L2){ sync(L1){} } sync(G){ sync(L2){ sync(L1){} } } sync(L1){ sync(L2){} } * ! : l(T1,G) l(T1,L1) l(T1,L2) u(T1,L2) u(T1,L1) s(T1,T3) l(T2,G) l(T2,L2) l(T2,L1) u(T2,L1) u(T2,L2) u(T2,G) l(T3,L1) l(T3,L2) u(T3,L2) u(T3,L1) j(T1,T3) l(T1,L2) l(T1,L1) u(T1,L1) u(T1,L2) Page 21 ( ' ! E $ F $ / E ( F/ ( % $ % 9 T1: T2: T3: sync(G){ sync(L1){ sync(L2){} } }; T3 = new T3(); j3.start(); J3.join(); sync(L2){ sync(L1){} } sync(G){ sync(L2){ sync(L1){} } } sync(L1){ sync(L2){} } % T3: L1 -> L2 % T2: L2 -> L1 4 cycles = 4 deadlock potentials reported (Visual Threads). 1 real deadlock! (3 false positives) Page 22 / ( 45556 3 T1 T2 T3 L2 G G L1 L1 L1 L2 L2 L2 L1 Page 23 / ( 45556 3 T1 T2 T3 L2 G G L1 L1 L1 L2 L2 L2 L1 Page 24 ( ( ' ; $ ( ! ' / ( $ % 9 T1: T2: T3: sync(G){ sync(L1){ sync(L2){} } }; T3 = new T3(); j3.start(); J3.join(); sync(L2){ sync(L1){} } sync(G){ sync(L2){ sync(L1){} } } sync(L1){ sync(L2){} } 2% Potential 1 & 2 % ! ! 2 cycles = 2 deadlock potentials reported. Page 25 ( Input: an execution trace % * 5 * * , GL : (Lock * CL : [Thread Lock ? + 5 2//@ @, A? + , GL '5 GL CL := CL !+ , CL := CL % $ +B $ ; { (o’,(t,g),o) | o’ CL(t) g = { o’’ | o’’ CL(t) }}; [ CL(t) {o} ]; [ CL(t) \ {o} ]; " $ + thread : Label thread(t,g) = t Thread guards : Label guards(t,g) = g Lock-set valid-cycle( c ) = e1,e2 c thread(e1) thread(e2) guards(e1) guards(e2) = { } *, ' C < ,D Page 26 $ 1 2 4 2 T1: T2: T3: sync(G){ sync(L1){ sync(L2){} } }; T3 = new T3(); j3.start(); J3.join(); sync(L2){ sync(L1){} } sync(G){ sync(L2){ sync(L1){} } } sync(L1){ sync(L2){} } % 3 x executes before y x y Page 27 * 36 : 36 ; < n : next free segment T1 t2.start() x T2 T1 T2 n n+1 t2.join() x n Let S* be the transitive closure of segmentation graph S. The happens-before relation is defined as: x y = (x,y) S* The in-parallel relation is defined as: y x || y = (x y) (y x) Page 28 ( ( ' ; $ ( ' / - ( $ 2% 9 T1: T2: sync(G){ sync(L1){ sync(L2){} } }; T3 = new T3(); j3.start(); J3.join(); sync(L2){ sync(L1){} } sync(L1){ sync(G){ sync(L2){ sync(L2){} } sync(L1){} } One potential left, the real deadlock! } ! ! &' % M: new T1().start(); new T2().start(); ( "##$ T3: M 3 1 0 " $$$$ T1 " $ "%%$ 2 5 T2 T3 7 4 6 Page 29 Input: an execution trace % * 5 * " GL : (Lock * * , GS : (nat , CL : [Thread (Lock , ? CS : [Thread ? ' 5 2D ; % + 5 2//@ @, A? + , GL '5 GL CL := CL !+ , CL := CL + 2 3, GS '5 GS CS := CS n := n + 2; G+ 2 3, GS '5 GS CS := CS n := n + 1; % $ +B $ $ / / { (o’,(s1,t,g,s2),o) | (o’, s1) CL(t) g = { o’’ | (o’’, *) CL(t) } s2 = CS(t)}; [ CL(t) {(o,CS(t))} ]; [ CL(t) \ {(o,*)} ]; { (CS(t1),n), (CS(t1),n+1)} [ 2 n, 3 n+1]; { (CS(t1),n), (CS(t2),n)}; [ 2 n]; " $ + *, ' C < ,D - ; ; ( / thread : Label Thread thread(s1,t,g,s2) = t guards : Label Lock-set guards(s1,t,g,s2) = g source : Label nat source(s1,t,g,s2) = s1 target : Label nat target(s1,t,g,s2) = s2 valid-cycle( c ) = e1,e2 c thread(e1) thread(e2) guards(e1) guards(e2) = { } target(e2) target(e1) Page 30 " Error report Error X in line Y … 2 model check project on threads extract trace Page 31 " # &; " $ 2 ! ; " ! % C ; B $ " $ *" )$ " $ " $ ! $ " )$ ' " $ " $ " T1: T2: long x; synchronized(R1){ synchronized(R2){}; x = big1*big2; } synchronized(R2){ System.out.println(x); synchronized(R1){}; } $ Page 32 " " $ " $ 2 " $ *" )$ " $ " $ " )$ " $ " $ " $ project on threads " " $ " $ " )$ $ " " $ *" )$ " $ " $ " $ $ Page 33 $ ; % ! 5 $ @@ 8 8 ! 2 H! 3 2 3 "2 I +2 2 I 2 JK, 8 ! 3 65 ' $ $ *( $ / 2 ' % L + , % 3== 6 5 . 365 / + 2 3 I @@ JK, / + , +@@ , Page 34 *+ " # 2 better # $ $ $ # # # . >? % . >@ ! ' 0 59 M $ + 7N +2/6 > ! 6 28 ! ,' , N=3: faster N=4: out of mem. Page 35 2 * * * ; ! / reflects : Cycle reflects(c, ) = (l1,(_,t,_,_),l2) c t holds l1 in t next wants l2 in $ / * @@ / soundness wrt. execution trace ! c valid-cycles(GL) ||Si Deadlocking( ) Bool reflects(c, ) completeness wrt. execution trace ! ||Si Deadlocking( ) c valid-cycles(GL) reflects(c, ) execution trace cycles ||Si Page 36 " 8 % A T1: T2: T3: sync(G){ sync(L1){ sync(L2){} } }; T3 = new T3(); j3.start(); J3.join(); sync(L2){ sync(L1){} } if(p) X := G else X := H; sync(X){ sync(L2){ sync(L1){} } } sync(L1){ sync(L2){} } If p evaluates to true Cycle becomes guarded and error is missed. Page 37 , # $ # O - % 1 . ! $ ; ! / ( ( ! ( $ % # - ( % / ( ! $ + ( ( ! ,/ Page 38 , ! . , 3 B 6! synchronized(L1){ if(random(1,n)==1) synchronized(L2){} } Probability for deadlock to occur: PD(k,n) = P(, 3 B 6 deadlocks in a run) = 1/n * P(deadlock | random == 1) = 1/n * (1 * (k-1)/k * (k-2)/k * … * 1/k) synchronized(L2){ if(random(1,n)==1) synchronized(L3){} } = 1/n * k!/k^k … Example: synchronized(Lk){ if(random(1,n)==1) synchronized(L1){} } PD(k=4,n=3) = 0.03 Page 39 *+ * , 3 B 6! synchronized(L1){ if(random(1,n)==1) synchronized(L2){} } 75 Probability for deadlock to occur: PC(k,n) = P(, 3 B 6 generates cycle in a run) = 1/n * P(cycle | random == 1) = 1/n * 1 synchronized(L2){ if(random(1,n)==1) synchronized(L3){} } = 1/n … Example: synchronized(Lk){ if(random(1,n)==1) synchronized(L1){} } PC(k=4,n=3) = 0.33 = 10 * PD(k=4,n=3) <1 Page 40 $ , trace model checking % –0 59 M +6 model checking % , ! , /, % –0 57 +7 –0 59 + ! ! ! , % ' –0 526 +7 3 –0 538 +3/6 2 –0 532 + ! ' ' , /, ' –0 57 +7 N –0 59 + ! , /, runtime analysis % ' –0 5288 +N –0 57 88 +33 –I , , % –0 59 +M –0 5288 +7 8 –0 57 88 +3 –I ' , , ! , Page 41 2 . ( (< C 7 6 888 ! 2 .( ( C ) N 888 ! 3$ .( ( << ! .( ( 0 ! << ! / ! 4 % % 4 % + << % ( ! / $ *( , B $ C/ ! 3 / ! ! + ! 4 % % & ! ,/ Page 42 $ ( % . ( ( ; $ *( < , With Chuck Fry, QSS, NASA Ames agent relay (communication system) external events Error message: TokenNetworkMutex traceLock main PlanRunner::trace_lock by thread: DeliberativePlanner at positions: planner - trySetVariableDomain() - PlanRunner::traceLock() TokenNetworkMutex TokenNetworkMutexby thread: Mission_Agent_Main at positions: - PlanRunner::traceLock() - getPredicateType() token network (plan) Page 43 # $% # # # # ( P Q % ! $ $ ! - ( % # $ 38 / $ + ! ! ! / ;/ << % ,/ ! / ( ! ;$ % # # ! % - ( % ! # # % $( % / / ! + ( / ! $ B ! / $ / ! ,/ C/ / , ! # ! # $ $ $ ' synchronized(A,B){…} $$ ( $ / Page 44 & Page 45