From e07d1635af6e5ffc3cc7dc43010b72620ff240c6 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 16 Mar 2019 18:07:58 +0100 Subject: [PATCH] Fix undefined behavior in hint::spin_loop for x86 targets without SSE2 The pause instruction requires SSE2 but was being unconditionally used on targets without it, resulting in undefined behavior. This PR fixes that by only using the pause intrinsic if SSE2 is available. It also removes the inline assembly which was not required since these instructions are available in core::arch, and extends support of the spin_loop hint to arm targets with the v6 feature which also support the yield instruction. Closes #59237 . --- src/libcore/hint.rs | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 89de5c1bc8af8..c6d1412f6f93b 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -2,7 +2,7 @@ //! Hints to compiler that affects how code should be emitted or optimized. -use intrinsics; +use {arch, intrinsics}; /// Informs the compiler that this point in the code is not reachable, enabling /// further optimizations. @@ -62,13 +62,32 @@ pub unsafe fn unreachable_unchecked() -> ! { #[inline] #[unstable(feature = "renamed_spin_loop", issue = "55002")] pub fn spin_loop() { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - unsafe { - asm!("pause" ::: "memory" : "volatile"); + #[cfg( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse2" + ) + )] { + #[cfg(target_arch = "x86")] { + unsafe { arch::x86::_mm_pause() }; + } + + #[cfg(target_arch = "x86_64")] { + unsafe { arch::x86_64::_mm_pause() }; + } } - #[cfg(target_arch = "aarch64")] - unsafe { - asm!("yield" ::: "memory" : "volatile"); + #[cfg( + any( + target_arch = "aarch64", + all(target_arch = "arm", target_feature = "v6") + ) + )] { + #[cfg(target_arch = "aarch64")] { + unsafe { arch::aarch64::__yield() }; + } + #[cfg(target_arch = "arm")] { + unsafe { arch::arm::__yield() }; + } } }