Skip to content
Closed
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
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
26 changes: 19 additions & 7 deletions concurrency/src/quiescent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,29 @@ 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 guard = self.active.lock();
// Loom and shuttle still expose `LockResult<MutexGuard>`; PRs
// extending the poison-as-panic wrapper to those backends will
// drop this `.expect` (the default backend already returns a
// naked guard).
#[cfg(any(feature = "loom", feature = "shuttle"))]
#[allow(clippy::expect_used)]
// the mutex is poisoned only in unrecoverable error cases
let mut guard = guard.expect("qsbr mutex poisoned");
#[cfg(not(any(feature = "loom", feature = "shuttle")))]
let mut guard = guard;
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 guard = self.active.lock();
#[cfg(any(feature = "loom", feature = "shuttle"))]
#[allow(clippy::expect_used)]
// the mutex is poisoned only in unrecoverable error cases
let mut active = guard.expect("qsbr mutex poisoned");
#[cfg(not(any(feature = "loom", feature = "shuttle")))]
let mut active = guard;
let mut min = u64::MAX;
let mut any_in_flight = false;
active.retain(|cell| {
Expand Down
45 changes: 45 additions & 0 deletions concurrency/src/sync/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Open Network Fabric Authors

//! Backend-routed synchronization primitives.
//!
//! Exposes a `parking_lot`-shaped surface for `Mutex` / `RwLock` that
//! compiles unchanged across backends. The default (non-model-checker)
//! backend currently routes through `std_backend` -- a thin
//! poison-as-panic wrapper around `std::sync::{Mutex, RwLock}` that
//! exposes naked guards (no `LockResult` to `.unwrap()` at call
//! sites). This workspace treats a crashed thread as a crashed
//! process, so silently inheriting state from a poisoned lock is
//! wrong; surfacing it as a panic propagates the failure correctly.
//!
//! Loom and shuttle still re-export their raw `LockResult`-based
//! primitives at this point in the stack; subsequent PRs add the same
//! poison-as-panic wrap for those backends.

#[cfg(not(any(feature = "loom", feature = "shuttle")))]
mod std_backend;
#[cfg(not(any(feature = "loom", feature = "shuttle")))]
pub use std_backend::*;

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

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

// Match the silence_clippy escape hatch in lib.rs: when both loom and
// shuttle are pulled in (under `--all-features`), route sync through
// `std` purely to keep clippy happy. The binary is never executed in
// that configuration.
#[cfg(all(feature = "shuttle", feature = "loom", feature = "silence_clippy"))]
mod std_backend;
#[cfg(all(feature = "shuttle", feature = "loom", feature = "silence_clippy"))]
pub use std_backend::*;
Loading
Loading