summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSteven Stewart-Gallus <sstewartgallus00@mylangara.bc.ca>2017-03-14 21:28:31 -0700
committerSteven Stewart-Gallus <sstewartgallus@sstewartgallus.com>2017-05-01 17:11:44 -0700
commitf4fe3cd0e997fc417a245fd33d0d27fb0b44ba10 (patch)
tree628224c250ff8dffd1017e913607d359a4384db4 /src
parent777ee20796e80a31d4b7c985dd68eda2941460d6 (diff)
downloadrust-f4fe3cd0e997fc417a245fd33d0d27fb0b44ba10.tar.gz
rust-f4fe3cd0e997fc417a245fd33d0d27fb0b44ba10.zip
Added spin loop pause function
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/SUMMARY.md1
-rw-r--r--src/doc/unstable-book/src/library-features/hint-core-should-pause.md41
-rw-r--r--src/libcore/sync/atomic.rs23
3 files changed, 65 insertions, 0 deletions
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`.