tlds
Transactional Operations for Linked Data Structures
|
Classes | |
struct | OrecEager_Generic |
Functions | |
TM_FASTCALL void * | read (STM_READ_SIG(,,)) |
TM_FASTCALL void | write (STM_WRITE_SIG(,,,)) |
bool | irrevoc (STM_IRREVOC_SIG(,)) |
NOINLINE void | validate (TxThread *) |
void | onSwitchTo () |
void * | read (STM_READ_SIG(tx, addr,)) |
void | write (STM_WRITE_SIG(tx, addr, val, mask)) |
bool | irrevoc (STM_IRREVOC_SIG(tx,)) |
Declare the functions that we're going to implement, so that we can avoid circular dependencies.
NB: OrecEager actually does better without fine-grained switching for read-only transactions, so we don't support the read-only optimization in this code.
bool anonymous_namespace{oreceager.cpp}::irrevoc | ( | STM_IRREVOC_SIG(,) | ) |
bool anonymous_namespace{oreceager.cpp}::irrevoc | ( | STM_IRREVOC_SIG(tx,) | ) |
OrecEager in-flight irrevocability:
Either commit the transaction or return false. Note that we're already serial by the time this code runs.
NB: This doesn't Undo anything, so there's no need to protect the stack.
void anonymous_namespace{oreceager.cpp}::onSwitchTo | ( | ) |
Switch to OrecEager:
The timestamp must be >= the maximum value of any orec. Some algs use timestamp as a zero-one mutex. If they do, then they back up the timestamp first, in timestamp_max.
TM_FASTCALL void* anonymous_namespace{oreceager.cpp}::read | ( | STM_READ_SIG(,,) | ) |
void* anonymous_namespace{oreceager.cpp}::read | ( | STM_READ_SIG(tx, addr,) | ) |
OrecEager read:
Must check orec twice, and may need to validate
OrecEager validation:
Make sure that all orecs that we've read have timestamps older than our start time, unless we locked those orecs. If we locked the orec, we did so when the time was smaller than our start time, so we're sure to be OK.
TM_FASTCALL void anonymous_namespace{oreceager.cpp}::write | ( | STM_WRITE_SIG(,,,) | ) |
void anonymous_namespace{oreceager.cpp}::write | ( | STM_WRITE_SIG(tx, addr, val, mask) | ) |
OrecEager write:
Lock the orec, log the old value, do the write