summaryrefslogtreecommitdiffstats
path: root/tokio/src/loom/std
diff options
context:
space:
mode:
authorCarl Lerche <me@carllerche.com>2020-03-26 12:23:12 -0700
committerGitHub <noreply@github.com>2020-03-26 12:23:12 -0700
commit1cb1e291c10adf6b4e530cb1475b95ba10fa615f (patch)
treeaabaebe663e2647fb72cb609d1486adcde0c4cc4 /tokio/src/loom/std
parent186196b911bb7cbbd67e74b4ef051d3daf2d64c1 (diff)
rt: track loom changes + tweak queue (#2315)
Loom is having a big refresh to improve performance and tighten up the concurrency model. This diff tracks those changes. Included in the changes is the removal of `CausalCell` deferred checks. This is due to it technically being undefined behavior in the C++11 memory model. To address this, the work-stealing queue is updated to avoid needing this behavior. This is done by limiting the queue to have one concurrent stealer.
Diffstat (limited to 'tokio/src/loom/std')
-rw-r--r--tokio/src/loom/std/atomic_ptr.rs32
-rw-r--r--tokio/src/loom/std/atomic_u8.rs44
-rw-r--r--tokio/src/loom/std/atomic_usize.rs5
-rw-r--r--tokio/src/loom/std/causal_cell.rs40
-rw-r--r--tokio/src/loom/std/mod.rs13
-rw-r--r--tokio/src/loom/std/unsafe_cell.rs16
6 files changed, 104 insertions, 46 deletions
diff --git a/tokio/src/loom/std/atomic_ptr.rs b/tokio/src/loom/std/atomic_ptr.rs
new file mode 100644
index 00000000..eb8e4755
--- /dev/null
+++ b/tokio/src/loom/std/atomic_ptr.rs
@@ -0,0 +1,32 @@
+use std::fmt;
+use std::ops::Deref;
+
+/// `AtomicPtr` providing an additional `load_unsync` function.
+pub(crate) struct AtomicPtr<T> {
+ inner: std::sync::atomic::AtomicPtr<T>,
+}
+
+impl<T> AtomicPtr<T> {
+ pub(crate) fn new(ptr: *mut T) -> AtomicPtr<T> {
+ let inner = std::sync::atomic::AtomicPtr::new(ptr);
+ AtomicPtr { inner }
+ }
+
+ pub(crate) fn with_mut<R>(&mut self, f: impl FnOnce(&mut *mut T) -> R) -> R {
+ f(self.inner.get_mut())
+ }
+}
+
+impl<T> Deref for AtomicPtr<T> {
+ type Target = std::sync::atomic::AtomicPtr<T>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
+
+impl<T> fmt::Debug for AtomicPtr<T> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.deref().fmt(fmt)
+ }
+}
diff --git a/tokio/src/loom/std/atomic_u8.rs b/tokio/src/loom/std/atomic_u8.rs
new file mode 100644
index 00000000..9f394a79
--- /dev/null
+++ b/tokio/src/loom/std/atomic_u8.rs
@@ -0,0 +1,44 @@
+use std::cell::UnsafeCell;
+use std::fmt;
+use std::ops::Deref;
+
+/// `AtomicU8` providing an additional `load_unsync` function.
+pub(crate) struct AtomicU8 {
+ inner: UnsafeCell<std::sync::atomic::AtomicU8>,
+}
+
+unsafe impl Send for AtomicU8 {}
+unsafe impl Sync for AtomicU8 {}
+
+impl AtomicU8 {
+ pub(crate) fn new(val: u8) -> AtomicU8 {
+ let inner = UnsafeCell::new(std::sync::atomic::AtomicU8::new(val));
+ AtomicU8 { inner }
+ }
+
+ /// Performs an unsynchronized load.
+ ///
+ /// # Safety
+ ///
+ /// All mutations must have happened before the unsynchronized load.
+ /// Additionally, there must be no concurrent mutations.
+ pub(crate) unsafe fn unsync_load(&self) -> u8 {
+ *(*self.inner.get()).get_mut()
+ }
+}
+
+impl Deref for AtomicU8 {
+ type Target = std::sync::atomic::AtomicU8;
+
+ fn deref(&self) -> &Self::Target {
+ // safety: it is always safe to access `&self` fns on the inner value as
+ // we never perform unsafe mutations.
+ unsafe { &*self.inner.get() }
+ }
+}
+
+impl fmt::Debug for AtomicU8 {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.deref().fmt(fmt)
+ }
+}
diff --git a/tokio/src/loom/std/atomic_usize.rs b/tokio/src/loom/std/atomic_usize.rs
index 78644b05..0fe998f1 100644
--- a/tokio/src/loom/std/atomic_usize.rs
+++ b/tokio/src/loom/std/atomic_usize.rs
@@ -25,6 +25,11 @@ impl AtomicUsize {
pub(crate) unsafe fn unsync_load(&self) -> usize {
*(*self.inner.get()).get_mut()
}
+
+ pub(crate) fn with_mut<R>(&mut self, f: impl FnOnce(&mut usize) -> R) -> R {
+ // safety: we have mutable access
+ f(unsafe { (*self.inner.get()).get_mut() })
+ }
}
impl ops::Deref for AtomicUsize {
diff --git a/tokio/src/loom/std/causal_cell.rs b/tokio/src/loom/std/causal_cell.rs
deleted file mode 100644
index 8300437a..00000000
--- a/tokio/src/loom/std/causal_cell.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use std::cell::UnsafeCell;
-
-#[derive(Debug)]
-pub(crate) struct CausalCell<T>(UnsafeCell<T>);
-
-#[derive(Default)]
-pub(crate) struct CausalCheck(());
-
-impl<T> CausalCell<T> {
- pub(crate) fn new(data: T) -> CausalCell<T> {
- CausalCell(UnsafeCell::new(data))
- }
-
- pub(crate) fn with<F, R>(&self, f: F) -> R
- where
- F: FnOnce(*const T) -> R,
- {
- f(self.0.get())
- }
-
- pub(crate) fn with_deferred<F, R>(&self, f: F) -> (R, CausalCheck)
- where
- F: FnOnce(*const T) -> R,
- {
- (f(self.0.get()), CausalCheck::default())
- }
-
- pub(crate) fn with_mut<F, R>(&self, f: F) -> R
- where
- F: FnOnce(*mut T) -> R,
- {
- f(self.0.get())
- }
-}
-
-impl CausalCheck {
- pub(crate) fn check(self) {}
-
- pub(crate) fn join(&mut self, _other: CausalCheck) {}
-}
diff --git a/tokio/src/loom/std/mod.rs b/tokio/src/loom/std/mod.rs
index a56d778a..6d7bcee1 100644
--- a/tokio/src/loom/std/mod.rs
+++ b/tokio/src/loom/std/mod.rs
@@ -1,12 +1,13 @@
#![cfg_attr(any(not(feature = "full"), loom), allow(unused_imports, dead_code))]
-mod atomic_u32;
+mod atomic_ptr;
mod atomic_u64;
+mod atomic_u8;
mod atomic_usize;
-mod causal_cell;
+mod unsafe_cell;
pub(crate) mod cell {
- pub(crate) use super::causal_cell::{CausalCell, CausalCheck};
+ pub(crate) use super::unsafe_cell::UnsafeCell;
}
#[cfg(any(feature = "sync", feature = "io-driver"))]
@@ -58,12 +59,12 @@ pub(crate) mod sync {
pub(crate) use std::sync::{Condvar, Mutex, MutexGuard, WaitTimeoutResult};
pub(crate) mod atomic {
- pub(crate) use crate::loom::std::atomic_u32::AtomicU32;
+ pub(crate) use crate::loom::std::atomic_ptr::AtomicPtr;
pub(crate) use crate::loom::std::atomic_u64::AtomicU64;
+ pub(crate) use crate::loom::std::atomic_u8::AtomicU8;
pub(crate) use crate::loom::std::atomic_usize::AtomicUsize;
- pub(crate) use std::sync::atomic::AtomicU8;
- pub(crate) use std::sync::atomic::{fence, AtomicPtr};
+ pub(crate) use std::sync::atomic::AtomicU16;
pub(crate) use std::sync::atomic::{spin_loop_hint, AtomicBool};
}
}
diff --git a/tokio/src/loom/std/unsafe_cell.rs b/tokio/src/loom/std/unsafe_cell.rs
new file mode 100644
index 00000000..f2b03d8d
--- /dev/null
+++ b/tokio/src/loom/std/unsafe_cell.rs
@@ -0,0 +1,16 @@
+#[derive(Debug)]
+pub(crate) struct UnsafeCell<T>(std::cell::UnsafeCell<T>);
+
+impl<T> UnsafeCell<T> {
+ pub(crate) fn new(data: T) -> UnsafeCell<T> {
+ UnsafeCell(std::cell::UnsafeCell::new(data))
+ }
+
+ pub(crate) fn with<R>(&self, f: impl FnOnce(*const T) -> R) -> R {
+ f(self.0.get())
+ }
+
+ pub(crate) fn with_mut<R>(&self, f: impl FnOnce(*mut T) -> R) -> R {
+ f(self.0.get())
+ }
+}