From 032b39487c2eb8219c0dc8322c56c5deaa78e27e Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Thu, 26 Sep 2019 12:16:34 -0700 Subject: [PATCH] sync: add `spin_loop_hint` to atomic waker (#1608) The algorithm backing `AtomicWaker` effectively uses a spin lock backed by notifying & yielding the current task. This adds a `spin_lock_hint` annotation to cover this case. While, in practice, the omission of `spin_lock_hint` would not cause problems, there are platforms that do not handle spin locks very well and could enter a deadlock in pathological cases. --- tokio-sync/src/task/atomic_waker.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tokio-sync/src/task/atomic_waker.rs b/tokio-sync/src/task/atomic_waker.rs index 4085bc0bd..1cd891660 100644 --- a/tokio-sync/src/task/atomic_waker.rs +++ b/tokio-sync/src/task/atomic_waker.rs @@ -1,4 +1,5 @@ -use crate::loom::{sync::atomic::AtomicUsize, sync::CausalCell}; +use crate::loom::sync::atomic::{self, AtomicUsize}; +use crate::loom::sync::CausalCell; use std::fmt; use std::sync::atomic::Ordering::{AcqRel, Acquire, Release}; @@ -171,6 +172,7 @@ impl AtomicWaker { debug!(" + register_task"); match self.state.compare_and_swap(WAITING, REGISTERING, Acquire) { WAITING => { + debug!(" + WAITING"); unsafe { // Locked acquired, update the waker cell self.waker.with_mut(|t| *t = Some(waker.into_waker())); @@ -211,10 +213,14 @@ impl AtomicWaker { } } WAKING => { + debug!(" + WAKING"); // Currently in the process of waking the task, i.e., // `wake` is currently being called on the old waker. // So, we call wake on the new waker. waker.wake(); + + // This is equivalent to a spin lock, so use a spin hint. + atomic::spin_loop_hint(); } state => { // In this case, a concurrent thread is holding the