]> git.lizzy.rs Git - rust.git/blobdiff - src/librustrt/mutex.rs
auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis
[rust.git] / src / librustrt / mutex.rs
index eec19e9d5db86bf9cb5ad55587516b9a2b668d40..f24c2609d09e81b93f6f7a1af38ba0201c9ee4d0 100644 (file)
@@ -115,6 +115,18 @@ pub unsafe fn new() -> StaticNativeMutex {
     ///     // critical section...
     /// } // automatically unlocked in `_guard`'s destructor
     /// ```
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe because it will not function correctly if this
+    /// mutex has been *moved* since it was last used. The mutex can move an
+    /// arbitrary number of times before its first usage, but once a mutex has
+    /// been used once it is no longer allowed to move (or otherwise it invokes
+    /// undefined behavior).
+    ///
+    /// Additionally, this type does not take into account any form of
+    /// scheduling model. This will unconditionally block the *os thread* which
+    /// is not always desired.
     pub unsafe fn lock<'a>(&'a self) -> LockGuard<'a> {
         self.inner.lock();
 
@@ -123,6 +135,10 @@ pub unsafe fn lock<'a>(&'a self) -> LockGuard<'a> {
 
     /// Attempts to acquire the lock. The value returned is `Some` if
     /// the attempt succeeded.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`.
     pub unsafe fn trylock<'a>(&'a self) -> Option<LockGuard<'a>> {
         if self.inner.trylock() {
             Some(LockGuard { lock: self })
@@ -135,6 +151,12 @@ pub unsafe fn trylock<'a>(&'a self) -> Option<LockGuard<'a>> {
     ///
     /// These needs to be paired with a call to `.unlock_noguard`. Prefer using
     /// `.lock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, this
+    /// does not guarantee that the mutex will ever be unlocked, and it is
+    /// undefined to drop an already-locked mutex.
     pub unsafe fn lock_noguard(&self) { self.inner.lock() }
 
     /// Attempts to acquire the lock without creating a
@@ -143,12 +165,22 @@ pub unsafe fn lock_noguard(&self) { self.inner.lock() }
     ///
     /// If `true` is returned, this needs to be paired with a call to
     /// `.unlock_noguard`. Prefer using `.trylock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock_noguard`.
     pub unsafe fn trylock_noguard(&self) -> bool {
         self.inner.trylock()
     }
 
     /// Unlocks the lock. This assumes that the current thread already holds the
     /// lock.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, it
+    /// is not guaranteed that this is unlocking a previously locked mutex. It
+    /// is undefined to unlock an unlocked mutex.
     pub unsafe fn unlock_noguard(&self) { self.inner.unlock() }
 
     /// Block on the internal condition variable.
@@ -156,9 +188,19 @@ pub unsafe fn unlock_noguard(&self) { self.inner.unlock() }
     /// This function assumes that the lock is already held. Prefer
     /// using `LockGuard.wait` since that guarantees that the lock is
     /// held.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, this
+    /// is unsafe because the mutex may not be currently locked.
     pub unsafe fn wait_noguard(&self) { self.inner.wait() }
 
     /// Signals a thread in `wait` to wake up
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe for the same reasons as `lock`. Additionally, this
+    /// is unsafe because the mutex may not be currently locked.
     pub unsafe fn signal_noguard(&self) { self.inner.signal() }
 
     /// This function is especially unsafe because there are no guarantees made
@@ -181,6 +223,7 @@ pub unsafe fn new() -> NativeMutex {
     /// already hold the lock.
     ///
     /// # Example
+    ///
     /// ```rust
     /// use std::rt::mutex::NativeMutex;
     /// unsafe {
@@ -192,12 +235,22 @@ pub unsafe fn new() -> NativeMutex {
     ///     } // automatically unlocked in `_guard`'s destructor
     /// }
     /// ```
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::lock`.
     pub unsafe fn lock<'a>(&'a self) -> LockGuard<'a> {
         self.inner.lock()
     }
 
     /// Attempts to acquire the lock. The value returned is `Some` if
     /// the attempt succeeded.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::trylock`.
     pub unsafe fn trylock<'a>(&'a self) -> Option<LockGuard<'a>> {
         self.inner.trylock()
     }
@@ -206,6 +259,11 @@ pub unsafe fn trylock<'a>(&'a self) -> Option<LockGuard<'a>> {
     ///
     /// These needs to be paired with a call to `.unlock_noguard`. Prefer using
     /// `.lock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::lock_noguard`.
     pub unsafe fn lock_noguard(&self) { self.inner.lock_noguard() }
 
     /// Attempts to acquire the lock without creating a
@@ -214,12 +272,22 @@ pub unsafe fn lock_noguard(&self) { self.inner.lock_noguard() }
     ///
     /// If `true` is returned, this needs to be paired with a call to
     /// `.unlock_noguard`. Prefer using `.trylock`.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::trylock_noguard`.
     pub unsafe fn trylock_noguard(&self) -> bool {
         self.inner.trylock_noguard()
     }
 
     /// Unlocks the lock. This assumes that the current thread already holds the
     /// lock.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::unlock_noguard`.
     pub unsafe fn unlock_noguard(&self) { self.inner.unlock_noguard() }
 
     /// Block on the internal condition variable.
@@ -227,9 +295,19 @@ pub unsafe fn unlock_noguard(&self) { self.inner.unlock_noguard() }
     /// This function assumes that the lock is already held. Prefer
     /// using `LockGuard.wait` since that guarantees that the lock is
     /// held.
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::wait_noguard`.
     pub unsafe fn wait_noguard(&self) { self.inner.wait_noguard() }
 
     /// Signals a thread in `wait` to wake up
+    ///
+    /// # Unsafety
+    ///
+    /// This method is unsafe due to the same reasons as
+    /// `StaticNativeMutex::signal_noguard`.
     pub unsafe fn signal_noguard(&self) { self.inner.signal_noguard() }
 }
 
@@ -263,18 +341,18 @@ mod imp {
     use libc;
     use self::os::{PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER,
                    pthread_mutex_t, pthread_cond_t};
-    use core::ty::Unsafe;
-    use core::kinds::marker;
+    use core::cell::UnsafeCell;
 
     type pthread_mutexattr_t = libc::c_void;
     type pthread_condattr_t = libc::c_void;
 
     #[cfg(target_os = "freebsd")]
+    #[cfg(target_os = "dragonfly")]
     mod os {
         use libc;
 
-        pub type pthread_mutex_t = *libc::c_void;
-        pub type pthread_cond_t = *libc::c_void;
+        pub type pthread_mutex_t = *mut libc::c_void;
+        pub type pthread_cond_t = *mut libc::c_void;
 
         pub static PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t =
             0 as pthread_mutex_t;
@@ -283,6 +361,7 @@ mod os {
     }
 
     #[cfg(target_os = "macos")]
+    #[cfg(target_os = "ios")]
     mod os {
         use libc;
 
@@ -294,6 +373,10 @@ mod os {
         static __PTHREAD_MUTEX_SIZE__: uint = 40;
         #[cfg(target_arch = "x86")]
         static __PTHREAD_COND_SIZE__: uint = 24;
+        #[cfg(target_arch = "arm")]
+        static __PTHREAD_MUTEX_SIZE__: uint = 40;
+        #[cfg(target_arch = "arm")]
+        static __PTHREAD_COND_SIZE__: uint = 24;
 
         static _PTHREAD_MUTEX_SIG_init: libc::c_long = 0x32AAABA7;
         static _PTHREAD_COND_SIG_init: libc::c_long = 0x3CB0B1BB;
@@ -332,6 +415,8 @@ mod os {
         static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
         #[cfg(target_arch = "mips")]
         static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
+        #[cfg(target_arch = "mipsel")]
+        static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
         #[cfg(target_arch = "x86_64")]
         static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
         #[cfg(target_arch = "x86")]
@@ -340,6 +425,8 @@ mod os {
         static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
         #[cfg(target_arch = "mips")]
         static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
+        #[cfg(target_arch = "mipsel")]
+        static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
 
         #[repr(C)]
         pub struct pthread_mutex_t {
@@ -379,19 +466,13 @@ pub struct pthread_cond_t { value: libc::c_int }
     }
 
     pub struct Mutex {
-        lock: Unsafe<pthread_mutex_t>,
-        cond: Unsafe<pthread_cond_t>,
+        lock: UnsafeCell<pthread_mutex_t>,
+        cond: UnsafeCell<pthread_cond_t>,
     }
 
     pub static MUTEX_INIT: Mutex = Mutex {
-        lock: Unsafe {
-            value: PTHREAD_MUTEX_INITIALIZER,
-            marker1: marker::InvariantType,
-        },
-        cond: Unsafe {
-            value: PTHREAD_COND_INITIALIZER,
-            marker1: marker::InvariantType,
-        },
+        lock: UnsafeCell { value: PTHREAD_MUTEX_INITIALIZER },
+        cond: UnsafeCell { value: PTHREAD_COND_INITIALIZER },
     };
 
     impl Mutex {
@@ -400,8 +481,8 @@ pub unsafe fn new() -> Mutex {
             // is better to avoid initialization of potentially
             // opaque OS data before it landed
             let m = Mutex {
-                lock: Unsafe::new(PTHREAD_MUTEX_INITIALIZER),
-                cond: Unsafe::new(PTHREAD_COND_INITIALIZER),
+                lock: UnsafeCell::new(PTHREAD_MUTEX_INITIALIZER),
+                cond: UnsafeCell::new(PTHREAD_COND_INITIALIZER),
             };
 
             return m;