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
16 changes: 2 additions & 14 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ infinity_pool = { version = "0.8.1", default-features = false }
insta = { version = "1.44.1", default-features = false }
jiff = { version = "0.2.16", default-features = false }
libc = { version = "0.2.178", default-features = false }
many_cpus = { version = "1.1.0", default-features = false }
many_cpus = { version = "2.0.0", default-features = false }
mockall = { version = "0.14.0", default-features = false }
mutants = { version = "0.0.3", default-features = false }
new_zealand = { version = "1.0.1", default-features = false }
Expand Down
23 changes: 16 additions & 7 deletions crates/thread_aware/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use std::thread::ThreadId;

use crate::affinity::{MemoryAffinity, PinnedAffinity};
use many_cpus::{Processor, ProcessorSet};
use many_cpus::Processor;

/// The number of processors to use for the registry.
///
Expand Down Expand Up @@ -62,7 +62,7 @@
/// If there are more than `u16::MAX` processors or memory regions.
#[must_use]
pub fn new(count: &ProcessorCount) -> Self {
let builder = many_cpus::ProcessorSet::builder();
let builder = many_cpus::SystemHardware::current().processors().to_builder();

let processors: Vec<_> = match count {
ProcessorCount::Auto | ProcessorCount::All => builder.take_all(),
Expand Down Expand Up @@ -145,12 +145,21 @@
let core_index = affinity.processor_index();
let processor = &self.processors[core_index];

ProcessorSet::from_processor(processor.clone()).pin_current_thread_to();
let processor_set = many_cpus::SystemHardware::current()
Copy link
Copy Markdown
Member

@sandersaares sandersaares Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid multiple calls to many_cpus::SystemHardware::current() - the optimal pattern is to acquire the "hardware" instance once and reuse it forever, not touching current() after that. This creates the opportunity to use a mock/fake platform in tests, so it is important not to call current() except in entrypoint functions.

Sidenote: does the possibility of faking the hardware create opportunities for additional testing we want to take advantage of here? We could have some fn with_hardware(count, &ProcessorCount, hardware: SystemHardware) that one could plug a fake hardware instance into. Might it, for example, catch that missed mutant?

.processors()
.to_builder()
.filter(|p| p.id() == processor.id())

Check warning on line 151 in crates/thread_aware/src/registry.rs

View workflow job for this annotation

GitHub Actions / mutation-testing

Missed mutant

replace == with != in ThreadRegistry::pin_to
.take_all();

self.threads
.lock()
.expect("Failed to acquire lock")
.insert(std::thread::current().id(), affinity);
// TODO: Handle not found here.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least log it as warn

if let Some(ps) = processor_set {
ps.pin_current_thread_to();

self.threads
.lock()
.expect("Failed to acquire lock")
Copy link
Copy Markdown
Member

@sandersaares sandersaares Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This expect() is just an unwrap() in disguise because it does not explain why we are panicking (what does "failed" mean and why does that require a panic). I suggest some meaningful message like "poisoned lock means type invariants may not hold - not safe to continue execution".

[alternatively, maybe parking_lot mutex which does not even support poisoning? but that is a bit off topic]

.insert(std::thread::current().id(), affinity);
}
}
}

Expand Down
Loading