diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 493448eaf88fa..35bf8d1b792f9 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -162,7 +162,10 @@ mod boxed { #[cfg(test)] mod boxed_test; pub mod collections; -#[cfg(target_has_atomic = "ptr")] +#[cfg(any( + all(stage0, target_has_atomic = "ptr"), + all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") +))] pub mod sync; pub mod rc; pub mod raw_vec; diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs index f14fe3a20da93..9792d52dd66d2 100644 --- a/src/liballoc/task.rs +++ b/src/liballoc/task.rs @@ -12,10 +12,16 @@ pub use core::task::*; -#[cfg(target_has_atomic = "ptr")] +#[cfg(any( + all(stage0, target_has_atomic = "ptr"), + all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") +))] pub use self::if_arc::*; -#[cfg(target_has_atomic = "ptr")] +#[cfg(any( + all(stage0, target_has_atomic = "ptr"), + all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") +))] mod if_arc { use super::*; use core::marker::PhantomData; @@ -47,7 +53,10 @@ mod if_arc { } } - #[cfg(target_has_atomic = "ptr")] + #[cfg(any( + all(stage0, target_has_atomic = "ptr"), + all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") + ))] struct ArcWrapped(PhantomData); unsafe impl UnsafeWake for ArcWrapped { diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 7aba8b51cff51..e9d1fb8911504 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -371,6 +371,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn swap(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } } @@ -401,6 +402,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -446,6 +448,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn compare_exchange(&self, current: bool, new: bool, @@ -537,6 +540,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_and(self.v.get(), val as u8, order) != 0 } } @@ -568,6 +572,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // We can't use atomic_nand here because it can result in a bool with // an invalid value. This happens because the atomic operation is done @@ -610,6 +615,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_or(self.v.get(), val as u8, order) != 0 } } @@ -640,6 +646,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } } @@ -786,6 +793,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T } } @@ -815,6 +823,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -853,6 +862,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn compare_exchange(&self, current: *mut T, new: *mut T, @@ -1138,6 +1148,7 @@ assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); ```"), #[inline] #[$stable] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -1170,6 +1181,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn compare_and_swap(&self, current: $int_type, new: $int_type, @@ -1223,6 +1235,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable_cxchg] + #[cfg(any(stage0, target_has_atomic = "cas"))] pub fn compare_exchange(&self, current: $int_type, new: $int_type, @@ -1677,6 +1690,7 @@ atomic_int!{ } #[inline] +#[cfg(any(stage0, target_has_atomic = "cas"))] fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, @@ -1713,6 +1727,7 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { } #[inline] +#[cfg(any(stage0, target_has_atomic = "cas"))] unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), @@ -1751,6 +1766,7 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] +#[cfg(any(stage0, target_has_atomic = "cas"))] unsafe fn atomic_compare_exchange(dst: *mut T, old: T, new: T, diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index f97e11ef72f49..342799d41bb56 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1367,6 +1367,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { let vendor = &sess.target.target.target_vendor; let min_atomic_width = sess.target.target.min_atomic_width(); let max_atomic_width = sess.target.target.max_atomic_width(); + let atomic_cas = sess.target.target.options.atomic_cas; let mut ret = HashSet::new(); // Target bindings. @@ -1406,6 +1407,9 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { } } } + if atomic_cas { + ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern("cas")))); + } if sess.opts.debug_assertions { ret.insert((Symbol::intern("debug_assertions"), None)); } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index e54cd773123c8..8ebf5f7c64deb 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -572,6 +572,9 @@ pub struct TargetOptions { /// Don't use this field; instead use the `.max_atomic_width()` method. pub max_atomic_width: Option, + /// Whether the target supports atomic CAS operations natively + pub atomic_cas: bool, + /// Panic strategy: "unwind" or "abort" pub panic_strategy: PanicStrategy, @@ -690,6 +693,7 @@ impl Default for TargetOptions { no_integrated_as: false, min_atomic_width: None, max_atomic_width: None, + atomic_cas: true, panic_strategy: PanicStrategy::Unwind, abi_blacklist: vec![], crt_static_allows_dylibs: false, @@ -946,6 +950,7 @@ impl Target { key!(no_integrated_as, bool); key!(max_atomic_width, Option); key!(min_atomic_width, Option); + key!(atomic_cas, bool); try!(key!(panic_strategy, PanicStrategy)); key!(crt_static_allows_dylibs, bool); key!(crt_static_default, bool); @@ -1154,6 +1159,7 @@ impl ToJson for Target { target_option_val!(no_integrated_as); target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); + target_option_val!(atomic_cas); target_option_val!(panic_strategy); target_option_val!(crt_static_allows_dylibs); target_option_val!(crt_static_default); diff --git a/src/librustc_target/spec/msp430_none_elf.rs b/src/librustc_target/spec/msp430_none_elf.rs index ce42a908b0e43..3ac4c459c6384 100644 --- a/src/librustc_target/spec/msp430_none_elf.rs +++ b/src/librustc_target/spec/msp430_none_elf.rs @@ -34,9 +34,10 @@ pub fn target() -> TargetResult { linker: Some("msp430-elf-gcc".to_string()), no_integrated_as: true, - // There are no atomic instructions available in the MSP430 + // There are no atomic CAS instructions available in the MSP430 // instruction set - max_atomic_width: Some(0), + max_atomic_width: Some(16), + atomic_cas: false, // Because these devices have very little resources having an // unwinder is too onerous so we default to "abort" because the diff --git a/src/librustc_target/spec/thumbv6m_none_eabi.rs b/src/librustc_target/spec/thumbv6m_none_eabi.rs index 9fea07c36f4ef..26812501814f5 100644 --- a/src/librustc_target/spec/thumbv6m_none_eabi.rs +++ b/src/librustc_target/spec/thumbv6m_none_eabi.rs @@ -29,9 +29,9 @@ pub fn target() -> TargetResult { // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them // with +strict-align. features: "+strict-align".to_string(), - // There are no atomic instructions available in the instruction set of the ARMv6-M + // There are no atomic CAS instructions available in the instruction set of the ARMv6-M // architecture - max_atomic_width: Some(0), + atomic_cas: false, .. super::thumb_base::opts() } }) diff --git a/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile new file mode 100644 index 0000000000000..c2eb4caea2635 --- /dev/null +++ b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +# The target used below doesn't support atomic CAS operations. Verify that's the case +all: + $(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v 'target_has_atomic="cas"' diff --git a/src/test/run-make-fulldeps/target-without-atomics/Makefile b/src/test/run-make-fulldeps/target-without-atomics/Makefile deleted file mode 100644 index c5f575ddf84c6..0000000000000 --- a/src/test/run-make-fulldeps/target-without-atomics/Makefile +++ /dev/null @@ -1,5 +0,0 @@ --include ../tools.mk - -# The target used below doesn't support atomic operations. Verify that's the case -all: - $(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v target_has_atomic