summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-27 13:11:48 +0000
committerbors <bors@rust-lang.org>2014-12-27 13:11:48 +0000
commit4a4c89c7a4a763c253a97ff04647f52aca6a5490 (patch)
treee7d313c7ebc0418284ea65089db287cca633bc99 /src/libstd
parent9be54be15b4b4ba5c1b22d958d7619a5154ab469 (diff)
parent1a73ccc8db0a10e82632808e058645f2d6fa0095 (diff)
downloadrust-4a4c89c7a4a763c253a97ff04647f52aca6a5490.tar.gz
rust-4a4c89c7a4a763c253a97ff04647f52aca6a5490.zip
auto merge of #20119 : FlaPer87/rust/oibit-send-and-friends, r=nikomatsakis
More work on opt-in built in traits. `Send` and `Sync` are not opt-in, `OwnedPtr` renamed to `UniquePtr` and the `Send` and `Sync` traits are now unsafe.

NOTE: This likely needs to be rebased on top of the yet-to-land snapshot.

r? @nikomatsakis 

cc #13231 
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/c_str.rs6
-rw-r--r--src/libstd/c_vec.rs8
-rw-r--r--src/libstd/collections/hash/table.rs20
-rw-r--r--src/libstd/comm/blocking.rs4
-rw-r--r--src/libstd/comm/mod.rs60
-rw-r--r--src/libstd/comm/mpsc_queue.rs3
-rw-r--r--src/libstd/comm/spsc_queue.rs4
-rw-r--r--src/libstd/comm/sync.rs8
-rw-r--r--src/libstd/io/buffered.rs6
-rw-r--r--src/libstd/io/stdio.rs41
-rw-r--r--src/libstd/rt/exclusive.rs4
-rw-r--r--src/libstd/sync/barrier.rs7
-rw-r--r--src/libstd/sync/condvar.rs6
-rw-r--r--src/libstd/sync/mutex.rs27
-rw-r--r--src/libstd/sync/once.rs3
-rw-r--r--src/libstd/sync/rwlock.rs6
-rw-r--r--src/libstd/sys/common/helper_thread.rs13
-rw-r--r--src/libstd/sys/common/mutex.rs3
-rw-r--r--src/libstd/sys/unix/c.rs6
-rw-r--r--src/libstd/sys/unix/mutex.rs3
-rw-r--r--src/libstd/sys/unix/pipe.rs9
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs2
-rw-r--r--src/libstd/sys/unix/tcp.rs4
-rw-r--r--src/libstd/sys/windows/mutex.rs2
-rw-r--r--src/libstd/sys/windows/pipe.rs12
-rw-r--r--src/libstd/sys/windows/tcp.rs12
-rw-r--r--src/libstd/sys/windows/timer.rs3
-rw-r--r--src/libstd/thread.rs23
-rw-r--r--src/libstd/thread_local/mod.rs4
-rw-r--r--src/libstd/thread_local/scoped.rs5
30 files changed, 249 insertions, 65 deletions
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index fb369924c64..ffe19203769 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -72,13 +72,12 @@ use libc;
 
 use fmt;
 use hash;
-use kinds::marker;
 use mem;
 use ptr;
 use slice::{mod, ImmutableIntSlice};
 use str;
 use string::String;
-
+use core::kinds::marker;
 
 /// The representation of a C String.
 ///
@@ -90,6 +89,9 @@ pub struct CString {
     owns_buffer_: bool,
 }
 
+unsafe impl Send for CString { }
+unsafe impl Sync for CString { }
+
 impl Clone for CString {
     /// Clone this CString into a new, uniquely owned CString. For safety
     /// reasons, this is always a deep clone with the memory allocated
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
index 44e7291150e..f4338815f75 100644
--- a/src/libstd/c_vec.rs
+++ b/src/libstd/c_vec.rs
@@ -180,12 +180,12 @@ mod tests {
 
     fn malloc(n: uint) -> CVec<u8> {
         unsafe {
-            let mem = libc::malloc(n as libc::size_t);
-            if mem.is_null() { ::alloc::oom() }
+            let mem = ptr::Unique(libc::malloc(n as libc::size_t));
+            if mem.0.is_null() { ::alloc::oom() }
 
-            CVec::new_with_dtor(mem as *mut u8,
+            CVec::new_with_dtor(mem.0 as *mut u8,
                                 n,
-                                move|| { libc::free(mem as *mut libc::c_void); })
+                                move|| { libc::free(mem.0 as *mut libc::c_void); })
         }
     }
 
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 8f2152c5a9d..3ae3a8ffbad 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -23,7 +23,7 @@ use num::{Int, UnsignedInt};
 use ops::{Deref, DerefMut, Drop};
 use option::Option;
 use option::Option::{Some, None};
-use ptr::{RawPtr, copy_nonoverlapping_memory, zero_memory};
+use ptr::{Unique, RawPtr, copy_nonoverlapping_memory, zero_memory};
 use ptr;
 use rt::heap::{allocate, deallocate};
 
@@ -69,7 +69,7 @@ const EMPTY_BUCKET: u64 = 0u64;
 pub struct RawTable<K, V> {
     capacity: uint,
     size:     uint,
-    hashes:   *mut u64,
+    hashes:   Unique<u64>,
     // Because K/V do not appear directly in any of the types in the struct,
     // inform rustc that in fact instances of K and V are reachable from here.
     marker:   marker::CovariantType<(K,V)>,
@@ -563,7 +563,7 @@ impl<K, V> RawTable<K, V> {
             return RawTable {
                 size: 0,
                 capacity: 0,
-                hashes: 0 as *mut u64,
+                hashes: Unique::null(),
                 marker: marker::CovariantType,
             };
         }
@@ -602,7 +602,7 @@ impl<K, V> RawTable<K, V> {
         RawTable {
             capacity: capacity,
             size:     0,
-            hashes:   hashes,
+            hashes:   Unique(hashes),
             marker:   marker::CovariantType,
         }
     }
@@ -611,14 +611,14 @@ impl<K, V> RawTable<K, V> {
         let hashes_size = self.capacity * size_of::<u64>();
         let keys_size = self.capacity * size_of::<K>();
 
-        let buffer = self.hashes as *mut u8;
+        let buffer = self.hashes.0 as *mut u8;
         let (keys_offset, vals_offset) = calculate_offsets(hashes_size,
                                                            keys_size, min_align_of::<K>(),
                                                            min_align_of::<V>());
 
         unsafe {
             RawBucket {
-                hash: self.hashes,
+                hash: self.hashes.0,
                 key:  buffer.offset(keys_offset as int) as *mut K,
                 val:  buffer.offset(vals_offset as int) as *mut V
             }
@@ -631,7 +631,7 @@ impl<K, V> RawTable<K, V> {
     pub fn new(capacity: uint) -> RawTable<K, V> {
         unsafe {
             let ret = RawTable::new_uninitialized(capacity);
-            zero_memory(ret.hashes, capacity);
+            zero_memory(ret.hashes.0, capacity);
             ret
         }
     }
@@ -651,7 +651,7 @@ impl<K, V> RawTable<K, V> {
         RawBuckets {
             raw: self.first_bucket_raw(),
             hashes_end: unsafe {
-                self.hashes.offset(self.capacity as int)
+                self.hashes.0.offset(self.capacity as int)
             },
             marker: marker::ContravariantLifetime,
         }
@@ -916,7 +916,7 @@ impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
 #[unsafe_destructor]
 impl<K, V> Drop for RawTable<K, V> {
     fn drop(&mut self) {
-        if self.hashes.is_null() {
+        if self.hashes.0.is_null() {
             return;
         }
         // This is done in reverse because we've likely partially taken
@@ -936,7 +936,7 @@ impl<K, V> Drop for RawTable<K, V> {
                                                     vals_size, min_align_of::<V>());
 
         unsafe {
-            deallocate(self.hashes as *mut u8, size, align);
+            deallocate(self.hashes.0 as *mut u8, size, align);
             // Remember how everything was allocated out of one buffer
             // during initialization? We only need one call to free here.
         }
diff --git a/src/libstd/comm/blocking.rs b/src/libstd/comm/blocking.rs
index c477acd70aa..412b7161305 100644
--- a/src/libstd/comm/blocking.rs
+++ b/src/libstd/comm/blocking.rs
@@ -13,6 +13,7 @@
 use thread::Thread;
 use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering};
 use sync::Arc;
+use kinds::{Sync, Send};
 use kinds::marker::{NoSend, NoSync};
 use mem;
 use clone::Clone;
@@ -22,6 +23,9 @@ struct Inner {
     woken: AtomicBool,
 }
 
+unsafe impl Send for Inner {}
+unsafe impl Sync for Inner {}
+
 #[deriving(Clone)]
 pub struct SignalToken {
     inner: Arc<Inner>,
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs
index d3bfaab83da..c85bea87218 100644
--- a/src/libstd/comm/mod.rs
+++ b/src/libstd/comm/mod.rs
@@ -319,6 +319,7 @@ pub use self::TrySendError::*;
 use self::Flavor::*;
 
 use alloc::arc::Arc;
+use core::kinds;
 use core::kinds::marker;
 use core::mem;
 use core::cell::UnsafeCell;
@@ -357,10 +358,12 @@ mod spsc_queue;
 #[unstable]
 pub struct Receiver<T> {
     inner: UnsafeCell<Flavor<T>>,
-    // can't share in an arc
-    _marker: marker::NoSync,
 }
 
+// The receiver port can be sent from place to place, so long as it
+// is not used to receive non-sendable things.
+unsafe impl<T:Send> Send for Receiver<T> { }
+
 /// An iterator over messages on a receiver, this iterator will block
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
@@ -374,15 +377,17 @@ pub struct Messages<'a, T:'a> {
 #[unstable]
 pub struct Sender<T> {
     inner: UnsafeCell<Flavor<T>>,
-    // can't share in an arc
-    _marker: marker::NoSync,
 }
 
+// The send port can be sent from place to place, so long as it
+// is not used to send non-sendable things.
+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.
 #[unstable = "this type may be renamed, but it will always exist"]
 pub struct SyncSender<T> {
-    inner: Arc<UnsafeCell<sync::Packet<T>>>,
+    inner: Arc<RacyCell<sync::Packet<T>>>,
     // can't share in an arc
     _marker: marker::NoSync,
 }
@@ -418,10 +423,10 @@ pub enum TrySendError<T> {
 }
 
 enum Flavor<T> {
-    Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
-    Stream(Arc<UnsafeCell<stream::Packet<T>>>),
-    Shared(Arc<UnsafeCell<shared::Packet<T>>>),
-    Sync(Arc<UnsafeCell<sync::Packet<T>>>),
+    Oneshot(Arc<RacyCell<oneshot::Packet<T>>>),
+    Stream(Arc<RacyCell<stream::Packet<T>>>),
+    Shared(Arc<RacyCell<shared::Packet<T>>>),
+    Sync(Arc<RacyCell<sync::Packet<T>>>),
 }
 
 #[doc(hidden)]
@@ -472,7 +477,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 /// ```
 #[unstable]
 pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
-    let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
+    let a = Arc::new(RacyCell::new(oneshot::Packet::new()));
     (Sender::new(Oneshot(a.clone())), Receiver::new(Oneshot(a)))
 }
 
@@ -512,7 +517,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
 #[unstable = "this function may be renamed to more accurately reflect the type \
               of channel that is is creating"]
 pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
-    let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
+    let a = Arc::new(RacyCell::new(sync::Packet::new(bound)));
     (SyncSender::new(a.clone()), Receiver::new(Sync(a)))
 }
 
@@ -524,7 +529,6 @@ impl<T: Send> Sender<T> {
     fn new(inner: Flavor<T>) -> Sender<T> {
         Sender {
             inner: UnsafeCell::new(inner),
-            _marker: marker::NoSync,
         }
     }
 
@@ -594,7 +598,8 @@ impl<T: Send> Sender<T> {
                     if !(*p).sent() {
                         return (*p).send(t);
                     } else {
-                        let a = Arc::new(UnsafeCell::new(stream::Packet::new()));
+                        let a =
+                            Arc::new(RacyCell::new(stream::Packet::new()));
                         match (*p).upgrade(Receiver::new(Stream(a.clone()))) {
                             oneshot::UpSuccess => {
                                 let ret = (*a.get()).send(t);
@@ -631,7 +636,7 @@ impl<T: Send> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
         let (packet, sleeper, guard) = match *unsafe { self.inner() } {
             Oneshot(ref p) => {
-                let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
+                let a = Arc::new(RacyCell::new(shared::Packet::new()));
                 unsafe {
                     let guard = (*a.get()).postinit_lock();
                     match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
@@ -642,7 +647,7 @@ impl<T: Send> Clone for Sender<T> {
                 }
             }
             Stream(ref p) => {
-                let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
+                let a = Arc::new(RacyCell::new(shared::Packet::new()));
                 unsafe {
                     let guard = (*a.get()).postinit_lock();
                     match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
@@ -686,7 +691,7 @@ impl<T: Send> Drop for Sender<T> {
 ////////////////////////////////////////////////////////////////////////////////
 
 impl<T: Send> SyncSender<T> {
-    fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
+    fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
         SyncSender { inner: inner, _marker: marker::NoSync }
     }
 
@@ -775,7 +780,7 @@ impl<T: Send> Drop for SyncSender<T> {
 
 impl<T: Send> Receiver<T> {
     fn new(inner: Flavor<T>) -> Receiver<T> {
-        Receiver { inner: UnsafeCell::new(inner), _marker: marker::NoSync }
+        Receiver { inner: UnsafeCell::new(inner) }
     }
 
     /// Blocks waiting for a value on this receiver
@@ -1018,6 +1023,27 @@ impl<T: Send> Drop for Receiver<T> {
     }
 }
 
+/// A version of `UnsafeCell` intended for use in concurrent data
+/// structures (for example, you might put it in an `Arc`).
+struct RacyCell<T>(pub UnsafeCell<T>);
+
+impl<T> RacyCell<T> {
+
+    fn new(value: T) -> RacyCell<T> {
+        RacyCell(UnsafeCell { value: value })
+    }
+
+    unsafe fn get(&self) -> *mut T {
+        self.0.get()
+    }
+
+}
+
+unsafe impl<T:Send> Send for RacyCell<T> { }
+
+unsafe impl<T> kinds::Sync for RacyCell<T> { } // Oh dear
+
+
 #[cfg(test)]
 mod test {
     use super::*;
diff --git a/src/libstd/comm/mpsc_queue.rs b/src/libstd/comm/mpsc_queue.rs
index db4e3eac449..cddef236664 100644
--- a/src/libstd/comm/mpsc_queue.rs
+++ b/src/libstd/comm/mpsc_queue.rs
@@ -76,6 +76,9 @@ pub struct Queue<T> {
     tail: UnsafeCell<*mut Node<T>>,
 }
 
+unsafe impl<T:Send> Send for Queue<T> { }
+unsafe impl<T:Send> Sync for Queue<T> { }
+
 impl<T> Node<T> {
     unsafe fn new(v: Option<T>) -> *mut Node<T> {
         mem::transmute(box Node {
diff --git a/src/libstd/comm/spsc_queue.rs b/src/libstd/comm/spsc_queue.rs
index db8fff772a4..becb78063ae 100644
--- a/src/libstd/comm/spsc_queue.rs
+++ b/src/libstd/comm/spsc_queue.rs
@@ -73,6 +73,10 @@ pub struct Queue<T> {
     cache_subtractions: AtomicUint,
 }
 
+unsafe impl<T: Send> Send for Queue<T> { }
+
+unsafe impl<T: Send> Sync for Queue<T> { }
+
 impl<T: Send> Node<T> {
     fn new() -> *mut Node<T> {
         unsafe {
diff --git a/src/libstd/comm/sync.rs b/src/libstd/comm/sync.rs
index f75186e70e3..88338849965 100644
--- a/src/libstd/comm/sync.rs
+++ b/src/libstd/comm/sync.rs
@@ -53,6 +53,10 @@ pub struct Packet<T> {
     lock: Mutex<State<T>>,
 }
 
+unsafe impl<T:Send> Send for Packet<T> { }
+
+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
@@ -69,6 +73,8 @@ struct State<T> {
     canceled: Option<&'static mut bool>,
 }
 
+unsafe impl<T: Send> Send for State<T> {}
+
 /// Possible flavors of threads who can be blocked on this channel.
 enum Blocker {
     BlockedSender(SignalToken),
@@ -88,6 +94,8 @@ struct Node {
     next: *mut Node,
 }
 
+unsafe impl Send for Node {}
+
 /// A simple ring-buffer
 struct Buffer<T> {
     buf: Vec<Option<T>>,
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 9d9e8827571..c26450310a9 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -22,6 +22,7 @@ use result::Result::{Ok, Err};
 use slice::{SliceExt};
 use slice;
 use vec::Vec;
+use kinds::{Send,Sync};
 
 /// Wraps a Reader and buffers input from it
 ///
@@ -51,6 +52,11 @@ pub struct BufferedReader<R> {
     cap: uint,
 }
 
+
+unsafe impl<R: Send> Send for BufferedReader<R> {}
+unsafe impl<R: Send+Sync> Sync for BufferedReader<R> {}
+
+
 impl<R: Reader> BufferedReader<R> {
     /// Creates a new `BufferedReader` with the specified buffer capacity
     pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> {
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 1c5ceaf2450..b7da57fed27 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -34,7 +34,7 @@ use failure::LOCAL_STDERR;
 use fmt;
 use io::{Reader, Writer, IoResult, IoError, OtherIoError, Buffer,
          standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
-use kinds::Send;
+use kinds::{Sync, Send};
 use libc;
 use mem;
 use option::Option;
@@ -98,26 +98,34 @@ thread_local! {
     }
 }
 
+struct RaceBox(BufferedReader<StdReader>);
+
+unsafe impl Send for RaceBox {}
+unsafe impl Sync for RaceBox {}
+
 /// A synchronized wrapper around a buffered reader from stdin
 #[deriving(Clone)]
 pub struct StdinReader {
-    inner: Arc<Mutex<BufferedReader<StdReader>>>,
+    inner: Arc<Mutex<RaceBox>>,
 }
 
+unsafe impl Send for StdinReader {}
+unsafe impl Sync for StdinReader {}
+
 /// A guard for exclusive access to `StdinReader`'s internal `BufferedReader`.
 pub struct StdinReaderGuard<'a> {
-    inner: MutexGuard<'a, BufferedReader<StdReader>>,
+    inner: MutexGuard<'a, RaceBox>,
 }
 
 impl<'a> Deref<BufferedReader<StdReader>> for StdinReaderGuard<'a> {
     fn deref(&self) -> &BufferedReader<StdReader> {
-        &*self.inner
+        &self.inner.0
     }
 }
 
 impl<'a> DerefMut<BufferedReader<StdReader>> for StdinReaderGuard<'a> {
     fn deref_mut(&mut self) -> &mut BufferedReader<StdReader> {
-        &mut *self.inner
+        &mut self.inner.0
     }
 }
 
@@ -147,7 +155,7 @@ impl StdinReader {
     /// The read is performed atomically - concurrent read calls in other
     /// threads will not interleave with this one.
     pub fn read_line(&mut self) -> IoResult<String> {
-        self.inner.lock().read_line()
+        self.inner.lock().0.read_line()
     }
 
     /// Like `Buffer::read_until`.
@@ -155,7 +163,7 @@ impl StdinReader {
     /// The read is performed atomically - concurrent read calls in other
     /// threads will not interleave with this one.
     pub fn read_until(&mut self, byte: u8) -> IoResult<Vec<u8>> {
-        self.inner.lock().read_until(byte)
+        self.inner.lock().0.read_until(byte)
     }
 
     /// Like `Buffer::read_char`.
@@ -163,13 +171,13 @@ impl StdinReader {
     /// The read is performed atomically - concurrent read calls in other
     /// threads will not interleave with this one.
     pub fn read_char(&mut self) -> IoResult<char> {
-        self.inner.lock().read_char()
+        self.inner.lock().0.read_char()
     }
 }
 
 impl Reader for StdinReader {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
-        self.inner.lock().read(buf)
+        self.inner.lock().0.read(buf)
     }
 
     // We have to manually delegate all of these because the default impls call
@@ -177,23 +185,23 @@ impl Reader for StdinReader {
     // incur the costs of repeated locking).
 
     fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult<uint> {
-        self.inner.lock().read_at_least(min, buf)
+        self.inner.lock().0.read_at_least(min, buf)
     }
 
     fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> {
-        self.inner.lock().push_at_least(min, len, buf)
+        self.inner.lock().0.push_at_least(min, len, buf)
     }
 
     fn read_to_end(&mut self) -> IoResult<Vec<u8>> {
-        self.inner.lock().read_to_end()
+        self.inner.lock().0.read_to_end()
     }
 
     fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
-        self.inner.lock().read_le_uint_n(nbytes)
+        self.inner.lock().0.read_le_uint_n(nbytes)
     }
 
     fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
-        self.inner.lock().read_be_uint_n(nbytes)
+        self.inner.lock().0.read_be_uint_n(nbytes)
     }
 }
 
@@ -221,7 +229,7 @@ pub fn stdin() -> StdinReader {
                 BufferedReader::new(stdin_raw())
             };
             let stdin = StdinReader {
-                inner: Arc::new(Mutex::new(stdin))
+                inner: Arc::new(Mutex::new(RaceBox(stdin)))
             };
             STDIN = mem::transmute(box stdin);
 
@@ -426,6 +434,9 @@ pub struct StdWriter {
     inner: StdSource
 }
 
+unsafe impl Send for StdWriter {}
+unsafe impl Sync for StdWriter {}
+
 impl StdWriter {
     /// Gets the size of this output window, if possible. This is typically used
     /// when the writer is attached to something like a terminal, this is used
diff --git a/src/libstd/rt/exclusive.rs b/src/libstd/rt/exclusive.rs
index 1d3082d1b4c..88bdb29caec 100644
--- a/src/libstd/rt/exclusive.rs
+++ b/src/libstd/rt/exclusive.rs
@@ -26,6 +26,10 @@ pub struct Exclusive<T> {
     data: UnsafeCell<T>,
 }
 
+unsafe impl<T:Send> Send for Exclusive<T> { }
+
+unsafe impl<T:Send> Sync for Exclusive<T> { }
+
 /// An RAII guard returned via `lock`
 pub struct ExclusiveGuard<'a, T:'a> {
     // FIXME #12808: strange name to try to avoid interfering with
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index 6573d9273ce..6cdb199819a 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use kinds::{Send, Sync};
 use sync::{Mutex, Condvar};
 
 /// A barrier enables multiple tasks to synchronize the beginning
@@ -35,12 +36,18 @@ pub struct Barrier {
     num_threads: uint,
 }
 
+unsafe impl Send for Barrier {}
+unsafe impl Sync for Barrier {}
+
 // The inner state of a double barrier
 struct BarrierState {
     count: uint,
     generation_id: uint,
 }
 
+unsafe impl Send for BarrierState {}
+unsafe impl Sync for BarrierState {}
+
 impl Barrier {
     /// Create a new barrier that can block a given number of threads.
     ///
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index be27c06b83c..f1940bfd829 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -58,6 +58,9 @@ use time::Duration;
 /// ```
 pub struct Condvar { inner: Box<StaticCondvar> }
 
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
 /// Statically allocated condition variables.
 ///
 /// This structure is identical to `Condvar` except that it is suitable for use
@@ -75,6 +78,9 @@ pub struct StaticCondvar {
     mutex: AtomicUint,
 }
 
+unsafe impl Send for StaticCondvar {}
+unsafe impl Sync for StaticCondvar {}
+
 /// Constant initializer for a statically allocated condition variable.
 pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
     inner: sys::CONDVAR_INIT,
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 4829be569cc..4d2fbfc4055 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -73,6 +73,10 @@ pub struct Mutex<T> {
     data: UnsafeCell<T>,
 }
 
+unsafe impl<T:Send> Send for Mutex<T> { }
+
+unsafe impl<T:Send> Sync for Mutex<T> { }
+
 /// The static mutex type is provided to allow for static allocation of mutexes.
 ///
 /// Note that this is a separate type because using a Mutex correctly means that
@@ -99,6 +103,8 @@ pub struct StaticMutex {
     poison: UnsafeCell<poison::Flag>,
 }
 
+unsafe impl Sync for StaticMutex {}
+
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
 /// dropped (falls out of scope), the lock will be unlocked.
 ///
@@ -278,6 +284,11 @@ mod test {
     use thread::Thread;
     use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
 
+    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
+
+    unsafe impl<T:'static+Send> Send for Packet<T> {}
+    unsafe impl<T> Sync for Packet<T> {}
+
     #[test]
     fn smoke() {
         let m = Mutex::new(());
@@ -337,19 +348,19 @@ mod test {
 
     #[test]
     fn test_mutex_arc_condvar() {
-        let arc = Arc::new((Mutex::new(false), Condvar::new()));
-        let arc2 = arc.clone();
+        let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
+        let packet2 = Packet(packet.0.clone());
         let (tx, rx) = channel();
         spawn(move|| {
             // wait until parent gets in
             rx.recv();
-            let &(ref lock, ref cvar) = &*arc2;
+            let &(ref lock, ref cvar) = &*packet2.0;
             let mut lock = lock.lock();
             *lock = true;
             cvar.notify_one();
         });
 
-        let &(ref lock, ref cvar) = &*arc;
+        let &(ref lock, ref cvar) = &*packet.0;
         let lock = lock.lock();
         tx.send(());
         assert!(!*lock);
@@ -361,20 +372,20 @@ mod test {
     #[test]
     #[should_fail]
     fn test_arc_condvar_poison() {
-        let arc = Arc::new((Mutex::new(1i), Condvar::new()));
-        let arc2 = arc.clone();
+        let packet = Packet(Arc::new((Mutex::new(1i), Condvar::new())));
+        let packet2 = Packet(packet.0.clone());
         let (tx, rx) = channel();
 
         spawn(move|| {
             rx.recv();
-            let &(ref lock, ref cvar) = &*arc2;
+            let &(ref lock, ref cvar) = &*packet2.0;
             let _g = lock.lock();
             cvar.notify_one();
             // Parent should fail when it wakes up.
             panic!();
         });
 
-        let &(ref lock, ref cvar) = &*arc;
+        let &(ref lock, ref cvar) = &*packet.0;
         let lock = lock.lock();
         tx.send(());
         while *lock == 1 {
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index a43f822e351..4d9fbb59908 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -14,6 +14,7 @@
 //! example use case would be for initializing an FFI library.
 
 use int;
+use kinds::Sync;
 use mem::drop;
 use ops::FnOnce;
 use sync::atomic;
@@ -41,6 +42,8 @@ pub struct Once {
     lock_cnt: atomic::AtomicInt,
 }
 
+unsafe impl Sync for Once {}
+
 /// Initialization value for static `Once` values.
 pub const ONCE_INIT: Once = Once {
     mutex: MUTEX_INIT,
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 3f177a42f44..76d05d9bfd4 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -60,6 +60,9 @@ pub struct RWLock<T> {
     data: UnsafeCell<T>,
 }
 
+unsafe impl<T:'static+Send> Send for RWLock<T> {}
+unsafe impl<T> Sync for RWLock<T> {}
+
 /// Structure representing a statically allocated RWLock.
 ///
 /// This structure is intended to be used inside of a `static` and will provide
@@ -88,6 +91,9 @@ pub struct StaticRWLock {
     poison: UnsafeCell<poison::Flag>,
 }
 
+unsafe impl Send for StaticRWLock {}
+unsafe impl Sync for StaticRWLock {}
+
 /// Constant initialization for a statically-initialized rwlock.
 pub const RWLOCK_INIT: StaticRWLock = StaticRWLock {
     inner: sys::RWLOCK_INIT,
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs
index 421778e2012..a629f035b07 100644
--- a/src/libstd/sys/common/helper_thread.rs
+++ b/src/libstd/sys/common/helper_thread.rs
@@ -59,6 +59,15 @@ pub struct Helper<M> {
     pub shutdown: UnsafeCell<bool>,
 }
 
+unsafe impl<M:Send> Send for Helper<M> { }
+
+unsafe impl<M:Send> Sync for Helper<M> { }
+
+struct RaceBox(helper_signal::signal);
+
+unsafe impl Send for RaceBox {}
+unsafe impl Sync for RaceBox {}
+
 impl<M: Send> Helper<M> {
     /// Lazily boots a helper thread, becoming a no-op if the helper has already
     /// been spawned.
@@ -81,9 +90,11 @@ impl<M: Send> Helper<M> {
                 let (receive, send) = helper_signal::new();
                 *self.signal.get() = send as uint;
 
+                let receive = RaceBox(receive);
+
                 let t = f();
                 Thread::spawn(move |:| {
-                    helper(receive, rx, t);
+                    helper(receive.0, rx, t);
                     let _g = self.lock.lock();
                     *self.shutdown.get() = true;
                     self.cond.notify_one()
diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs
index 1a8a92a105a..567c26956ef 100644
--- a/src/libstd/sys/common/mutex.rs
+++ b/src/libstd/sys/common/mutex.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use kinds::Sync;
 use sys::mutex as imp;
 
 /// An OS-based mutual exclusion lock.
@@ -17,6 +18,8 @@ use sys::mutex as imp;
 /// at the top level of the crate instead of this type.
 pub struct Mutex(imp::Mutex);
 
+unsafe impl Sync for Mutex {}
+
 /// Constant initializer for statically allocated mutexes.
 pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT);
 
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index e76f2a2b872..a4ebcbd25d0 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -162,6 +162,9 @@ mod signal {
         sa_restorer: *mut libc::c_void,
     }
 
+    unsafe impl ::kinds::Send for sigaction { }
+    unsafe impl ::kinds::Sync for sigaction { }
+
     #[repr(C)]
     #[cfg(target_word_size = "32")]
     pub struct sigset_t {
@@ -211,6 +214,9 @@ mod signal {
         sa_resv: [libc::c_int, ..1],
     }
 
+    impl ::kinds::Send for sigaction { }
+    impl ::kinds::Sync for sigaction { }
+
     #[repr(C)]
     pub struct sigset_t {
         __val: [libc::c_ulong, ..32],
diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs
index 2f01c53cb2c..81f8659d6ae 100644
--- a/src/libstd/sys/unix/mutex.rs
+++ b/src/libstd/sys/unix/mutex.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use cell::UnsafeCell;
+use kinds::Sync;
 use sys::sync as ffi;
 use sys_common::mutex;
 
@@ -23,6 +24,8 @@ pub const MUTEX_INIT: Mutex = Mutex {
     inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
 };
 
+unsafe impl Sync for Mutex {}
+
 impl Mutex {
     #[inline]
     pub unsafe fn new() -> Mutex {
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 348b7cfad33..f1b078b4e80 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -117,6 +117,9 @@ pub struct UnixStream {
     write_deadline: u64,
 }
 
+unsafe impl Send for UnixStream {}
+unsafe impl Sync for UnixStream {}
+
 impl UnixStream {
     pub fn connect(addr: &CString,
                    timeout: Option<u64>) -> IoResult<UnixStream> {
@@ -215,6 +218,9 @@ pub struct UnixListener {
     path: CString,
 }
 
+unsafe impl Send for UnixListener {}
+unsafe impl Sync for UnixListener {}
+
 impl UnixListener {
     pub fn bind(addr: &CString) -> IoResult<UnixListener> {
         bind(addr, libc::SOCK_STREAM).map(|fd| {
@@ -259,6 +265,9 @@ struct AcceptorInner {
     closed: atomic::AtomicBool,
 }
 
+unsafe impl Send for AcceptorInner {}
+unsafe impl Sync for AcceptorInner {}
+
 impl UnixAcceptor {
     pub fn fd(&self) -> fd_t { self.inner.listener.fd() }
 
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 340f9514241..bcbbb8766b7 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -160,7 +160,7 @@ mod imp {
 
         pub static SIGSTKSZ: libc::size_t = 8192;
 
-        pub static SIG_DFL: sighandler_t = 0i as sighandler_t;
+        pub const SIG_DFL: sighandler_t = 0i as sighandler_t;
 
         // This definition is not as accurate as it could be, {si_addr} is
         // actually a giant union. Currently we're only interested in that field,
diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs
index 5c99ad1e0ce..e2a78947e16 100644
--- a/src/libstd/sys/unix/tcp.rs
+++ b/src/libstd/sys/unix/tcp.rs
@@ -33,6 +33,8 @@ pub struct TcpListener {
     pub inner: FileDesc,
 }
 
+unsafe impl Sync for TcpListener {}
+
 impl TcpListener {
     pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
         let fd = try!(net::socket(addr, libc::SOCK_STREAM));
@@ -96,6 +98,8 @@ struct AcceptorInner {
     closed: atomic::AtomicBool,
 }
 
+unsafe impl Sync for AcceptorInner {}
+
 impl TcpAcceptor {
     pub fn fd(&self) -> sock_t { self.inner.listener.fd() }
 
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index ddd89070ed5..3ac7c09154e 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -22,6 +22,8 @@ pub struct Mutex { inner: atomic::AtomicUint }
 
 pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::INIT_ATOMIC_UINT };
 
+unsafe impl Sync for Mutex {}
+
 #[inline]
 pub unsafe fn raw(m: &Mutex) -> ffi::LPCRITICAL_SECTION {
     m.get()
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index bf658d0efd0..fc3640f2604 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -214,6 +214,9 @@ pub struct UnixStream {
     write_deadline: u64,
 }
 
+unsafe impl Send for UnixStream {}
+unsafe impl Sync for UnixStream {}
+
 impl UnixStream {
     fn try_connect(p: *const u16) -> Option<libc::HANDLE> {
         // Note that most of this is lifted from the libuv implementation.
@@ -559,6 +562,9 @@ pub struct UnixListener {
     name: CString,
 }
 
+unsafe impl Send for UnixListener {}
+unsafe impl Sync for UnixListener {}
+
 impl UnixListener {
     pub fn bind(addr: &CString) -> IoResult<UnixListener> {
         // Although we technically don't need the pipe until much later, we
@@ -603,11 +609,17 @@ pub struct UnixAcceptor {
     deadline: u64,
 }
 
+unsafe impl Send for UnixAcceptor {}
+unsafe impl Sync for UnixAcceptor {}
+
 struct AcceptorState {
     abort: Event,
     closed: atomic::AtomicBool,
 }
 
+unsafe impl Send for AcceptorState {}
+unsafe impl Sync for AcceptorState {}
+
 impl UnixAcceptor {
     pub fn accept(&mut self) -> IoResult<UnixStream> {
         // This function has some funky implementation details when working with
diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs
index 505e6137bf9..513c1d38e36 100644
--- a/src/libstd/sys/windows/tcp.rs
+++ b/src/libstd/sys/windows/tcp.rs
@@ -24,6 +24,9 @@ pub use sys_common::net::TcpStream;
 
 pub struct Event(c::WSAEVENT);
 
+unsafe impl Send for Event {}
+unsafe impl Sync for Event {}
+
 impl Event {
     pub fn new() -> IoResult<Event> {
         let event = unsafe { c::WSACreateEvent() };
@@ -49,6 +52,9 @@ impl Drop for Event {
 
 pub struct TcpListener { sock: sock_t }
 
+unsafe impl Send for TcpListener {}
+unsafe impl Sync for TcpListener {}
+
 impl TcpListener {
     pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
         sys::init_net();
@@ -109,6 +115,9 @@ pub struct TcpAcceptor {
     deadline: u64,
 }
 
+unsafe impl Send for TcpAcceptor {}
+unsafe impl Sync for TcpAcceptor {}
+
 struct AcceptorInner {
     listener: TcpListener,
     abort: Event,
@@ -116,6 +125,9 @@ struct AcceptorInner {
     closed: atomic::AtomicBool,
 }
 
+unsafe impl Send for AcceptorInner {}
+unsafe impl Sync for AcceptorInner {}
+
 impl TcpAcceptor {
     pub fn socket(&self) -> sock_t { self.inner.listener.socket() }
 
diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs
index 7e4dd768aa9..874838950cd 100644
--- a/src/libstd/sys/windows/timer.rs
+++ b/src/libstd/sys/windows/timer.rs
@@ -48,6 +48,9 @@ pub enum Req {
     RemoveTimer(libc::HANDLE, Sender<()>),
 }
 
+unsafe impl Send for Req {}
+
+
 fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) {
     let mut objs = vec![input];
     let mut chans = vec![];
diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs
index 89773207347..56731bd7ec3 100644
--- a/src/libstd/thread.rs
+++ b/src/libstd/thread.rs
@@ -129,7 +129,7 @@ use borrow::IntoCow;
 use boxed::Box;
 use cell::UnsafeCell;
 use clone::Clone;
-use kinds::Send;
+use kinds::{Send, Sync};
 use ops::{Drop, FnOnce};
 use option::Option::{mod, Some, None};
 use result::Result::{Err, Ok};
@@ -211,8 +211,8 @@ impl Builder {
     }
 
     fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> JoinGuard<T> {
-        let my_packet = Arc::new(UnsafeCell::new(None));
-        let their_packet = my_packet.clone();
+        let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
+        let their_packet = Packet(my_packet.0.clone());
 
         let Builder { name, stack_size, stdout, stderr } = self;
 
@@ -266,7 +266,7 @@ impl Builder {
                 }
             };
             unsafe {
-                *their_packet.get() = Some(match (output, try_result) {
+                *their_packet.0.get() = Some(match (output, try_result) {
                     (Some(data), Ok(_)) => Ok(data),
                     (None, Err(cause)) => Err(cause),
                     _ => unreachable!()
@@ -289,12 +289,16 @@ struct Inner {
     cvar: Condvar,
 }
 
+unsafe impl Sync for Inner {}
+
 #[deriving(Clone)]
 /// A handle to a thread.
 pub struct Thread {
     inner: Arc<Inner>,
 }
 
+unsafe impl Sync for Thread {}
+
 impl Thread {
     // Used only internally to construct a thread object without spawning
     fn new(name: Option<String>) -> Thread {
@@ -379,6 +383,11 @@ impl thread_info::NewThread for Thread {
 /// A thread that completes without panicking is considered to exit successfully.
 pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
 
+struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
+
+unsafe impl<T:'static+Send> Send for Packet<T> {}
+unsafe impl<T> Sync for Packet<T> {}
+
 #[must_use]
 /// An RAII-style guard that will block until thread termination when dropped.
 ///
@@ -387,9 +396,11 @@ pub struct JoinGuard<T> {
     native: imp::rust_thread,
     thread: Thread,
     joined: bool,
-    packet: Arc<UnsafeCell<Option<Result<T>>>>,
+    packet: Packet<T>,
 }
 
+unsafe impl<T: Send> Sync for JoinGuard<T> {}
+
 impl<T: Send> JoinGuard<T> {
     /// Extract a handle to the thread this guard will join on.
     pub fn thread(&self) -> &Thread {
@@ -406,7 +417,7 @@ impl<T: Send> JoinGuard<T> {
         unsafe { imp::join(self.native) };
         self.joined = true;
         unsafe {
-            (*self.packet.get()).take().unwrap()
+            (*self.packet.0.get()).take().unwrap()
         }
     }
 
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs
index 04718dcc6ae..242dceb4256 100644
--- a/src/libstd/thread_local/mod.rs
+++ b/src/libstd/thread_local/mod.rs
@@ -280,6 +280,8 @@ mod imp {
         pub dtor_running: UnsafeCell<bool>, // should be Cell
     }
 
+    unsafe impl<T> ::kinds::Sync for Key<T> { }
+
     #[doc(hidden)]
     impl<T> Key<T> {
         pub unsafe fn get(&'static self) -> Option<&'static T> {
@@ -410,6 +412,8 @@ mod imp {
         pub os: OsStaticKey,
     }
 
+    unsafe impl<T> ::kinds::Sync for Key<T> { }
+
     struct Value<T: 'static> {
         key: &'static Key<T>,
         value: T,
diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs
index 643a0f55e74..756c86c2115 100644
--- a/src/libstd/thread_local/scoped.rs
+++ b/src/libstd/thread_local/scoped.rs
@@ -198,10 +198,11 @@ impl<T> Key<T> {
 mod imp {
     use std::cell::UnsafeCell;
 
-    // FIXME: Should be a `Cell`, but that's not `Sync`
     #[doc(hidden)]
     pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
 
+    unsafe impl<T> ::kinds::Sync for KeyInner<T> { }
+
     #[doc(hidden)]
     impl<T> KeyInner<T> {
         #[doc(hidden)]
@@ -222,6 +223,8 @@ mod imp {
         pub marker: marker::InvariantType<T>,
     }
 
+    unsafe impl<T> ::kinds::Sync for KeyInner<T> { }
+
     #[doc(hidden)]
     impl<T> KeyInner<T> {
         #[doc(hidden)]