Rollup merge of #76097 - pickfire:stabilize-spin-loop, r=KodrAus
Stabilize hint::spin_loop Partially fix #55002, deprecate in another release r? ``````@KodrAus``````
This commit is contained in:
commit
1f034f77bc
4 changed files with 56 additions and 24 deletions
|
@ -119,7 +119,6 @@
|
||||||
#![feature(raw_ref_op)]
|
#![feature(raw_ref_op)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(receiver_trait)]
|
#![feature(receiver_trait)]
|
||||||
#![feature(renamed_spin_loop)]
|
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(slice_ptr_get)]
|
#![feature(slice_ptr_get)]
|
||||||
#![feature(slice_ptr_len)]
|
#![feature(slice_ptr_len)]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#![stable(feature = "core_hint", since = "1.27.0")]
|
#![stable(feature = "core_hint", since = "1.27.0")]
|
||||||
|
|
||||||
//! Hints to compiler that affects how code should be emitted or optimized.
|
//! Hints to compiler that affects how code should be emitted or optimized.
|
||||||
|
//! Hints may be compile time or runtime.
|
||||||
|
|
||||||
use crate::intrinsics;
|
use crate::intrinsics;
|
||||||
|
|
||||||
|
@ -24,7 +25,6 @@ use crate::intrinsics;
|
||||||
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
|
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
|
||||||
/// optimizations but will panic when executed.
|
/// optimizations but will panic when executed.
|
||||||
///
|
///
|
||||||
///
|
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -51,18 +51,62 @@ pub const unsafe fn unreachable_unchecked() -> ! {
|
||||||
unsafe { intrinsics::unreachable() }
|
unsafe { intrinsics::unreachable() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a machine instruction hinting to the processor that it is running in busy-wait
|
/// Emits a machine instruction to signal the processor that it is running in
|
||||||
/// spin-loop ("spin lock").
|
/// a busy-wait spin-loop ("spin lock").
|
||||||
///
|
///
|
||||||
/// For a discussion of different locking strategies and their trade-offs, see
|
/// Upon receiving the spin-loop signal the processor can optimize its behavior by,
|
||||||
/// [`core::sync::atomic::spin_loop_hint`].
|
/// for example, saving power or switching hyper-threads.
|
||||||
///
|
///
|
||||||
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
|
/// This function is different from [`thread::yield_now`] which directly
|
||||||
/// do anything at all.
|
/// yields to the system's scheduler, whereas `spin_loop` does not interact
|
||||||
|
/// with the operating system.
|
||||||
///
|
///
|
||||||
/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
|
/// A common use case for `spin_loop` is implementing bounded optimistic
|
||||||
|
/// spinning in a CAS loop in synchronization primitives. To avoid problems
|
||||||
|
/// like priority inversion, it is strongly recommended that the spin loop is
|
||||||
|
/// terminated after a finite amount of iterations and an appropriate blocking
|
||||||
|
/// syscall is made.
|
||||||
|
///
|
||||||
|
/// **Note**: On platforms that do not support receiving spin-loop hints this
|
||||||
|
/// function does not do anything at all.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
/// use std::sync::Arc;
|
||||||
|
/// use std::{hint, thread};
|
||||||
|
///
|
||||||
|
/// // A shared atomic value that threads will use to coordinate
|
||||||
|
/// let live = Arc::new(AtomicBool::new(false));
|
||||||
|
///
|
||||||
|
/// // In a background thread we'll eventually set the value
|
||||||
|
/// let bg_work = {
|
||||||
|
/// let live = live.clone();
|
||||||
|
/// thread::spawn(move || {
|
||||||
|
/// // Do some work, then make the value live
|
||||||
|
/// do_some_work();
|
||||||
|
/// live.store(true, Ordering::Release);
|
||||||
|
/// })
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // Back on our current thread, we wait for the value to be set
|
||||||
|
/// while live.load(Ordering::Acquire) {
|
||||||
|
/// // The spin loop is a hint to the CPU that we're waiting, but probably
|
||||||
|
/// // not for very long
|
||||||
|
/// hint::spin_loop();
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // The value is now set
|
||||||
|
/// # fn do_some_work() {}
|
||||||
|
/// do_some_work();
|
||||||
|
/// bg_work.join()?;
|
||||||
|
/// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
|
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
|
||||||
pub fn spin_loop() {
|
pub fn spin_loop() {
|
||||||
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
|
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
|
||||||
{
|
{
|
||||||
|
|
|
@ -115,23 +115,13 @@ use crate::hint::spin_loop;
|
||||||
|
|
||||||
/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
|
/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
|
||||||
///
|
///
|
||||||
/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
|
/// This function is expected to be deprecated in favor of
|
||||||
/// power or switching hyper-threads.
|
/// [`hint::spin_loop`].
|
||||||
///
|
|
||||||
/// This function is different from [`std::thread::yield_now`] which directly yields to the
|
|
||||||
/// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system.
|
|
||||||
///
|
|
||||||
/// A common use case for `spin_loop_hint` is implementing bounded optimistic spinning in a CAS
|
|
||||||
/// loop in synchronization primitives. To avoid problems like priority inversion, it is strongly
|
|
||||||
/// recommended that the spin loop is terminated after a finite amount of iterations and an
|
|
||||||
/// appropriate blocking syscall is made.
|
|
||||||
///
|
///
|
||||||
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
|
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
|
||||||
/// do anything at all.
|
/// do anything at all.
|
||||||
///
|
///
|
||||||
/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html
|
/// [`hint::spin_loop`]: crate::hint::spin_loop
|
||||||
/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html
|
|
||||||
/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
|
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
|
||||||
pub fn spin_loop_hint() {
|
pub fn spin_loop_hint() {
|
||||||
|
|
|
@ -296,7 +296,6 @@
|
||||||
#![feature(raw)]
|
#![feature(raw)]
|
||||||
#![feature(raw_ref_macros)]
|
#![feature(raw_ref_macros)]
|
||||||
#![feature(ready_macro)]
|
#![feature(ready_macro)]
|
||||||
#![feature(renamed_spin_loop)]
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(shrink_to)]
|
#![feature(shrink_to)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue