From ac85190aef3f633fb7ada5aa456d48daa9816e47 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 Apr 2020 14:13:25 +0200 Subject: [PATCH 1/3] AtomicPtr: avoid ptr-to-int casts --- src/libcore/sync/atomic.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 220f221cdd36d..2ec0a782e4194 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -121,6 +121,7 @@ use self::Ordering::*; use crate::cell::UnsafeCell; use crate::fmt; use crate::intrinsics; +use crate::mem; use crate::hint::spin_loop; @@ -970,7 +971,7 @@ impl AtomicPtr { pub fn store(&self, ptr: *mut T, order: Ordering) { // SAFETY: data races are prevented by atomic intrinsics. unsafe { - atomic_store(self.p.get() as *mut usize, ptr as usize, order); + atomic_store(self.p.get() as *mut usize, mem::transmute(ptr), order); } } @@ -1003,7 +1004,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. - unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T } + unsafe { atomic_swap(self.p.get() as *mut usize, mem::transmute(ptr), order) as *mut T } } /// Stores a value into the pointer if the current value is the same as the `current` value. @@ -1091,8 +1092,8 @@ impl AtomicPtr { unsafe { let res = atomic_compare_exchange( self.p.get() as *mut usize, - current as usize, - new as usize, + mem::transmute(current), + mem::transmute(new), success, failure, ); @@ -1155,8 +1156,8 @@ impl AtomicPtr { unsafe { let res = atomic_compare_exchange_weak( self.p.get() as *mut usize, - current as usize, - new as usize, + mem::transmute(current), + mem::transmute(new), success, failure, ); From d03394b23c86c3365cd24dc42e60b7967725eb83 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 Apr 2020 14:14:09 +0200 Subject: [PATCH 2/3] Windows Mutex: use AtomicPtr, not AtomicUsize, for ptr-typed accesses --- src/libstd/sys/windows/mutex.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 63dfc640908e9..e0578ed938960 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -21,9 +21,10 @@ use crate::cell::UnsafeCell; use crate::mem::{self, MaybeUninit}; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{AtomicUsize, AtomicPtr, Ordering}; use crate::sys::c; use crate::sys::compat; +use crate::ptr; pub struct Mutex { lock: AtomicUsize, @@ -112,12 +113,16 @@ impl Mutex { let re = box ReentrantMutex::uninitialized(); re.init(); let re = Box::into_raw(re); - match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) { - 0 => re, - n => { - Box::from_raw(re).destroy(); - n as *mut _ - } + // Get an `AtomicPtr` view of `self.lock`. + let lock_ptr = &*(&self.lock as *const AtomicUsize as *const AtomicPtr); + let old = lock_ptr.compare_and_swap(ptr::null_mut(), re, Ordering::SeqCst); + if old == ptr::null_mut() { + // Update successful. + re + } else { + // Someone else won the race, clean up our attempt and return their value. + Box::from_raw(re).destroy(); + old } } From 2d1a51f8fecebdd2f42e93f1b61a1f6a139c47e6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 Apr 2020 14:19:13 +0200 Subject: [PATCH 3/3] comment, fmt --- src/libcore/sync/atomic.rs | 3 +++ src/libstd/sys/windows/mutex.rs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 2ec0a782e4194..dd94d93019dc9 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -970,6 +970,9 @@ impl AtomicPtr { #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, ptr: *mut T, order: Ordering) { // SAFETY: data races are prevented by atomic intrinsics. + // We transmute to an integer instead of casting to avoid losing pointer + // provenance -- in particular this helps Miri not lose track of the pointer + // when checking for memory leaks. unsafe { atomic_store(self.p.get() as *mut usize, mem::transmute(ptr), order); } diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index e0578ed938960..e59de1dfe0faa 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -21,10 +21,10 @@ use crate::cell::UnsafeCell; use crate::mem::{self, MaybeUninit}; -use crate::sync::atomic::{AtomicUsize, AtomicPtr, Ordering}; +use crate::ptr; +use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; use crate::sys::c; use crate::sys::compat; -use crate::ptr; pub struct Mutex { lock: AtomicUsize,