CMRX kernel is mostly implemented as non-blocking. More...
Typedefs | |
typedef uint8_t | Txn_t |
Transaction handle type. | |
Enumerations | |
enum | TxnType { TXN_READONLY , TXN_READWRITE } |
Type of the transaction performed. More... | |
Functions | |
Txn_t | os_txn_start () |
Start a transaction. | |
int | os_txn_commit (Txn_t transaction, enum TxnType type) |
Try to commit the transaction. | |
int | os_txn_start_commit () |
Start new transaction and commit it immediately. | |
void | os_txn_done () |
Finish the transaction commit. | |
Txn_t | os_sys_txn_start (Txn_t *domain) |
Implementation of txn_start syscall. | |
int | os_sys_txn_commit (Txn_t *domain, Txn_t txn, enum TxnType type) |
Implementation of txn_commit syscall. | |
CMRX kernel is mostly implemented as non-blocking.
Where exclusivity is needed, transactions are used in place of mutexes. Transactions provide a means of ensuring that the internal state of program has been consistent thorough the execution of transaction.
CMRX kernel provides two types of transactions:
This approach trades better SMP capabilities and less contention for a bit of complexity on the user side. Any code that uses transactions has to define what will happen if transaction commit fails.
For most use cases the way to deal with transaction commit failure is to redo the action but some of them may figure out that the action is not needed anymore.
typedef uint8_t Txn_t |
Transaction handle type.
enum TxnType |
Implementation of txn_commit syscall.
This function performs some additional argument checking.
domain | domain in which transactions are allocated |
txn | identifier of transaction to be committed |
type | identifies if transaction is read-only or read-write |
Implementation of txn_start syscall.
This function performs some additional argument checking.
domain | domain in which transactions are allocated |
Try to commit the transaction.
This function will try to enter the critical section so that the code running afterwards has exclusive access to the shared resource. If another transaction has been commited meanwhile, then this call will fail as transaction couldn't be commited. Then the critical section is left immediately. If no other transaction conflicted with this one, the code remains in the critical section and can modify the shared context. After the code is done with modifying the shared context, it must call os_txn_done which will leave the critical section. No modification of the shared context is allowed outside of the critical section.
[in] | transaction | the ID of transaction as obtained by the call to ox_txn_start() |
[in] | type | the type of transaction |
void os_txn_done | ( | ) |
Finish the transaction commit.
This function will leave the critical section related to the transaction. This function has to be called for read-write transaction after all the data changes in the transaction were commited.
Txn_t os_txn_start | ( | ) |
Start a transaction.
This function will start a transaction. Starting a transaction means that the code will remember actual record version number (active rolling counter value). rolling counters are updated whenever read-write transaction is commited.
int os_txn_start_commit | ( | ) |
Start new transaction and commit it immediately.
This is a combination of os_txn_start and os_txn_commit for special cases where there is no intermediate computation needed. This is for cases, such as freeing memory, releasing handles, etc. In these cases no search for free entry or any similar action has to be done. Just a known-in-advance entry is freed and this change needs to be transacted. It will start new transaction and immediately commit it. As this is done atomically, the commit never fails. This function always returns E_OK, which means that the code is in commit mode, may change shared data and must call os_txn_done when all changes are written.