pub struct ChainLockTransaction<E: TransactionHooks> { /* private fields */ }Expand description
Environment-independent framework for chain lock transactions.
Chain lock transactions are a layer on top of chain locks that track the state necessary for entities (i.e. CPUs) to acquire a series of one or more chain locks and correctly handle arbitration with other entities contending for the same locks.
Implementations§
Source§impl<E: TransactionHooks> ChainLockTransaction<E>
impl<E: TransactionHooks> ChainLockTransaction<E>
Sourcepub const UNLOCKED_TOKEN_VALUE: u64 = UNLOCKED_TOKEN_VALUE
pub const UNLOCKED_TOKEN_VALUE: u64 = UNLOCKED_TOKEN_VALUE
Token value representing an unlocked ChainLock.
Sourcepub const RESERVED_TOKEN_VALUES: u64 = RESERVED_TOKEN_VALUES
pub const RESERVED_TOKEN_VALUES: u64 = RESERVED_TOKEN_VALUES
Number of reserved token values (1..=RESERVED_TOKEN_VALUES).
Sourcepub const INITIAL_TOKEN_VALUE: u64 = INITIAL_TOKEN_VALUE
pub const INITIAL_TOKEN_VALUE: u64 = INITIAL_TOKEN_VALUE
Initial value for the global dynamic transaction token generator.
Sourcepub const MAX_TOKEN_VALUE: u64 = MAX_TOKEN_VALUE
pub const MAX_TOKEN_VALUE: u64 = MAX_TOKEN_VALUE
Maximum possible token value, used transiently during lock release.
Sourcepub const DEBUG_ACCOUNTING_ENABLED: bool = <E::Accounting>::ENABLED
pub const DEBUG_ACCOUNTING_ENABLED: bool = <E::Accounting>::ENABLED
Whether debug lock accounting is enabled for this transaction type.
Sourcepub const CONTENTION_TRACING_ENABLED: bool = <E::Tracing>::ENABLED
pub const CONTENTION_TRACING_ENABLED: bool = <E::Tracing>::ENABLED
Whether contention spin tracing is enabled for this transaction type.
Sourcepub const DONE: DoneType = DONE
pub const DONE: DoneType = DONE
Constant value of DoneType for completing a ()-returning transaction.
Sourcepub fn next_token() -> Token
pub fn next_token() -> Token
Allocates the next monotonically increasing dynamic transaction Token from the global
token generator.
Sourcepub fn reserved_token(reserved_index: usize) -> Token
pub fn reserved_token(reserved_index: usize) -> Token
Returns the reserved Token for reserved_index (e.g., a CPU number).
Asserts in debug builds that reserved_index < Self::RESERVED_TOKEN_VALUES.
Sourcepub fn until_done<O, F, R>(
option: O,
callsite_info: E::CallsiteInfo,
callable: F,
) -> R::Outputwhere
O: StateOption<Self>,
F: FnMut(&ChainLockTransactionToken<Self>) -> R,
R: IntoTransactionResult,
pub fn until_done<O, F, R>(
option: O,
callsite_info: E::CallsiteInfo,
callable: F,
) -> R::Outputwhere
O: StateOption<Self>,
F: FnMut(&ChainLockTransactionToken<Self>) -> R,
R: IntoTransactionResult,
Provides a common sequence for executing a chain lock transaction and the required backoff arbitration logic.
The caller is responsible for providing three arguments:
- An implementation of
StateOption<Self>(such asOption<O>): Used to instantiate the environment-providedStateSavertype, indicating the relevant states to save, such as IRQ enable flags, preemption flags, etc., and restore after each transaction attempt. - An instance of
E::CallsiteInfo: Used for debugging and tracing to identify the code location of the transaction. - A callable implementing a single transaction attempt: This can be a function or closure
accepting a
&ChainLockTransactionToken<Self>and returning a type implementingIntoTransactionResult.
The callable should match one of the following signatures:
a. FnMut(&ChainLockTransactionToken<Self>) -> TransactionResult<()>: A transaction that
has a return type ().
b. FnMut(&ChainLockTransactionToken<Self>) -> TransactionResult<T>: A transaction that
has a user-defined return type T.
c. FnMut(&ChainLockTransactionToken<Self>) -> DoneType: A transaction that has an implied
return type ().
The overall return type of until_done is either T or (), depending on the signature
of callable, as described above.
A basic transaction is structured as follows:
- Define a callable that will be executed until the transaction is complete. In this
example, the callable will return
zx_status_twhen the transaction is complete, which will become the return value ofuntil_done.
let do_transaction =
|token: &ChainLockTransactionToken| -> TransactionResult<zx_status_t> {
if !object.get_lock().acquire_or_backoff(token) {
return Action::Backoff.into(); // Execute the backoff protocol and re-enter.
}
if restart_transaction_condition {
object.get_lock().release(token);
return Action::Restart.into(); // Restart the transaction and re-enter.
}
if !locked_operation_on_object(object, token) {
object.get_lock().release(token);
// Complete the transaction, returning the error to the caller.
return TransactionResult::Value(ZX_ERR_BAD_STATE);
}
object.get_lock().release(token);
// Complete the transaction, returning success to the caller.
TransactionResult::Value(ZX_OK)
};In cases where the user return type is (), the callable can return
ChainLockTransaction::DONE (or DONE.into() / TransactionResult::DONE) to complete
the transaction.
- Execute the transaction using the given options and callable. In this example, the
constant
STATE_OPTION_Ais a value of typeOption<O>with an environment-specific option value to pass to the state saver. The callable is invoked cyclically, with intervening backoffs, until a terminal value (of a user-defined return type in this case) is returned.
return ChainLockTransaction::until_done(
STATE_OPTION_A,
clt_callsite!("foo"),
do_transaction,
);Sourcepub fn backoff_count(&self) -> u64
pub fn backoff_count(&self) -> u64
Returns the number of times this transaction has backed off.
Sourcepub const fn extra(&self) -> &E::ExtraState
pub const fn extra(&self) -> &E::ExtraState
Returns a reference to the environment-specific extra state (e.g., conflict_id_ in the
kernel).
Sourcepub fn assert_at_least_one_lock_held(&self)
pub fn assert_at_least_one_lock_held(&self)
Asserts that at least one lock is currently held by this transaction (when debug accounting is enabled).
Sourcepub fn assert_at_most_one_lock_held(&self)
pub fn assert_at_most_one_lock_held(&self)
Asserts that at most one lock is currently held by this transaction (when debug accounting is enabled).
Sourcepub fn assert_num_locks_held(&self, expected: u32)
pub fn assert_num_locks_held(&self, expected: u32)
Asserts that exactly expected locks are currently held by this transaction (when debug
accounting is enabled).
Sourcepub fn assert_finalized(&self)
pub fn assert_finalized(&self)
Asserts that this transaction has been finalized (when debug accounting is enabled).
Sourcepub fn assert_not_finalized(&self)
pub fn assert_not_finalized(&self)
Asserts that this transaction has not been finalized (when debug accounting is enabled).
Sourcepub unsafe fn assert_active() -> ChainLockTransactionToken<Self>
pub unsafe fn assert_active() -> ChainLockTransactionToken<Self>
Asserts in debug builds that a transaction is currently active and mints a
ChainLockTransactionToken<Self>.
§Safety
The caller must ensure that a ChainLockTransaction<E> is currently registered as active
on the current execution context, and that the returned token is not used while that
transaction is unregistered or after it is dropped.
Sourcepub unsafe fn mark_active() -> ChainLockTransactionToken<Self>
pub unsafe fn mark_active() -> ChainLockTransactionToken<Self>
Mints a ChainLockTransactionToken<Self> without checking at runtime for efficiency in
trivial cases.
§Safety
The caller must ensure that a ChainLockTransaction<E> is currently registered as active
on the current execution context, and that the returned token is not used while that
transaction is unregistered or after it is dropped.
Sourcepub fn active() -> Option<NonNull<Self>>
pub fn active() -> Option<NonNull<Self>>
Returns a pointer to the active transaction, or None if none is active.
Sourcepub fn active_ref(_token: &ChainLockTransactionToken<Self>) -> &Self
pub fn active_ref(_token: &ChainLockTransactionToken<Self>) -> &Self
Returns a reference to the active transaction. Asserts in debug builds that a transaction is active.
Sourcepub fn save_state_and_use_reserved_token(
token: &ChainLockTransactionToken<Self>,
) -> SavedState<E>
pub fn save_state_and_use_reserved_token( token: &ChainLockTransactionToken<Self>, ) -> SavedState<E>
Saves the pointer to the current transaction and allocates a reserved token to sync leaf chain locks to during critical sequences.
Sourcepub fn save_state_initial(
&self,
_token: &ChainLockTransactionToken<Self>,
) -> SavedState<E>
pub fn save_state_initial( &self, _token: &ChainLockTransactionToken<Self>, ) -> SavedState<E>
Creates a saved state for a bare transaction used to kick off a new thread.
Sourcepub unsafe fn restore_state(saved_state: SavedState<E>)
pub unsafe fn restore_state(saved_state: SavedState<E>)
Restores the active transaction using the given saved state.
§Safety
The caller must ensure that saved_state was produced by
Self::save_state_and_use_reserved_token or Self::save_state_initial for a
ChainLockTransaction<E> instance that remains alive and pinned at its memory address for
as long as it remains registered as the active transaction on the current execution
context.
Sourcepub fn finalize(token: &ChainLockTransactionToken<Self>)
pub fn finalize(token: &ChainLockTransactionToken<Self>)
Directly finalizes the active transaction, ending an active contention tracing duration, if any.
Sourcepub fn restart(
&self,
callsite_info: E::CallsiteInfo,
_token: &ChainLockTransactionToken<Self>,
)
pub fn restart( &self, callsite_info: E::CallsiteInfo, _token: &ChainLockTransactionToken<Self>, )
Restarts this transaction, resetting key state including the callsite info.
Sourcepub fn locks_held(&self) -> u32
pub fn locks_held(&self) -> u32
Returns the number of locks currently held by this transaction.
Requires Self::DEBUG_ACCOUNTING_ENABLED to be true at compile time.
Sourcepub fn is_finalized(&self) -> bool
pub fn is_finalized(&self) -> bool
Returns whether this transaction is currently finalized.
Requires Self::DEBUG_ACCOUNTING_ENABLED to be true at compile time.
Sourcepub fn new_unregistered(
callsite_info: E::CallsiteInfo,
locks_held: u32,
finalized: bool,
) -> Self
pub fn new_unregistered( callsite_info: E::CallsiteInfo, locks_held: u32, finalized: bool, ) -> Self
Creates an unregistered bare transaction with the given initial state.
Because Rust does not guarantee copy elision (RVO) when returning by value, callers
creating a bare transaction outside Self::until_done must place the returned
transaction in its stack variable first, and then call Self::register (or
Self::restore_state with Self::save_state_initial). Note that Drop for
ChainLockTransaction unconditionally calls Self::unregister, so the transaction
must be registered as active before it is dropped.
Sourcepub unsafe fn register(&self) -> ChainLockTransactionToken<Self>
pub unsafe fn register(&self) -> ChainLockTransactionToken<Self>
Registers self as the active transaction for the current execution context and mints a
ChainLockTransactionToken<Self>.
Asserts that no transaction is currently active.
§Safety
The caller must ensure that:
selfremains alive and pinned at its current memory address (i.e. not moved or forgotten without unregistering) for as long as it remains registered as the active transaction on the current execution context.- The returned
ChainLockTransactionToken<Self>is not used whileselfis unregistered or afterselfis dropped.
Sourcepub unsafe fn unregister(&self)
pub unsafe fn unregister(&self)
Unregisters self as the active transaction for the current execution context.
Asserts in debug builds that self is the currently active transaction.
§Safety
The caller must ensure that:
selfis currently the active transaction on the current execution context.- No
ChainLockTransactionToken<Self>associated withselfis used to access the active transaction whileselfis unregistered.
Trait Implementations§
Source§impl<E: TransactionHooks> Drop for ChainLockTransaction<E>
impl<E: TransactionHooks> Drop for ChainLockTransaction<E>
Source§impl<E: TransactionHooks> Transaction for ChainLockTransaction<E>
impl<E: TransactionHooks> Transaction for ChainLockTransaction<E>
Source§type ContentionState = <E as TransactionHooks>::ContentionState
type ContentionState = <E as TransactionHooks>::ContentionState
ChainLock to store contended lock state for backoff mitigation.Source§fn active() -> Option<NonNull<Self>>
fn active() -> Option<NonNull<Self>>
None if
no transaction is active.Source§fn active_ref(token: &ChainLockTransactionToken<Self>) -> &Self
fn active_ref(token: &ChainLockTransactionToken<Self>) -> &Self
Source§fn assert_not_finalized(&self)
fn assert_not_finalized(&self)
Source§fn assert_num_locks_held(&self, expected: u32)
fn assert_num_locks_held(&self, expected: u32)
expected locks (when debug accounting is
enabled).Source§fn on_acquire(&self, _token: &ChainLockTransactionToken<Self>)
fn on_acquire(&self, _token: &ChainLockTransactionToken<Self>)
ChainLock is acquired by this transaction.Source§fn on_release(&self, _token: &ChainLockTransactionToken<Self>)
fn on_release(&self, _token: &ChainLockTransactionToken<Self>)
ChainLock is released by this transaction.Source§fn on_contention(&self, _token: &ChainLockTransactionToken<Self>)
fn on_contention(&self, _token: &ChainLockTransactionToken<Self>)
ChainLock.Source§fn record_backoff_or_retry(
&self,
observed_token: Token,
lock_state: &AtomicToken,
contention_state: &Self::ContentionState,
_token: &ChainLockTransactionToken<Self>,
) -> bool
fn record_backoff_or_retry( &self, observed_token: Token, lock_state: &AtomicToken, contention_state: &Self::ContentionState, _token: &ChainLockTransactionToken<Self>, ) -> bool
ChainLock encounters a higher-priority owner. Read moreSource§fn release_and_notify<F: FnOnce()>(
&self,
contention_state: &Self::ContentionState,
do_release: F,
_token: &ChainLockTransactionToken<Self>,
)
fn release_and_notify<F: FnOnce()>( &self, contention_state: &Self::ContentionState, do_release: F, _token: &ChainLockTransactionToken<Self>, )
ChainLock to sample contention state, invoke
do_release, and notify backed-off contenders.