#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct HardwareMemoryTransactionManager
{
#[cfg(target_arch = "x86_64")] cpu_supports_hardware_transactions: bool,
}
impl HardwareMemoryTransactionManager
{
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub fn new() -> Self
{
Self
{
cpu_supports_hardware_transactions:
{
let cpu_id = CpuId::new();
if let Some(extended_features) = cpu_id.get_extended_feature_info()
{
extended_features.has_rtm()
}
else
{
false
}
}
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn new() -> Self
{
Self
{
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn execute_transaction_once_gracefully<TransactionCallback: FnMut() -> Result<(), u8>>(&self, mut transaction_callback: TransactionCallback) -> Result<(), Option<HardwareMemoryTransactionResult>>
{
Err(None)
}
#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn execute_transaction_once_gracefully<TransactionCallback: FnMut() -> Result<(), u8>>(&self, transaction_callback: TransactionCallback) -> Result<(), Option<HardwareMemoryTransactionResult>>
{
if self.cpu_supports_hardware_transactions()
{
self.execute_transaction_once(transaction_callback).map_err(|error| Some(error))
}
else
{
Err(None)
}
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub fn execute_transaction_once<TransactionCallback: FnMut() -> Result<(), u8>>(&self, mut transaction_callback: TransactionCallback) -> Result<(), HardwareMemoryTransactionResult>
{
debug_assert!(self.cpu_supports_hardware_transactions(), "This x86_64 CPU does not have hardware transactions that we can use");
let xbegin_result_code = unsafe { _xbegin() };
if xbegin_result_code == _XBEGIN_STARTED
{
match transaction_callback()
{
Ok(()) =>
{
unsafe { _xend() };
Ok(())
},
Err(result_status_code) => unsafe { _xabort(result_status_code as u32) },
}
}
else
{
Err(HardwareMemoryTransactionResult::new(xbegin_result_code))
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn execute_transaction_once<TransactionCallback: FnMut() -> u8>(mut transaction_callback: TransactionCallback) -> Result<(), HardwareMemoryTransactionResult>
{
panic!("TSX hardware transactions are not supported on non x86_64 platforms")
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub fn cpu_supports_hardware_transactions(&self) -> bool
{
self.cpu_supports_hardware_transactions
}
#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn is_inside_a_running_transaction(&self) -> bool
{
if self.cpu_supports_hardware_transactions()
{
unsafe { _xtest() }
}
else
{
false
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn cpu_supports_hardware_transactions(&self) -> bool
{
false
}
}