Software Perspectives on
Transactional Memory
Ben Liblit
CS 838-3
• You gave us instruction sets
– We made high level languages
• You gave us RISC instead
– We made optimizing compilers
• You gave us context switching
– We made a big ugly mess: threads + locks
• You may soon give us transactions
– Ooh! New toy! What can we make with it?
2
• Yes, locks are really that bad
– Entire careers built on making them less awful
• But not a problem for most programmers (!)
– Most aren’t crazy enough to use threads
– Used only in restricted contexts, or by specialized “mad genius” programmers
•
Need something better
– Maybe transactions are that something
3
Transactions and Language Design
• Look at two key design questions
– Control structures
– Non-transactional operations (“magic”)
– Assorted issues & tricky bits
• Running themes
– Compositionality
– What happens in hardware/software?
4
atomic {
...
atomic {
...
}
...
}
• Obvious stuff
– Start trans on entry
– Commit trans on exit
• Nesting?
– We will nest, whether hardware likes it or not
– Compositionality!
– Locks are deeply broken here
5
atomic ( g ) { work() ;
}
• Wait until g is true
– Useful where condition variables might be used
• What can guard be?
– Just a memory word?
– Negated?
– Arbitrary expression?
– …with side effects?
6
atomic ( g ) { work() ;
} done = false; while (!done) { begin() ; if ( g ) { work() ; done = commit() ;
} else wait() ;
}
7
• Abort transaction
• Back to begin()
• Spin wait, or…
• Hardware assist!
– Track locations read
– Wait for write to any of them
– Can you do this?
done = false; while (!done) { begin() ; if ( g ) { work() ; done = commit() ;
} else wait() ;
}
8
atomic {
...
throw foo;
...
}
• Abort or commit?
• If abort, what happens to exception object?
• Consensus: commit
– Just one more way to exit a block of code
– Nothing special from programmer ’s standpoint, but…
9
atomic {
...
throw foo;
...
}
Can hardware still help?
done = false; while (!done) { begin() ; try { work() ; done = commit() ;
} catch (t) { done = commit() ; if (done) throw t;
}
}
10
void move(Map src, Map dest, int key) { atomic { try {
}
}
} catch (MapFullException e) { src.insert(key, val);
}
Object val = src.remove(key); dest.insert(key, val);
Am I getting too greedy?
Does this exceed the transactional mandate?
11
atomic { if (x != y) while (1) {}
} atomic {
++x;
++y;
}
• If right commits between left reads … stuck!
• Either don’t speculate or add periodic validation
– Is your favorite transactional hardware vulnerable?
– Can hardware help here, or is this compiler’s job?
12
atomic { if (x != y) launchMissiles() ;
} atomic {
++x;
++y;
}
• If right commits between left reads … stuck!
• Either don’t speculate or add periodic validation
– Is your favorite transactional hardware vulnerable?
– Can hardware help here, or is this compiler’s job?
13
void begin(); bool commit();
// basics
// basics void wait(); void abort();
// CCRs
// greedy?
bool validate(); // speculate
14
• All software has “magic” on the edges
– Magical operations outside system definition
– Walk off the edge? No coming back!
– Operations which cannot be rolled back
• Operating system: physical world
• User code: system calls
• Bytecode: native methods / system calls (?)
15
• Standard examples
– Input/output
– Memory allocation
– Query current time
– Thread creation
• Can/should these be rolled back?
– Can user code help hardware “fake it”?
16
• Forbid magic inside atomic blocks
– Non-compositional
– Limits transactional memory to tiny tasks
– Detect violations at compile time / run time?
• Ban speculation for blocks with magic
– Compositionality survives
– Sacrifice performance
– What about our beloved abort() call?
17
• Magic + compensation == transactional
– (Well, we pretend it is)
• Software, not hardware
– Example: buffering
– Delicate interaction with hardware roll-back
• Language/library designers must
– Decide on abstract machine model
– Build compensations consistent with model
18
• Will see a mix of strategies
• Virtual compensation in virtual machines
• Initially, dynamic enforcement
– Or no enforcement at all!
• Eventual development of static program analyses to prevent dynamic violations
19
• Other threads in same process?
• Other atomic blocks in same process?
– But not threads which are outside atomic blocks
• Other processes on same machine?
– Consider shared memory-mapped pages
– Consider shared file system
– Connections to security, journaling file systems
20
• Difference between address and “thing”
• Which of these can cause roll-backs?
– int x, y;
– struct { int x, y; } point;
– long long int xy;
• Shame to expose machine-level details
– But precedents exist in C and even Java
21
• Read large amounts of memory
– Likely to clash with everything else
– Cause transaction thrashing?
• Concurrent garbage collection
– We know how to do this now, but it wasn’t easy!
– How will we do it with transactions?
• Future employment opportunity for “mad genius” programmers who used to do fine-grained lock coding!
22
• Locks are a nightmare; time to wake up
• Atomicity may be the right abstraction
– Study: 80% of Java methods are atomic
• Push years of PL research into the archives
– But we’ll thank you for it
– Atomicity is nicer for program analysis too!
• Compositionality is critical
23