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
72 changes: 45 additions & 27 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ jobs:
profile: "debug"
sanitize: ""
instrument: "none"
- &release-build
name: "release"
- name: "release"
profile: "release"
sanitize: "" # TODO: enable cfi and safe-stack when possible
instrument: "none"
Expand Down Expand Up @@ -502,45 +501,64 @@ jobs:
recipe_args: "${{ matrix.recipe.args }}"
- *tmate

features:
concurrency:
if: >-
${{
needs.check_changes.outputs.devfiles == 'true'
|| startsWith(github.event.ref, 'refs/tags/v')
|| github.event_name == 'workflow_dispatch'
}}
name: "features/${{ matrix.build.name }}/${{ matrix.features }}"
name: "concurrency"
runs-on: "lab"
needs:
- check_changes
- check
permissions: *check-perms
env: *check-env
strategy:
fail-fast: false
max-parallel: 1
matrix:
include:
# The `loom` feature flips `concurrency::sync` to loom's
# primitives workspace-wide, which breaks crates that rely on
# `Weak`, `Arc::downgrade`, etc. (those aren't in
# `loom::sync`). Scope the loom build to only the concurrency
# package (which hosts the quiescent tests) so workspace
# feature unification doesn't poison unrelated crates.
- build: *release-build
features: "loom"
test_package: "concurrency"
- build: *release-build
features: "shuttle"
test_package: ""
steps:
- *checkout
- *nix-setup
- name: "test/${{ matrix.features }}"
- name: "shuttle"
env:
JUST_VARS: >-
profile=release
features=shuttle
uses: *just
with:
recipe: "test"
- name: "shuttle_pct"
env:
JUST_VARS: >-
profile=release
features=shuttle_pct
uses: *just
with:
recipe: "test"
- name: "shuttle_dfs"
env:
JUST_VARS: >-
profile=release
features=shuttle_dfs
uses: *just
with:
recipe: "test"
# The `loom` feature flips `concurrency::sync` to loom's
# primitives workspace-wide, which breaks crates that rely on
# `Weak`, `Arc::downgrade`, etc. (those aren't in
# `loom::sync`). Scope the loom build to only the concurrency
# package (which hosts the core concurrency tests) so workspace
# feature unification doesn't poison unrelated crates.
#
# TODO: gate tests which can't be used with loom
- name: "loom"
env:
JUST_VARS: >-
profile=release
features=loom
uses: *just
with:
recipe: "test"
recipe_args: "${{ matrix.test_package }}"
recipe_args: "concurrency"
- *tmate

vlab:
Expand Down Expand Up @@ -633,7 +651,7 @@ jobs:
needs:
- check
- sanitize
- features
- concurrency
- build
- vlab
- test_each
Expand All @@ -653,10 +671,10 @@ jobs:
run: |
echo '::error:: Some check job(s) failed'
exit 1
- name: "Flag any features matrix failures"
if: ${{ needs.features.result != 'success' && needs.features.result != 'skipped' }}
- name: "Flag any concurrency job failures"
if: ${{ needs.concurrency.result != 'success' && needs.concurrency.result != 'skipped' }}
run: |
echo '::error:: Some features job(s) failed'
echo '::error:: concurrency job failed'
exit 1
- name: "Flag any test_each matrix failures"
if: ${{ needs.test_each.result != 'success' && needs.test_each.result != 'skipped' }}
Expand Down
63 changes: 58 additions & 5 deletions 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.1.0", 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.8.4", 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
Loading
Loading