From f4fe3cd0e997fc417a245fd33d0d27fb0b44ba10 Mon Sep 17 00:00:00 2001 From: Steven Stewart-Gallus Date: Tue, 14 Mar 2017 21:28:31 -0700 Subject: [PATCH] Added spin loop pause function --- src/doc/unstable-book/src/SUMMARY.md | 1 + .../hint-core-should-pause.md | 41 +++++++++++++++++++ src/libcore/sync/atomic.rs | 23 +++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/hint-core-should-pause.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 0d0485dc872..3d9e7c7fd86 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -145,6 +145,7 @@ - [future_atomic_orderings](library-features/future-atomic-orderings.md) - [get_type_id](library-features/get-type-id.md) - [heap_api](library-features/heap-api.md) + - [hint_core_should_pause](library-features/hint-core-should-pause.md) - [i128](library-features/i128.md) - [inclusive_range](library-features/inclusive-range.md) - [integer_atomics](library-features/integer-atomics.md) diff --git a/src/doc/unstable-book/src/library-features/hint-core-should-pause.md b/src/doc/unstable-book/src/library-features/hint-core-should-pause.md new file mode 100644 index 00000000000..05e057be493 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/hint-core-should-pause.md @@ -0,0 +1,41 @@ +# `hint_core_should_pause` + +The tracking issue for this feature is: [#41196] + +[#41196]: https://github.com/rust-lang/rust/issues/41196 + +------------------------ + +Many programs have spin loops like the following: + +```rust,no_run +use std::sync::atomic::{AtomicBool,Ordering}; + +fn spin_loop(value: &AtomicBool) { + loop { + if value.load(Ordering::Acquire) { + break; + } + } +} +``` + +These programs can be improved in performance like so: + +```rust,no_run +#![feature(hint_core_should_pause)] +use std::sync::atomic; +use std::sync::atomic::{AtomicBool,Ordering}; + +fn spin_loop(value: &AtomicBool) { + loop { + if value.load(Ordering::Acquire) { + break; + } + atomic::hint_core_should_pause(); + } +} +``` + +Further improvements could combine `hint_core_should_pause` with +exponential backoff or `std::thread::yield_now`. diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index fad58deecd4..3c51dbc2550 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -94,6 +94,29 @@ use intrinsics; use cell::UnsafeCell; use fmt; +/// Save power or switch hyperthreads in a busy-wait spin-loop. +/// +/// This function is deliberately more primitive than +/// `std::thread::yield_now` and does not directly yield to the +/// system's scheduler. In some cases it might be useful to use a +/// combination of both functions. Careful benchmarking is advised. +/// +/// On some platforms this function may not do anything at all. +#[inline] +#[unstable(feature = "hint_core_should_pause", issue = "41196")] +pub fn hint_core_should_pause() +{ + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + unsafe { + asm!("pause" ::: "memory" : "volatile"); + } + + #[cfg(target_arch = "aarch64")] + unsafe { + asm!("yield" ::: "memory" : "volatile"); + } +} + /// A boolean type which can be safely shared between threads. /// /// This type has the same in-memory representation as a `bool`.