1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker //! Mutex type whose methods panic rather than returning error in case of 6*bb4ee6a4SAndroid Build Coastguard Worker //! poison. 7*bb4ee6a4SAndroid Build Coastguard Worker //! 8*bb4ee6a4SAndroid Build Coastguard Worker //! The Mutex type in this module wraps the standard library Mutex and mirrors 9*bb4ee6a4SAndroid Build Coastguard Worker //! the same methods, except that they panic where the standard library would 10*bb4ee6a4SAndroid Build Coastguard Worker //! return a PoisonError. This API codifies our error handling strategy around 11*bb4ee6a4SAndroid Build Coastguard Worker //! poisoned mutexes in crosvm. 12*bb4ee6a4SAndroid Build Coastguard Worker //! 13*bb4ee6a4SAndroid Build Coastguard Worker //! - Crosvm releases are built with panic=abort so poisoning never occurs. A panic while a mutex is 14*bb4ee6a4SAndroid Build Coastguard Worker //! held (or ever) takes down the entire process. Thus we would like for code not to have to 15*bb4ee6a4SAndroid Build Coastguard Worker //! consider the possibility of poison. 16*bb4ee6a4SAndroid Build Coastguard Worker //! 17*bb4ee6a4SAndroid Build Coastguard Worker //! - We could ask developers to always write `.lock().unwrap()` on a standard library mutex. 18*bb4ee6a4SAndroid Build Coastguard Worker //! However, we would like to stigmatize the use of unwrap. It is confusing to permit unwrap but 19*bb4ee6a4SAndroid Build Coastguard Worker //! only on mutex lock results. During code review it may not always be obvious whether a 20*bb4ee6a4SAndroid Build Coastguard Worker //! particular unwrap is unwrapping a mutex lock result or a different error that should be 21*bb4ee6a4SAndroid Build Coastguard Worker //! handled in a more principled way. 22*bb4ee6a4SAndroid Build Coastguard Worker //! 23*bb4ee6a4SAndroid Build Coastguard Worker //! Developers should feel free to use sync::Mutex anywhere in crosvm that they 24*bb4ee6a4SAndroid Build Coastguard Worker //! would otherwise be using std::sync::Mutex. 25*bb4ee6a4SAndroid Build Coastguard Worker 26*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt; 27*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Debug; 28*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Display; 29*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Mutex as StdMutex; 30*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::MutexGuard; 31*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::TryLockError; 32*bb4ee6a4SAndroid Build Coastguard Worker 33*bb4ee6a4SAndroid Build Coastguard Worker /// A mutual exclusion primitive useful for protecting shared data. 34*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)] 35*bb4ee6a4SAndroid Build Coastguard Worker pub struct Mutex<T: ?Sized> { 36*bb4ee6a4SAndroid Build Coastguard Worker std: StdMutex<T>, 37*bb4ee6a4SAndroid Build Coastguard Worker } 38*bb4ee6a4SAndroid Build Coastguard Worker 39*bb4ee6a4SAndroid Build Coastguard Worker impl<T> Mutex<T> { 40*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new mutex in an unlocked state ready for use. new(value: T) -> Mutex<T>41*bb4ee6a4SAndroid Build Coastguard Worker pub const fn new(value: T) -> Mutex<T> { 42*bb4ee6a4SAndroid Build Coastguard Worker Mutex { 43*bb4ee6a4SAndroid Build Coastguard Worker std: StdMutex::new(value), 44*bb4ee6a4SAndroid Build Coastguard Worker } 45*bb4ee6a4SAndroid Build Coastguard Worker } 46*bb4ee6a4SAndroid Build Coastguard Worker 47*bb4ee6a4SAndroid Build Coastguard Worker /// Consumes this mutex, returning the underlying data. into_inner(self) -> T48*bb4ee6a4SAndroid Build Coastguard Worker pub fn into_inner(self) -> T { 49*bb4ee6a4SAndroid Build Coastguard Worker match self.std.into_inner() { 50*bb4ee6a4SAndroid Build Coastguard Worker Ok(value) => value, 51*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => panic!("mutex is poisoned"), 52*bb4ee6a4SAndroid Build Coastguard Worker } 53*bb4ee6a4SAndroid Build Coastguard Worker } 54*bb4ee6a4SAndroid Build Coastguard Worker } 55*bb4ee6a4SAndroid Build Coastguard Worker 56*bb4ee6a4SAndroid Build Coastguard Worker impl<T: ?Sized> Mutex<T> { 57*bb4ee6a4SAndroid Build Coastguard Worker /// Acquires a mutex, blocking the current thread until it is able to do so. 58*bb4ee6a4SAndroid Build Coastguard Worker /// 59*bb4ee6a4SAndroid Build Coastguard Worker /// This function will block the local thread until it is available to 60*bb4ee6a4SAndroid Build Coastguard Worker /// acquire the mutex. Upon returning, the thread is the only thread with 61*bb4ee6a4SAndroid Build Coastguard Worker /// the lock held. An RAII guard is returned to allow scoped unlock of the 62*bb4ee6a4SAndroid Build Coastguard Worker /// lock. When the guard goes out of scope, the mutex will be unlocked. lock(&self) -> MutexGuard<T>63*bb4ee6a4SAndroid Build Coastguard Worker pub fn lock(&self) -> MutexGuard<T> { 64*bb4ee6a4SAndroid Build Coastguard Worker match self.std.lock() { 65*bb4ee6a4SAndroid Build Coastguard Worker Ok(guard) => guard, 66*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => panic!("mutex is poisoned"), 67*bb4ee6a4SAndroid Build Coastguard Worker } 68*bb4ee6a4SAndroid Build Coastguard Worker } 69*bb4ee6a4SAndroid Build Coastguard Worker 70*bb4ee6a4SAndroid Build Coastguard Worker /// Attempts to acquire this lock. 71*bb4ee6a4SAndroid Build Coastguard Worker /// 72*bb4ee6a4SAndroid Build Coastguard Worker /// If the lock could not be acquired at this time, then Err is returned. 73*bb4ee6a4SAndroid Build Coastguard Worker /// Otherwise, an RAII guard is returned. The lock will be unlocked when the 74*bb4ee6a4SAndroid Build Coastguard Worker /// guard is dropped. 75*bb4ee6a4SAndroid Build Coastguard Worker /// 76*bb4ee6a4SAndroid Build Coastguard Worker /// This function does not block. try_lock(&self) -> Result<MutexGuard<T>, WouldBlock>77*bb4ee6a4SAndroid Build Coastguard Worker pub fn try_lock(&self) -> Result<MutexGuard<T>, WouldBlock> { 78*bb4ee6a4SAndroid Build Coastguard Worker match self.std.try_lock() { 79*bb4ee6a4SAndroid Build Coastguard Worker Ok(guard) => Ok(guard), 80*bb4ee6a4SAndroid Build Coastguard Worker Err(TryLockError::Poisoned(_)) => panic!("mutex is poisoned"), 81*bb4ee6a4SAndroid Build Coastguard Worker Err(TryLockError::WouldBlock) => Err(WouldBlock), 82*bb4ee6a4SAndroid Build Coastguard Worker } 83*bb4ee6a4SAndroid Build Coastguard Worker } 84*bb4ee6a4SAndroid Build Coastguard Worker 85*bb4ee6a4SAndroid Build Coastguard Worker /// Returns a mutable reference to the underlying data. 86*bb4ee6a4SAndroid Build Coastguard Worker /// 87*bb4ee6a4SAndroid Build Coastguard Worker /// Since this call borrows the Mutex mutably, no actual locking needs to 88*bb4ee6a4SAndroid Build Coastguard Worker /// take place -- the mutable borrow statically guarantees no locks exist. get_mut(&mut self) -> &mut T89*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_mut(&mut self) -> &mut T { 90*bb4ee6a4SAndroid Build Coastguard Worker match self.std.get_mut() { 91*bb4ee6a4SAndroid Build Coastguard Worker Ok(value) => value, 92*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => panic!("mutex is poisoned"), 93*bb4ee6a4SAndroid Build Coastguard Worker } 94*bb4ee6a4SAndroid Build Coastguard Worker } 95*bb4ee6a4SAndroid Build Coastguard Worker } 96*bb4ee6a4SAndroid Build Coastguard Worker 97*bb4ee6a4SAndroid Build Coastguard Worker impl<T> From<T> for Mutex<T> { from(value: T) -> Self98*bb4ee6a4SAndroid Build Coastguard Worker fn from(value: T) -> Self { 99*bb4ee6a4SAndroid Build Coastguard Worker Mutex { 100*bb4ee6a4SAndroid Build Coastguard Worker std: StdMutex::from(value), 101*bb4ee6a4SAndroid Build Coastguard Worker } 102*bb4ee6a4SAndroid Build Coastguard Worker } 103*bb4ee6a4SAndroid Build Coastguard Worker } 104*bb4ee6a4SAndroid Build Coastguard Worker 105*bb4ee6a4SAndroid Build Coastguard Worker impl<T: ?Sized + Debug> Debug for Mutex<T> { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result106*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 107*bb4ee6a4SAndroid Build Coastguard Worker Debug::fmt(&self.std, formatter) 108*bb4ee6a4SAndroid Build Coastguard Worker } 109*bb4ee6a4SAndroid Build Coastguard Worker } 110*bb4ee6a4SAndroid Build Coastguard Worker 111*bb4ee6a4SAndroid Build Coastguard Worker /// The lock could not be acquired at this time because the operation would 112*bb4ee6a4SAndroid Build Coastguard Worker /// otherwise block. 113*bb4ee6a4SAndroid Build Coastguard Worker /// 114*bb4ee6a4SAndroid Build Coastguard Worker /// Error returned by Mutex::try_lock. 115*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)] 116*bb4ee6a4SAndroid Build Coastguard Worker pub struct WouldBlock; 117*bb4ee6a4SAndroid Build Coastguard Worker 118*bb4ee6a4SAndroid Build Coastguard Worker impl Display for WouldBlock { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result119*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 120*bb4ee6a4SAndroid Build Coastguard Worker Display::fmt(&TryLockError::WouldBlock::<()>, formatter) 121*bb4ee6a4SAndroid Build Coastguard Worker } 122*bb4ee6a4SAndroid Build Coastguard Worker } 123*bb4ee6a4SAndroid Build Coastguard Worker 124*bb4ee6a4SAndroid Build Coastguard Worker impl std::error::Error for WouldBlock {} 125