The Why, What, and How of Software Transactions for More Reliable Concurrency Dan Grossman University of Washington 8 September 2006.

Slides:



Advertisements
Similar presentations
Design and Implementation Issues for Atomicity Dan Grossman University of Washington Workshop on Declarative Programming Languages for Multicore Architectures.
Advertisements

Transaction Management: Concurrency Control CS634 Class 17, Apr 7, 2014 Slides based on “Database Management Systems” 3 rd ed, Ramakrishnan and Gehrke.
D u k e S y s t e m s Time, clocks, and consistency and the JMM Jeff Chase Duke University.
Chapter 6: Process Synchronization
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
Process Synchronization. Module 6: Process Synchronization Background The Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores.
Concurrency 101 Shared state. Part 1: General Concepts 2.
CSE , Autumn 2011 Michael Bond.  Name  Program & year  Where are you coming from?  Research interests  Or what’s something you find interesting?
CSE332: Data Abstractions Lecture 23: Programming with Locks and Critical Sections Dan Grossman Spring 2010.
Threading Part 2 CS221 – 4/22/09. Where We Left Off Simple Threads Program: – Start a worker thread from the Main thread – Worker thread prints messages.
Summer School on Language-Based Techniques for Concurrent and Distributed Software Software Transactions: Software Implementations Dan Grossman University.
Software Transactions: A Programming-Languages Perspective Dan Grossman University of Washington 28 February 2008.
The Transactional Memory / Garbage Collection Analogy Dan Grossman University of Washington OOPSLA 2007.
Atomicity via Source-to-Source Translation Benjamin Hindman Dan Grossman University of Washington 22 October 2006.
My programming-languages view of TM: Research and Conjectures Dan Grossman University of Washington June 2008.
Software Transactions: A Programming-Languages Perspective Dan Grossman University of Washington 27 March 2008.
Atomicity for Today's Programming Languages Dan Grossman University of Washington 24 March 2005.
Honors Compilers Addressing of Local Variables Mar 19 th, 2002.
Concurrency CS 510: Programming Languages David Walker.
CS510 Concurrent Systems Class 2 A Lock-Free Multiprocessor OS Kernel.
Run time vs. Compile time
Language Support for Lightweight transactions Tim Harris & Keir Fraser Presented by Narayanan Sundaram 04/28/2008.
1 New Architectures Need New Languages A triumph of optimism over experience! Ian Watson 3 rd July 2009.
The Why, What, and How of Software Transactions for More Reliable Concurrency Dan Grossman University of Washington 17 November 2006.
Synchronization in Java Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
The Why, What, and How of Software Transactions for More Reliable Concurrency Dan Grossman University of Washington 26 May 2006.
Summer School on Language-Based Techniques for Concurrent and Distributed Software Software Transactions: Language-Design Dan Grossman University of Washington.
1 Sharing Objects – Ch. 3 Visibility What is the source of the issue? Volatile Dekker’s algorithm Publication and Escape Thread Confinement Immutability.
Chapter 6: Synchronization. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Principles Module 6: Synchronization 6.1 Background 6.2 The Critical-Section.
Department of Computer Science Presenters Dennis Gove Matthew Marzilli The ATOMO ∑ Transactional Programming Language.
29-Jun-15 Java Concurrency. Definitions Parallel processes—two or more Threads are running simultaneously, on different cores (processors), in the same.
1 Run time vs. Compile time The compiler must generate code to handle issues that arise at run time Representation of various data types Procedure linkage.
A. Frank - P. Weisberg Operating Systems Introduction to Cooperating Processes.
Software Transactions: A Programming-Languages Perspective Dan Grossman University of Washington 5 December 2006.
Software Transactions: A Programming-Languages Perspective Dan Grossman University of Washington 29 March 2007.
Synchronization CSCI 444/544 Operating Systems Fall 2008.
Concurrency Recitation – 2/24 Nisarg Raval Slides by Prof. Landon Cox.
C. FlanaganType Systems for Multithreaded Software1 Cormac Flanagan UC Santa Cruz Stephen N. Freund Williams College Shaz Qadeer Microsoft Research.
1 Testing Concurrent Programs Why Test?  Eliminate bugs?  Software Engineering vs Computer Science perspectives What properties are we testing for? 
CS510 Concurrent Systems Jonathan Walpole. A Lock-Free Multiprocessor OS Kernel.
Threading and Concurrency Issues ● Creating Threads ● In Java ● Subclassing Thread ● Implementing Runnable ● Synchronization ● Immutable ● Synchronized.
Java Threads 11 Threading and Concurrent Programming in Java Introduction and Definitions D.W. Denbo Introduction and Definitions D.W. Denbo.
Optimistic Design 1. Guarded Methods Do something based on the fact that one or more objects have particular states  Make a set of purchases assuming.
COMP 111 Threads and concurrency Sept 28, Tufts University Computer Science2 Who is this guy? I am not Prof. Couch Obvious? Sam Guyer New assistant.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Mutual Exclusion.
Aritra Sengupta, Swarnendu Biswas, Minjia Zhang, Michael D. Bond and Milind Kulkarni ASPLOS 2015, ISTANBUL, TURKEY Hybrid Static-Dynamic Analysis for Statically.
Objects & Dynamic Dispatch CSE 413 Autumn Plan We’ve learned a great deal about functional and object-oriented programming Now,  Look at semantics.
Shared Memory Consistency Models. SMP systems support shared memory abstraction: all processors see the whole memory and can perform memory operations.
Data races, informally [More formal definition to follow] “race condition” means two different things Data race: Two threads read/write, write/read, or.
Wait-Free Multi-Word Compare- And-Swap using Greedy Helping and Grabbing Håkan Sundell PDPTA 2009.
13-1 Chapter 13 Concurrency Topics Introduction Introduction to Subprogram-Level Concurrency Semaphores Monitors Message Passing Java Threads C# Threads.
CS533 – Spring Jeanie M. Schwenk Experiences and Processes and Monitors with Mesa What is Mesa? “Mesa is a strongly typed, block structured programming.
Thread basics. A computer process Every time a program is executed a process is created It is managed via a data structure that keeps all things memory.
Fall 2008Programming Development Techniques 1 Topic 20 Concurrency Section 3.4.
AtomCaml: First-class Atomicity via Rollback Michael F. Ringenburg and Dan Grossman University of Washington International Conference on Functional Programming.
Optimistic Design CDP 1. Guarded Methods Do something based on the fact that one or more objects have particular states Make a set of purchases assuming.
Lecture 5 Page 1 CS 111 Summer 2013 Bounded Buffers A higher level abstraction than shared domains or simple messages But not quite as high level as RPC.
CSE 120 Principles of Operating
Threads Cannot Be Implemented As a Library
Threads and Memory Models Hal Perkins Autumn 2011
Dan Grossman University of Washington 18 July 2006
Atomicity in Multithreaded Software
Module 7a: Classic Synchronization
Threads and Memory Models Hal Perkins Autumn 2009
Design and Implementation Issues for Atomicity
CSE 451: Operating Systems Autumn 2003 Lecture 7 Synchronization
CSE 451: Operating Systems Autumn 2005 Lecture 7 Synchronization
CSE 451: Operating Systems Winter 2003 Lecture 7 Synchronization
CSE 153 Design of Operating Systems Winter 19
CSE 332: Concurrency and Locks
Presentation transcript:

The Why, What, and How of Software Transactions for More Reliable Concurrency Dan Grossman University of Washington 8 September 2006

Dan Grossman, Software Transactions2 Atomic An easier-to-use and harder-to-implement primitive lock acquire/release(behave as if) no interleaved computation (but no starvation) void deposit(int x){ synchronized(this){ int tmp = balance; tmp += x; balance = tmp; }} void deposit(int x){ atomic { int tmp = balance; tmp += x; balance = tmp; }}

8 September 2006Dan Grossman, Software Transactions3 Why now? Multicore unleashing small-scale parallel computers on the programming masses Threads and shared memory a key model –Most common if not the best Locks and condition variables not enough –Cumbersome, error-prone, slow Transactions should be a hot area. It is…

8 September 2006Dan Grossman, Software Transactions4 A big deal Software-transactions research broad… Programming languages PLDI, POPL, ICFP, OOPSLA, ECOOP, HASKELL, … Architecture ISCA, HPCA, ASPLOS, MSPC, … Parallel programming PPoPP, PODC, … … and coming together TRANSACT (at PLDI06)

8 September 2006Dan Grossman, Software Transactions5 Viewpoints Software transactions good for: Software engineering (avoid races & deadlocks) Performance (optimistic “no conflict” without locks) key semantic decisions may depend on emphasis Research should be guiding: New hardware support Language implementation with existing ISAs “is this a hardware or software question or both”

8 September 2006Dan Grossman, Software Transactions6 Our view SCAT (*) project at UW is motivated by “reliable concurrent software without new hardware” Theses: 1.Atomicity is better than locks, much as garbage collection is better than malloc/free 2.“Strong” atomicity is key 3.If 1 thread runs at a time, strong atomicity is easy & fast 4.Else static analysis can improve performance * (Scalable Concurrency Abstractions via Transactions)

8 September 2006Dan Grossman, Software Transactions7 Non-outline Paper trail: Added to OCaml [ICFP05; Ringenburg] Added to Java via source-to-source [MSPC06; Hindman] Memory-model issues [MSPC06; Manson, Pugh] Garbage-collection analogy [TechRpt, Apr06] Static-analysis for barrier-removal [TBA; Balensiefer, Moore, Intel PSL] Focus on UW work, happy to point to great work at Sun, Intel, Microsoft, Stanford, Purdue, UMass, Rochester, Brown, MIT, Penn, Maryland, Berkeley, Wisconsin, …

8 September 2006Dan Grossman, Software Transactions8 Outline Why (local reasoning) –Example –Case for strong atomicity –The GC analogy What (tough semantic “details”) –Interaction with exceptions –Memory-model questions How (usually the focus) –In a uniprocessor model –Static analysis for removing barriers on an SMP

8 September 2006Dan Grossman, Software Transactions9 Atomic An easier-to-use and harder-to-implement primitive lock acquire/release(behave as if) no interleaved computation (but no starvation) void deposit(int x){ synchronized(this){ int tmp = balance; tmp += x; balance = tmp; }} void deposit(int x){ atomic { int tmp = balance; tmp += x; balance = tmp; }}

8 September 2006Dan Grossman, Software Transactions10 Code evolution Having chosen “self-locking” yesterday, hard to add a correct transfer method tomorrow void deposit(…) { synchronized(this) { … }} void withdraw(…) { synchronized(this) { … }} int balance(…) { synchronized(this) { … }} void transfer(Acct from, int amt) { //race if(from.balance()>=amt) { from.withdraw(amt); this.deposit(amt); } }

8 September 2006Dan Grossman, Software Transactions11 Code evolution Having chosen “self-locking” yesterday, hard to add a correct transfer method tomorrow void deposit(…) { synchronized(this) { … }} void withdraw(…) { synchronized(this) { … }} int balance(…) { synchronized(this) { … }} void transfer(Acct from, int amt) { synchronized(this) { //race if(from.balance()>=amt) { from.withdraw(amt); this.deposit(amt); }

8 September 2006Dan Grossman, Software Transactions12 Code evolution Having chosen “self-locking” yesterday, hard to add a correct transfer method tomorrow void deposit(…) { synchronized(this) { … }} void withdraw(…) { synchronized(this) { … }} int balance(…) { synchronized(this) { … }} void transfer(Acct from, int amt) { synchronized(this) { synchronized(from) { //deadlock(still) if(from.balance()>=amt) { from.withdraw(amt); this.deposit(amt); } }} }

8 September 2006Dan Grossman, Software Transactions13 Code evolution Having chosen “self-locking” yesterday, hard to add a correct transfer method tomorrow void deposit(…) { atomic { … }} void withdraw(…) { atomic { … }} int balance(…) { atomic { … }} void transfer(Acct from, int amt) { //race if(from.balance()>=amt) { from.withdraw(amt); this.deposit(amt); } }

8 September 2006Dan Grossman, Software Transactions14 Code evolution Having chosen “self-locking” yesterday, hard to add a correct transfer method tomorrow void deposit(…) { atomic { … }} void withdraw(…) { atomic { … }} int balance(…) { atomic { … }} void transfer(Acct from, int amt) { atomic { //correct if(from.balance()>=amt) { from.withdraw(amt); this.deposit(amt); }

8 September 2006Dan Grossman, Software Transactions15 Moral Locks do not compose –Leads to hard-to-change design decisions –Real-life example: Java’s StringBuffer Transactions have other advantages But we assumed “wrapping transfer in atomic” prohibited all interleavings… –transfer implemented with local knowledge

8 September 2006Dan Grossman, Software Transactions16 Strong atomicity (behave as if) no interleaved computation Before a transaction “commits” –Other threads don’t “read its writes” –It doesn’t “read other threads’ writes” This is just the semantics –Can interleave more unobservably

8 September 2006Dan Grossman, Software Transactions17 Weak atomicity (behave as if) no interleaved transactions Before a transaction “commits” –Other threads’ transactions don’t “read its writes” –It doesn’t “read other threads’ transactions’ writes” This is just the semantics –Can interleave more unobservably

8 September 2006Dan Grossman, Software Transactions18 Wanting strong Software-engineering advantages of strong atomicity 1.Local (sequential) reasoning in transaction Strong: sound Weak: only if all (mutable) data is not simultaneously accessed outside transaction 2.Transactional data-access a local code decision Strong: new transaction “just works” Weak: what data “is transactional” is global

8 September 2006Dan Grossman, Software Transactions19 Caveat Need not implement strong atomicity to get it, given weak For example: Sufficient (but unnecessary) to ensure all mutable thread-shared data accesses are in transactions Doable via: –“Programmer discipline” –Monads [Harris, Peyton Jones, et al] –Program analysis [Flanagan, Freund et al] –“Transactions everywhere” [Leiserson et al]

8 September 2006Dan Grossman, Software Transactions20 Outline Why (local reasoning) –Example –Case for strong atomicity –The GC analogy What (tough semantic “details”) –Interaction with exceptions –Memory-model questions How (usually the focus) –In a uniprocessor model –Static analysis for removing barriers on an SMP

8 September 2006Dan Grossman, Software Transactions21 Why an analogy Already hinted at crisp technical reasons why atomic is better than locks –Locks weaker than weak atomicity Analogies aren’t logically valid, but can be –Convincing –Memorable –Research-guiding Software transactions are to concurrency as garbage collection is to memory management

8 September 2006Dan Grossman, Software Transactions22 Hard balancing acts memory management correct, small footprint? free too much: dangling ptr free too little: leak, exhaust memory non-modular deallocation needs “whole-program is done with data” concurrency correct, fast synchronization? lock too little: race lock too much: sequentialize, deadlock non-modular access needs “whole-program uses same lock”

8 September 2006Dan Grossman, Software Transactions23 Move to the run-time Correct [manual memory management / lock-based synchronization] needs subtle whole-program invariants So does [Garbage-collection / software-transactions] but they are localized in the run-time system –Complexity doesn’t increase with size of program –Can use compiler and/or hardware cooperation

8 September 2006Dan Grossman, Software Transactions24 Old way still there Alas: “stubborn” programmers can nullify many advantages GC: application-level object buffers Transactions: application-level locks… class SpinLock { private boolean b = false; void acquire() { while(true) atomic { if(b) continue; b = true; return; } void release() { atomic { b = false; }} }

8 September 2006Dan Grossman, Software Transactions25 Much more Basic trade-offs –Mark-sweep vs. copy –Rollback vs. private-memory I/O (writing pointers / mid-transaction data) … I now think “analogically” about each new idea

8 September 2006Dan Grossman, Software Transactions26 Outline Why (local reasoning) –Example –Case for strong atomicity –The GC analogy What (tough semantic “details”) –Interaction with exceptions –Memory-model questions How (usually the focus) –In a uniprocessor model –Static analysis for removing barriers on an SMP

8 September 2006Dan Grossman, Software Transactions27 Basic design With higher-order functions, no need to change to parser and type-checker – atomic a first-class function –Argument evaluated without interleaving external atomic : (unit-> α )-> α = “atomic” In atomic (dynamically): retry : unit->unit causes abort-and-retry No point retrying until relevant state changes –Can view as an implementation issue

8 September 2006Dan Grossman, Software Transactions28 Exceptions What if code in atomic raises an exception? Options: 1.Commit 2.Abort-and-retry 3.Abort-and-continue Claim: “Commit” makes the most semantic sense… atomic { … f(); /* throws */ …}

8 September 2006Dan Grossman, Software Transactions29 Abort-and-retry Abort-and-retry does not preserve sequential behavior –Atomic should be about restricting interleaving –Exceptions are just an “alternate return” atomic {throw new E();} //infinite loop? Violates this design goal: In a single-threaded program, adding atomic has no observable behavior

8 September 2006Dan Grossman, Software Transactions30 “But I want abort-and-retry” The abort-and-retry lobby says: “in good code, exceptions indicate bad situations” That is not the semantics Can build abort-and-retry from commit, not vice-versa Commit is the primitive; sugar for abort-and-retry fine atomic { try { … } catch(Throwable e) { retry; } }

8 September 2006Dan Grossman, Software Transactions31 Abort-and-continue Abort-and-continue has even more semantic problems “Abort is a blunt hammer, rolling back all state” Continuation needs “why it failed”, but cannot see state that got rolled back (integer error codes?) Foo obj = new Foo(); atomic { obj.x = 42; f();//exception undoes unreachable state } assert(obj.x==42);

8 September 2006Dan Grossman, Software Transactions32 Outline Why (local reasoning) –Example –Case for strong atomicity –The GC analogy What (tough semantic “details”) –Interaction with exceptions –Memory-model questions How (usually the focus) –In a uniprocessor model –Static analysis for removing barriers on an SMP

8 September 2006Dan Grossman, Software Transactions33 Relaxed memory models Modern languages don’t provide sequential consistency Lack of hardware support Prevents otherwise sensible & ubiquitous compiler transformations (e.g., common-subexpression elim) So safe languages need complicated definitions: 1.What is “properly synchronized”? 2.What “happens-before events” must compiler obey? A flavor of simplistic ideas and the consequences…

8 September 2006Dan Grossman, Software Transactions34 Data-handoff okay? “Properly synchronized”  All thread-shared mutable memory accessed in transactions Consequence: Data-handoff code deemed “bad” //Producer tmp1=new C(); tmp1.x=42; atomic { q.put(tmp1); } //Consumer atomic { tmp2=q.get(); } tmp2.x++; //Consumer atomic { tmp2=q.get(); tmp2.x++; }

8 September 2006Dan Grossman, Software Transactions35 Happens-before A total “happens-before” order among all transactions? Consequence: atomic has barrier semantics, making dubious code correct x = 1; y = 1; r = y; s = x; assert(s>=r);//invalid initially x=y=0

8 September 2006Dan Grossman, Software Transactions36 Happens-before A total “happens-before” order among all transactions Consequence: atomic has barrier semantics, making dubious code correct x = 1; atomic { } y = 1; r = y; atomic { } s = x; assert(s>=r);//valid? initially x=y=0

8 September 2006Dan Grossman, Software Transactions37 Happens-before A total “happens-before” order among transactions with conflicting memory accesses Consequence: “memory access” now in the language definition; affects dead-code elimination x = 1; atomic {z=1;} y = 1; r = y; atomic {tmp=0*z;} s = x; assert(s>=r);//valid? initially x=y=0

8 September 2006Dan Grossman, Software Transactions38 Outline Why (local reasoning) –Example –Case for strong atomicity –The GC analogy What (tough semantic “details”) –Interaction with exceptions –Memory-model questions How (usually the focus) –In a uniprocessor model –Static analysis for removing barriers on an SMP

8 September 2006Dan Grossman, Software Transactions39 Interleaved execution The “uniprocessor (and then some)” assumption: Threads communicating via shared memory don't execute in “true parallel” Important special case: Many language implementations assume it (e.g., OCaml, DrScheme) Many concurrent apps don’t need a multiprocessor (e.g., many user-interfaces) Uniprocessors still exist

8 September 2006Dan Grossman, Software Transactions40 Implementing atomic Key pieces: Execution of an atomic block logs writes If scheduler pre-empts a thread in atomic, rollback the thread Duplicate code so non-atomic code is not slowed by logging Smooth interaction with GC

8 September 2006Dan Grossman, Software Transactions41 Logging example Executing atomic block: build LIFO log of old values: y:0z:?x:0y:2 Rollback on pre-emption: Pop log, doing assignments Set program counter and stack to beginning of atomic On exit from atomic: Drop log int x=0, y=0; void f() { int z = y+1; x = z; } void g() { y = x+1; } void h() { atomic { y = 2; f(); g(); }

8 September 2006Dan Grossman, Software Transactions42 Logging efficiency Keep the log small: Don’t log reads (key uniprocessor advantage) Need not log memory allocated after atomic entered –Particularly initialization writes Need not log an address more than once –To keep logging fast, switch from array to hashtable when log has “many” (50) entries y:0z:?x:0y:2

8 September 2006Dan Grossman, Software Transactions43 Code duplication Duplicate code so callees know to log or not: For each function f, compile f_atomic and f_normal Atomic blocks and atomic functions call atomic functions Function pointers compile to pair of code pointers int x=0, y=0; void f() { int z = y+1; x = z; } void g() { y = x+1; } void h() { atomic { y = 2; f(); g(); }

8 September 2006Dan Grossman, Software Transactions44 Representing closures Representation of function-pointers/closures/objects an interesting (and pervasive) design decision OCaml: headercode ptrfree variables… add 3, push, …

8 September 2006Dan Grossman, Software Transactions45 Representing closures Representation of function-pointers/closures/objects an interesting (and pervasive) design decision One approach: bigger closures headercode ptr1free variables… add 3, push, … code ptr2 add 3, push, … Note: atomic is first-class, so it is one of these too!

8 September 2006Dan Grossman, Software Transactions46 Representing closures Representation of function-pointers/closures/objects an interesting (and pervasive) design decision Alternate approach: slower calls in atomic headercode ptr1free variables… add 3, push, … code ptr2 add 3, push, … Note: Same overhead as OO dynamic dispatch

8 September 2006Dan Grossman, Software Transactions47 GC Interaction What if GC occurs mid-transaction? The log is a root (in case of rollback) Moving objects is fine –Rollback produces equivalent state –Naïve hardware solutions may log/rollback GC! What about rolling back the allocator? Don’t bother: after rollback, objects allocated in transaction are unreachable! –Naïve hardware solutions may log/rollback initialization writes!

8 September 2006Dan Grossman, Software Transactions48 Evaluation Strong atomicity for Caml at little cost –Already assumes a uniprocessor –See the paper for “in the noise” performance Mutable data overhead Choice: larger closures or slower calls in transactions Code bloat (worst-case 2x, easy to do better) Rare rollback not in atomicin atomic readnone writenonelog (2 more writes)

8 September 2006Dan Grossman, Software Transactions49 Outline Why (local reasoning) –Example –Case for strong atomicity –The GC analogy What (tough semantic “details”) –Interaction with exceptions –Memory-model questions How (usually the focus) –In a uniprocessor model –Static analysis for removing barriers on an SMP

8 September 2006Dan Grossman, Software Transactions50 Performance problem Recall uniprocessor overhead: not in atomicin atomic readnone writenonesome With parallelism: not in atomicin atomic readnone iff weaksome writenone iff weaksome Start way behind in performance, especially in imperative languages (cf. concurrent GC)

8 September 2006Dan Grossman, Software Transactions51 Optimizing away barriers Thread local Immutable Not used in atomic New: static analysis for not-used-in-atomic…

8 September 2006Dan Grossman, Software Transactions52 Not-used-in-atomic Revisit overhead of not-in-atomic for strong atomicity, given how data is used in atomic Yet another client of pointer-analysis Preliminary numbers very encouraging (with Intel) –Simple whole-program pointer-analysis suffices in atomic no atomic access no atomic write atomic write readnone some writenonesome not in atomic

8 September 2006Dan Grossman, Software Transactions53 Our view SCAT (*) project at UW is motivated by “reliable concurrent software without new hardware” Theses: 1.Atomicity is better than locks, much as garbage collection is better than malloc/free 2.“Strong” atomicity is key 3.If 1 thread runs at a time, strong atomicity is easy & fast 4.Else static analysis can improve performance * (Scalable Concurrency Abstractions via Transactions)

8 September 2006Dan Grossman, Software Transactions54 Credit and other OCaml: Michael Ringenburg Java via source-to-source: Benjamin Hindman (B.S., Dec06) Static barrier-removal: Steven Balensiefer, Katherine Moore Transactions 1/n of my current research –Semi-portable low-level code: Marius Nita, Sam Guarnieri –Better type-error messages for ML: Benjamin Lerner –Cyclone (safe C-level programming) More in the WASP group: wasp.cs.washington.edu

8 September 2006Dan Grossman, Software Transactions55 [Presentation ends here; additional slides follow]

8 September 2006Dan Grossman, Software Transactions56 Blame analysis Atomic localizes errors (Bad code messes up only the thread executing it) void bad1(){ x.balance += 42; } void bad2(){ synchronized(lk){ while(true) ; } Unsynchronized actions by other threads are invisible to atomic Atomic blocks that are too long may get starved, but won’t starve others –Can give longer time slices

8 September 2006Dan Grossman, Software Transactions57 Non-motivation Several things make shared-memory concurrency hard 1.Critical-section granularity –Fundamental application-level issue? –Transactions no help beyond easier evolution? 2.Application-level progress –Strictly speaking, transactions avoid deadlock –But they can livelock –And the application can deadlock

8 September 2006Dan Grossman, Software Transactions58 Handling I/O I/O one instance of native code … let f () = write_file_foo(); … read_file_foo() let g () = atomic f; (* read won’t see write *) f() (* read may see write *) Buffering sends (output) easy and necessary Logging receives (input) easy and necessary But input-after-output does not work

8 September 2006Dan Grossman, Software Transactions59 Native mechanism Previous approaches: no native calls in atomic –raise an exception – atomic no longer preserves meaning We let the C code decide: –Provide 2 functions (in-atomic, not-in-atomic) –in-atomic can call not-in-atomic, raise exception, or do something else –in-atomic can register commit- & abort- actions (sufficient for buffering) –a pragmatic, imperfect solution (necessarily)

8 September 2006Dan Grossman, Software Transactions60 Granularity Perhaps assume “object-based” ownership Granularity may be too coarse (especially arrays) –False sharing Granularity may be too fine (object affinity) –Too much time acquiring/releasing ownership Conjecture: Profile-guided optimization can help Note: Issue orthogonal to weak vs. strong

8 September 2006Dan Grossman, Software Transactions61 Representing closures/objects Representation of function-pointers/closures/objects an interesting (and pervasive) design decision OO already pays the overhead atomic needs (interfaces, multiple inheritance, … no problem) headerclass ptrfields… …code ptrs…

8 September 2006Dan Grossman, Software Transactions62 Digression Recall atomic a first-class function –Probably not useful –Very elegant A Caml closure implemented in C Code ptr1: calls into run-time, then call thunk, then more calls into run-time Code ptr2: just call thunk

8 September 2006Dan Grossman, Software Transactions63 Code evolution Suppose StringBuffers are “self-locked” and you want to write append (JDK1.4, thanks to Flanagan et al) int length() { synchronized(this) { … }} void getChars(…) { synchronized(this) { … }} void append(StringBuffer sb) { synchronized(this) { // race int len = sb.length(); if(this.count + len > this.value.length) this.expand(…); sb.getChars(0,len,this.value,this.count); }

8 September 2006Dan Grossman, Software Transactions64 Code evolution Suppose StringBuffers are “self-locked” and you want to write append (JDK1.4, thanks to Flanagan et al) int length() { synchronized(this) { … }} void getChars(…) { synchronized(this) { … }} void append(StringBuffer sb) { synchronized(this) { synchronized(sb) { // deadlock (still) int len = sb.length(); if(this.count + len > this.value.length) this.expand(…); sb.getChars(0,len,this.value,this.count); }} }

8 September 2006Dan Grossman, Software Transactions65 Code evolution Suppose StringBuffers are “self-locked” and you want to write append (JDK1.4, thanks to Flanagan et al) int length() { atomic { … }} void getChars(…) { atomic { … }} void append(StringBuffer sb) { // race int len = sb.length(); if(this.count + len > this.value.length) this.expand(…); sb.getChars(0,len,this.value,this.count); }

8 September 2006Dan Grossman, Software Transactions66 Code evolution Suppose StringBuffers are “self-locked” and you want to write append (JDK1.4, thanks to Flanagan et al) int length() { atomic { … }} void getChars(…) { atomic { … }} void append(StringBuffer sb) { atomic { // correct int len = sb.length(); if(this.count + len > this.value.length) this.expand(…); sb.getChars(0,len,this.value,this.count); }