@@ -9,7 +9,10 @@ use core::{
99 ptr,
1010} ;
1111
12- use super :: seq_lock:: SeqLock ;
12+ use super :: {
13+ atomic_memcpy:: { self , store as write} ,
14+ seq_lock:: SeqLock ,
15+ } ;
1316use crate :: {
1417 CachePadded ,
1518 primitive:: sync:: atomic:: { self , Ordering } ,
@@ -407,10 +410,10 @@ macro_rules! impl_arithmetic {
407410 }
408411 } ,
409412 {
410- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
411- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
412- let old = * value ;
413- * value = value . wrapping_add( val) ;
413+ let dst = self . as_ptr( ) ;
414+ let _guard = lock ( dst as usize ) . write ( ) ;
415+ let old = unsafe { ptr :: read ( dst ) } ;
416+ unsafe { write ( dst , MaybeUninit :: new ( old . wrapping_add( val) ) ) }
414417 old
415418 }
416419 }
@@ -446,10 +449,10 @@ macro_rules! impl_arithmetic {
446449 }
447450 } ,
448451 {
449- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
450- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
451- let old = * value ;
452- * value = value . wrapping_sub( val) ;
452+ let dst = self . as_ptr( ) ;
453+ let _guard = lock ( dst as usize ) . write ( ) ;
454+ let old = unsafe { ptr :: read ( dst ) } ;
455+ unsafe { write ( dst , MaybeUninit :: new ( old . wrapping_sub( val) ) ) }
453456 old
454457 }
455458 }
@@ -483,10 +486,10 @@ macro_rules! impl_arithmetic {
483486 }
484487 } ,
485488 {
486- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
487- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
488- let old = * value ;
489- * value &= val;
489+ let dst = self . as_ptr( ) ;
490+ let _guard = lock ( dst as usize ) . write ( ) ;
491+ let old = unsafe { ptr :: read ( dst ) } ;
492+ unsafe { write ( dst , MaybeUninit :: new ( old & val) ) }
490493 old
491494 }
492495 }
@@ -520,10 +523,10 @@ macro_rules! impl_arithmetic {
520523 }
521524 } ,
522525 {
523- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
524- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
525- let old = * value ;
526- * value = !( old & val) ;
526+ let dst = self . as_ptr( ) ;
527+ let _guard = lock ( dst as usize ) . write ( ) ;
528+ let old = unsafe { ptr :: read ( dst ) } ;
529+ unsafe { write ( dst , MaybeUninit :: new ( !( old & val) ) ) }
527530 old
528531 }
529532 }
@@ -557,10 +560,10 @@ macro_rules! impl_arithmetic {
557560 }
558561 } ,
559562 {
560- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
561- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
562- let old = * value ;
563- * value |= val;
563+ let dst = self . as_ptr( ) ;
564+ let _guard = lock ( dst as usize ) . write ( ) ;
565+ let old = unsafe { ptr :: read ( dst ) } ;
566+ unsafe { write ( dst , MaybeUninit :: new ( old | val) ) }
564567 old
565568 }
566569 }
@@ -594,10 +597,10 @@ macro_rules! impl_arithmetic {
594597 }
595598 } ,
596599 {
597- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
598- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
599- let old = * value ;
600- * value ^= val;
600+ let dst = self . as_ptr( ) ;
601+ let _guard = lock ( dst as usize ) . write ( ) ;
602+ let old = unsafe { ptr :: read ( dst ) } ;
603+ unsafe { write ( dst , MaybeUninit :: new ( old ^ val) ) }
601604 old
602605 }
603606 }
@@ -632,10 +635,10 @@ macro_rules! impl_arithmetic {
632635 }
633636 } ,
634637 {
635- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
636- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
637- let old = * value ;
638- * value = cmp:: max( old, val) ;
638+ let dst = self . as_ptr( ) ;
639+ let _guard = lock ( dst as usize ) . write ( ) ;
640+ let old = unsafe { ptr :: read ( dst ) } ;
641+ unsafe { write ( dst , MaybeUninit :: new ( cmp:: max( old, val) ) ) }
639642 old
640643 }
641644 }
@@ -670,10 +673,10 @@ macro_rules! impl_arithmetic {
670673 }
671674 } ,
672675 {
673- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
674- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
675- let old = * value ;
676- * value = cmp:: min( old, val) ;
676+ let dst = self . as_ptr( ) ;
677+ let _guard = lock ( dst as usize ) . write ( ) ;
678+ let old = unsafe { ptr :: read ( dst ) } ;
679+ unsafe { write ( dst , MaybeUninit :: new ( cmp:: min( old, val) ) ) }
677680 old
678681 }
679682 }
@@ -792,10 +795,10 @@ impl AtomicCell<bool> {
792795 }
793796 } ,
794797 {
795- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
796- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
797- let old = * value ;
798- * value &= val;
798+ let dst = self . as_ptr( ) ;
799+ let _guard = lock ( dst as usize ) . write ( ) ;
800+ let old = unsafe { ptr :: read ( dst ) } ;
801+ unsafe { write ( dst , MaybeUninit :: new ( old & val) ) }
799802 old
800803 }
801804 }
@@ -835,10 +838,10 @@ impl AtomicCell<bool> {
835838 }
836839 } ,
837840 {
838- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
839- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
840- let old = * value ;
841- * value = !( old & val) ;
841+ let dst = self . as_ptr( ) ;
842+ let _guard = lock ( dst as usize ) . write ( ) ;
843+ let old = unsafe { ptr :: read ( dst ) } ;
844+ unsafe { write ( dst , MaybeUninit :: new ( !( old & val) ) ) }
842845 old
843846 }
844847 }
@@ -875,10 +878,10 @@ impl AtomicCell<bool> {
875878 }
876879 } ,
877880 {
878- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
879- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
880- let old = * value ;
881- * value |= val;
881+ let dst = self . as_ptr( ) ;
882+ let _guard = lock ( dst as usize ) . write ( ) ;
883+ let old = unsafe { ptr :: read ( dst ) } ;
884+ unsafe { write ( dst , MaybeUninit :: new ( old | val) ) }
882885 old
883886 }
884887 }
@@ -915,10 +918,10 @@ impl AtomicCell<bool> {
915918 }
916919 } ,
917920 {
918- let _guard = lock ( self . as_ptr( ) as usize ) . write ( ) ;
919- let value = unsafe { & mut * ( self . as_ptr ( ) ) } ;
920- let old = * value ;
921- * value ^= val;
921+ let dst = self . as_ptr( ) ;
922+ let _guard = lock ( dst as usize ) . write ( ) ;
923+ let old = unsafe { ptr :: read ( dst ) } ;
924+ unsafe { write ( dst , MaybeUninit :: new ( old ^ val) ) }
922925 old
923926 }
924927 }
@@ -1045,13 +1048,7 @@ where
10451048
10461049 // Try doing an optimistic read first.
10471050 if let Some ( stamp) = lock. optimistic_read( ) {
1048- // We need a volatile read here because other threads might concurrently modify the
1049- // value. In theory, data races are *always* UB, even if we use volatile reads and
1050- // discard the data when a data race is detected. The proper solution would be to
1051- // do atomic reads and atomic writes, but we can't atomically read and write all
1052- // kinds of data since `AtomicU8` is not available on stable Rust yet.
1053- // Load as `MaybeUninit` because we may load a value that is not valid as `T`.
1054- let val = unsafe { ptr:: read_volatile( src. cast:: <MaybeUninit <T >>( ) ) } ;
1051+ let val = unsafe { atomic_memcpy:: load( src) } ;
10551052
10561053 if lock. validate_read( stamp) {
10571054 return unsafe { val. assume_init( ) } ;
@@ -1082,7 +1079,7 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T) {
10821079 } ,
10831080 {
10841081 let _guard = lock( dst as usize ) . write( ) ;
1085- unsafe { ptr :: write( dst, val) }
1082+ unsafe { write( dst, MaybeUninit :: new ( val) ) }
10861083 }
10871084 }
10881085}
@@ -1102,7 +1099,9 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T) -> T {
11021099 } ,
11031100 {
11041101 let _guard = lock( dst as usize ) . write( ) ;
1105- unsafe { ptr:: replace( dst, val) }
1102+ let old = unsafe { ptr:: read( dst. cast:: <MaybeUninit <T >>( ) ) } ;
1103+ unsafe { write( dst, MaybeUninit :: new( val) ) }
1104+ unsafe { old. assume_init( ) }
11061105 }
11071106 }
11081107}
@@ -1156,7 +1155,7 @@ where
11561155
11571156 let old = unsafe { ptr:: read( dst) } ;
11581157 if T :: eq( & old, & current) {
1159- unsafe { ptr :: write( dst, new) }
1158+ unsafe { write( dst, MaybeUninit :: new( new ) ) }
11601159 Ok ( old)
11611160 } else {
11621161 // The value hasn't been changed. Drop the guard without incrementing the stamp.
0 commit comments