1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
// This file is part of intel-tsx-rtm. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/intel-tsx-rtm/master/COPYRIGHT. No part of predicator, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
// Copyright © 2017 The developers of intel-tsx-rtm. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/intel-tsx-rtm/master/COPYRIGHT.


bitflags!
{
	/// This structure wraps the results of an execution of a transaction.
	pub struct HardwareMemoryTransactionResult: u32
	{
		#[doc(hidden)]
		const _XABORT_EXPLICIT = (1 << 0);
		
		#[doc(hidden)]
		const _XABORT_RETRY = (1 << 1);
		
		#[doc(hidden)]
		const _XABORT_CONFLICT = (1 << 2);
		
		#[doc(hidden)]
		const _XABORT_CAPACITY = (1 << 3);
		
		#[doc(hidden)]
		const _XABORT_DEBUG = (1 << 4);
		
		#[doc(hidden)]
		const _XABORT_NESTED = (1 << 5);
	}
}

impl HardwareMemoryTransactionResult
{
	/// Return this from `TransactionCallback` if a transaction is successful.
	pub const TransactionIsSuccessful: u8 = 0;
	
	/// Return this from `TransactionCallback` if a transaction fails due to a busy lock.
	/// Unofficial, see source code comments in <https://github.com/gcc-mirror/gcc/blob/da8dff89fa9398f04b107e388cb706517ced9505/libitm/config/x86/target.h>.
	pub const TransactionFailedDueToBusyLock: u8 = 0xFF;
	
	#[inline(always)]
	fn new(status: u32) -> Self
	{
		Self
		{
			bits: status,
		}
	}
	
//	/// The transaction succeeded.
//	#[inline(always)]
//	pub fn transaction_was_successful(self) -> bool
//	{
//		self.is_empty()
//	}
	
	/// Returns `Some(status_code)` if explicitly aborted.
	/// `status_code` will never be zero.
	/// Transaction was explicitly aborted with `_xabort()`. The parameter passed to `_xabort` is available with `_XABORT_CODE(status)`.
	#[inline(always)]
	pub fn transaction_was_explicitly_aborted_by_callback(self) -> Option<u8>
	{
		if self.contains(Self::_XABORT_EXPLICIT)
		{
			// Equivalent to `_XCODE_ABORT(status)`.
			let status = (self.bits >> 24) & 0xFF;
			Some(status as u8)
		}
		else
		{
			None
		}
	}
	
	/// Transaction can be retried.
	#[inline(always)]
	pub fn transaction_retry_is_possible(self) -> bool
	{
		self.contains(Self::_XABORT_RETRY)
	}
	
	/// Transaction abort due to a memory conflict with another thread.
	/// A re-try of this transaction is likely to succeed.
	/// Ideally use a back off.
	#[inline(always)]
	pub fn transaction_was_aborted_due_to_conflict_with_another_thread(self) -> bool
	{
		self.contains(Self::_XABORT_CONFLICT)
	}
	
	/// Capacity of the cache was exceeded.
	/// A re-try of this transaction might succeed, but it's not likely.
	#[inline(always)]
	pub fn transaction_was_aborted_due_to_using_too_much_memory(self) -> bool
	{
		self.contains(Self::_XABORT_CAPACITY)
	}
	
	/// Transaction aborted due to a debug trap.
	/// A re-try of this transaction is likely to succeed if the debug trap is removed.
	#[inline(always)]
	pub fn transaction_was_aborted_due_to_a_debug_trap(self) -> bool
	{
		self.contains(Self::_XABORT_DEBUG)
	}
	
	/// Transaction abort in an inner nested transaction.
	/// Transactions inside transactions are a failure of logic, and so it is highly unlikely that a retry would succeed.
	#[inline(always)]
	pub fn transaction_was_aborted_due_to_issuing_a_nested_transaction(self) -> bool
	{
		self.contains(Self::_XABORT_NESTED)
	}
}