Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () { return c.balance()+s.balance(); } c s W c s R T 1 W transfer total rd(c) R T 2 W 20 c s TiC’06 25
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () { return c.balance()+s.balance(); } c s W c s rd(c) R T 1 W wt( ? ) transfer total rd(c) R T 2 W 20 c s TiC’06 26
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 { return c.balance()+s.balance(); } c s W c s rd(c) R T 1 W wt(c) transfer total rd(c) R T 2 W 20 c s TiC’06 27
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(s) wt(c) transfer total rd(c) R T 2 W 20 c s TiC’06 28
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(s) wt(c) transfer total rd(c) R T 2 W 20 c s TiC’06 29
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 SERIAL W wt(s) wt(c) transfer c: 10 s: 90 total rd(c) R T 2 W 20 c s TiC’06 30
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(s) wt(c) transfer total rd(c) R T 2 W 20 c s TiC’06 31
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(s) wt(c) transfer total rd(c) R T 2 W 20 c s TiC’06 32
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(s) wt(c) transfer total rd(c) R T 2 W 20 c s TiC’06 33
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(s) wt(c) transfer total rd(c) R T 2 W 20 c s TiC’06 34
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(c) wt(s) transfer total rd(c) rd(s) R T 2 W 20 + 90 = 110 c s TiC’06 35
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s SERIAL W c s 100 rd(c) rd(s) R T 1 W wt(c) wt(s) transfer total rd(c) rd(s) R T 2 W 20 + 90 = 110 c s TiC’06 36
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(c) wt(s) transfer total rd(c) rd(s) R T 2 W 20 + 90 = 110 c s TiC’06 37
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(c) wt(s) transfer total rd(c) rd(s) R T 2 W 20 + 90 = 110 c s TiC’06 38
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s W c s rd(c) rd(s) R T 1 W wt(c) wt(s) transfer total R T 2 W c s TiC’06 39
Ensuring Serializability 10 // checking // savings void synchronized transfer (int sum) Account c; Account s; { c.withdraw(sum); s.deposit(sum); } 20 80 float synchronized total () 10 90 { return c.balance()+s.balance(); } c s SERIAL W c s 100 rd(c) rd(s) R T 1 W wt(c) wt(s) transfer total rd(c) rd(s) R T 2 W 10 + 90 = 100 c s TiC’06 40
Design and Implementation Choices • Transactional memory (atomics) vs. transactional monitors: � Using atomics provides stronger safety guarantees � Serializability with respect to all concurrently executing transactions � Transactional monitors more closely mirror lock-based programming methodology • When do writes become visible to the global store? � Log writes locally, and update only on commit (redo) � Update globally, and revert on abort (undo) • Should writers witness readers? � Visible vs. invisible reads � Influences contention management � How aggressively should readers be aborted? TiC’06 41
Observations • Classical lock-based approaches to coordinating activities of multiple threads: � Impose a heavy burden on programmer to balance safety and performance. � Have well-known issues with deadlocks, data races, priority inversion, interaction with external actions, etc. � Scalability impacted by the use of mutual-exclusion. • But ... � There is much legacy code (e.g., libraries) that use locks. � Well-known tuned implementations. � Thin locks. TiC’06 42
Observations • Software transactions: � Enforce atomicity and isolation on the regions they protect: � Atomicity: actions within a transaction appear to execute all- at-once or not-at-all. � Isolation: effects of other threads are not witnessed once a transaction starts. � Conceptually simple programming model • But ... � More complicated implementation model. � Must track atomicity and isolation violations at runtime. � Revocation of effects when violations occur not always possible. � Performance benefit only in the presence of contention. TiC’06 43
Reconcilation • Hybrid Approach: � Enforce atomicity and isolation properties using locks when contention is low or when transactional semantics is undesirable or infeasible. � Enforce these properties using transactions when contention is high and when transactional semantics is sensible. Low contention High Contention Locks Transactions Guarded Region TiC’06 44
Goals • Protocol choice must be transparent to applications. � Applications continue to use existing synchronization primitives. • Transparency does not come at the expense of correctness. � Program behavior must not depend on how a guarded region is executed. � Must work in the presence of nested guarded regions. • Performance. � No performance degradation when contention is low. � Performance improvement when contention is high. TiC’06 45
Correctness • When is it safe to use hybrid execution? • Semantics � Define a two-tiered execution model: � First tier defines data visibility (memory model) and interleaving � Schedules � Does not define a concurrency control protocol � Second tier defines safety properties on schedules with respect to a specific concurrency control protocol. TiC’06 46
ℓ’: Semantics Schedules ACQ ℓ ACQ ℓ WR z RD z REL ℓ ACQ ℓ ’ T 1 z ! ... ℓ: z ! ... T 2 z ! ... T 3 T 4 Local memory Global memory TiC’06 47
Constraints • Impose constraints on schedules to derive specific concurrency protocols. • Mutual Exclusion: (M-safe schedules) ACQ ℓ WR z ACQ ℓ RD z REL ℓ ACQ ℓ Multiple threads cannot concurrently execute within the body of a guarded region. Does not enforce atomicity. TiC’06 48
Transactional Constraints • Isolation: (I-safe schedules) ACQ ℓ ACQ ℓ WR z RD z REL ℓ REL ℓ REL ℓ ℓ: z ! v’ ℓ: z ! v A non-isolated schedule TiC’06 49
Transactional Constraints • Atomicity: (A-safe schedules) ACQ ℓ ’ ACQ ℓ ACQ ℓ’ REL ℓ’ REL ℓ A non-atomic schedule TiC’06 50
Safety • Any schedule which is both i-safe and a-safe can be permuted to one which is m-safe without change in observable behavior. � Can treat synchronized blocks as closed nested transactions in Java programs with i-safe and a-safe schedules without modifying existing Java semantics. � Closed nesting: the effect of a nested synchronized block B executed transactionally becomes visible to other transactions only when B ’s outermost transaction commits. TiC’06 51
Design • Consider programs whose generated schedules are i-safe and a-safe. � Execute synchronized blocks and methods � Transactionally, when contention is high. � Serially, when contention is low. • Closed nested transaction model. � Performance challenge � Each monitor defines a locus of contention. � Non-trivial overhead to maintain meta-data to validate transaction safety. � Consider optimizations to reduce this overhead. � Delegate meta-data management from a nested transaction to its parent. TiC’06 52
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () { return c.balance()+s.balance(); } mon T 1 TiC’06 53
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () { return c.balance()+s.balance(); } c s mon W c s R T 1 W TiC’06 54
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () { return c.balance()+s.balance(); } c s mon W c s R T 1 W TiC’06 55
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () T 2 acc.total() { return c.balance()+s.balance(); } c s mon W c s R T 1 W TiC’06 56
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () T 2 acc.total() { return c.balance()+s.balance(); } c s mon W c s R T 1 W R T 2 W c s TiC’06 57
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () T 2 acc.total() { return c.balance()+s.balance(); } c s mon W c s R T 1 W R T 2 W c s TiC’06 58
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () T 2 acc.total() { return c.balance()+s.balance(); } c s mon W c s rd(c) rd(s) R T 1 wt(c) wt(s) W R T 2 W c s rd(c) TiC’06 59
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () T 2 acc.total() { return c.balance()+s.balance(); } c s mon W c s rd(c) rd(s) R T 1 wt(c) wt(s) W R T 2 W c s rd(c) TiC’06 60
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () T 2 acc.total() { return c.balance()+s.balance(); } c s mon W c s rd(c) rd(s) R T 1 wt(c) wt(s) W R T 2 W c s rd(c) rd(s) TiC’06 61
Delegation void synchronized transfer (int sum) T 1 synchronized (mon) { c.withdraw(sum); { acc.transfer(10) } s.deposit(sum); } float synchronized total () T 2 acc.total() { return c.balance()+s.balance(); } c s mon W c s rd(c) rd(s) R T 1 wt(c) wt(s) W R T 2 W c s rd(c) rd(s) TiC’06 62
Delegation Summary • Optimized version of closed nested transactions • Setting a delegate – inexpensive • Only delegate setting required in non-contended case • Potential for lowering overhead related to nesting even if monitors contended TiC’06 63
Mutual Exclusion • When should transactional execution switch to mutual exclusion? � Native methods (e.g., I/O) � Explicit thread synchronization (wait/notify) � Absence of contention • All parent monitors must be re-acquired in mutual exclusion mode. TiC’06 64
Implementation • Optimistic protocol for reads • Pessimistic protocol for writes � Prevent multiple writers to the same object • Validation phase � Enforce i-safe and a-safe constraints � Discard copies if safety is violated • Write-back � Lazily propagate updated copies to the shared heap. • Implementation in Jikes RVM � Use read and write barriers to � Create versions � Redirect reads to the appropriate version � Track data dependencies using read/write hash maps TiC’06 65
Overheads Sources of overhead � Object header expansion � meta-data necessary to enforce transaction safety � forwarding pointers, delegates, hash codes, etc. � Code duplication � Two versions for each method � Still need (fast) read barriers even on non-transactional paths � Access latest version of an object � Triggering transactional execution � Lightweight heuristic to measure contention � Trigger transactional execution when thin-lock is inflated and more than one thread is waiting when locking thread exits. TiC’06 66
Barrier Optimizations • Goal: omit barriers on loads of primitive values • Problem: accesses through stale on-stack references • Solution: update references on stack using modified GC stack scanning procedure � At version creation � eager � At pre-specified memory“synchronization” points � monitor entry � access to volatile variables � wait/notify operations TiC’06 67
Performance: Uncontended Execution Single-threaded Specjvm98 and 50 Java Grande benchmarks 40 Barriers are primary source of 30 Overhead (%) overheads 20 10 7% average but large variance 0 Costs can be significantly -10 reduced through simple compiler optimizations -20 raytrace heap sparse compress db series crypt fft lufact sor TiC’06 68
Performance: Contended Execution 2 2 Level 1 Level 1 Level 1 Level 1 Level 3 Level 3 Level 3 Level 3 Level 6 Level 6 Level 6 Level 6 100000 100000 1.5 1.5 Elapsed time (normalized) Elapsed time (normalized) Number of aborts Number of aborts 10000 10000 1 1 1000 1000 0.5 0.5 100 100 0 0 10 20 30 40 50 60 70 80 90 10 20 30 40 50 60 70 80 90 10 20 30 40 50 60 70 80 90 10 20 30 40 50 60 70 80 90 Percent of writes (100% - percent of reads) Percent of writes (100% - percent of reads) Percent of writes (100% - percent of reads) Percent of writes (100% - percent of reads) 007, a tunable concurrent database benchmark (a) transactions-only (b) hybrid-mode (a) transactions-only (b) hybrid-mode � 64 threads, 8 processors Hybrid execution more resilient to write-biased workloads TiC’06 69
Summary • Effective support for transactions involves efficient implementation of a number of complex actions: � logging and copying data to restore program state � fast consistency checks to determine if serialization invariants are violated � revert thread control-flow to earlier program point in case of abort • Interaction with other realistic language features add further complications: � irrevocable actions (e.g, I/O) � native method calls � interaction with other concurrency mechanisms (e.g., wait/notify, locks) � language memory model and execution semantics • Can we selectively pick aspects of this implementation space to address other interesting concurrency issues? TiC’06 70
A Transactional Calculus • TFJ is a concurrent, imperative object calculus with dynamically scoped transactions: onacid and commit • TFJ supports multi-threaded and nested transactions :: = 0 | P | P | t [ e ] P :: = class C { f ; M } L :: = m ( x ) { returne ; } M :: = x | this | v | e . f | e . m ( e ) | e . f : = e | e new C () | spawn e | onacid | commit | null TiC’06 71
Semantics • Two-level operational semantics, • Semantics parameterized by definition of core transactional operations write, read, reflect, commit, spawn ⇒ t � � P � � • Labeled reduction relation n � P ⇒ = is a program state where Γ is composed of a sequence wr v u write p of thread environments rd v read ⇒ xt v new associates a thread with ts t , E where ac � start transaction its transaction onments. co commit transaction environment sp spawn thread A transaction environment associates a transaction label with a binding environment or log TiC’06 72
Read/Write E � , C ( u ) = read ( v , E ) fields ( C ) = ( f ) (R-F IELD ) rd v → E � u i E v . f i − E �� = write ( v �→ C ( v ) ↓ v � E � , C ( v ) = read ( v , E ) i , E � ) (R-A SSIGN ) E v . f i : = v � wr vv � → E �� v � − P = P �� | t [ e ] � P � = P �� | t [ e � ] → E � e � E e − � � = reflect ( t , E � , � �� ) � = t , E . � �� � ( t , � ) = l (G-P LAIN ) � ⇒ t � � P � � P = TiC’06 73
Commit Concurrent threads within a l transaction synchronize on l' commit co t2 ac co t1 co t3 P = P �� | t [ e ] P � = P �� | t [ e � ] e ⇓ commit e � t = intranse ( l , � ) � � = commit ( t , E , � ) � = t 0 E . � �� � ( t � , � ) = l (G-C OMM ) co ⇒ t � � � P � � P = TiC’06 74
Optimistic Semantics Per-thread environments as sequences of transaction logs • read adds the object read to the issuing thread's current transaction log • write adds the new value • reflect propagates changes from one thread environment to all other threads in the same transaction l l' t1 l'' t2 t1 –– l:[ v=C(v'), v=C(v'')] l':[ u=C(u) ] t2 –– l:[ v=C(v'), v=C(v'')] l'':[ v=C(v'') ] TiC’06 75
Commit Commit copies the log of the current transaction into the directly enclosing one t1 –– l:[ v=C(v') v=C(v'') ] l':[ u=C(u) u=C(u') ] commit l' t1 –– l:[ v=C(v') v=C(v'') u=C(u) u=C(u') ] Succeeds if all values read are still current in the enclosing environment TiC’06 76
Pessimistic Semantics 2 phase locking : � acquire a lock before reading and writing. � release before commit Define a lock environment that maps a lock to the transaction label sequence that specifies the transaction that currently holds it. E = E ′ . l : ρ findlast ( r , E ) = C ( r ) E ′′ = E ′ . l :( ρ . r �→ C ( r )) E ′ = acquirelock ( r , E ) findlast ( r , E ) = D ( u ) E ′′ = E ′ . l : ρ E ′′′ = E ′′ . l :( ρ . r �→ D ( u ) . r �→ C ( r )) checklock ( r , E ) = true read ( r , E ) = E ′′ , C ( r ) write ( r �→ C ( r ) , E ) = E ′′′ TiC’06 77
Serial Trace • A program trace is serial if for all pairs of reductions steps taken by a transaction L, steps occurring between them are taken on behalf of L or transactions nested within L l 2 l 1 l 1 l 1 ,l 3 l 1 ,l 3 l 1 l 4 l 2 wr v 1 ,v 2 wr v 4 ,v 5 wr v 5 ,v 1 wr v 3 ,v 2 rd v 1 wr v 0 ,v 8 ac co TiC’06 78
Soundness The soundness theorem states that for any trace R, there is an equivalent serial trace R' l 1 l 4 l 2 l 1 ,l 3 l 2 l 1 l 1 ,l 3 S0 S1 wr v 5 ,v 1 wr v 1 ,v 2 wr v 4 ,v 5 ac wr v 0 ,v 8 wr v 3 ,v 2 co S1 l 4 l 2 l 1 l 1 l 1 ,l 3 l 1 ,l 3 l 2 S0 wr v 5 ,v 1 wr v 1 ,v 2 wr v 4 ,v 5 wr v 3 ,v 2 co wr v 0 ,v 8 ac TiC’06 79
Dependencies Control and data dependencies induce a partial order on actions used to structure transaction traces wr v' u' l' rd v' l' xt v' l' rd t' wr t' xt t' sp t' ac t' co t' l' l' l' l' l' l' rd t l t = t' l' < l ( w r vv � , t , l ) or ( w r v � v , t , l ) , and A 2 is either ( w r vv �� , t � , l � ) or ( x t v , t � , l � ) , with l � � l . The key property for our soundness result is the permutation lemma which describes the conditions under which two reduction steps can be permuted. Let A and A � be a pair of actions which are not related under a control or data dependency. We write A d ; A � and A ; A � to mean action A has, respectively, c no c -dependence or d -dependence on A � . u = v' & l ' < l Definition 4 (Independence). Actions A and A � are independent if A ; A � c u = v' & l ' < l ; A � . d and A Lemma 1 (Permute). Assume that Γ and Γ �� are well-defined, and let R be the two-step sequence of reductions P Γ ⇒ t P 0 Γ 0 α = α � ⇒ t � P � Γ � . If A and A � are = independent then there exists a two-step sequence R � such that R � is P Γ = ⇒ t � α � P 1 Γ 1 = ⇒ t P � Γ � . α wr v u l Definition 5 (Program Trace). Let R be the sequence of reductions P 0 Γ 0 . . . P n Γ n = α n ⇒ t n P n +1 Γ n +1 . The trace of the reduction sequence R , written tr ( R ) , = α 0 ⇒ t 0 is ( α 0 , t 0 , l 0 ) . . . ( α n , t n , l 0 ) assuming that l i = � ( t i , Γ i ) for 0 ≤ i ≤ n . A program trace is serial if for all pairs of reduction steps with the same trans- action label ( l ), all reductions occurring between the two steps are taken on behalf of that very transaction or nested transactions ( l � l � ). wr t l t = t' l' < l v = v' & l ' < l Definition 6 (Serial Trace). A program trace, tr ( R ) = ( α 0 , t 0 , l 0 ) . . . ( α n , t n , l n ) v = v' & l ' < l is serial i ff ∀ i, j, k such that 0 ≤ i ≤ j ≤ k ≤ n and l i = l k we have l i � l j . We can now formulate the soundness theorem which states that any sequence of reductions which ends in a good state can be reordered so that its program trace is serial. Theorem 1 (Soundness). Let R be a sequence of reductions P 0 Γ 0 ⇒ t 0 . . . α 0 = P n Γ n = ⇒ t n P n +1 Γ n +1 . If Γ n +1 is well-defined, then there exists a sequence R � α n α � α � such that R � is P 0 Γ 0 = ⇒ t � 0 0 . . . P � n Γ � n ⇒ t � n = n P n +1 Γ n +1 and tr ( R � ) is serial. 6 Related Work The association of transactions with programming control structures has prove- nance in systems such as Argus [17, 15, 18], Camelot [10] Avalon/C++ [9] and xt t l t = t' l' < l rd v l v = v' & l ' < l v = v' & l ' < l sp t l t = t' l' < l ac t l t = t' l' < l xt v l v = v' & l ' < l v = v' & l ' < l co t l l' < l l' < l l' < l t = t' l' < l Control Data TiC’06 80
Permutation • The key property for proving soundness is the permutation lemma which states that two independent actions can be permuted. Actions are independent if they have no data or control dependency with one another. S0 S1 l 2 l 1 wr v 1 ,v 2 wr v 3 ,v 2 S0 S1 l 1 l 2 wr v 3 ,v 2 wr v 1 ,v 2 Must be proved for each transaction semantics. TiC’06 81
Case Study: Futures If sequential program P is annotated with futures to yield concurrent program P F, then the observable behavior of P is equivalent to P F • Logical serial order trivially satisfied when no side-effects • Problems arise with mutation of shared data • Consider futures API in JDK 1.5 • Like transactions, correct implementation of futures requires tracking dependencies � But, constraints imposed are stronger: behavior must conform to a serial execution, not a serializable one � Pairwise association of concurrent execution states � No issues of livelock or deadlock. It is always safe to revert to sequential execution. • Target applications are those which decompose into speculative units (with little to modest sharing) TiC’06 82
Rationale • Alternative concurrency model � No explicit threads � Concurrent program easily derived from its sequential counterpart � No non-determinism • Utility � Concurrent program development and debugging � Convenient way to define arbitrary regions of speculative code • Best used when (strong notions of) safety dominate performance requirements TiC’06 83
Safety Properties • An access to a location l (either a read or write) performed by a future should not witness a write to l performed by its continuation. • The last write to a location l performed by a future must occur before the first access to l by the continuation. • How do we maintain these properties? � version shared data � track shared data dependencies � revoke non-serial execution • These properties must hold even in the presence of exceptions, and irrevocable actions TiC’06 84
Using Futures void transfer (int sum) { c.withdraw(sum); float sum = acc.total(); s.deposit(sum); } acc.transfer(10); print(sum); float total () { return c.balance()+s.balance(); } TiC’06 85
Using Futures void transfer (int sum) { c.withdraw(sum); Future f = F[ acc.total() ] ; s.deposit(sum); } acc.transfer(10); print( f.get() ); float total () { return c.balance()+s.balance(); } TiC’06 86
Using Futures void transfer (int sum) { c.withdraw(sum); Future f = F[ acc.total() ] ; s.deposit(sum); } acc.transfer(10); print( f.get() ); float total () { return c.balance()+s.balance(); } LOGICAL SERIAL ORDER: total() TiC’06 87
Using Futures void transfer (int sum) { c.withdraw(sum); Future f = F[ acc.total() ] ; s.deposit(sum); } acc.transfer(10); print( f.get() ); float total () { return c.balance()+s.balance(); } LOGICAL SERIAL ORDER: total() FUTURE TiC’06 88
Using Futures void transfer (int sum) { c.withdraw(sum); Future f = F[ acc.total() ] ; s.deposit(sum); } acc.transfer(10); print( f.get() ); float total () { return c.balance()+s.balance(); } LOGICAL SERIAL ORDER: total() transfer() FUTURE TiC’06 89
Using Futures void transfer (int sum) { c.withdraw(sum); Future f = F[ acc.total() ] ; s.deposit(sum); } acc.transfer(10); print( f.get() ); float total () { return c.balance()+s.balance(); } LOGICAL SERIAL ORDER: total() transfer() get() FUTURE TiC’06 90
Using Futures void transfer (int sum) { c.withdraw(sum); Future f = F[ acc.total() ] ; s.deposit(sum); } acc.transfer(10); print( f.get() ); float total () { return c.balance()+s.balance(); } LOGICAL SERIAL ORDER: total() transfer() get() FUTURE CONTINUATION TiC’06 91
Safe Futures • Programmer annotates method calls • Logical serial order enforced by the run-time � Futures and continuations encapsulated into optimistic transactions � Foundational mechanisms shared with transactional monitors � The notion of logical serial order stronger than serializability • Consistency checks: � Data accesses hashed into read and write maps � Maps used by continuation to detect conflicts for accesses from its future � Validation at synchronization points (when a future is claimed) • Log updates by maintaining versions: � Versions used by future to prevent seeing updates by its continuation • Aborts: � Automatic roll-back when conflict detected TiC’06 92
Dependency Violations C f C c int i = o.bar; o.bar = 0; o.foo = 0; int j = o.foo; C f C c C f C c read( o ) write( o ) write( o ) read( o ) read( o ) write( o ) write( o ) read( o ) (a) Forward (b) Backward Forward dependency violations can be handled by tracking data dependencies. Backward dependency violations can be handled by versioning updates. Future never sees a premature update by its continuation. TiC’06 93
Ensuring Safety Account c; Account s; F1 Future f1 = F[ acc.transfer(10) ] ; F2 20 80 Future f2 = F[ acc.total() ] ; acc.transfer(10); f1.get(); C print(f2.get()); T F1 T F2 T C TiC’06 94
Ensuring Safety Account c; Account s; F1 Future f1 = F[ acc.transfer(10) ] ; F2 0 90 Future f2 = F[ acc.total() ] ; acc.transfer(10); f1.get(); C print(f2.get()); rd(c) wt(c) T F1 rd(c) rd(c) rd(s) 20 + 90 = 110 T F2 rd(c) rd(s) wt(c) wt(s) T C TiC’06 95
Ensuring Safety Account c; Account s; F1 Future f1 = F[ acc.transfer(10) ] ; F2 0 90 Future f2 = F[ acc.total() ] ; acc.transfer(10); f1.get(); C SERIAL print(f2.get()); 100 rd(c) wt(c) T F1 rd(c) rd(c) rd(s) 20 + 90 = 110 T F2 rd(c) rd(s) wt(c) wt(s) T C TiC’06 96
Ensuring Safety Account c; Account s; F1 Future f1 = F[ acc.transfer(10) ] ; F2 0 90 Future f2 = F[ acc.total() ] ; acc.transfer(10); f1.get(); C print(f2.get()); rd(c) wt(c) T F1 rd(c) rd(c) rd(s) 20 + 90 = 110 T F2 rd(c) rd(s) wt(c) wt(s) T C TiC’06 97
Ensuring Safety Account c; Account s; F1 Future f1 = F[ acc.transfer(10) ] ; F2 0 90 Future f2 = F[ acc.total() ] ; acc.transfer(10); f1.get(); C Forward print(f2.get()); Violations rd(c) wt(c) T F1 rd(c) rd(c) rd(s) 20 + 90 = 110 T F2 rd(c) rd(s) wt(c) wt(s) T C TiC’06 98
Ensuring Safety Account c; Account s; F1 Future f1 = F[ acc.transfer(10) ] ; F2 0 90 Future f2 = F[ acc.total() ] ; acc.transfer(10); f1.get(); C print(f2.get()); rd(c) c s wt(c) R T F1 W c s rd(c) rd(c) rd(s) 20 + 90 = 110 R T F2 W rd(c) rd(s) c s wt(c) wt(s) R T C W TiC’06 99
Ensuring Safety Account c; Account s; F1 Future f1 = F[ acc.transfer(10) ] ; F2 0 90 Future f2 = F[ acc.total() ] ; acc.transfer(10); f1.get(); C print(f2.get()); rd(c) c s wt(c) R T F1 W c s rd(c) rd(c) rd(s) 20 + 90 = 110 R T F2 W rd(c) rd(s) c s wt(c) wt(s) R T C W TiC’06 100
Recommend
More recommend