Skip to content

Commit

Permalink
feat(miri): activate more miri tests
Browse files Browse the repository at this point in the history
  • Loading branch information
wvwwvwwv committed Jul 25, 2024
1 parent 176b0d9 commit 7417063
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 233 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/sdd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
- name: Loom
run: cargo test --features loom --release --lib
- name: Miri
run: cargo +nightly miri test --lib --bins --tests
run: MIRIFLAGS="-Zmiri-disable-data-race-detector" cargo +nightly miri test --lib --bins --tests
benchmark:
runs-on: ubuntu-latest
timeout-minutes: 15
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

2.0.0

* `{Owned, Shared}::release` no longer receives a `Guard`.

1.7.0

* Add `loom` support.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "sdd"
description = "Scalable lock-free delayed memory reclaimer"
documentation = "https://docs.rs/sdd"
version = "1.7.0"
version = "2.0.0"
authors = ["wvwwvwwv <[email protected]>"]
edition = "2021"
rust-version = "1.65.0"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,6 @@ suspend();

## Performance

The average time taken to enter and exit a protected region: 1.9 nanoseconds on Apple M2 Max.
The average time taken to enter and exit a protected region: 2.4 nanoseconds on Apple M2 Max.

## [Changelog](https://github.com/wvwwvwwv/scalable-delayed-dealloc/blob/main/CHANGELOG.md)
79 changes: 68 additions & 11 deletions src/collectible.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
use std::ptr::NonNull;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;

/// [`Collectible`] defines the memory layout for the type in order to be passed to the garbage
/// collector.
///
/// # Examples
///
/// ```
/// use sdd::{Collectible, Guard};
/// use sdd::{Collectible, Guard, Link};
/// use std::ptr::NonNull;
///
/// struct LazyString(String, Option<NonNull<dyn Collectible>>);
/// struct LazyString(String, Link);
///
/// impl Collectible for LazyString {
/// fn next_ptr_mut(&mut self) -> &mut Option<NonNull<dyn Collectible>> {
/// &mut self.1
/// fn next_ptr(&self) -> Option<NonNull<dyn Collectible>> {
/// self.1.next_ptr()
/// }
/// fn set_next_ptr(&self, next_ptr: Option<NonNull<dyn Collectible>>) {
/// self.1.set_next_ptr(next_ptr);
/// }
/// }
///
/// let boxed: Box<LazyString> = Box::new(LazyString(String::from("Lazy"), None));
/// let boxed: Box<LazyString> = Box::new(LazyString(String::from("Lazy"), Link::default()));
///
/// let static_ref: &'static LazyString = unsafe { std::mem::transmute(&*boxed) };
/// let guard_for_ref = Guard::new();
Expand All @@ -31,15 +36,62 @@ use std::ptr::NonNull;
/// assert_eq!(static_ref.0, "Lazy");
/// ```
pub trait Collectible {
/// Returns a mutable reference to the next [`Collectible`] pointer.
fn next_ptr_mut(&mut self) -> &mut Option<NonNull<dyn Collectible>>;
/// Returns the next [`Collectible`] pointer.
fn next_ptr(&self) -> Option<NonNull<dyn Collectible>>;

/// Sets the next [`Collectible`] pointer.
fn set_next_ptr(&self, next_ptr: Option<NonNull<dyn Collectible>>);
}

/// [`Link`] implements [`Collectible`].
#[derive(Debug, Default)]
pub struct Link {
data: [AtomicUsize; 2],
}

/// [`DeferredClosure`] implements [`Collectible`] for a closure to execute it after all the
/// current readers in the process are gone.
pub(super) struct DeferredClosure<F: 'static + FnOnce()> {
f: Option<F>,
link: Option<NonNull<dyn Collectible>>,
link: Link,
}

impl Link {
#[inline]
pub(super) const fn new_shared() -> Self {
Link {
data: [AtomicUsize::new(1), AtomicUsize::new(0)],
}
}

#[inline]
pub(super) const fn new_unique() -> Self {
Link {
data: [AtomicUsize::new(0), AtomicUsize::new(0)],
}
}

#[inline]
pub(super) const fn ref_cnt(&self) -> &AtomicUsize {
&self.data[0]
}
}

impl Collectible for Link {
#[inline]
fn next_ptr(&self) -> Option<NonNull<dyn Collectible>> {
let fat_ptr: [usize; 2] = [self.data[0].load(Relaxed), self.data[1].load(Relaxed)];
unsafe { std::mem::transmute(fat_ptr) }
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[inline]
fn set_next_ptr(&self, next_ptr: Option<NonNull<dyn Collectible>>) {
let data: [usize; 2] =
next_ptr.map_or_else(|| [0, 0], |p| unsafe { std::mem::transmute(p) });
self.data[0].store(data[0], Relaxed);
self.data[1].store(data[1], Relaxed);
}
}

impl<F: 'static + FnOnce()> DeferredClosure<F> {
Expand All @@ -48,15 +100,20 @@ impl<F: 'static + FnOnce()> DeferredClosure<F> {
pub fn new(f: F) -> Self {
DeferredClosure {
f: Some(f),
link: None,
link: Link::default(),
}
}
}

impl<F: 'static + FnOnce()> Collectible for DeferredClosure<F> {
#[inline]
fn next_ptr_mut(&mut self) -> &mut Option<NonNull<dyn Collectible>> {
&mut self.link
fn next_ptr(&self) -> Option<NonNull<dyn Collectible>> {
self.link.next_ptr()
}

#[inline]
fn set_next_ptr(&self, next_ptr: Option<NonNull<dyn Collectible>>) {
self.link.set_next_ptr(next_ptr);
}
}

Expand Down
Loading

0 comments on commit 7417063

Please sign in to comment.