Dynamic data race prediction, part 2 (Tutorial)

Bas van den Heuvel

2024-05-17

Overview

  1. Ilias quiz
  2. Summary:
    • Vector clocks
    • FastTrack
    • Lockset
  3. Examples

Summary

Vector Clocks

What is a vector clock?

Given nn threads and event eje_j in thread TiT_i, the vector clock of eje_j is denoted [v1,,vi,,vn],[v_1,\ldots,v_i,\ldots,v_n], where vkv_k is the last-known timestamp of thread kk. Hence, vi=jv_i = j!

How do we compare vector clocks?

Given two vector clocks V=[v1,,vn],V=[v1,,vn]V = [v_1,\ldots,v_n],V'=[v'_1,\ldots,v'_n], we say V<VV < V' if 1kn.vkvk1kn.vk<vk.\forall 1 \leq k \leq n . v_k \leq v'_k \wedge \exists 1 \leq k \leq n . v_k < v'_k. Hence, V<VV < V' if VV' is aware of the “latest information” of VV on all threads, but has later information on at least one thread!

How do we compute vector clocks?

Given an event ee in thread TiT_i. The vector clock VeV_e depends on other events:

Hence:

How can we derive data races from vector clocks?

Recall event sets. Given events e,fe,f with event sets ESe,ESfES_e,ES_f, respectively, we consider e<fe<f if ESeESfES_e \subset ES_f.

We can prove that ESeESfES_e \subset ES_f if and only if Ve<VfV_e < V_f. Hence, e<fe<f if Ve<VfV_e<V_f!

FastTrack

See lecture notes.

Locksets

Given an event ee, the lockset LS(e)LS(e) of ee is the set of locks that ee is a critical section of: the acquire and release events surround ee in the same thread.

Two events are “concurrent” if their locksets do not overlap.

Computing locksets.

Examples

Example 1

    T1       T2

e1. fork(T2)
e2. wr(x)
e3. rd(x)
e4.          rd(x)
e5.          wr(x)
Solution
    T1       T2    VC

e1. fork(T2)       [1,0]
e2. wr(x)          [2,0]
e3. rd(x)          [3,0]
e4.          rd(x) [1,1]
e5.          wr(x) [1,2]

Data race; for example, [2,0][2,0] and [1,1][1,1] are incomparable (\not< and \not> and \neq).

    T1       T2    FT

e1. fork(T2)       Th(2)=[1,1]
                   Th(1)=[2,0]
e2. wr(x)          W(x)=1#2
                   Th(1)=[3,0]
e3. rd(x)          R(x)=[3,0]
                   Th(1)=[4,0]
e4.          rd(x) j#k=W(x)=1#2
                   k>Th(2)(j)=2>1
                   read-write
                   R(x)=[3,1]
                   Th(2)=[1,2]
e5.          wr(x) not R(x)<Th(2)
                   write-read
    T1       T2    LS

e1. fork(T2)       {}
e2. wr(x)          {}
e3. rd(x)          {}
e4.          rd(x) {}
e5.          wr(x) {}
None of the locksets overlap, so all conflicting events are in a data race (false positive when last-writer violated).

Example 2

    T1       T2

e1. fork(T2)
e2. wr(x)
e3. wr(y)
e4.          rd(y)
e5.          wr(x)
Solution
    T1       T2    VC

e1. fork(T2)       [1,0]
e2. wr(x)          [2,0]
e3. wr(y)          [3,0]
e4.          rd(y) [1,1]
e5.          wr(x) [1,2]

[2,0][2,0] and [1,2][1,2] are incomparable, but false positive: last-writer violated!

    T1       T2    FT

e1. fork(T2)       Th(2)=[1,1]
                   Th(1)=[2,0]
e2. wr(x)          W(x)=1#2
                   Th(1)=[3,0]
e3. wr(y)          W(y)=1#3
                   Th(1)=[4,0]
e4.          rd(y) j#k=W(y)=1#3
                   k>Th(2)(j)=3>1
                   read-write
                   R(y)=[1,1]
                   Th(2)=[1,2]
e5.          wr(x) j#k=W(x)=1#2
                   k>Th(2)(j)=2>1
                   write-write

Example 3

     T1       T2

e1.  fork(T2)
e2.  wr(a)
e3.  acq(x)
e4.  wr(b)
e5.  rel(x)
e6.  wr(c)
e7.           acq(x)
e8.           rd(a)
e9.           rd(b)
e10.          rel(x)
e11.          wr(c)
Solution
     T1       T2     VC

e1.  fork(T2)        [1,0]
e2.  wr(a)           [2,0]
e3.  acq(x)          [3,0]
e4.  wr(b)           [4,0]
e5.  rel(x)          [5,0]
e6.  wr(c)           [6,0]
e7.           acq(x) [5,1]
e8.           rd(a)  [5,2]
e9.           rd(b)  [5,3]
e10.          rel(x) [5,4]
e11.          wr(c)  [5,5]

All vector clocks are ordered, except [6,0][6,0] and [5,5][5,5]: data race (true positive).

     T1       T2     FT

e1.  fork(T2)        Th(2)=[1,1]
                     Th(1)=[2,0]
e2.  wr(a)           W(a)=1#2
                     Th(1)=[3,0]
e3.  acq(x)          Th(1)=[4,0]
e4.  wr(b)           W(b)=1#4
                     Th(1)=[5,0]
e5.  rel(x)          Rel(x)=[5,0]
                     Th(1)=[6,0]
e6.  wr(c)           W(c)=1#6
                     Th(1)=[7,0]
e7.           acq(x) Th(2)=[5,1]
                     Th(2)=[5,2]
e8.           rd(a)  j#k=W(a)=1#2
                     not k>Th(2)(j)=2>5
                     R(a)=[5,2]
                     Th(2)=[5,3]
e9.           rd(b)  j#k=W(b)=1#4
                     not k>Th(2)(j)=4>5
                     R(b)=[5,3]
                     Th(2)=[5,4]
e10.          rel(x) Rel(x)=[5,4]
                     Th(2)=[5,5]
e11.          wr(c)  j#k=W(c)=1#6
                     k>Th(2)(j)=6>5
                     write-write
     T1       T2     LS

                     ls(1)={}
                     ls(2)={}
e1.  fork(T2)        
e2.  wr(a)           LS(e2)=ls(1)={}
e3.  acq(x)          ls(1)=ls(1)+{x}={x}
e4.  wr(b)           LS(e4)=ls(1)={x}
e5.  rel(x)          ls(1)=ls(1)-{y}={}
e6.  wr(c)           LS(e6)=ls(1)={}
e7.           acq(x) ls(2)=ls(2)+{x}={x}
e8.           rd(a)  LS(e8)=ls(2)={x}
e9.           rd(b)  LS(e8)=ls(2)={x}
e10.          rel(x) ls(2)=ls(2)-{x}={}
e11.          wr(c)  LS(e11)=ls(2)={}
Non-overlapping locksets: data races (all true positives).

Example 4

    T1       T2    

e1. fork(T2)       
e2. acq(x)         
e3. wr(a)          
e4. rel(x)         
e5.          acq(x)
e6.          rd(a) 
e7.          rel(x)
Solution
    T1       T2     VC

e1. fork(T2)        [1,0]
e2. acq(x)          [2,0]
e3. wr(a)           [3,0]
e4. rel(x)          [4,0]
e5.          acq(x) [4,1]
e6.          rd(a)  [4,2]
e7.          rel(x) [4,3]

All vector clocks are ordered: no data race (true negative).

    T1       T2     FT

e1. fork(T2)        Th(2)=[1,1]
                    Th(1)=[2,0]
e2. acq(x)          Th(1)=[3,0]
e3. wr(a)           W(a)=1#3
                    Th(1)=[4,0]
e4. rel(x)          Rel(x)=[4,0]
                    Th(1)=[5,0]
e5.          acq(x) Th(2)=[4,1]
                    Th(2)=[4,2]
e6.          rd(a)  j#k=W(a)=1#3
                    not k>Th(2)(j)=3>4
                    R(a)=[4,2]
                    Th(2)=[4,3]
e7.          rel(x) Rel(x)=[4,3]
                    Th(2)=[4,4]
    T1       T2     LS

                    ls(1)={}
                    ls(2)={}
e1. fork(T2)        
e2. acq(x)          ls(1)={x}
e3. wr(a)           LS(e3)={x}
e4. rel(x)          ls(1)={}
e5.          acq(x) ls(2)={x}
e6.          rd(a)  LS(e6)={x}
e7.          rel(x) ls(2)={}

All locksets overlap: no data race (true negative).

Example 5

    T1       T2

e1. fork(T2)
e2. acq(l)
e3. wr(x)
e4. rel(l)
e5.          acq(l)
e6.          wr(x)
e7.          rel(l)
e8.          rd(x)
Solution
    T1       T2     VC

e1. fork(T2)        [1,0]
e2. acq(l)          [2,0]
e3. wr(x)           [3,0]
e4. rel(l)          [4,0]
e5.          acq(l) [4,1]
e6.          wr(x)  [4,2]
e7.          rel(l) [4,3]
e8.          rd(x)  [4,4]

All vector clocks are ordered: no data race (false negative).

    T1       T2     FT

e1. fork(T2)        Th(2)=[1,1]
                    Th(1)=[2,0]
e2. acq(l)          Th(1)=[3,0]
e3. wr(x)           W(x)=1#3
                    Th(1)=[4,0]
e4. rel(l)          Rel(l)=[4,0]
                    Th(1)=[5,0]
e5.          acq(l) Th(2)=[4,1]
                    Th(2)=[4,2]
e6.          wr(x)  j#k=W(x)=1#3
                    not k>Th(2)(j)=3>4
                    W(x)=2#2
                    Th(2)=[4,3]
e7.          rel(l) Rel(l)=[4,3]
                    Th(2)=[4,4]
e8.          rd(x)  j#k=W(x)=2#2
                    not k>Th(2)(j)=2>4
    T1       T2     LS

                    ls(1)={}
                    ls(2)={}
e1. fork(T2)        
e2. acq(l)          ls(1)={l}
e3. wr(x)           LS(e3)={l}
e4. rel(l)          ls(1)={}
e5.          acq(l) ls(2)={l}
e6.          wr(x)  LS(e6)={l}
e7.          rel(l) ls(2)={}
e8.          rd(x)  LS(e8)={}

Non-overlapping locksets: data race (true positive).

Example 6

     T1       T2    T3

e1.  fork(T3)
e2.  acq(l)
e3.  fork(T2)
e4.           wr(x)
e5.  join(T2)
e6.  rel(l)
e7.                 acq(l)
e8.                 wr(x)
e9.                 rel(l)
e10.                rd(x)
Solution
     T1       T2    T3     VC

e1.  fork(T3)              [1,0,0]
e2.  acq(l)                [2,0,0]
e3.  fork(T2)              [3,0,0]
e4.           wr(x)        [3,1,0]
e5.  join(T2)              [4,1,0]
e6.  rel(l)                [5,1,0]
e7.                 acq(l) [5,1,1]
e8.                 wr(x)  [5,1,2]
e9.                 rel(l) [5,1,3]
e10.                rd(x)  [5,1,4]

All vector clocks are ordered: no data race (false negative).

     T1       T2    T3     FT

e1.  fork(T3)              Th(3)=[1,0,1]
                           Th(1)=[2,0,0]
e2.  acq(l)                Th(1)=[3,0,0]
e3.  fork(T2)              Th(2)=[3,1,0]
                           Th(1)=[4,0,0]
e4.           wr(x)        W(x)=2#1
                           Th(2)=[3,2,0]
e5.  join(T2)              Th(1)=[4,2,0]
                           Th(1)=[5,2,0]
e6.  rel(l)                Rel(l)=[5,2,0]
                           Th(1)=[6,2,0]
e7.                 acq(l) Th(3)=[5,2,1]
                           Th(3)=[5,2,2]
e8.                 wr(x)  j#k=W(x)=2#1
                           not k>Th(3)(j)=1>5
                           W(x)=3#2
                           Th(3)=[5,2,3]
e9.                 rel(l) Rel(l)=[5,2,3]
                           Th(3)=[5,2,4]
e10.                rd(x)  j#k=W(x)=3#2
                           not k>Th(3)(j)=2>4
     T1       T2    T3     LS

                           ls(1)={}
                           ls(2)={}
                           ls(3)={}
e1.  fork(T3)              
e2.  acq(l)                ls(1)={l}
e3.  fork(T2)              
e4.           wr(x)        LS(e4)={}
e5.  join(T2)              
e6.  rel(l)                ls(1)={}
e7.                 acq(l) ls(3)={l}
e8.                 wr(x)  LS(e8)={l}
e9.                 rel(l) ls(3)={}
e10.                rd(x)  LS(e10)={}

Non-overlapping locksets: data race (both false and true positive).