Skip to content
Open
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ _fmt := if env_var_or_default("GITHUB_ACTIONS", "") != "true" { "" } else {
```
}

_loom_max_preemptions := env_var_or_default("LOOM_MAX_PREEMPTIONS", "2")
_loom_max_branches := env_var_or_default("LOOM_MAX_BRANCHES", "10000")

# default recipe to display help information
default:
@echo "justfile for Mycelium"
Expand Down Expand Up @@ -110,6 +113,7 @@ loom crate='' *args='': _get-nextest

export RUSTFLAGS="--cfg loom ${RUSTFLAGS:-}"
export LOOM_MAX_PREEMPTIONS="${LOOM_MAX_PREEMPTIONS:-2}"
export LOOM_MAX_BRANCHES="${LOOM_MAX_BRANCHES:-10000}"
export LOOM_LOG="${LOOM_LOG:-mycelium=trace,maitake=trace,cordyceps=trace,debug}"

# if logging is enabled, also enable location tracking.
Expand All @@ -120,7 +124,7 @@ loom crate='' *args='': _get-nextest
status "Disabled" "logging and location tracking"
fi

status "Configured" "loom, LOOM_MAX_PREEMPTIONS=${LOOM_MAX_PREEMPTIONS}"
status "Configured" "loom, LOOM_MAX_PREEMPTIONS=${LOOM_MAX_PREEMPTIONS}, LOOM_MAX_BRANCHES=${LOOM_MAX_BRANCHES}"

if [[ "${LOOM_CHECKPOINT_FILE:-}" ]]; then
export LOOM_CHECKPOINT_FILE="${LOOM_CHECKPOINT_FILE:-}"
Expand Down
7 changes: 6 additions & 1 deletion util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ mycelium-bitfield = { path = "../bitfield", default-features = false }

[dev-dependencies]
proptest = "1"
tracing-subscriber = { git = "https://github.com/tokio-rs/tracing" }
tracing-subscriber = { git = "https://github.com/tokio-rs/tracing", features = ["fmt", "env-filter"] }
tracing = { git = "https://github.com/tokio-rs/tracing", default_features = false, features = ["attributes", "std"] }

[target.'cfg(loom)'.dependencies]
loom = "0.5.5"

[target.'cfg(loom)'.dev-dependencies]
tracing_01 = { package = "tracing", version = "0.1.36" }
tracing-subscriber_03 = { package = "tracing-subscriber", version = "0.3.15", features = ["fmt", "env-filter"] }


[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
17 changes: 17 additions & 0 deletions util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,20 @@ pub(crate) mod loom;
pub use self::macros::*;
pub use cordyceps as intrusive;
pub use mycelium_bitfield as bits;

#[cfg(test)]
pub(crate) mod test_util {
#[cfg(not(loom))]
pub(crate) fn trace_init() -> impl Drop {
use tracing_subscriber::{EnvFilter, prelude::*};
let filter = EnvFilter::from_env("LOOM_LOG");
tracing_subscriber::fmt().with_test_writer().without_time().with_env_filter(filter).set_default()
}

#[cfg(loom)]
pub(crate) fn trace_init() -> impl Drop {
use tracing_subscriber_03::{EnvFilter, prelude::*};
let filter = EnvFilter::from_env("LOOM_LOG");
tracing_subscriber_03::fmt().with_test_writer().without_time().with_env_filter(filter).set_default()
}
}
36 changes: 36 additions & 0 deletions util/src/loom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,42 @@ mod inner {
mod inner {
#![allow(dead_code)]

#[cfg(test)]
pub(crate) use std::thread;

#[cfg(test)]
pub(crate) fn model(f: impl Fn()) {
f()
}


#[cfg(test)]
pub(crate) mod model {
#[non_exhaustive]
#[derive(Default)]
pub(crate) struct Builder {
pub(crate) max_threads: usize,
pub(crate) max_branches: usize,
pub(crate) max_permutations: Option<usize>,
// pub(crate) max_duration: Option<Duration>,
pub(crate) preemption_bound: Option<usize>,
// pub(crate) checkpoint_file: Option<PathBuf>,
pub(crate) checkpoint_interval: usize,
pub(crate) location: bool,
pub(crate) log: bool,
}

impl Builder {
pub(crate) fn new() -> Self {
Self::default()
}

pub(crate) fn check(&self, f: impl Fn()) {
super::model(f)
}
}
}

pub(crate) mod alloc {
/// Track allocations, detecting leaks
#[derive(Debug, Default)]
Expand Down
31 changes: 31 additions & 0 deletions util/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,34 @@ macro_rules! unreachable_unchecked {
}
});
}

#[cfg(all(test, not(loom)))]
macro_rules! test_dbg {
($x:expr) => {
match $x {
x => {
tracing::debug!("{} = {x:?}", stringify!($x));
x
}
}
};
}

#[cfg(all(test, loom))]
macro_rules! test_dbg {
($x:expr) => {
match $x {
x => {
tracing_01::debug!("{} = {x:?}", stringify!($x));
x
}
}
};
}

#[cfg(not(test))]
macro_rules! test_dbg {
($x:expr) => {
$x
};
}
2 changes: 2 additions & 0 deletions util/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub use core::sync::atomic;
pub mod cell;
pub mod once;
pub mod spin;
pub mod tearable;

#[doc(inline)]
pub use self::once::{InitOnce, Lazy};

Expand Down
10 changes: 10 additions & 0 deletions util/src/sync/spin/backoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,20 @@ impl Backoff {
#[inline(always)]
pub fn spin(&mut self) {
// Issue 2^exp pause instructions.
#[cfg(not(loom))]
for _ in 0..(1 << self.exp) {
hint::spin_loop();
}

#[cfg(loom)]
{
// when `loom` is in use, we only issue the hint once, because
// otherwise, loom will do a bunch of meaningless thread switches.
// Issue 2^exp pause instructions.
test_dbg!(1 << self.exp);
hint::spin_loop();
}

if self.exp < self.max {
self.exp += 1
}
Expand Down
4 changes: 2 additions & 2 deletions util/src/sync/spin/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ impl<'a, T: fmt::Display> fmt::Display for MutexGuard<'a, T> {
}
}

#[cfg(all(test, loom))]
#[cfg(test)]
mod tests {
use loom::thread;
use crate::loom::{self, thread};
use std::prelude::v1::*;
use std::sync::Arc;

Expand Down
Loading