sync: Don't sleep while holding a spinlock

Drop order in rust is weird.  Temporaries created in an if let
expression are dropped _after_ the else branch.  In this case that meant
we were sleeping while holding the spin lock, which could potentially
lead to the test hanging ~forever if the thread trying to update the
value repeatedly failed to acquire the lock.

Move the sleep out of the else branch so that the lock is dropped after
checking for the waiter but before the thread goes to sleep.

BUG=none
TEST=Run unit tests and see that they no longer get randomly stuck for
     several seconds.

Change-Id: I08aa80169071959593bee157acda39411472cf11
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2804870
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
Chirantan Ekbote 2021-04-02 21:35:58 +09:00 committed by Commit Bot
parent 6fc5f20fd9
commit 9e44b5b3d7

View file

@ -1255,12 +1255,14 @@ mod test {
fn wake_future(waker: Arc<SpinLock<Option<Waker>>>) {
loop {
if let Some(waker) = waker.lock().take() {
waker.wake();
if let Some(w) = waker.lock().take() {
w.wake();
return;
} else {
thread::sleep(Duration::from_millis(10));
}
// This sleep cannot be moved into an else branch because we would end up holding
// the lock while sleeping due to rust's drop ordering rules.
thread::sleep(Duration::from_millis(10));
}
}