about summary refs log tree commit diff
path: root/src/libstd/sync
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2015-05-12 12:48:14 +1200
committerNick Cameron <ncameron@mozilla.com>2015-05-12 12:48:14 +1200
commite0216fcc42d5f4961d07378a783c87814097015f (patch)
treee5f503c129942a2b7c2815b1c8e4db85b5bbcf1b /src/libstd/sync
parentaa5ca282b20391c6df51fdfa94e0de5672ccfac1 (diff)
parent750f2c63f2737305d33288303cdecb7a470a7922 (diff)
downloadrust-e0216fcc42d5f4961d07378a783c87814097015f.tar.gz
rust-e0216fcc42d5f4961d07378a783c87814097015f.zip
Merge branch 'master' into
Diffstat (limited to 'src/libstd/sync')
-rw-r--r--src/libstd/sync/barrier.rs4
-rw-r--r--src/libstd/sync/mpsc/mod.rs26
-rw-r--r--src/libstd/sync/mpsc/mpsc_queue.rs2
-rw-r--r--src/libstd/sync/mpsc/oneshot.rs14
-rw-r--r--src/libstd/sync/mpsc/select.rs32
-rw-r--r--src/libstd/sync/mpsc/shared.rs6
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs2
-rw-r--r--src/libstd/sync/mpsc/stream.rs8
-rw-r--r--src/libstd/sync/mpsc/sync.rs18
-rw-r--r--src/libstd/sync/mutex.rs56
-rw-r--r--src/libstd/sync/once.rs4
-rw-r--r--src/libstd/sync/rwlock.rs103
12 files changed, 168 insertions, 107 deletions
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index 34fcf6cdadd..8360620c345 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -10,7 +10,7 @@
 
 use sync::{Mutex, Condvar};
 
-/// A barrier enables multiple tasks to synchronize the beginning
+/// A barrier enables multiple threads to synchronize the beginning
 /// of some computation.
 ///
 /// ```
@@ -128,7 +128,7 @@ mod tests {
             });
         }
 
-        // At this point, all spawned tasks should be blocked,
+        // At this point, all spawned threads should be blocked,
         // so we shouldn't get anything from the port
         assert!(match rx.try_recv() {
             Err(TryRecvError::Empty) => true,
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 61932225d79..77aeeca7968 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -107,7 +107,7 @@
 //!
 //! let (tx, rx) = sync_channel::<i32>(0);
 //! thread::spawn(move|| {
-//!     // This will wait for the parent task to start receiving
+//!     // This will wait for the parent thread to start receiving
 //!     tx.send(53).unwrap();
 //! });
 //! rx.recv().unwrap();
@@ -253,7 +253,7 @@
 // blocking. The implementation is essentially the entire blocking procedure
 // followed by an increment as soon as its woken up. The cancellation procedure
 // involves an increment and swapping out of to_wake to acquire ownership of the
-// task to unblock.
+// thread to unblock.
 //
 // Sadly this current implementation requires multiple allocations, so I have
 // seen the throughput of select() be much worse than it should be. I do not
@@ -272,6 +272,7 @@ use error;
 use fmt;
 use mem;
 use cell::UnsafeCell;
+use marker::Reflect;
 
 pub use self::select::{Select, Handle};
 use self::select::StartResult;
@@ -288,7 +289,7 @@ mod mpsc_queue;
 mod spsc_queue;
 
 /// The receiving-half of Rust's channel type. This half can only be owned by
-/// one task
+/// one thread
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Receiver<T> {
     inner: UnsafeCell<Flavor<T>>,
@@ -315,7 +316,7 @@ pub struct IntoIter<T> {
 }
 
 /// The sending-half of Rust's asynchronous channel type. This half can only be
-/// owned by one task, but it can be cloned to send to other tasks.
+/// owned by one thread, but it can be cloned to send to other threads.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Sender<T> {
     inner: UnsafeCell<Flavor<T>>,
@@ -326,7 +327,7 @@ pub struct Sender<T> {
 unsafe impl<T: Send> Send for Sender<T> { }
 
 /// The sending-half of Rust's synchronous channel type. This half can only be
-/// owned by one task, but it can be cloned to send to other tasks.
+/// owned by one thread, but it can be cloned to send to other threads.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SyncSender<T> {
     inner: Arc<UnsafeCell<sync::Packet<T>>>,
@@ -420,7 +421,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 /// Creates a new asynchronous channel, returning the sender/receiver halves.
 ///
 /// All data sent on the sender will become available on the receiver, and no
-/// send will block the calling task (this channel has an "infinite buffer").
+/// send will block the calling thread (this channel has an "infinite buffer").
 ///
 /// # Examples
 ///
@@ -955,8 +956,7 @@ impl<T> fmt::Display for SendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> error::Error for SendError<T> {
-
+impl<T: Send + Reflect> error::Error for SendError<T> {
     fn description(&self) -> &str {
         "sending on a closed channel"
     }
@@ -991,7 +991,7 @@ impl<T> fmt::Display for TrySendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> error::Error for TrySendError<T> {
+impl<T: Send + Reflect> error::Error for TrySendError<T> {
 
     fn description(&self) -> &str {
         match *self {
@@ -1596,7 +1596,7 @@ mod tests {
             drop(rx);  // destroy a shared
             tx2.send(()).unwrap();
         });
-        // make sure the other task has gone to sleep
+        // make sure the other thread has gone to sleep
         for _ in 0..5000 { thread::yield_now(); }
 
         // upgrade to a shared chan and send a message
@@ -1604,7 +1604,7 @@ mod tests {
         drop(tx);
         t.send(()).unwrap();
 
-        // wait for the child task to exit before we exit
+        // wait for the child thread to exit before we exit
         rx2.recv().unwrap();
     }
 }
@@ -2060,7 +2060,7 @@ mod sync_tests {
             drop(rx);  // destroy a shared
             tx2.send(()).unwrap();
         });
-        // make sure the other task has gone to sleep
+        // make sure the other thread has gone to sleep
         for _ in 0..5000 { thread::yield_now(); }
 
         // upgrade to a shared chan and send a message
@@ -2068,7 +2068,7 @@ mod sync_tests {
         drop(tx);
         t.send(()).unwrap();
 
-        // wait for the child task to exit before we exit
+        // wait for the child thread to exit before we exit
         rx2.recv().unwrap();
     }
 
diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs
index 4ab5a796fcb..2c0da938cbf 100644
--- a/src/libstd/sync/mpsc/mpsc_queue.rs
+++ b/src/libstd/sync/mpsc/mpsc_queue.rs
@@ -28,7 +28,7 @@
 //! A mostly lock-free multi-producer, single consumer queue.
 //!
 //! This module contains an implementation of a concurrent MPSC queue. This
-//! queue can be used to share data between tasks, and is also used as the
+//! queue can be used to share data between threads, and is also used as the
 //! building block of channels in rust.
 //!
 //! Note that the current implementation of this queue has a caveat of the `pop`
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index ab45b722c45..7e9c017617d 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -23,7 +23,7 @@
 /// # Implementation
 ///
 /// Oneshots are implemented around one atomic usize variable. This variable
-/// indicates both the state of the port/chan but also contains any tasks
+/// indicates both the state of the port/chan but also contains any threads
 /// blocked on the port. All atomic operations happen on this one word.
 ///
 /// In order to upgrade a oneshot channel, an upgrade is considered a disconnect
@@ -55,7 +55,7 @@ const DISCONNECTED: usize = 2;   // channel is disconnected OR upgraded
 // whoever changed the state.
 
 pub struct Packet<T> {
-    // Internal state of the chan/port pair (stores the blocked task as well)
+    // Internal state of the chan/port pair (stores the blocked thread as well)
     state: AtomicUsize,
     // One-shot data slot location
     data: Option<T>,
@@ -139,7 +139,7 @@ impl<T> Packet<T> {
     }
 
     pub fn recv(&mut self) -> Result<T, Failure<T>> {
-        // Attempt to not block the task (it's a little expensive). If it looks
+        // Attempt to not block the thread (it's a little expensive). If it looks
         // like we're not empty, then immediately go through to `try_recv`.
         if self.state.load(Ordering::SeqCst) == EMPTY {
             let (wait_token, signal_token) = blocking::tokens();
@@ -317,8 +317,8 @@ impl<T> Packet<T> {
         }
     }
 
-    // Remove a previous selecting task from this port. This ensures that the
-    // blocked task will no longer be visible to any other threads.
+    // Remove a previous selecting thread from this port. This ensures that the
+    // blocked thread will no longer be visible to any other threads.
     //
     // The return value indicates whether there's data on this port.
     pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
@@ -329,7 +329,7 @@ impl<T> Packet<T> {
             s @ DATA |
             s @ DISCONNECTED => s,
 
-            // If we've got a blocked task, then use an atomic to gain ownership
+            // If we've got a blocked thread, then use an atomic to gain ownership
             // of it (may fail)
             ptr => self.state.compare_and_swap(ptr, EMPTY, Ordering::SeqCst)
         };
@@ -338,7 +338,7 @@ impl<T> Packet<T> {
         // about it.
         match state {
             EMPTY => unreachable!(),
-            // our task used for select was stolen
+            // our thread used for select was stolen
             DATA => Ok(true),
 
             // If the other end has hung up, then we have complete ownership
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index fde99e11040..679cc550454 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -58,7 +58,7 @@
 
 use core::prelude::*;
 
-use core::cell::Cell;
+use core::cell::{Cell, UnsafeCell};
 use core::marker;
 use core::mem;
 use core::ptr;
@@ -70,9 +70,13 @@ use sync::mpsc::blocking::{self, SignalToken};
 /// The "receiver set" of the select interface. This structure is used to manage
 /// a set of receivers which are being selected over.
 pub struct Select {
+    inner: UnsafeCell<SelectInner>,
+    next_id: Cell<usize>,
+}
+
+struct SelectInner {
     head: *mut Handle<'static, ()>,
     tail: *mut Handle<'static, ()>,
-    next_id: Cell<usize>,
 }
 
 impl !marker::Send for Select {}
@@ -84,7 +88,7 @@ pub struct Handle<'rx, T:Send+'rx> {
     /// The ID of this handle, used to compare against the return value of
     /// `Select::wait()`
     id: usize,
-    selector: &'rx Select,
+    selector: *mut SelectInner,
     next: *mut Handle<'static, ()>,
     prev: *mut Handle<'static, ()>,
     added: bool,
@@ -127,8 +131,10 @@ impl Select {
     /// ```
     pub fn new() -> Select {
         Select {
-            head: ptr::null_mut(),
-            tail: ptr::null_mut(),
+            inner: UnsafeCell::new(SelectInner {
+                head: ptr::null_mut(),
+                tail: ptr::null_mut(),
+            }),
             next_id: Cell::new(1),
         }
     }
@@ -141,7 +147,7 @@ impl Select {
         self.next_id.set(id + 1);
         Handle {
             id: id,
-            selector: self,
+            selector: self.inner.get(),
             next: ptr::null_mut(),
             prev: ptr::null_mut(),
             added: false,
@@ -223,7 +229,7 @@ impl Select {
             // woken us up (although the wakeup is guaranteed to fail).
             //
             // This situation happens in the window of where a sender invokes
-            // increment(), sees -1, and then decides to wake up the task. After
+            // increment(), sees -1, and then decides to wake up the thread. After
             // all this is done, the sending thread will set `selecting` to
             // `false`. Until this is done, we cannot return. If we were to
             // return, then a sender could wake up a receiver which has gone
@@ -250,7 +256,7 @@ impl Select {
         }
     }
 
-    fn iter(&self) -> Packets { Packets { cur: self.head } }
+    fn iter(&self) -> Packets { Packets { cur: unsafe { &*self.inner.get() }.head } }
 }
 
 impl<'rx, T: Send> Handle<'rx, T> {
@@ -271,7 +277,7 @@ impl<'rx, T: Send> Handle<'rx, T> {
     /// while it is added to the `Select` set.
     pub unsafe fn add(&mut self) {
         if self.added { return }
-        let selector: &mut Select = mem::transmute(&*self.selector);
+        let selector = &mut *self.selector;
         let me: *mut Handle<'static, ()> = mem::transmute(&*self);
 
         if selector.head.is_null() {
@@ -292,7 +298,7 @@ impl<'rx, T: Send> Handle<'rx, T> {
     pub unsafe fn remove(&mut self) {
         if !self.added { return }
 
-        let selector: &mut Select = mem::transmute(&*self.selector);
+        let selector = &mut *self.selector;
         let me: *mut Handle<'static, ()> = mem::transmute(&*self);
 
         if self.prev.is_null() {
@@ -317,8 +323,10 @@ impl<'rx, T: Send> Handle<'rx, T> {
 
 impl Drop for Select {
     fn drop(&mut self) {
-        assert!(self.head.is_null());
-        assert!(self.tail.is_null());
+        unsafe {
+            assert!((&*self.inner.get()).head.is_null());
+            assert!((&*self.inner.get()).tail.is_null());
+        }
     }
 }
 
diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs
index 09a02923f14..41c79dd52c8 100644
--- a/src/libstd/sync/mpsc/shared.rs
+++ b/src/libstd/sync/mpsc/shared.rs
@@ -91,8 +91,8 @@ impl<T> Packet<T> {
     }
 
     // This function is used at the creation of a shared packet to inherit a
-    // previously blocked task. This is done to prevent spurious wakeups of
-    // tasks in select().
+    // previously blocked thread. This is done to prevent spurious wakeups of
+    // threads in select().
     //
     // This can only be called at channel-creation time
     pub fn inherit_blocker(&mut self,
@@ -424,7 +424,7 @@ impl<T> Packet<T> {
         }
     }
 
-    // Cancels a previous task waiting on this port, returning whether there's
+    // Cancels a previous thread waiting on this port, returning whether there's
     // data on the port.
     //
     // This is similar to the stream implementation (hence fewer comments), but
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index f4b9c7d45fd..b72da91c0a0 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -30,7 +30,7 @@
 //! A single-producer single-consumer concurrent queue
 //!
 //! This module contains the implementation of an SPSC queue which can be used
-//! concurrently between two tasks. This data structure is safe to use and
+//! concurrently between two threads. This data structure is safe to use and
 //! enforces the semantics that there is one pusher and one popper.
 
 #![unstable(feature = "std_misc")]
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index 1200e71d9af..404814b4cd4 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -181,7 +181,7 @@ impl<T> Packet<T> {
             data => return data,
         }
 
-        // Welp, our channel has no data. Deschedule the current task and
+        // Welp, our channel has no data. Deschedule the current thread and
         // initiate the blocking protocol.
         let (wait_token, signal_token) = blocking::tokens();
         if self.decrement(signal_token).is_ok() {
@@ -385,7 +385,7 @@ impl<T> Packet<T> {
         }
     }
 
-    // Removes a previous task from being blocked in this port
+    // Removes a previous thread from being blocked in this port
     pub fn abort_selection(&mut self,
                            was_upgrade: bool) -> Result<bool, Receiver<T>> {
         // If we're aborting selection after upgrading from a oneshot, then
@@ -414,7 +414,7 @@ impl<T> Packet<T> {
         let prev = self.bump(steals + 1);
 
         // If we were previously disconnected, then we know for sure that there
-        // is no task in to_wake, so just keep going
+        // is no thread in to_wake, so just keep going
         let has_data = if prev == DISCONNECTED {
             assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
             true // there is data, that data is that we're disconnected
@@ -428,7 +428,7 @@ impl<T> Packet<T> {
             //
             // If the previous count was positive then we're in a tougher
             // situation. A possible race is that a sender just incremented
-            // through -1 (meaning it's going to try to wake a task up), but it
+            // through -1 (meaning it's going to try to wake a thread up), but it
             // hasn't yet read the to_wake. In order to prevent a future recv()
             // from waking up too early (this sender picking up the plastered
             // over to_wake), we spin loop here waiting for to_wake to be 0.
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 4687df107f6..904eab1fd7e 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -19,7 +19,7 @@
 /// which means that every successful send is paired with a successful recv.
 ///
 /// This flavor of channels defines a new `send_opt` method for channels which
-/// is the method by which a message is sent but the task does not panic if it
+/// is the method by which a message is sent but the thread does not panic if it
 /// cannot be delivered.
 ///
 /// Another major difference is that send() will *always* return back the data
@@ -62,12 +62,12 @@ unsafe impl<T: Send> Sync for Packet<T> { }
 struct State<T> {
     disconnected: bool, // Is the channel disconnected yet?
     queue: Queue,       // queue of senders waiting to send data
-    blocker: Blocker,   // currently blocked task on this channel
+    blocker: Blocker,   // currently blocked thread on this channel
     buf: Buffer<T>,     // storage for buffered messages
     cap: usize,         // capacity of this channel
 
     /// A curious flag used to indicate whether a sender failed or succeeded in
-    /// blocking. This is used to transmit information back to the task that it
+    /// blocking. This is used to transmit information back to the thread that it
     /// must dequeue its message from the buffer because it was not received.
     /// This is only relevant in the 0-buffer case. This obviously cannot be
     /// safely constructed, but it's guaranteed to always have a valid pointer
@@ -84,7 +84,7 @@ enum Blocker {
     NoneBlocked
 }
 
-/// Simple queue for threading tasks together. Nodes are stack-allocated, so
+/// Simple queue for threading threads together. Nodes are stack-allocated, so
 /// this structure is not safe at all
 struct Queue {
     head: *mut Node,
@@ -130,7 +130,7 @@ fn wait<'a, 'b, T>(lock: &'a Mutex<State<T>>,
 
 /// Wakes up a thread, dropping the lock at the correct time
 fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
-    // We need to be careful to wake up the waiting task *outside* of the mutex
+    // We need to be careful to wake up the waiting thread *outside* of the mutex
     // in case it incurs a context switch.
     drop(guard);
     token.signal();
@@ -298,7 +298,7 @@ impl<T> Packet<T> {
         };
         mem::drop(guard);
 
-        // only outside of the lock do we wake up the pending tasks
+        // only outside of the lock do we wake up the pending threads
         pending_sender1.map(|t| t.signal());
         pending_sender2.map(|t| t.signal());
     }
@@ -394,8 +394,8 @@ impl<T> Packet<T> {
         }
     }
 
-    // Remove a previous selecting task from this port. This ensures that the
-    // blocked task will no longer be visible to any other threads.
+    // Remove a previous selecting thread from this port. This ensures that the
+    // blocked thread will no longer be visible to any other threads.
     //
     // The return value indicates whether there's data on this port.
     pub fn abort_selection(&self) -> bool {
@@ -446,7 +446,7 @@ impl<T> Buffer<T> {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Queue, a simple queue to enqueue tasks with (stack-allocated nodes)
+// Queue, a simple queue to enqueue threads with (stack-allocated nodes)
 ////////////////////////////////////////////////////////////////////////////////
 
 impl Queue {
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 30c7407a96d..febf5f1b183 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -30,7 +30,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 ///
 /// The mutexes in this module implement a strategy called "poisoning" where a
 /// mutex is considered poisoned whenever a thread panics while holding the
-/// lock. Once a mutex is poisoned, all other tasks are unable to access the
+/// lock. Once a mutex is poisoned, all other threads are unable to access the
 /// data by default as it is likely tainted (some invariant is not being
 /// upheld).
 ///
@@ -56,7 +56,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 /// // Spawn a few threads to increment a shared variable (non-atomically), and
 /// // let the main thread know once all increments are done.
 /// //
-/// // Here we're using an Arc to share memory among tasks, and the data inside
+/// // Here we're using an Arc to share memory among threads, and the data inside
 /// // the Arc is protected with a mutex.
 /// let data = Arc::new(Mutex::new(0));
 ///
@@ -69,7 +69,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 ///         // which can access the shared state when the lock is held.
 ///         //
 ///         // We unwrap() the return value to assert that we are not expecting
-///         // tasks to ever fail while holding the lock.
+///         // threads to ever fail while holding the lock.
 ///         let mut data = data.lock().unwrap();
 ///         *data += 1;
 ///         if *data == N {
@@ -112,7 +112,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 /// *guard += 1;
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Mutex<T> {
+pub struct Mutex<T: ?Sized> {
     // Note that this static mutex is in a *box*, not inlined into the struct
     // itself. Once a native mutex has been used once, its address can never
     // change (it can't be moved). This mutex type can be safely moved at any
@@ -124,9 +124,9 @@ pub struct Mutex<T> {
 
 // these are the only places where `T: Send` matters; all other
 // functionality works fine on a single thread.
-unsafe impl<T: Send> Send for Mutex<T> { }
+unsafe impl<T: ?Sized + Send> Send for Mutex<T> { }
 
-unsafe impl<T: Send> Sync for Mutex<T> { }
+unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
 
 /// The static mutex type is provided to allow for static allocation of mutexes.
 ///
@@ -164,7 +164,7 @@ pub struct StaticMutex {
 /// `Deref` and `DerefMut` implementations
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct MutexGuard<'a, T: 'a> {
+pub struct MutexGuard<'a, T: ?Sized + 'a> {
     // funny underscores due to how Deref/DerefMut currently work (they
     // disregard field privacy).
     __lock: &'a StaticMutex,
@@ -172,7 +172,7 @@ pub struct MutexGuard<'a, T: 'a> {
     __poison: poison::Guard,
 }
 
-impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
+impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {}
 
 /// Static initialization of a mutex. This constant can be used to initialize
 /// other mutex constants.
@@ -192,11 +192,13 @@ impl<T> Mutex<T> {
             data: UnsafeCell::new(t),
         }
     }
+}
 
-    /// Acquires a mutex, blocking the current task until it is able to do so.
+impl<T: ?Sized> Mutex<T> {
+    /// Acquires a mutex, blocking the current thread until it is able to do so.
     ///
-    /// This function will block the local task until it is available to acquire
-    /// the mutex. Upon returning, the task is the only task with the mutex
+    /// This function will block the local thread until it is available to acquire
+    /// the mutex. Upon returning, the thread is the only thread with the mutex
     /// held. An RAII guard is returned to allow scoped unlock of the lock. When
     /// the guard goes out of scope, the mutex will be unlocked.
     ///
@@ -245,7 +247,7 @@ impl<T> Mutex<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for Mutex<T> {
+impl<T: ?Sized> Drop for Mutex<T> {
     fn drop(&mut self) {
         // This is actually safe b/c we know that there is no further usage of
         // this mutex (it's up to the user to arrange for a mutex to get
@@ -255,12 +257,12 @@ impl<T> Drop for Mutex<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug + 'static> fmt::Debug for Mutex<T> {
+impl<T: ?Sized + fmt::Debug + 'static> fmt::Debug for Mutex<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_lock() {
-            Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", *guard),
+            Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
             Err(TryLockError::Poisoned(err)) => {
-                write!(f, "Mutex {{ data: Poisoned({:?}) }}", **err.get_ref())
+                write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
             },
             Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
         }
@@ -310,7 +312,7 @@ impl StaticMutex {
     }
 }
 
-impl<'mutex, T> MutexGuard<'mutex, T> {
+impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
 
     fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
            -> LockResult<MutexGuard<'mutex, T>> {
@@ -325,7 +327,7 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
+impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
     type Target = T;
 
     fn deref<'a>(&'a self) -> &'a T {
@@ -333,14 +335,14 @@ impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
+impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
         unsafe { &mut *self.__data.get() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Drop for MutexGuard<'a, T> {
+impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
     #[inline]
     fn drop(&mut self) {
         unsafe {
@@ -350,11 +352,11 @@ impl<'a, T> Drop for MutexGuard<'a, T> {
     }
 }
 
-pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
+pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
     &guard.__lock.lock
 }
 
-pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
+pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
     &guard.__lock.poison
 }
 
@@ -528,4 +530,16 @@ mod tests {
         let lock = arc.lock().unwrap();
         assert_eq!(*lock, 2);
     }
+
+    #[test]
+    fn test_mutex_unsized() {
+        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
+        {
+            let b = &mut *mutex.lock().unwrap();
+            b[0] = 4;
+            b[2] = 5;
+        }
+        let comp: &[i32] = &[4, 2, 5];
+        assert_eq!(&*mutex.lock().unwrap(), comp);
+    }
 }
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 2d712369228..57baedaad9c 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -55,13 +55,13 @@ impl Once {
     /// will be executed if this is the first time `call_once` has been called,
     /// and otherwise the routine will *not* be invoked.
     ///
-    /// This method will block the calling task if another initialization
+    /// This method will block the calling thread if another initialization
     /// routine is currently running.
     ///
     /// When this function returns, it is guaranteed that some initialization
     /// has run and completed (it may not be the closure specified). It is also
     /// guaranteed that any memory writes performed by the executed closure can
-    /// be reliably observed by other tasks at this point (there is a
+    /// be reliably observed by other threads at this point (there is a
     /// happens-before relation between the closure and code executing after the
     /// return).
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index a133bb01b61..625377df7d6 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -25,7 +25,7 @@ use sys_common::rwlock as sys;
 /// typically allows for read-only access (shared access).
 ///
 /// The type parameter `T` represents the data that this lock protects. It is
-/// required that `T` satisfies `Send` to be shared across tasks and `Sync` to
+/// required that `T` satisfies `Send` to be shared across threads and `Sync` to
 /// allow concurrent access through readers. The RAII guards returned from the
 /// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
 /// to allow access to the contained of the lock.
@@ -60,13 +60,13 @@ use sys_common::rwlock as sys;
 /// } // write lock is dropped here
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct RwLock<T> {
+pub struct RwLock<T: ?Sized> {
     inner: Box<StaticRwLock>,
     data: UnsafeCell<T>,
 }
 
-unsafe impl<T: Send + Sync> Send for RwLock<T> {}
-unsafe impl<T: Send + Sync> Sync for RwLock<T> {}
+unsafe impl<T: ?Sized + Send + Sync> Send for RwLock<T> {}
+unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 
 /// Structure representing a statically allocated RwLock.
 ///
@@ -111,24 +111,24 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
 /// dropped.
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct RwLockReadGuard<'a, T: 'a> {
+pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
 }
 
-impl<'a, T> !marker::Send for RwLockReadGuard<'a, T> {}
+impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
 
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct RwLockWriteGuard<'a, T: 'a> {
+pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
     __poison: poison::Guard,
 }
 
-impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {}
+impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {}
 
 impl<T> RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
@@ -144,7 +144,9 @@ impl<T> RwLock<T> {
     pub fn new(t: T) -> RwLock<T> {
         RwLock { inner: box RW_LOCK_INIT, data: UnsafeCell::new(t) }
     }
+}
 
+impl<T: ?Sized> RwLock<T> {
     /// Locks this rwlock with shared read access, blocking the current thread
     /// until it can be acquired.
     ///
@@ -169,14 +171,16 @@ impl<T> RwLock<T> {
         RwLockReadGuard::new(&*self.inner, &self.data)
     }
 
-    /// Attempts to acquire this lock with shared read access.
+    /// Attempts to acquire this rwlock with shared read access.
+    ///
+    /// If the access could not be granted at this time, then `Err` is returned.
+    /// Otherwise, an RAII guard is returned which will release the shared access
+    /// when it is dropped.
     ///
-    /// This function will never block and will return immediately if `read`
-    /// would otherwise succeed. Returns `Some` of an RAII guard which will
-    /// release the shared access of this thread when dropped, or `None` if the
-    /// access could not be granted. This method does not provide any
-    /// guarantees with respect to the ordering of whether contentious readers
-    /// or writers will acquire the lock first.
+    /// This function does not block.
+    ///
+    /// This function does not provide any guarantees with respect to the ordering
+    /// of whether contentious readers or writers will acquire the lock first.
     ///
     /// # Failure
     ///
@@ -217,9 +221,14 @@ impl<T> RwLock<T> {
 
     /// Attempts to lock this rwlock with exclusive write access.
     ///
-    /// This function does not ever block, and it will return `None` if a call
-    /// to `write` would otherwise block. If successful, an RAII guard is
-    /// returned.
+    /// If the lock could not be acquired at this time, then `Err` is returned.
+    /// Otherwise, an RAII guard is returned which will release the lock when
+    /// it is dropped.
+    ///
+    /// This function does not block.
+    ///
+    /// This function does not provide any guarantees with respect to the ordering
+    /// of whether contentious readers or writers will acquire the lock first.
     ///
     /// # Failure
     ///
@@ -230,7 +239,7 @@ impl<T> RwLock<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
-        if unsafe { self.inner.lock.try_read() } {
+        if unsafe { self.inner.lock.try_write() } {
             Ok(try!(RwLockWriteGuard::new(&*self.inner, &self.data)))
         } else {
             Err(TryLockError::WouldBlock)
@@ -250,19 +259,19 @@ impl<T> RwLock<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for RwLock<T> {
+impl<T: ?Sized> Drop for RwLock<T> {
     fn drop(&mut self) {
         unsafe { self.inner.lock.destroy() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for RwLock<T> {
+impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_read() {
-            Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", *guard),
+            Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", &*guard),
             Err(TryLockError::Poisoned(err)) => {
-                write!(f, "RwLock {{ data: Poisoned({:?}) }}", **err.get_ref())
+                write!(f, "RwLock {{ data: Poisoned({:?}) }}", &**err.get_ref())
             },
             Err(TryLockError::WouldBlock) => write!(f, "RwLock {{ <locked> }}")
         }
@@ -341,8 +350,7 @@ impl StaticRwLock {
     }
 }
 
-impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
-
+impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
     fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
            -> LockResult<RwLockReadGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |_| {
@@ -353,8 +361,8 @@ impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
         })
     }
 }
-impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
 
+impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
     fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
            -> LockResult<RwLockWriteGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
@@ -368,33 +376,35 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'rwlock, T> Deref for RwLockReadGuard<'rwlock, T> {
+impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> {
     type Target = T;
 
     fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
+
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'rwlock, T> Deref for RwLockWriteGuard<'rwlock, T> {
+impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> {
     type Target = T;
 
     fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
+
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'rwlock, T> DerefMut for RwLockWriteGuard<'rwlock, T> {
+impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> {
     fn deref_mut(&mut self) -> &mut T {
         unsafe { &mut *self.__data.get() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Drop for RwLockReadGuard<'a, T> {
+impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> {
     fn drop(&mut self) {
         unsafe { self.__lock.lock.read_unlock(); }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
+impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
     fn drop(&mut self) {
         self.__lock.poison.done(&self.__poison);
         unsafe { self.__lock.lock.write_unlock(); }
@@ -410,7 +420,7 @@ mod tests {
     use rand::{self, Rng};
     use sync::mpsc::channel;
     use thread;
-    use sync::{Arc, RwLock, StaticRwLock, RW_LOCK_INIT};
+    use sync::{Arc, RwLock, StaticRwLock, TryLockError, RW_LOCK_INIT};
 
     #[test]
     fn smoke() {
@@ -562,4 +572,33 @@ mod tests {
         let lock = arc.read().unwrap();
         assert_eq!(*lock, 2);
     }
+
+    #[test]
+    fn test_rwlock_unsized() {
+        let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
+        {
+            let b = &mut *rw.write().unwrap();
+            b[0] = 4;
+            b[2] = 5;
+        }
+        let comp: &[i32] = &[4, 2, 5];
+        assert_eq!(&*rw.read().unwrap(), comp);
+    }
+
+    #[test]
+    fn test_rwlock_try_write() {
+        use mem::drop;
+
+        let lock = RwLock::new(0isize);
+        let read_guard = lock.read().unwrap();
+
+        let write_result = lock.try_write();
+        match write_result {
+            Err(TryLockError::WouldBlock) => (),
+            Ok(_) => assert!(false, "try_write should not succeed while read_guard is in scope"),
+            Err(_) => assert!(false, "unexpected error"),
+        }
+
+        drop(read_guard);
+    }
 }