Skip to content

Commit

Permalink
Stabilize hint::spin_loop
Browse files Browse the repository at this point in the history
Partially fix #55002, deprecate in another release

Co-authored-by: Ashley Mannix <kodraus@hey.com>

Update stable version for stabilize_spin_loop

Co-authored-by: Joshua Nelson <joshua@yottadb.com>

Use better example for spinlock

As suggested by KodrAus

Remove renamed_spin_loop already available in master

Fix spin loop example
  • Loading branch information
pickfire committed Nov 6, 2020
1 parent 9f6c670 commit e8b5be5
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 24 deletions.
1 change: 0 additions & 1 deletion library/alloc/src/lib.rs
Expand Up @@ -119,7 +119,6 @@
#![feature(raw_ref_op)]
#![feature(rustc_attrs)]
#![feature(receiver_trait)]
#![feature(renamed_spin_loop)]
#![feature(min_specialization)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
Expand Down
62 changes: 53 additions & 9 deletions library/core/src/hint.rs
@@ -1,6 +1,7 @@
#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.
//! Hints may be compile time or runtime.

use crate::intrinsics;

Expand All @@ -24,7 +25,6 @@ use crate::intrinsics;
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
///
/// # Example
///
/// ```
Expand All @@ -51,18 +51,62 @@ pub const unsafe fn unreachable_unchecked() -> ! {
unsafe { intrinsics::unreachable() }
}

/// Emits a machine instruction hinting to the processor that it is running in busy-wait
/// spin-loop ("spin lock").
/// Emits a machine instruction to signal the processor that it is running in
/// a busy-wait spin-loop ("spin lock").
///
/// Upon receiving the spin-loop signal the processor can optimize its behavior by,
/// for example, saving power or switching hyper-threads.
///
/// This function is different from [`thread::yield_now`] which directly
/// yields to the system's scheduler, whereas `spin_loop` does not interact
/// with the operating system.
///
/// 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
///
/// For a discussion of different locking strategies and their trade-offs, see
/// [`core::sync::atomic::spin_loop_hint`].
/// ```
/// 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);
/// })
/// };
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
/// // 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>>(())
/// ```
///
/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
pub fn spin_loop() {
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
{
Expand Down
16 changes: 3 additions & 13 deletions library/core/src/sync/atomic.rs
Expand Up @@ -115,23 +115,13 @@ use crate::hint::spin_loop;

/// 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
/// power or switching hyper-threads.
///
/// 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.
/// This function is expected to be deprecated in favor of
/// [`hint::spin_loop`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html
/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html
/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html
/// [`hint::spin_loop`]: crate::hint::spin_loop
#[inline]
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
pub fn spin_loop_hint() {
Expand Down
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Expand Up @@ -296,7 +296,6 @@
#![feature(raw)]
#![feature(raw_ref_macros)]
#![feature(ready_macro)]
#![feature(renamed_spin_loop)]
#![feature(rustc_attrs)]
#![feature(rustc_private)]
#![feature(shrink_to)]
Expand Down

0 comments on commit e8b5be5

Please sign in to comment.