From 284e8daffc5c97813c22e300b93700b57d9074a8 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 1 Sep 2024 08:45:35 +0900 Subject: [PATCH] tests: Add quickcheck tests for AtomicPtr --- src/imp/interrupt/mod.rs | 24 ++++++++++++++++-------- src/imp/mod.rs | 13 +++++++++++-- src/imp/riscv.rs | 30 ++++++++++++++++++++++++++++++ src/tests/helper.rs | 31 +++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 10 deletions(-) diff --git a/src/imp/interrupt/mod.rs b/src/imp/interrupt/mod.rs index 0a6ea6cd..f13c28ac 100644 --- a/src/imp/interrupt/mod.rs +++ b/src/imp/interrupt/mod.rs @@ -176,8 +176,10 @@ impl AtomicPtr { any(target_arch = "riscv32", target_arch = "riscv64"), any( portable_atomic_force_amo, - target_feature = "zaamo", - portable_atomic_target_feature = "zaamo", + all( + any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"), + portable_atomic_unsafe_assume_single_core, + ), ), ))] { @@ -187,8 +189,10 @@ impl AtomicPtr { any(target_arch = "riscv32", target_arch = "riscv64"), any( portable_atomic_force_amo, - target_feature = "zaamo", - portable_atomic_target_feature = "zaamo", + all( + any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"), + portable_atomic_unsafe_assume_single_core, + ), ), )))] // SAFETY: any data races are prevented by disabling interrupts (see @@ -297,8 +301,10 @@ macro_rules! atomic_int { any(target_arch = "riscv32", target_arch = "riscv64"), any( portable_atomic_force_amo, - target_feature = "zaamo", - portable_atomic_target_feature = "zaamo", + all( + any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"), + portable_atomic_unsafe_assume_single_core, + ), ), ))] atomic_int!(cas $([$kind])?, $atomic_type, $int_type); @@ -306,8 +312,10 @@ macro_rules! atomic_int { any(target_arch = "riscv32", target_arch = "riscv64"), any( portable_atomic_force_amo, - target_feature = "zaamo", - portable_atomic_target_feature = "zaamo", + all( + any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"), + portable_atomic_unsafe_assume_single_core, + ), ), )))] atomic_int!(cas[emulate], $atomic_type, $int_type); diff --git a/src/imp/mod.rs b/src/imp/mod.rs index 0538264d..862d1a06 100644 --- a/src/imp/mod.rs +++ b/src/imp/mod.rs @@ -134,10 +134,19 @@ pub(crate) mod msp430; // atomic load/store for RISC-V without A-extension #[cfg(any(test, not(feature = "critical-section")))] -#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))] +#[cfg_attr( + portable_atomic_no_cfg_target_has_atomic, + cfg(any( + all(test, not(any(miri, portable_atomic_sanitize_thread))), + portable_atomic_no_atomic_cas, + )) +)] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), - cfg(any(test, not(target_has_atomic = "ptr"))) + cfg(any( + all(test, not(any(miri, portable_atomic_sanitize_thread))), + not(target_has_atomic = "ptr"), + )) )] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] mod riscv; diff --git a/src/imp/riscv.rs b/src/imp/riscv.rs index 6e37584c..a4c3b7d0 100644 --- a/src/imp/riscv.rs +++ b/src/imp/riscv.rs @@ -273,6 +273,7 @@ macro_rules! atomic_ptr { ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty, $asm_suffix:tt) => { atomic_load_store!($([$($generics)*])? $atomic_type, $value_type, $asm_suffix); #[cfg(any( + test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", @@ -505,6 +506,34 @@ mod tests { test_atomic_int_load_store!(isize); test_atomic_int_load_store!(usize); + macro_rules! test_atomic_ptr_amo { + () => { + #[allow( + clippy::alloc_instead_of_core, + clippy::std_instead_of_alloc, + clippy::std_instead_of_core, + clippy::undocumented_unsafe_blocks + )] + mod test_atomic_ptr_amo { + use super::*; + test_atomic_ptr_amo!(AtomicPtr); + } + }; + ($atomic_type:ty) => { + ::quickcheck::quickcheck! { + fn quickcheck_swap(x: usize, y: usize) -> bool { + let x = sptr::invalid_mut(x); + let y = sptr::invalid_mut(y); + for &order in &test_helper::SWAP_ORDERINGS { + let a = <$atomic_type>::new(x); + assert_eq!(a.swap(y, order), x); + assert_eq!(a.swap(x, order), y); + } + true + } + } + }; + } macro_rules! test_atomic_int_amo { ($int_type:ident) => { paste::paste! { @@ -793,6 +822,7 @@ mod tests { } }; } + test_atomic_ptr_amo!(); test_atomic_int_amo_sub_word!(i8); test_atomic_int_amo_sub_word!(u8); test_atomic_int_amo_sub_word!(i16); diff --git a/src/tests/helper.rs b/src/tests/helper.rs index cdfade60..b8fb3008 100644 --- a/src/tests/helper.rs +++ b/src/tests/helper.rs @@ -1385,6 +1385,37 @@ macro_rules! __test_atomic_ptr { assert_eq!(a.load(Ordering::Relaxed), x as *mut _); } } + ::quickcheck::quickcheck! { + fn quickcheck_swap(x: usize, y: usize) -> bool { + let x = sptr::invalid_mut(x); + let y = sptr::invalid_mut(y); + for &order in &test_helper::SWAP_ORDERINGS { + let a = <$atomic_type>::new(x); + assert_eq!(a.swap(y, order), x); + assert_eq!(a.swap(x, order), y); + } + true + } + fn quickcheck_compare_exchange(x: usize, y: usize) -> bool { + let z = loop { + let z = fastrand::usize(..); + if z != y { + break z; + } + }; + let x = sptr::invalid_mut(x); + let y = sptr::invalid_mut(y); + let z = sptr::invalid_mut(z); + for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { + let a = <$atomic_type>::new(x); + assert_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); + assert_eq!(a.load(Ordering::Relaxed), y); + assert_eq!(a.compare_exchange(z, x, success, failure).unwrap_err(), y); + assert_eq!(a.load(Ordering::Relaxed), y); + } + true + } + } }; ($atomic_type:ty) => { __test_atomic_ptr!($atomic_type, single_thread);