Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 5 additions & 1 deletion Cargo.lock

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

19 changes: 18 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ repository = "https://github.com/githedgehog/dataplane/"
#
# 1. correctly documenting what each package actually depends on,
# 2. allowing builds under different environments (e.g. cross-compilation, wasm, miri, and so on).
#
# Exceptions: see `tokio = { ..., features = ["parking_lot"] }` below. Each exception has a comment
# justifying why it is workspace-wide.

# Internal
args = { path = "./args", package = "dataplane-args", features = [] }
Expand Down Expand Up @@ -110,6 +113,7 @@ chrono = { version = "0.4.44", default-features = false, features = [] }
clap = { version = "4.6.1", default-features = true, features = [] }
color-eyre = { version = "0.6.5", default-features = false, features = [] }
colored = { version = "3.1.1", default-features = false, features = [] }
crossbeam-utils = { version = "0.8.21", default-features = false, features = [] }
ctrlc = { version = "3.5.2", default-features = false, features = [] }
dashmap = { version = "6.2.1", default-features = false, features = [] }
derive_builder = { version = "0.20.2", default-features = false, features = [] }
Expand Down Expand Up @@ -158,6 +162,7 @@ pci-ids = { version = "0.2.6", default-features = false, features = [] }
prefix-trie = { version = "0.9.2", default-features = false, features = [] }
pretty_assertions = { version = "1.4.1", default-features = false, features = [] }
priority-queue = { version = "2.7.0", default-features = false, features = [] }
proc-macro-crate = { version = "3.5.0", default-features = false, features = [] }
proc-macro2 = { version = "1.0.106", default-features = false, features = [] }
procfs = { version = "0.18.0", default-features = false, features = [] }
pyroscope = { version = "2.0.3", default-features = false, features = [] }
Expand All @@ -183,7 +188,13 @@ strum_macros = { version = "0.28.0", default-features = false, features = [] }
syn = { version = "2.0.117", default-features = false, features = [] }
thiserror = { version = "2.0.18", default-features = false, features = [] }
thread_local = { version = "1.1.9", default-features = false, features = [] }
tokio = { version = "1.52.3", default-features = false, features = [] }
# Exception to the "no workspace-wide features" rule above. `tokio/parking_lot` is
# not an additive feature in the usual sense -- it picks the lock implementation
# tokio uses internally for its runtime. Production builds already pull
# parking_lot in via `concurrency::sync`, so the only thing scoping this
# per-crate would buy is divergent runtime behaviour between test binaries
# and the real dataplane. Keep it global.
tokio = { version = "1.52.3", default-features = false, features = ["parking_lot"] }
tokio-util = { version = "0.7.18", default-features = false, features = [] }
tonic = { version = "0.14.6", default-features = false, features = [] }
tracing = { version = "0.1.44", default-features = false, features = [] }
Expand Down Expand Up @@ -247,6 +258,12 @@ package = "dataplane-cli"
miri = true
wasm = false # split

[workspace.metadata.package.concurrency]
package = "dataplane-concurrency"
miri = true # must ALWAYS work
# NOTE: concurrency should likely be dependency gated as `cfg(unix)` or `cfg(not(target_arch = "wasm32"))`
wasm = false # hopeless + pointless

[workspace.metadata.package.dataplane]
package = "dataplane"
miri = false # hopeless + pointless
Expand Down
3 changes: 2 additions & 1 deletion common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ publish.workspace = true
repository.workspace = true

[dependencies]
left-right = { workspace = true }
arc-swap = { workspace = true }
concurrency = { workspace = true }
left-right = { workspace = true }
31 changes: 29 additions & 2 deletions common/src/cliprovider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
//! A trait for a type that can provide CLI data

use arc_swap::{ArcSwap, ArcSwapOption};
use concurrency::slot::{Slot, SlotOption};
use concurrency::sync::Arc;
use left_right::ReadHandle;
use std::fmt::Display;
use std::sync::Arc;

/// A trait for types that can produce contents for the cli
pub trait CliDataProvider {
Expand Down Expand Up @@ -72,9 +73,35 @@ where
T: CliDataProvider,
{
fn provide(&self) -> String {
// No type annotation on `p`: `arc_swap::ArcSwapOption` always
// yields `std::sync::Arc<T>`, which is not the same type as
// `concurrency::sync::Arc<T>` under the `loom` backend.
// Letting inference do its job keeps this `impl` compiling on
// every backend.
self.load()
.as_ref()
.map(|p: &Arc<T>| p.provide())
.map(|p| p.provide())
.unwrap_or_else(|| "(none)".to_string())
}
}

impl<T> CliDataProvider for Slot<T>
where
T: CliDataProvider,
{
fn provide(&self) -> String {
self.load_full().provide()
}
}

impl<T> CliDataProvider for SlotOption<T>
where
T: CliDataProvider,
{
fn provide(&self) -> String {
self.load_full()
.as_ref()
.map(|p| p.provide())
.unwrap_or_else(|| "(none)".to_string())
}
}
Expand Down
19 changes: 19 additions & 0 deletions concurrency/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,26 @@ publish.workspace = true
version.workspace = true

[features]
default = ["parking_lot"]
loom = ["dep:loom", "concurrency-macros/loom"]
parking_lot = ["dep:parking_lot"]
# `shuttle*` are three views of one backend, not three backends:
#
# * `shuttle` -- shuttle with the random scheduler (the default
# for first-time users -- you almost always want
# this one).
# * `shuttle_pct` -- shuttle with the PCT scheduler. Use when you
# want to bias toward rare interleavings.
# * `shuttle_dfs` -- shuttle with the DFS scheduler. Use for
# exhaustive small-state exploration.
#
# Arranged as a chain (`shuttle_dfs` -> `shuttle_pct` -> `shuttle`)
# so a single `feature = "shuttle"` cfg check is true under every
# variant. The scheduler is selected at runtime by
# `concurrency::stress` (added in a later PR of this stack).
shuttle = ["dep:shuttle", "concurrency-macros/shuttle"]
shuttle_pct = ["shuttle"]
shuttle_dfs = ["shuttle_pct"]
silence_clippy = ["concurrency-macros/silence_clippy"] # Do not manually enable this feature, let --all-features do it for you
# Force the Mutex-based slot fallback even without a model checker.
# Intended for the CI miri job that exercises the fallback slot under
Expand All @@ -20,6 +38,7 @@ _strict_provenance = []
arc-swap = { workspace = true }
concurrency-macros = { workspace = true, features = [] }
loom = { workspace = true, optional = true, features = [] }
parking_lot = { workspace = true, optional = true, features = [] }
shuttle = { workspace = true, optional = true, features = [] }
static_assertions = { workspace = true }

Expand Down
21 changes: 1 addition & 20 deletions concurrency/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,21 @@
#![allow(missing_docs)]

pub mod macros;
pub mod sync;

#[cfg(all(miri, any(feature = "shuttle", feature = "loom")))]
compile_error!("miri does not meaningfully support 'loom' or 'shuttle'");

#[cfg(not(any(feature = "loom", feature = "shuttle")))]
pub use std::sync;

#[cfg(not(any(feature = "loom", feature = "shuttle")))]
pub use std::thread;

#[cfg(all(
feature = "loom",
not(feature = "shuttle"),
not(feature = "silence_clippy")
))]
pub use loom::sync;

#[cfg(all(
feature = "loom",
not(feature = "shuttle"),
not(feature = "silence_clippy")
))]
pub use loom::thread;

#[cfg(all(
feature = "shuttle",
not(feature = "loom"),
not(feature = "silence_clippy")
))]
pub use shuttle::sync;

#[cfg(all(
feature = "shuttle",
not(feature = "loom"),
Expand All @@ -57,9 +41,6 @@ compile_error!("Cannot enable both 'loom' and 'shuttle' features at the same tim
//////////////////////
// This is a workaround to silence clippy warnings when both loom and shuttle
// features are enabled in the clippy checks which uses --all-features.
#[cfg(all(feature = "shuttle", feature = "loom", feature = "silence_clippy"))]
pub use std::sync;

#[cfg(all(feature = "shuttle", feature = "loom", feature = "silence_clippy"))]
pub use std::thread;
//////////////////////
Expand Down
10 changes: 3 additions & 7 deletions concurrency/src/quiescent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,13 @@ impl Domain {

fn register(&self) -> Epoch {
let epoch = Epoch::new();
#[allow(clippy::expect_used)] // the mutex is poisoned only in unrecoverable error cases
self.active
.lock()
.expect("qsbr mutex poisoned")
.push(Arc::clone(&epoch.cell));
let mut guard = self.active.lock();
guard.push(Arc::clone(&epoch.cell));
epoch
}

fn min_observed(&self) -> Option<Version> {
#[allow(clippy::expect_used)] // the mutex is poisoned only in unrecoverable error cases
let mut active = self.active.lock().expect("qsbr mutex poisoned");
let mut active = self.active.lock();
let mut min = u64::MAX;
let mut any_in_flight = false;
active.retain(|cell| {
Expand Down
Loading
Loading