diff --git a/Cargo.toml b/Cargo.toml
index 13b4ab795a7a857400a51d97e63d8c8e71b604e3..983d302e07b1b587a426c74961a3b0bdca904914 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,3 +17,6 @@ version = "0.2.0"
 
 [dependencies]
 untagged-option = "0.1.1"
+
+[dev-dependencies]
+scoped_threadpool = "0.1.8"
diff --git a/blacklist.txt b/blacklist.txt
index 54defd9d6fbc0c8ce18d2594088fda6363886ad9..bf051e53d43c7b2770a383860ce0b20c0a5e929d 100644
--- a/blacklist.txt
+++ b/blacklist.txt
@@ -1,4 +1,7 @@
-# false positives from thread::spawn (?)
+# false positives in thread::spawn (?)
 race:*dealloc
 race:*drop_slow*
 race:__call_tls_dtors
+
+# false positives in scoped_threadpool (?)
+race:*drop*
diff --git a/src/cfail.rs b/src/cfail.rs
new file mode 100644
index 0000000000000000000000000000000000000000..50c3a920747f2bfd3a756decc7da33cbb42a0ce9
--- /dev/null
+++ b/src/cfail.rs
@@ -0,0 +1,80 @@
+//! Compile fail tests
+//!
+//! # `Send`-ness
+//!
+//! Collections of `Send`-able things are `Send`
+//!
+//! ```
+//! use heapless::{RingBuffer, Vec};
+//! use heapless::ring_buffer::{Consumer, Producer};
+//!
+//! struct IsSend;
+//!
+//! unsafe impl Send for IsSend {}
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Consumer<IsSend, [IsSend; 4]>>();
+//! is_send::<Producer<IsSend, [IsSend; 4]>>();
+//! is_send::<RingBuffer<IsSend, [IsSend; 4]>>();
+//! is_send::<Vec<IsSend, [IsSend; 4]>>();
+//! ```
+//!
+//! Collections of non-`Send`-able things are *not* `Send`
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::ring_buffer::Consumer;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Consumer<NotSend, [NotSend; 4]>>();
+//! ```
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::ring_buffer::Producer;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Producer<NotSend, [NotSend; 4]>>();
+//! ```
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::RingBuffer;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<RingBuffer<NotSend, [NotSend; 4]>>();
+//! ```
+//!
+//! ``` compile_fail
+//! use std::marker::PhantomData;
+//! use heapless::Vec;
+//!
+//! type NotSend = PhantomData<*const ()>;
+//!
+//! fn is_send<T>() where T: Send {}
+//!
+//! is_send::<Vec<NotSend, [NotSend; 4]>>();
+//! ```
+//!
+//! # Freeze
+//!
+//! Splitting a `RingBuffer` should invalidate the original reference.
+//!
+//! ``` compile_fail
+//! use heapless::RingBuffer;
+//!
+//! let mut rb: RingBuffer<u8, [u8; 4]> = RingBuffer::new();
+//!
+//! let (p, c) = rb.split();
+//! rb.enqueue(0).unwrap();
+//! ```
diff --git a/src/lib.rs b/src/lib.rs
index e8f83cbd160859606a248ba5ae1451b1ea7924f2..f36ef00d20d5b6e5c5c10280dae62fab1e5afb00 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -36,8 +36,6 @@
 //!
 //! ### Single producer single consumer mode
 //!
-//! For use in *single core* systems like microcontrollers
-//!
 //! ```
 //! use heapless::RingBuffer;
 //!
@@ -77,72 +75,6 @@
 //!     // ..
 //! }
 //! ```
-//!
-//! # `Send`-ness
-//!
-//! Collections of `Send`-able things are `Send`
-//!
-//! ```
-//! use heapless::{RingBuffer, Vec};
-//! use heapless::ring_buffer::{Consumer, Producer};
-//!
-//! struct IsSend;
-//!
-//! unsafe impl Send for IsSend {}
-//!
-//! fn is_send<T>() where T: Send {}
-//!
-//! is_send::<Consumer<IsSend, [IsSend; 4]>>();
-//! is_send::<Producer<IsSend, [IsSend; 4]>>();
-//! is_send::<RingBuffer<IsSend, [IsSend; 4]>>();
-//! is_send::<Vec<IsSend, [IsSend; 4]>>();
-//! ```
-//!
-//! Collections of not `Send`-able things are *not* `Send`
-//!
-//! ``` compile_fail
-//! use std::marker::PhantomData;
-//! use heapless::ring_buffer::Consumer;
-//!
-//! type NotSend = PhantomData<*const ()>;
-//!
-//! fn is_send<T>() where T: Send {}
-//!
-//! is_send::<Consumer<NotSend, [NotSend; 4]>>();
-//! ```
-//!
-//! ``` compile_fail
-//! use std::marker::PhantomData;
-//! use heapless::ring_buffer::Producer;
-//!
-//! type NotSend = PhantomData<*const ()>;
-//!
-//! fn is_send<T>() where T: Send {}
-//!
-//! is_send::<Producer<NotSend, [NotSend; 4]>>();
-//! ```
-//!
-//! ``` compile_fail
-//! use std::marker::PhantomData;
-//! use heapless::RingBuffer;
-//!
-//! type NotSend = PhantomData<*const ()>;
-//!
-//! fn is_send<T>() where T: Send {}
-//!
-//! is_send::<RingBuffer<NotSend, [NotSend; 4]>>();
-//! ```
-//!
-//! ``` compile_fail
-//! use std::marker::PhantomData;
-//! use heapless::Vec;
-//!
-//! type NotSend = PhantomData<*const ()>;
-//!
-//! fn is_send<T>() where T: Send {}
-//!
-//! is_send::<Vec<NotSend, [NotSend; 4]>>();
-//! ```
 
 #![deny(missing_docs)]
 #![feature(const_fn)]
@@ -157,8 +89,9 @@ extern crate untagged_option;
 pub use vec::Vec;
 pub use ring_buffer::RingBuffer;
 
-pub mod ring_buffer;
+mod cfail;
 mod vec;
+pub mod ring_buffer;
 
 /// Error raised when the buffer is full
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
diff --git a/src/ring_buffer/spsc.rs b/src/ring_buffer/spsc.rs
index 4c93f429dae84c820f7277ad90115a1f092452ff..488c07a87a91a8d34f90a0bf0f55536c4dc2dd5d 100644
--- a/src/ring_buffer/spsc.rs
+++ b/src/ring_buffer/spsc.rs
@@ -1,5 +1,5 @@
 use core::ptr::{self, Shared};
-use core::marker::Unsize;
+use core::marker::{PhantomData, Unsize};
 
 use BufferFullError;
 use ring_buffer::RingBuffer;
@@ -9,13 +9,15 @@ where
     A: Unsize<[T]>,
 {
     /// Splits a statically allocated ring buffer into producer and consumer end points
-    pub fn split(&'static mut self) -> (Producer<T, A>, Consumer<T, A>) {
+    pub fn split(&mut self) -> (Producer<T, A>, Consumer<T, A>) {
         (
             Producer {
                 rb: unsafe { Shared::new_unchecked(self) },
+                _marker: PhantomData,
             },
             Consumer {
                 rb: unsafe { Shared::new_unchecked(self) },
+                _marker: PhantomData,
             },
         )
     }
@@ -23,15 +25,16 @@ where
 
 /// A ring buffer "consumer"; it can dequeue items from the ring buffer
 // NOTE the consumer semantically owns the `head` pointer of the ring buffer
-pub struct Consumer<T, A>
+pub struct Consumer<'a, T, A>
 where
     A: Unsize<[T]>,
 {
     // XXX do we need to use `Shared` (for soundness) here?
     rb: Shared<RingBuffer<T, A>>,
+    _marker: PhantomData<&'a ()>,
 }
 
-impl<T, A> Consumer<T, A>
+impl<'a, T, A> Consumer<'a, T, A>
 where
     A: Unsize<[T]>,
 {
@@ -54,7 +57,7 @@ where
     }
 }
 
-unsafe impl<T, A> Send for Consumer<T, A>
+unsafe impl<'a, T, A> Send for Consumer<'a, T, A>
 where
     A: Unsize<[T]>,
     T: Send,
@@ -63,15 +66,16 @@ where
 
 /// A ring buffer "producer"; it can enqueue items into the ring buffer
 // NOTE the producer semantically owns the `tail` pointer of the ring buffer
-pub struct Producer<T, A>
+pub struct Producer<'a, T, A>
 where
     A: Unsize<[T]>,
 {
     // XXX do we need to use `Shared` (for soundness) here?
     rb: Shared<RingBuffer<T, A>>,
+    _marker: PhantomData<&'a ()>,
 }
 
-impl<T, A> Producer<T, A>
+impl<'a, T, A> Producer<'a, T, A>
 where
     A: Unsize<[T]>,
 {
@@ -99,7 +103,7 @@ where
     }
 }
 
-unsafe impl<T, A> Send for Producer<T, A>
+unsafe impl<'a, T, A> Send for Producer<'a, T, A>
 where
     A: Unsize<[T]>,
     T: Send,
diff --git a/tests/tsan.rs b/tests/tsan.rs
index dcef81cf40f75e56866d93c1de9decd4abd2356d..6680cd248500fb6a910f18e3c992541e434f58fc 100644
--- a/tests/tsan.rs
+++ b/tests/tsan.rs
@@ -1,10 +1,12 @@
 #![deny(warnings)]
 
 extern crate heapless;
+extern crate scoped_threadpool;
 
 use std::thread;
 
 use heapless::RingBuffer;
+use scoped_threadpool::Pool;
 
 #[test]
 fn once() {
@@ -48,3 +50,26 @@ fn twice() {
         c.dequeue().unwrap();
     });
 }
+
+#[test]
+fn scoped() {
+    let mut rb: RingBuffer<i32, [i32; 4]> = RingBuffer::new();
+
+    rb.enqueue(0).unwrap();
+
+    {
+        let (mut p, mut c) = rb.split();
+
+        Pool::new(2).scoped(move |scope| {
+            scope.execute(move || {
+                p.enqueue(1).unwrap();
+            });
+
+            scope.execute(move || {
+                c.dequeue().unwrap();
+            });
+        });
+    }
+
+    rb.dequeue().unwrap();
+}