tokio-rs/loom
Concurrency permutation testing tool for Rust.
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 3mo ago
- ✓39+ active contributors
- ✓Distributed ownership (top contributor 25% of recent commits)
Show all 6 evidence items →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/tokio-rs/loom)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/tokio-rs/loom on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: tokio-rs/loom
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/tokio-rs/loom shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 3mo ago
- 39+ active contributors
- Distributed ownership (top contributor 25% of recent commits)
- MIT licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live tokio-rs/loom
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/tokio-rs/loom.
What it runs against: a local clone of tokio-rs/loom — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in tokio-rs/loom | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 106 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of tokio-rs/loom. If you don't
# have one yet, run these first:
#
# git clone https://github.com/tokio-rs/loom.git
# cd loom
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of tokio-rs/loom and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "tokio-rs/loom(\\.git)?\\b" \\
&& ok "origin remote is tokio-rs/loom" \\
|| miss "origin remote is not tokio-rs/loom (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/lib.rs" \\
&& ok "src/lib.rs" \\
|| miss "missing critical file: src/lib.rs"
test -f "src/rt/scheduler.rs" \\
&& ok "src/rt/scheduler.rs" \\
|| miss "missing critical file: src/rt/scheduler.rs"
test -f "src/rt/execution.rs" \\
&& ok "src/rt/execution.rs" \\
|| miss "missing critical file: src/rt/execution.rs"
test -f "src/sync/atomic/mod.rs" \\
&& ok "src/sync/atomic/mod.rs" \\
|| miss "missing critical file: src/sync/atomic/mod.rs"
test -f "src/rt/mod.rs" \\
&& ok "src/rt/mod.rs" \\
|| miss "missing critical file: src/rt/mod.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 106 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~76d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/tokio-rs/loom"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Loom is a permutation testing tool that systematically executes Rust concurrent code under different thread interleavings to detect data races and synchronization bugs. It implements the C11 memory model with state reduction techniques (inspired by CDSChecker) to explore concurrency bugs without combinatorial explosion, running the same test code many times with different thread scheduling permutations. Single-crate Rust library organized into three logical layers: public API surface (src/sync/, src/cell/, src/future/ with Arc, Mutex, AtomicUsize, etc.), conditional compilation via cfg(loom) to swap in test-time implementations, and core permutation engine (src/rt/ with scheduler.rs, execution.rs, object.rs handling thread state and synchronization). The src/model.rs entry point wraps the permutation loop; feature flags control checkpoint serialization (serde integration).
👥Who it's for
Rust library and systems developers building concurrent code (lock-free data structures, async systems, tokio-based libraries) who need to validate their synchronization logic against the C11 memory model without manually reasoning through all possible thread interleavings.
🌱Maturity & risk
Actively maintained and production-ready for most use cases. The project has a structured CI pipeline (.github/workflows/ci.yml, release.yml), comprehensive module organization (src/rt/, src/sync/), and clear versioning (currently 0.7.2). However, the README explicitly documents known limitations (SeqCst accesses treated as AcqRel causing false alarms, missing load buffering exploration), indicating this is a specialized tool with known incomplete coverage rather than a fully mature general-purpose testing framework.
Low dependency risk—only 6 runtime dependencies (cfg-if, scoped-tls, generator, serde/serde_json optional, tracing/tracing-subscriber), all from stable crates.io projects. The single-maintainer risk is present (Carl Lerche listed as primary author), but the tokio-rs organization backing and CI automation mitigate this. Main risk is semantic: the tool can produce false positives (incomplete) and false negatives (unsound), so passing Loom tests doesn't guarantee correctness in production—this is not a substitute for formal verification.
Active areas of work
The repo shows active maintenance: version 0.7.2 with recent Cargo.toml and CI workflows in place. No specific new features are visible in the file list, suggesting steady-state maintenance mode focusing on bug fixes and compatibility (Rust 1.73 MSRV). The checkpoint feature flag and tracing integration suggest ongoing work on observability and state serialization for complex test scenarios.
🚀Get running
git clone https://github.com/tokio-rs/loom.git
cd loom
cargo test --release
For testing concurrent code with loom in your own project, add to Cargo.toml: [target.'cfg(loom)'.dependencies]\nloom = "0.7" and run tests with RUSTFLAGS="--cfg loom" cargo test --release.
Daily commands:
Loom is a testing library, not a runtime. To run the built-in tests: cargo test --release. To run loom tests in another crate: RUSTFLAGS="--cfg loom" cargo test --test <test_name> --release. The #[test] macro combined with loom::model(|| { ... }) closure is the entry point; Loom's scheduler will execute the closure body under many thread interleavings.
🗺️Map of the codebase
src/lib.rs— Main library entry point that exports the public API; every contributor must understand the high-level module structure and how tests invoke loom.src/rt/scheduler.rs— Core scheduler that manages permutation exploration and state reduction; essential for understanding how loom controls concurrent execution.src/rt/execution.rs— Tracks execution state and synchronization events during test runs; critical for understanding how loom records and replays concurrent behaviors.src/sync/atomic/mod.rs— Atomic wrapper implementations that enforce C11 memory model semantics; foundational for all synchronization primitives.src/rt/mod.rs— Runtime module facade coordinating threads, synchronization, and access tracking; orchestrates the entire testing harness.src/model.rs— Primary test macro and model execution logic; the user-facing entry point for writing concurrent tests.Cargo.toml— Defines features (checkpoint, futures) and minimal dependencies; contributors must understand the generator-based runtime dependency.
🛠️How to make changes
Add a new synchronization primitive wrapper
- Create new wrapper in src/sync/ (e.g., src/sync/barrier.rs) that wraps the std equivalent and instruments reads/writes via access tracking. (
src/sync/barrier.rs) - Add corresponding runtime implementation in src/rt/ (e.g., src/rt/barrier.rs) that hooks into the scheduler's synchronization tracking. (
src/rt/barrier.rs) - Export wrapper and runtime impl from src/sync/mod.rs and src/rt/mod.rs respectively. (
src/sync/mod.rs) - Add integration test in tests/ (e.g., tests/barrier.rs) using loom::model! macro to verify correct synchronization under permutations. (
tests/barrier.rs)
Implement a new memory ordering constraint
- Define ordering enum variant in src/sync/atomic/mod.rs and add semantics validation logic. (
src/sync/atomic/mod.rs) - Update src/rt/synchronize.rs to enforce happens-before edges for the new ordering. (
src/rt/synchronize.rs) - Add vector clock increment logic in src/rt/vv.rs if order affects causality tracking. (
src/rt/vv.rs) - Create a litmus test in tests/ to verify the ordering constraint blocks invalid reorderings. (
tests/litmus.rs)
Add data race detection for a new access type
- Extend src/rt/access.rs to track the new access kind (read, write, or rmw variant). (
src/rt/access.rs) - Update src/rt/execution.rs to record access events during test execution. (
src/rt/execution.rs) - Add conflict detection logic in src/rt/object.rs to report data races between incompatible accesses. (
src/rt/object.rs) - Create regression test in tests/ (e.g., tests/data_race_detection.rs) demonstrating the detection. (
tests/data_race.rs)
Enhance scheduler state reduction heuristics
- Study src/rt/scheduler.rs to understand current permutation exploration and backtracking strategy. (
src/rt/scheduler.rs) - Add new heuristic function or modify decision points to prune equivalent executions. (
src/rt/scheduler.rs) - Add benchmarking test in tests/ to measure permutation count reduction on real-world patterns. (
tests/perf.rs)
🔧Why these technologies
- generator crate (coroutine-based runtime) — Enables cooperative multitasking and lightweight context switching for exploring many concurrent schedules without OS threads; essential for permutation exploration efficiency.
- C11 memory model (atomics semantics) — Provides formal foundation for validating synchronization correctness; loom enforces these constraints to catch subtle data races that depend on CPU memory ordering.
- Vector clocks (happens-before tracking) — Enables efficient detection of causality violations without exploring all O(n!) orderings; state reduction technique that makes permutation testing tractable.
- cfg(loom) conditional compilation — Allows tests to swap in loom-instrumented primitives without modifying production code; minimal runtime overhead when loom is not active.
⚖️Trade-offs already made
-
Generator-based runtime instead of async/await
- Why: Generators provide simpler control flow for test code; async machinery adds complexity that interferes with permutation exploration.
- Consequence: Tests must be synchronous; cannot test async runtimes directly, though futures feature provides some bridge support.
-
State reduction via happens-before vs. full exploration
- Why: Full exploration is infeasible (exponential in thread count); state reduction prunes equivalent executions.
- Consequence: May miss rare bugs that require specific thread interleavings, but practical for most real-world concurrent code.
-
Single-threaded permutation exploration rather than parallel
- Why: Scheduler must maintain total control over interleaving; parallelizing the search itself would lose determinism and ordering control.
- Consequence: Test execution time scales with permutation count; large tests may be slow.
-
Compile-time instrumentation via cfg(loom) rather than runtime bytecode rewriting
- Why: Rust's macro system and conditional compilation are simpler and more reliable than dynamic bytecode instrumentation.
- Consequence: Requires test code to opt-in via #[cfg(loom)]; cannot test external black-box libraries.
🚫Non-goals (don't propose these)
- Testing async/await code directly (futures feature is limited bridge only)
- Detecting timing-based race conditions (detects data races under memory model, not timing attacks)
- Supporting dynamic language features or reflection
- Running on platforms other than those supported by Rust std and generator crate
🪤Traps & gotchas
- cfg(loom) is required: Types like
loom::sync::Arconly intercept operations when compiled withRUSTFLAGS="--cfg loom". Without this flag, you're testing against std types, defeating the purpose. 2. SeqCst is weaker than C11: Sequentially consistent atomics are internally treated as AcqRel, so SeqCst-only bugs may not be detected (see issue #180). Usefence(SeqCst)instead if you need true sequential consistency. 3. Test must be deterministic: Non-deterministic test code (real system calls, external I/O, random numbers without seeding) will cause spurious failures across permutations. 4. Load buffering not explored: Certain reordering scenarios allowed by C11 are skipped, so Loom can give false negatives (see tests/litmus.rs for examples). 5. Limited to singleloom::model()call per test: Nested or sequential model blocks can cause unexpected behavior; each test should wrap its entire concurrent scenario in one model block.
🏗️Architecture
💡Concepts to learn
- C11 Memory Model (Memory Ordering) — Loom's entire purpose is to validate code against C11 semantics; understanding Acquire/Release/Relaxed/SeqCst is fundamental to writing correct loom tests and interpreting results.
- State Reduction & DPOR (Dynamic Partial Order Reduction) — Loom avoids exploring equivalent thread interleavings using partial order reduction; knowing when two permutations are equivalent saves test time and prevents combinatorial explosion.
- Vector Clocks (Happens-Before) — src/rt/vv.rs implements vector clocks to track causal dependencies between thread operations; this is how Loom determines if one memory access happens-before another.
- Symmetric Multiprocessing & Context Switching — Loom uses the
generatorcrate to simulate SMP-style preemption deterministically; understanding coroutine-based thread simulation is key to diagnosing scheduler-related bugs. - Data Race Detection via Lockset & Happens-Before — Loom combines lockset analysis (tracking which locks protect which variables) with happens-before relations to detect races; this is why proper synchronization is critical to pass Loom.
- Conditional Compilation with cfg(loom) — Unlike most Rust testing tools, Loom requires flipping a compile-time feature flag to intercept operations; misunderstanding when cfg(loom) is active causes false test results.
- False Positives vs. False Negatives in Testing — The README explicitly documents that Loom can produce both (incomplete detection + unsoundness); developers must understand these limitations to avoid false confidence in passing tests.
🔗Related repos
crossbeam-rs/crossbeam— Complementary library providing lock-free data structures (Deque, SegQueue) that developers use with Loom for testing correctness under permutationstokio-rs/tokio— Primary user of Loom; tokio's concurrent primitives are tested extensively with Loom to validate the async runtime's synchronization guaranteesawslabs/mio— Low-level async I/O library whose networking primitives benefit from Loom testing for race condition detection in platform-specific code pathsmodel-checking/rpmalloc-rust— Memory allocator that uses Loom-style permutation testing for concurrent allocation correctness, showing cross-domain application of the techniquerayon-rs/rayon— Data parallelism library that can benefit from Loom testing to validate work-stealing scheduler correctness under fine-grained concurrency
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive tests for src/rt/vv.rs (vector-vector clock implementation)
The vector-vector clock implementation in src/rt/vv.rs is a critical component for tracking happens-before relationships in the concurrency model, but there are no dedicated tests for it in the tests/ directory. This is a core synchronization primitive that deserves explicit test coverage for correctness.
- [ ] Create tests/vv.rs with unit tests for vector-vector clock operations
- [ ] Test clock increment, merge, and comparison operations
- [ ] Add tests for happens-before relationship detection
- [ ] Test edge cases like clock overflow and concurrent updates
- [ ] Verify integration with src/rt/synchronize.rs
Add integration tests for src/rt/location.rs and stack trace tracking
The location.rs module tracks source locations for synchronization events, which is important for debugging concurrent issues. However, there are no tests validating that location information is properly captured and associated with concurrent operations. This would improve debuggability.
- [ ] Create tests/location.rs to test location capture during concurrent operations
- [ ] Verify stack traces are correctly recorded for mutex/atomic operations
- [ ] Test that location information is preserved through the execution model
- [ ] Add tests validating location data is accessible via src/rt/object.rs
- [ ] Document expected behavior in location tracking
Add stress tests for src/sync/atomic/ module with all memory orderings
While tests/atomic.rs and tests/atomic_int.rs exist, there are no comprehensive tests covering the full matrix of all atomic types (bool, int variants, ptr) with all C11 memory orderings (Relaxed, Release, Acquire, AcqRel, SeqCst). The tests/atomic_relaxed.rs focuses only on relaxed ordering.
- [ ] Expand tests/atomic.rs to systematically test all memory orderings for AtomicBool
- [ ] Create comprehensive tests for src/sync/atomic/int.rs covering u32, u64, usize with all orderings
- [ ] Add tests for src/sync/atomic/ptr.rs with various pointer types and orderings
- [ ] Include fence operations (tests/fence.rs exists but could be expanded)
- [ ] Test interaction between different orderings in the same execution
🌿Good first issues
- Add comprehensive documentation to src/rt/vv.rs (vector clock implementation) explaining how happens-before relationships are tracked across permutations—currently undocumented but critical for understanding state reduction.
- Implement and test
SeqCstmemory ordering correctly instead of demoting toAcqRel(see README unsupported features #1)—requires modifying src/rt/atomic.rs and adding litmus test cases to tests/litmus.rs for SeqCst-only orderings. - Add support for
NotifyandWaitQueueprimitives in src/sync/notify.rs and src/rt/notify.rs similar to condvar.rs pattern, filling the gap between Mutex/Barrier and full async notification (mentioned in src/future/atomic_waker.rs but incomplete).
⭐Top contributors
Click to expand
Top contributors
- @taiki-e — 25 commits
- @hawkw — 14 commits
- @carllerche — 8 commits
- @Darksonn — 5 commits
- @tower120 — 4 commits
📝Recent commits
Click to expand
Recent commits
948c8cc— tests: Fix typo: mutal -> mutual (#404) (Ollie-Pearce)6abd413— add?Sizedtrait bound toRwLock(#401) (pedrocarlo)dbf32b0— Add license badge in README (#381) (Ocheretovich)2dc2327— Fix discord link (#380) (Ocheretovich)850faca— DocumentNotifylimitation (#373) (SpecificProtagonist)0624ff3— Fix build error on not 64 bit arch (#370) (ryota2357)3ef62e2— Document what effect hints have on loom (#358) (udoprog)b810b4a— Use std::pin::pin! macro instead of pin-utils (#366) (taiki-e)bf80a9c— Migrate to Rust 2021 (#365) (taiki-e)be150d6— Bump MSRV to 1.73 (#364) (taiki-e)
🔒Security observations
Loom is a specialized testing framework with generally solid security posture. The primary concerns are: (1) outdated/unpinned generator dependency which has historical soundness concerns; (2) loose dependency version constraints allowing uncontrolled updates; (3) optional JSON serialization feature requiring careful usage documentation. No hardcoded secrets, injection vulnerabilities, or critical infrastructure misconfigurations detected. The codebase follows Rust safety principles appropriate for a concurrency testing tool. Recommend dependency audit and tightening version constraints.
- Medium · Outdated Dependency: generator 0.8.1 —
Cargo.toml - dependencies section. The 'generator' crate version 0.8.1 is pinned to an older version. Generators have had historical soundness concerns in Rust. This dependency is used for the runtime implementation in loom, which is critical for the testing framework's correctness. Fix: Review the generator crate's changelog and security advisories. Consider updating to the latest stable version or evaluating alternative implementations. Verify the crate maintains memory safety guarantees required for concurrent testing. - Medium · Permissive Dependency Version Constraints —
Cargo.toml - dependencies section. Several dependencies use loose version constraints (e.g., 'scoped-tls = 1.0.0', 'generator = 0.8.1') without upper bounds. This allows automatic updates to potentially incompatible or vulnerable versions during dependency resolution. Fix: Use more restrictive version specifications such as '~0.8.1' for patch-level updates only, or regularly audit and test dependency updates before deploying to ensure no breaking changes or security regressions. - Low · Optional Dependencies for Checkpoint Feature —
Cargo.toml - checkpoint feature. The 'checkpoint' feature introduces JSON serialization dependencies (serde, serde_json). While optional, if enabled, these add potential deserialization attack surface. The use case for checkpoint serialization should be carefully validated. Fix: Ensure checkpoint serialization is only used in trusted contexts. Validate that serde_json is not processing untrusted input. Document the security implications of enabling this feature. - Low · Missing RUST_BACKTRACE in CI/CD —
.github/workflows/. The CI workflows (.github/workflows/ci.yml, release.yml) are not visible in detail, but critical security context is missing. Unable to verify if security-related environment variables, secret scanning, or dependency audits are configured. Fix: Ensure CI/CD includes: 'cargo audit' for known vulnerabilities, SBOM generation, signed releases, and secret scanning to prevent accidental credential exposure.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.