about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorFlavio Percoco <flaper87@gmail.com>2014-12-06 11:39:25 -0500
committerFlavio Percoco <flaper87@gmail.com>2014-12-26 17:26:32 +0100
commitfb803a857000813e4d572900799f0498fb20050b (patch)
treea1247d535c6dbb3fcaca0743cda7900481d14053 /src/libstd
parentc43efee6def9a4a4e943feef0236d3e17b3f581d (diff)
downloadrust-fb803a857000813e4d572900799f0498fb20050b.tar.gz
rust-fb803a857000813e4d572900799f0498fb20050b.zip
Require types to opt-in Sync
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/c_str.rs6
-rw-r--r--src/libstd/collections/hash/table.rs20
-rw-r--r--src/libstd/comm/blocking.rs1
-rw-r--r--src/libstd/comm/mod.rs40
-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.rs7
-rw-r--r--src/libstd/rt/exclusive.rs4
-rw-r--r--src/libstd/sync/mutex.rs15
-rw-r--r--src/libstd/sync/once.rs1
-rw-r--r--src/libstd/sys/common/helper_thread.rs4
-rw-r--r--src/libstd/sys/common/mutex.rs1
-rw-r--r--src/libstd/sys/unix/c.rs6
-rw-r--r--src/libstd/sys/unix/mutex.rs7
-rw-r--r--src/libstd/sys/unix/pipe.rs2
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs2
-rw-r--r--src/libstd/sys/unix/tcp.rs2
-rw-r--r--src/libstd/thread.rs11
-rw-r--r--src/libstd/thread_local/mod.rs4
-rw-r--r--src/libstd/thread_local/scoped.rs6
20 files changed, 101 insertions, 45 deletions
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index fb44961017f..27b63be6cd0 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,
 }
 
+impl Send for CString { }
+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/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 8f2152c5a9d..ee37eb27795 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::{OwnedPtr, 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:   OwnedPtr<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: OwnedPtr::null(),
                 marker: marker::CovariantType,
             };
         }
@@ -602,7 +602,7 @@ impl<K, V> RawTable<K, V> {
         RawTable {
             capacity: capacity,
             size:     0,
-            hashes:   hashes,
+            hashes:   OwnedPtr(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..a154224824c 100644
--- a/src/libstd/comm/blocking.rs
+++ b/src/libstd/comm/blocking.rs
@@ -17,6 +17,7 @@ use kinds::marker::{NoSend, NoSync};
 use mem;
 use clone::Clone;
 
+#[deriving(Send, Sync)]
 struct Inner {
     thread: Thread,
     woken: AtomicBool,
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs
index 7352cdfbfe7..18b50c621e9 100644
--- a/src/libstd/comm/mod.rs
+++ b/src/libstd/comm/mod.rs
@@ -321,7 +321,7 @@ use self::Flavor::*;
 use alloc::arc::Arc;
 use core::kinds::marker;
 use core::mem;
-use core::cell::UnsafeCell;
+use core::cell::{UnsafeCell, RacyCell};
 
 pub use self::select::{Select, Handle};
 use self::select::StartResult;
@@ -359,10 +359,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.
+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.
@@ -376,15 +378,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.
+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,
 }
@@ -420,10 +424,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)]
@@ -474,7 +478,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)))
 }
 
@@ -514,7 +518,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)))
 }
 
@@ -526,7 +530,6 @@ impl<T: Send> Sender<T> {
     fn new(inner: Flavor<T>) -> Sender<T> {
         Sender {
             inner: UnsafeCell::new(inner),
-            _marker: marker::NoSync,
         }
     }
 
@@ -596,7 +599,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);
@@ -633,7 +637,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()))) {
@@ -644,7 +648,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()))) {
@@ -688,7 +692,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 }
     }
 
@@ -777,7 +781,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
diff --git a/src/libstd/comm/mpsc_queue.rs b/src/libstd/comm/mpsc_queue.rs
index db4e3eac449..6298896a18b 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>>,
 }
 
+impl<T:Send> Send for Queue<T> { }
+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..dbf1f255997 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,
 }
 
+impl<T: Send> Send for Queue<T> { }
+
+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..f4f4c7472e2 100644
--- a/src/libstd/comm/sync.rs
+++ b/src/libstd/comm/sync.rs
@@ -53,6 +53,11 @@ pub struct Packet<T> {
     lock: Mutex<State<T>>,
 }
 
+impl<T:Send> Send for Packet<T> { }
+
+impl<T:Send> Sync for Packet<T> { }
+
+#[deriving(Send)]
 struct State<T> {
     disconnected: bool, // Is the channel disconnected yet?
     queue: Queue,       // queue of senders waiting to send data
@@ -88,6 +93,8 @@ struct Node {
     next: *mut Node,
 }
 
+impl Send for Node {}
+
 /// A simple ring-buffer
 struct Buffer<T> {
     buf: Vec<Option<T>>,
diff --git a/src/libstd/rt/exclusive.rs b/src/libstd/rt/exclusive.rs
index 1d3082d1b4c..a878066ad16 100644
--- a/src/libstd/rt/exclusive.rs
+++ b/src/libstd/rt/exclusive.rs
@@ -26,6 +26,10 @@ pub struct Exclusive<T> {
     data: UnsafeCell<T>,
 }
 
+impl<T:Send> Send for Exclusive<T> { }
+
+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/mutex.rs b/src/libstd/sync/mutex.rs
index 4829be569cc..2849813c510 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -10,7 +10,7 @@
 
 use prelude::*;
 
-use cell::UnsafeCell;
+use cell::{UnsafeCell, RacyCell};
 use kinds::marker;
 use sync::{poison, AsMutexGuard};
 use sys_common::mutex as sys;
@@ -70,9 +70,13 @@ pub struct Mutex<T> {
     // time, so to ensure that the native mutex is used correctly we box the
     // inner lock to give it a constant address.
     inner: Box<StaticMutex>,
-    data: UnsafeCell<T>,
+    data: RacyCell<T>,
 }
 
+impl<T:Send> Send for Mutex<T> { }
+
+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
@@ -94,9 +98,10 @@ pub struct Mutex<T> {
 /// }
 /// // lock is unlocked here.
 /// ```
+#[deriving(Sync)]
 pub struct StaticMutex {
     lock: sys::Mutex,
-    poison: UnsafeCell<poison::Flag>,
+    poison: RacyCell<poison::Flag>,
 }
 
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
@@ -125,7 +130,7 @@ pub struct StaticMutexGuard {
 /// other mutex constants.
 pub const MUTEX_INIT: StaticMutex = StaticMutex {
     lock: sys::MUTEX_INIT,
-    poison: UnsafeCell { value: poison::Flag { failed: false } },
+    poison: RacyCell(UnsafeCell { value: poison::Flag { failed: false } }),
 };
 
 impl<T: Send> Mutex<T> {
@@ -133,7 +138,7 @@ impl<T: Send> Mutex<T> {
     pub fn new(t: T) -> Mutex<T> {
         Mutex {
             inner: box MUTEX_INIT,
-            data: UnsafeCell::new(t),
+            data: RacyCell::new(t),
         }
     }
 
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index a43f822e351..4b940b0420a 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -35,6 +35,7 @@ use sync::{StaticMutex, MUTEX_INIT};
 ///     // run initialization here
 /// });
 /// ```
+#[deriving(Sync)]
 pub struct Once {
     mutex: StaticMutex,
     cnt: atomic::AtomicInt,
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs
index 421778e2012..9df69d8e0d6 100644
--- a/src/libstd/sys/common/helper_thread.rs
+++ b/src/libstd/sys/common/helper_thread.rs
@@ -59,6 +59,10 @@ pub struct Helper<M> {
     pub shutdown: UnsafeCell<bool>,
 }
 
+impl<M:Send> Send for Helper<M> { }
+
+impl<M:Send> Sync for Helper<M> { }
+
 impl<M: Send> Helper<M> {
     /// Lazily boots a helper thread, becoming a no-op if the helper has already
     /// been spawned.
diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs
index 1a8a92a105a..5869c280517 100644
--- a/src/libstd/sys/common/mutex.rs
+++ b/src/libstd/sys/common/mutex.rs
@@ -15,6 +15,7 @@ use sys::mutex as imp;
 /// This is the thinnest cross-platform wrapper around OS mutexes. All usage of
 /// this mutex is unsafe and it is recommended to instead use the safe wrapper
 /// at the top level of the crate instead of this type.
+#[deriving(Sync)]
 pub struct Mutex(imp::Mutex);
 
 /// Constant initializer for statically allocated mutexes.
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index e76f2a2b872..a5796f8dd01 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,
     }
 
+    impl ::kinds::Send for sigaction { }
+    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..52ed0649694 100644
--- a/src/libstd/sys/unix/mutex.rs
+++ b/src/libstd/sys/unix/mutex.rs
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use cell::UnsafeCell;
+use cell::{UnsafeCell, RacyCell};
 use sys::sync as ffi;
 use sys_common::mutex;
 
-pub struct Mutex { inner: UnsafeCell<ffi::pthread_mutex_t> }
+#[deriving(Sync)]
+pub struct Mutex { inner: RacyCell<ffi::pthread_mutex_t> }
 
 #[inline]
 pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
@@ -20,7 +21,7 @@ pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
 }
 
 pub const MUTEX_INIT: Mutex = Mutex {
-    inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
+    inner: RacyCell(UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER }),
 };
 
 impl Mutex {
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 348b7cfad33..8d1010937bc 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -210,6 +210,7 @@ impl Clone for UnixStream {
 // Unix Listener
 ////////////////////////////////////////////////////////////////////////////////
 
+#[deriving(Sync)]
 pub struct UnixListener {
     inner: Inner,
     path: CString,
@@ -252,6 +253,7 @@ pub struct UnixAcceptor {
     deadline: u64,
 }
 
+#[deriving(Sync)]
 struct AcceptorInner {
     listener: UnixListener,
     reader: FileDesc,
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..60ca76171b1 100644
--- a/src/libstd/sys/unix/tcp.rs
+++ b/src/libstd/sys/unix/tcp.rs
@@ -29,6 +29,7 @@ pub use sys_common::net::TcpStream;
 // TCP listeners
 ////////////////////////////////////////////////////////////////////////////////
 
+#[deriving(Sync)]
 pub struct TcpListener {
     pub inner: FileDesc,
 }
@@ -89,6 +90,7 @@ pub struct TcpAcceptor {
     deadline: u64,
 }
 
+#[deriving(Sync)]
 struct AcceptorInner {
     listener: TcpListener,
     reader: FileDesc,
diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs
index 89773207347..e3b97afb31d 100644
--- a/src/libstd/thread.rs
+++ b/src/libstd/thread.rs
@@ -127,9 +127,9 @@
 use any::Any;
 use borrow::IntoCow;
 use boxed::Box;
-use cell::UnsafeCell;
+use cell::RacyCell;
 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,7 +211,7 @@ impl Builder {
     }
 
     fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> JoinGuard<T> {
-        let my_packet = Arc::new(UnsafeCell::new(None));
+        let my_packet = Arc::new(RacyCell::new(None));
         let their_packet = my_packet.clone();
 
         let Builder { name, stack_size, stdout, stderr } = self;
@@ -283,13 +283,14 @@ impl Builder {
     }
 }
 
+#[deriving(Sync)]
 struct Inner {
     name: Option<String>,
     lock: Mutex<bool>,          // true when there is a buffered unpark
     cvar: Condvar,
 }
 
-#[deriving(Clone)]
+#[deriving(Clone, Sync)]
 /// A handle to a thread.
 pub struct Thread {
     inner: Arc<Inner>,
@@ -387,7 +388,7 @@ pub struct JoinGuard<T> {
     native: imp::rust_thread,
     thread: Thread,
     joined: bool,
-    packet: Arc<UnsafeCell<Option<Result<T>>>>,
+    packet: Arc<RacyCell<Option<Result<T>>>>,
 }
 
 impl<T: Send> JoinGuard<T> {
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs
index 04718dcc6ae..55fb3151133 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
     }
 
+    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,
     }
 
+    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..83e61373dd1 100644
--- a/src/libstd/thread_local/scoped.rs
+++ b/src/libstd/thread_local/scoped.rs
@@ -198,10 +198,12 @@ impl<T> Key<T> {
 mod imp {
     use std::cell::UnsafeCell;
 
-    // FIXME: Should be a `Cell`, but that's not `Sync`
+    // SNAP c9f6d69 switch to `Cell`
     #[doc(hidden)]
     pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
 
+    #[cfg(not(stage0))] impl<T> ::kinds::Sync for KeyInner<T> { }
+
     #[doc(hidden)]
     impl<T> KeyInner<T> {
         #[doc(hidden)]
@@ -222,6 +224,8 @@ mod imp {
         pub marker: marker::InvariantType<T>,
     }
 
+    #[cfg(not(stage0))] impl<T> ::kinds::Sync for KeyInner<T> { }
+
     #[doc(hidden)]
     impl<T> KeyInner<T> {
         #[doc(hidden)]