Built-in functions for transaction execution

Transactional memory is a model for controlling concurrent memory accesses in the scope of parallel programming. In this model, you can designate a block of instructions or statements to be treated atomically. Such a block is called a transaction.

When a thread of execution executes a transaction, it is seen by other threads as an atomic block. That is, all of the memory operations within the transaction are seen to occur simultaneously. At the end of the transaction, a decision is made to commit or abort the transaction. If the transaction is committed, results are written and the execution moves on. If it is aborted, the execution branches back to the beginning of the transaction and the original register state is restored, except for a single bit to indicate that a failure has occurred. The program can decide to retry or skip the transaction.

For parallel programming, a transaction implementation can be tremendously more efficient than other implementation methods. The following built-in functions provide the ability to mark the beginning and end of transactions, and to diagnose the reasons for failure. All the functions and types here will be defined in builtins.h.

Table 1. Built-in functions for transactional memory
PROTOTYPE and Notes® Description
long __TM_simple_begin();
long __TM_begin(void* const TM_buff);

The __TM_simple_begin() function leads to the cheap kind of transaction. Cheap transactions have higher performance, but if the transaction fails, the failure information available is only the two-bit cc returned by the tbegin hardware instruction.

The __TM_begin(const void* TM_buff) function leads to the expensive kind of transaction. The address provided (TM_buff) must be valid. It points to a 256-byte transaction diagnostic block (TDB) containing various debug information. If the transaction fails, the TDB is populated with lots of information.

Note: Extensive control is provided over what state is saved and restored. These built-ins save all gpr’s, and no fpr’s or ar’s. Using float values or ar-mode is not supported, and the facility of filtering some interrupts is not provided.

These functions start a transaction, a cheap transaction or an expensive one, corresponding to only some debugging capability or full debugging capability.

The return value is "0" or non-zero indicating success or failure of the transaction.

long __TM_end();

This function marks the end of a transaction.

The return value is non-zero if the thread was not in transactional state before the instruction started, and "0" otherwise.

void __TM_abort();
void __TM_named_abort(unsigned char const code);

These functions abort a transaction with a failure code, or "0" if none is provided.

Providing a code enables the named abort functionality. The parameter code is constrained to be 0 <= code <=255.

void __TM_abort_assist(unsigned int op1);

This function requests assistance from the processor in performing a transaction-abort assist function.

"op1" specifies the number of times the transaction has aborted.

long __TM_is_user_abort(void* const TM_buff); 
long __TM_is_named_user_abort(void* const TM_buff, 
unsigned char* code);

These functions return "1" if the transaction failed due to a user abort instruction, otherwise "0". The value returned in the parameter code is the code that was passed to the tabort instruction, or "0" if none was passed.

If the TDB specified by TM_buff is valid and the transaction abort code is >=256, return "true" and set code to the transaction abort code minus 256, otherwise return "0".

long __TM_is_illegal(void* const TM_buff); 

Returns "1" if the TDB specified by TM_buff is valid and the transaction aborted due to trying to do something illegal (an instruction not permitted in transactional mode or some other kind of illegal access.)

Returns "1" if the TDB specified by TM_buff is valid and the transaction abort code is "11" or "4".

long __TM_is_footprint_exceeded(void* const TM_buff);

Returns "1" if the TDB specified by TM_buff is valid and the transaction aborted due to reaching the maximum number of cache lines, otherwise "0".

Returns "1" if the TDB pointed at by TM_buff is valid and the transaction abort code is "7" or "8", otherwise returns "0".

long __TM_nesting_depth(void* const TM_buff);

Returns the current nesting depth. If the thread is not in transactional mode, returns the depth at which the most recent transaction aborted, or "0" if it is completed successfully.

long __TM_is_nested_too_deep(void* const TM_buff);

Returns "1" if the transaction aborted due to reaching the maximum nesting depth.

Returns "1" if the TDB pointed at by TM_buff is valid and the transaction abort code is "13".

long __TM_is_conflict(void* const TM_buff);

Returns "1" if the transaction aborted due to a conflict.

Returns "1" if the TDB piointed at by TM_buff is valid and the transaction abort code is "9" or "10", otherwise returns "0".

long __TM_is_failure_persistent(long const result);

Returns "1" if the transaction aborted due to a reason that is persistent.

Returns "1" if result==3 (result should be the CC value returned by tbegin, which is stored in the int return value of tbegin), otherwise returns "0".

long __TM_failure_address(void* const TM_buff);

Returns the code address at which the most recent transaction aborted.

For 64 bit: returns the fourth doubleword of the TDB.

For 31 bit or 24 bit: returns the rightmost word of the TDB.

long long __TM_failure_code(void* const TM_buff);

Returns the raw failure code.

Returns bytes 8-15 of the TDB.

void __TM_non_transactional_store(void* const addr, 
long long const value);

This function indicates that 8 bytes provided by value are stored at the address pointed at by addr. The store is non-transactional.