about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-01-09 00:29:09 +0900
committerGitHub <noreply@github.com>2020-01-09 00:29:09 +0900
commit256f401b85da7ae6e3d146a41089897c37c2589a (patch)
treebb11420c7c9c655c1ab8b8f0aa6514e1f3af7d91
parentb85b1dd465e32dfdfe6a61d9ebffb1c5e50ac40b (diff)
parentb25eeef88d55a412c0e0bec7c0989d5a7969f195 (diff)
downloadrust-256f401b85da7ae6e3d146a41089897c37c2589a.tar.gz
rust-256f401b85da7ae6e3d146a41089897c37c2589a.zip
Rollup merge of #67798 - matklad:spin-thouse-docs, r=Amanieu
Remove wrong advice about spin locks from `spin_loop_hint` docs

Using a pure spin lock for a critical section in a preemptable thread
is always wrong, however short the critical section may be. The thread
might be preempted, which will cause all other threads to hammer
busily at the core for the whole quant. Moreover, if threads have
different priorities, this might lead to a priority inversion problem
and a deadlock. More generally, a spinlock is not more efficient than
a well-written mutex, which typically does several spin iterations at
the start anyway.

The advise about UP vs SMP is also irrelevant in the context of
preemptive threads.

See also accompanying piece: https://matklad.github.io/2020/01/02/spinlocs-considered-harmful.html

And another, independent piece: https://probablydance.com/2019/12/30/measuring-mutexes-spinlocks-and-how-bad-the-linux-scheduler-really-is

EDIT: obligatory disclosure that I am not an expert in these things, and might be terribly wrong :)
-rw-r--r--src/libcore/sync/atomic.rs14
1 files changed, 4 insertions, 10 deletions
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index a2352c08e73..fae95ca5cdb 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -134,16 +134,10 @@ use crate::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.
 ///
-/// Spin locks can be very efficient for short lock durations because they do not involve context
-/// switches or interaction with the operating system. For long lock durations they become wasteful
-/// however because they use CPU cycles for the entire lock duration, and using a
-/// [`std::sync::Mutex`] is likely the better approach. If actively spinning for a long time is
-/// required, e.g. because code polls a non-blocking API, calling [`std::thread::yield_now`]
-/// or [`std::thread::sleep`] may be the best option.
-///
-/// **Note**: Spin locks are based on the underlying assumption that another thread will release
-/// the lock 'soon'. In order for this to work, that other thread must run on a different CPU or
-/// core (at least potentially). Spin locks do not work efficiently on single CPU / core platforms.
+/// 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
 /// do anything at all.