Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions crossbeam-channel/tests/golang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1580,9 +1580,7 @@ mod race_chan_test {
}

// https://github.com/golang/go/blob/master/test/ken/chan.go
#[cfg(not(miri))] // Miri is too slow
mod chan {

use super::*;

const MESSAGES_PER_CHANEL: u32 = 76;
Expand Down Expand Up @@ -2052,6 +2050,7 @@ mod chan {
}

#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn main() {
let mut ctx = Context {
nproc: Arc::new(Mutex::new(0)),
Expand Down
1 change: 1 addition & 0 deletions crossbeam-channel/tests/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ fn len_empty_full() {
}

#[test]
#[cfg_attr(miri, ignore)] // this test makes timing assumptions, but Miri is so slow it violates them
fn try_recv() {
let (s, r) = unbounded();

Expand Down
1 change: 0 additions & 1 deletion crossbeam-channel/tests/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ fn both_ready() {
.unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn loop_try() {
const RUNS: usize = 20;
Expand Down
1 change: 0 additions & 1 deletion crossbeam-channel/tests/select_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ fn both_ready() {
.unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn loop_try() {
const RUNS: usize = 20;
Expand Down
6 changes: 4 additions & 2 deletions crossbeam-channel/tests/zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,11 @@ fn stress_oneshot() {
}
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn stress_iter() {
#[cfg(miri)]
const COUNT: usize = 50;
#[cfg(not(miri))]
const COUNT: usize = 1000;

let (request_s, request_r) = bounded(0);
Expand Down Expand Up @@ -485,7 +487,7 @@ fn fairness() {
#[test]
fn fairness_duplicates() {
#[cfg(miri)]
const COUNT: usize = 50;
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

Expand Down
5 changes: 2 additions & 3 deletions crossbeam-deque/src/deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::cmp;
use std::fmt;
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::mem::{self, ManuallyDrop, MaybeUninit};
use std::ptr;
use std::sync::atomic::{self, AtomicIsize, AtomicPtr, AtomicUsize, Ordering};
use std::sync::Arc;
Expand Down Expand Up @@ -38,9 +38,8 @@ impl<T> Buffer<T> {
fn alloc(cap: usize) -> Buffer<T> {
debug_assert_eq!(cap, cap.next_power_of_two());

let mut v = Vec::with_capacity(cap);
let mut v = ManuallyDrop::new(Vec::with_capacity(cap));
let ptr = v.as_mut_ptr();
mem::forget(v);

Buffer { ptr, cap }
}
Expand Down
24 changes: 24 additions & 0 deletions crossbeam-epoch/src/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ impl<T> Atomic<T> {
/// use crossbeam_epoch::Atomic;
///
/// let a = Atomic::new(1234);
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn new(init: T) -> Atomic<T> {
Self::init(init)
Expand All @@ -320,6 +321,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// use crossbeam_epoch::Atomic;
///
/// let a = Atomic::<i32>::init(1234);
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn init(init: T::Init) -> Atomic<T> {
Self::from(Owned::init(init))
Expand Down Expand Up @@ -373,6 +375,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// let a = Atomic::new(1234);
/// let guard = &epoch::pin();
/// let p = a.load(SeqCst, guard);
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn load<'g>(&self, ord: Ordering, _: &'g Guard) -> Shared<'g, T> {
unsafe { Shared::from_usize(self.data.load(ord)) }
Expand All @@ -398,6 +401,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// let a = Atomic::new(1234);
/// let guard = &epoch::pin();
/// let p = a.load_consume(guard);
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn load_consume<'g>(&self, _: &'g Guard) -> Shared<'g, T> {
unsafe { Shared::from_usize(self.data.load_consume()) }
Expand All @@ -415,8 +419,10 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// use std::sync::atomic::Ordering::SeqCst;
///
/// let a = Atomic::new(1234);
/// # unsafe { drop(a.load(SeqCst, &crossbeam_epoch::pin()).into_owned()); } // avoid leak
/// a.store(Shared::null(), SeqCst);
/// a.store(Owned::new(1234), SeqCst);
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn store<P: Pointer<T>>(&self, new: P, ord: Ordering) {
self.data.store(new.into_usize(), ord);
Expand All @@ -437,6 +443,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// let a = Atomic::new(1234);
/// let guard = &epoch::pin();
/// let p = a.swap(Shared::null(), SeqCst, guard);
/// # unsafe { drop(p.into_owned()); } // avoid leak
/// ```
pub fn swap<'g, P: Pointer<T>>(&self, new: P, ord: Ordering, _: &'g Guard) -> Shared<'g, T> {
unsafe { Shared::from_usize(self.data.swap(new.into_usize(), ord)) }
Expand Down Expand Up @@ -471,6 +478,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// let curr = a.load(SeqCst, guard);
/// let res1 = a.compare_exchange(curr, Shared::null(), SeqCst, SeqCst, guard);
/// let res2 = a.compare_exchange(curr, Owned::new(5678), SeqCst, SeqCst, guard);
/// # unsafe { drop(curr.into_owned()); } // avoid leak
/// ```
pub fn compare_exchange<'g, P>(
&self,
Expand Down Expand Up @@ -526,6 +534,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
///
/// let mut new = Owned::new(5678);
/// let mut ptr = a.load(SeqCst, guard);
/// # unsafe { drop(a.load(SeqCst, guard).into_owned()); } // avoid leak
/// loop {
/// match a.compare_exchange_weak(ptr, new, SeqCst, SeqCst, guard) {
/// Ok(p) => {
Expand All @@ -546,6 +555,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// Err(err) => curr = err.current,
/// }
/// }
/// # unsafe { drop(curr.into_owned()); } // avoid leak
/// ```
pub fn compare_exchange_weak<'g, P>(
&self,
Expand Down Expand Up @@ -608,6 +618,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
///
/// let res2 = a.fetch_update(SeqCst, SeqCst, guard, |x| None);
/// assert!(res2.is_err());
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn fetch_update<'g, F>(
&self,
Expand Down Expand Up @@ -666,6 +677,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// let curr = a.load(SeqCst, guard);
/// let res1 = a.compare_and_set(curr, Shared::null(), SeqCst, guard);
/// let res2 = a.compare_and_set(curr, Owned::new(5678), SeqCst, guard);
/// # unsafe { drop(curr.into_owned()); } // avoid leak
/// ```
// TODO: remove in the next major version.
#[allow(deprecated)]
Expand Down Expand Up @@ -723,6 +735,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
///
/// let mut new = Owned::new(5678);
/// let mut ptr = a.load(SeqCst, guard);
/// # unsafe { drop(a.load(SeqCst, guard).into_owned()); } // avoid leak
/// loop {
/// match a.compare_and_set_weak(ptr, new, SeqCst, guard) {
/// Ok(p) => {
Expand All @@ -743,6 +756,7 @@ impl<T: ?Sized + Pointable> Atomic<T> {
/// Err(err) => curr = err.current,
/// }
/// }
/// # unsafe { drop(curr.into_owned()); } // avoid leak
/// ```
// TODO: remove in the next major version.
#[allow(deprecated)]
Expand Down Expand Up @@ -925,6 +939,7 @@ impl<T: ?Sized + Pointable> From<Owned<T>> for Atomic<T> {
/// use crossbeam_epoch::{Atomic, Owned};
///
/// let a = Atomic::<i32>::from(Owned::new(1234));
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
fn from(owned: Owned<T>) -> Self {
let data = owned.data;
Expand Down Expand Up @@ -1108,6 +1123,7 @@ impl<T: ?Sized + Pointable> Owned<T> {
/// let o = Owned::new(1234);
/// let guard = &epoch::pin();
/// let p = o.into_shared(guard);
/// # unsafe { drop(p.into_owned()); } // avoid leak
/// ```
#[allow(clippy::needless_lifetimes)]
pub fn into_shared<'g>(self, _: &'g Guard) -> Shared<'g, T> {
Expand Down Expand Up @@ -1291,6 +1307,7 @@ impl<'g, T> Shared<'g, T> {
/// let guard = &epoch::pin();
/// let p = a.load(SeqCst, guard);
/// assert_eq!(p.as_raw(), raw);
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn as_raw(&self) -> *const T {
let (raw, _) = decompose_tag::<T>(self.data);
Expand Down Expand Up @@ -1329,6 +1346,7 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> {
/// assert!(a.load(SeqCst, guard).is_null());
/// a.store(Owned::new(1234), SeqCst);
/// assert!(!a.load(SeqCst, guard).is_null());
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn is_null(&self) -> bool {
let (raw, _) = decompose_tag::<T>(self.data);
Expand Down Expand Up @@ -1365,6 +1383,7 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> {
/// unsafe {
/// assert_eq!(p.deref(), &1234);
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub unsafe fn deref(&self) -> &'g T {
let (raw, _) = decompose_tag::<T>(self.data);
Expand Down Expand Up @@ -1406,6 +1425,7 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> {
/// unsafe {
/// assert_eq!(p.deref(), &vec![1, 2, 3, 4, 5]);
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub unsafe fn deref_mut(&mut self) -> &'g mut T {
let (raw, _) = decompose_tag::<T>(self.data);
Expand Down Expand Up @@ -1442,6 +1462,7 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> {
/// unsafe {
/// assert_eq!(p.as_ref(), Some(&1234));
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub unsafe fn as_ref(&self) -> Option<&'g T> {
let (raw, _) = decompose_tag::<T>(self.data);
Expand Down Expand Up @@ -1493,6 +1514,7 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> {
/// let guard = &epoch::pin();
/// let p = a.load(SeqCst, guard);
/// assert_eq!(p.tag(), 2);
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn tag(&self) -> usize {
let (_, tag) = decompose_tag::<T>(self.data);
Expand All @@ -1516,6 +1538,7 @@ impl<'g, T: ?Sized + Pointable> Shared<'g, T> {
/// assert_eq!(p1.tag(), 0);
/// assert_eq!(p2.tag(), 2);
/// assert_eq!(p1.as_raw(), p2.as_raw());
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn with_tag(&self, tag: usize) -> Shared<'g, T> {
unsafe { Self::from_usize(compose_tag::<T>(self.data, tag)) }
Expand All @@ -1536,6 +1559,7 @@ impl<T> From<*const T> for Shared<'_, T> {
///
/// let p = Shared::from(Box::into_raw(Box::new(1234)) as *const _);
/// assert!(!p.is_null());
/// # unsafe { drop(p.into_owned()); } // avoid leak
/// ```
fn from(raw: *const T) -> Self {
let raw = raw as usize;
Expand Down
6 changes: 2 additions & 4 deletions crossbeam-epoch/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl fmt::Debug for LocalHandle {

#[cfg(all(test, not(crossbeam_loom)))]
mod tests {
use std::mem;
use std::mem::ManuallyDrop;
use std::sync::atomic::{AtomicUsize, Ordering};

use crossbeam_utils::thread;
Expand Down Expand Up @@ -402,15 +402,13 @@ mod tests {
v.push(i as i32);
}

let ptr = v.as_mut_ptr() as usize;
let len = v.len();
let ptr = ManuallyDrop::new(v).as_mut_ptr() as usize;
guard.defer_unchecked(move || {
drop(Vec::from_raw_parts(ptr as *const i32 as *mut i32, len, len));
DESTROYS.fetch_add(len, Ordering::Relaxed);
});
guard.flush();

mem::forget(v);
}

while DESTROYS.load(Ordering::Relaxed) < COUNT {
Expand Down
6 changes: 6 additions & 0 deletions crossbeam-epoch/src/guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use crate::internal::Local;
/// if let Some(num) = unsafe { p.as_ref() } {
/// println!("The number is {}.", num);
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
///
/// # Multiple guards
Expand Down Expand Up @@ -184,6 +185,7 @@ impl Guard {
/// });
/// }
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub unsafe fn defer_unchecked<F, R>(&self, f: F)
where
Expand Down Expand Up @@ -263,6 +265,7 @@ impl Guard {
/// guard.defer_destroy(p);
/// }
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub unsafe fn defer_destroy<T>(&self, ptr: Shared<'_, T>) {
self.defer_unchecked(move || ptr.into_owned());
Expand Down Expand Up @@ -320,6 +323,7 @@ impl Guard {
/// let p = a.load(SeqCst, &guard);
/// assert_eq!(unsafe { p.as_ref() }, Some(&777));
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn repin(&mut self) {
if let Some(local) = unsafe { self.local.as_ref() } {
Expand Down Expand Up @@ -356,6 +360,7 @@ impl Guard {
/// let p = a.load(SeqCst, &guard);
/// assert_eq!(unsafe { p.as_ref() }, Some(&777));
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
pub fn repin_after<F, R>(&mut self, f: F) -> R
where
Expand Down Expand Up @@ -451,6 +456,7 @@ impl fmt::Debug for Guard {
///
/// // Dropping `dummy` doesn't affect the current thread - it's just a noop.
/// }
/// # unsafe { drop(a.into_owned()); } // avoid leak
/// ```
///
/// The most common use of this function is when constructing or destructing a data structure.
Expand Down
8 changes: 6 additions & 2 deletions crossbeam-queue/tests/array_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,11 @@ fn spsc_ring_buffer() {
}
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn mpmc() {
#[cfg(miri)]
const COUNT: usize = 50;
#[cfg(not(miri))]
const COUNT: usize = 25_000;
const THREADS: usize = 4;

Expand Down Expand Up @@ -230,9 +232,11 @@ fn mpmc() {
}
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn mpmc_ring_buffer() {
#[cfg(miri)]
const COUNT: usize = 50;
#[cfg(not(miri))]
const COUNT: usize = 25_000;
const THREADS: usize = 4;

Expand Down
4 changes: 3 additions & 1 deletion crossbeam-queue/tests/seg_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@ fn spsc() {
.unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn mpmc() {
#[cfg(miri)]
const COUNT: usize = 50;
#[cfg(not(miri))]
const COUNT: usize = 25_000;
const THREADS: usize = 4;

Expand Down
5 changes: 3 additions & 2 deletions crossbeam-utils/src/atomic/atomic_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,10 +1009,11 @@ where
// discard the data when a data race is detected. The proper solution would be to
// do atomic reads and atomic writes, but we can't atomically read and write all
// kinds of data since `AtomicU8` is not available on stable Rust yet.
let val = ptr::read_volatile(src);
// Load as `MaybeUninit` because we may load a value that is not valid as `T`.
let val = ptr::read_volatile(src as *mut MaybeUninit<T>);

if lock.validate_read(stamp) {
return val;
return val.assume_init();
}
}

Expand Down
Loading