From 38e5ab26e768e0c69b55017b325dc2e72e9e8131 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 10 Sep 2023 22:37:11 +0900 Subject: [PATCH] Relax memory ordering in AtomicCell::replace --- src/no_std/node.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/no_std/node.rs b/src/no_std/node.rs index 9f5a130..8901eb2 100644 --- a/src/no_std/node.rs +++ b/src/no_std/node.rs @@ -218,12 +218,20 @@ impl AtomicCell { /// Swap the value out. fn replace(&self, value: Option>) -> Option> { - let value = value.map_or(ptr::null_mut(), |value| Box::into_raw(value)); - let old_value = self.0.swap(value, Ordering::SeqCst); + let old_value = match value { + Some(value) => self.0.swap(Box::into_raw(value), Ordering::AcqRel), + // Acquire is needed to synchronize with the store of a non-null ptr, but since a null ptr + // will never be dereferenced, there is no need to synchronize the store of a null ptr. + None => self.0.swap(ptr::null_mut(), Ordering::Acquire), + }; if old_value.is_null() { None } else { + // SAFETY: + // - AcqRel/Acquire ensures that it does not read a pointer to potentially invalid memory. + // - We've checked that old_value is not null. + // - We do not store invalid pointers other than null in self.0. Some(unsafe { Box::from_raw(old_value) }) } }