Skip to content

Commit 6a5fc9e

Browse files
committed
Auto merge of #41207 - sstewartgallus:spinpause, r=alexcrichton
Spin loop pause function redux GitHub's interface is screwy. This is the same PR as rust-lang/rust#40537
2 parents ed1f26d + f4fe3cd commit 6a5fc9e

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@
145145
- [future_atomic_orderings](library-features/future-atomic-orderings.md)
146146
- [get_type_id](library-features/get-type-id.md)
147147
- [heap_api](library-features/heap-api.md)
148+
- [hint_core_should_pause](library-features/hint-core-should-pause.md)
148149
- [i128](library-features/i128.md)
149150
- [inclusive_range](library-features/inclusive-range.md)
150151
- [integer_atomics](library-features/integer-atomics.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# `hint_core_should_pause`
2+
3+
The tracking issue for this feature is: [#41196]
4+
5+
[#41196]: https://github.com/rust-lang/rust/issues/41196
6+
7+
------------------------
8+
9+
Many programs have spin loops like the following:
10+
11+
```rust,no_run
12+
use std::sync::atomic::{AtomicBool,Ordering};
13+
14+
fn spin_loop(value: &AtomicBool) {
15+
loop {
16+
if value.load(Ordering::Acquire) {
17+
break;
18+
}
19+
}
20+
}
21+
```
22+
23+
These programs can be improved in performance like so:
24+
25+
```rust,no_run
26+
#![feature(hint_core_should_pause)]
27+
use std::sync::atomic;
28+
use std::sync::atomic::{AtomicBool,Ordering};
29+
30+
fn spin_loop(value: &AtomicBool) {
31+
loop {
32+
if value.load(Ordering::Acquire) {
33+
break;
34+
}
35+
atomic::hint_core_should_pause();
36+
}
37+
}
38+
```
39+
40+
Further improvements could combine `hint_core_should_pause` with
41+
exponential backoff or `std::thread::yield_now`.

src/libcore/sync/atomic.rs

+23
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,29 @@ use intrinsics;
9494
use cell::UnsafeCell;
9595
use fmt;
9696

97+
/// Save power or switch hyperthreads in a busy-wait spin-loop.
98+
///
99+
/// This function is deliberately more primitive than
100+
/// `std::thread::yield_now` and does not directly yield to the
101+
/// system's scheduler. In some cases it might be useful to use a
102+
/// combination of both functions. Careful benchmarking is advised.
103+
///
104+
/// On some platforms this function may not do anything at all.
105+
#[inline]
106+
#[unstable(feature = "hint_core_should_pause", issue = "41196")]
107+
pub fn hint_core_should_pause()
108+
{
109+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
110+
unsafe {
111+
asm!("pause" ::: "memory" : "volatile");
112+
}
113+
114+
#[cfg(target_arch = "aarch64")]
115+
unsafe {
116+
asm!("yield" ::: "memory" : "volatile");
117+
}
118+
}
119+
97120
/// A boolean type which can be safely shared between threads.
98121
///
99122
/// This type has the same in-memory representation as a `bool`.

0 commit comments

Comments
 (0)