From 10bd0fcdfd88a1cc3a80249facbb7c0dd3b52083 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 8 Jan 2022 15:04:53 +0900 Subject: [PATCH 1/3] Support AtomicCell<*64> arithmetics on targets that do not support Atomic*64 --- crossbeam-utils/src/atomic/atomic_cell.rs | 81 +++++++++-------------- 1 file changed, 30 insertions(+), 51 deletions(-) diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index 55eb40108..edbe99c8a 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -295,7 +295,7 @@ impl AtomicCell { } macro_rules! impl_arithmetic { - ($t:ty, $example:tt) => { + ($t:ty, fallback, $example:tt) => { impl AtomicCell<$t> { /// Increments the current value by `val` and returns the previous value. /// @@ -313,16 +313,11 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_add(&self, val: $t) -> $t { - if can_transmute::<$t, atomic::AtomicUsize>() { - let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) }; - a.fetch_add(val as usize, Ordering::AcqRel) as $t - } else { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value = value.wrapping_add(val); - old - } + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value = value.wrapping_add(val); + old } /// Decrements the current value by `val` and returns the previous value. @@ -341,16 +336,11 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_sub(&self, val: $t) -> $t { - if can_transmute::<$t, atomic::AtomicUsize>() { - let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) }; - a.fetch_sub(val as usize, Ordering::AcqRel) as $t - } else { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value = value.wrapping_sub(val); - old - } + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value = value.wrapping_sub(val); + old } /// Applies bitwise "and" to the current value and returns the previous value. @@ -367,16 +357,11 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_and(&self, val: $t) -> $t { - if can_transmute::<$t, atomic::AtomicUsize>() { - let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) }; - a.fetch_and(val as usize, Ordering::AcqRel) as $t - } else { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value &= val; - old - } + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value &= val; + old } /// Applies bitwise "or" to the current value and returns the previous value. @@ -393,16 +378,11 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_or(&self, val: $t) -> $t { - if can_transmute::<$t, atomic::AtomicUsize>() { - let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) }; - a.fetch_or(val as usize, Ordering::AcqRel) as $t - } else { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value |= val; - old - } + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value |= val; + old } /// Applies bitwise "xor" to the current value and returns the previous value. @@ -419,16 +399,11 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_xor(&self, val: $t) -> $t { - if can_transmute::<$t, atomic::AtomicUsize>() { - let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) }; - a.fetch_xor(val as usize, Ordering::AcqRel) as $t - } else { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value ^= val; - old - } + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value ^= val; + old } } }; @@ -541,6 +516,10 @@ impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);"); impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);"); #[cfg(not(crossbeam_no_atomic_64))] impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);"); +#[cfg(crossbeam_no_atomic_64)] +impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);"); +#[cfg(crossbeam_no_atomic_64)] +impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);"); // TODO: AtomicU128 is unstable // impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);"); // impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);"); From 85e2fe8d58d4726a314e7b242f7cdf6389bc0d07 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 8 Jan 2022 15:10:06 +0900 Subject: [PATCH 2/3] Support AtomicCell<*128> arithmetics --- crossbeam-utils/src/atomic/atomic_cell.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index edbe99c8a..325cf3797 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -523,6 +523,8 @@ impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);"); // TODO: AtomicU128 is unstable // impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);"); // impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);"); +impl_arithmetic!(u128, fallback, "let a = AtomicCell::new(7u128);"); +impl_arithmetic!(i128, fallback, "let a = AtomicCell::new(7i128);"); impl_arithmetic!( usize, From 3db81f9438087b0d146aa716ae6d6dbb54b32105 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 8 Jan 2022 15:36:26 +0900 Subject: [PATCH 3/3] Fix build error on cfg(crossbeam_loom) --- crossbeam-utils/src/atomic/atomic_cell.rs | 90 ++++++++++++++++------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index 325cf3797..995de4405 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -313,11 +313,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_add(&self, val: $t) -> $t { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value = value.wrapping_add(val); - old + #[cfg(crossbeam_loom)] + { + let _ = val; + unimplemented!("loom does not support non-atomic atomic ops"); + } + #[cfg(not(crossbeam_loom))] + { + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value = value.wrapping_add(val); + old + } } /// Decrements the current value by `val` and returns the previous value. @@ -336,11 +344,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_sub(&self, val: $t) -> $t { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value = value.wrapping_sub(val); - old + #[cfg(crossbeam_loom)] + { + let _ = val; + unimplemented!("loom does not support non-atomic atomic ops"); + } + #[cfg(not(crossbeam_loom))] + { + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value = value.wrapping_sub(val); + old + } } /// Applies bitwise "and" to the current value and returns the previous value. @@ -357,11 +373,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_and(&self, val: $t) -> $t { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value &= val; - old + #[cfg(crossbeam_loom)] + { + let _ = val; + unimplemented!("loom does not support non-atomic atomic ops"); + } + #[cfg(not(crossbeam_loom))] + { + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value &= val; + old + } } /// Applies bitwise "or" to the current value and returns the previous value. @@ -378,11 +402,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_or(&self, val: $t) -> $t { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value |= val; - old + #[cfg(crossbeam_loom)] + { + let _ = val; + unimplemented!("loom does not support non-atomic atomic ops"); + } + #[cfg(not(crossbeam_loom))] + { + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value |= val; + old + } } /// Applies bitwise "xor" to the current value and returns the previous value. @@ -399,11 +431,19 @@ macro_rules! impl_arithmetic { /// ``` #[inline] pub fn fetch_xor(&self, val: $t) -> $t { - let _guard = lock(self.value.get() as usize).write(); - let value = unsafe { &mut *(self.value.get()) }; - let old = *value; - *value ^= val; - old + #[cfg(crossbeam_loom)] + { + let _ = val; + unimplemented!("loom does not support non-atomic atomic ops"); + } + #[cfg(not(crossbeam_loom))] + { + let _guard = lock(self.value.get() as usize).write(); + let value = unsafe { &mut *(self.value.get()) }; + let old = *value; + *value ^= val; + old + } } } };