Auto merge of #2562 - pvdrz:miri-num-cpus, r=RalfJung

Add flag to specify the number of cpus

Apparently you can't rename a branch from github's website without it closing all your PRs with that branch. So this is  just #2545
This commit is contained in:
bors 2022-09-27 01:13:09 +00:00
commit 20adc75304
8 changed files with 33 additions and 8 deletions

View File

@ -293,6 +293,9 @@ environment variable. We first document the most relevant and most commonly used
value of forwarded variables stays the same. Has no effect if `-Zmiri-disable-isolation` is set.
* `-Zmiri-ignore-leaks` disables the memory leak checker, and also allows some
remaining threads to exist when the main thread exits.
* `-Zmiri-num-cpus` states the number of available CPUs to be reported by miri. By default, the
number of available CPUs is `1`. Note that this flag does not affect how miri handles threads in
any way.
* `-Zmiri-permissive-provenance` disables the warning for integer-to-pointer casts and
[`ptr::from_exposed_addr`](https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html).
This will necessarily miss some bugs as those operations are not efficiently and accurately
@ -357,7 +360,7 @@ to Miri failing to detect cases of undefined behavior in a program.
This is **work in progress**; currently, only integer arguments and return values are
supported (and no, pointer/integer casts to work around this limitation will not work;
they will fail horribly). It also only works on unix hosts for now.
Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365).
Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365).
* `-Zmiri-measureme=<name>` enables `measureme` profiling for the interpreted program.
This can be used to find which parts of your program are executing slowly under Miri.
The profile is written out to a file with the prefix `<name>`, and can be processed
@ -387,7 +390,7 @@ to Miri failing to detect cases of undefined behavior in a program.
Borrows "protectors". Specifying this argument multiple times does not overwrite the previous
values, instead it appends its values to the list. Listing an id multiple times has no effect.
* `-Zmiri-track-pointer-tag=<tag1>,<tag2>,...` shows a backtrace when a given pointer tag
is created and when (if ever) it is popped from a borrow stack (which is where the tag becomes invalid
is created and when (if ever) it is popped from a borrow stack (which is where the tag becomes invalid
and any future use of it will error). This helps you in finding out why UB is
happening and where in your code would be a good place to look for it.
Specifying this argument multiple times does not overwrite the previous

View File

@ -550,6 +550,13 @@ fn main() {
} else {
show_error!("-Zmiri-extern-so-file `{}` does not exist", filename);
}
} else if let Some(param) = arg.strip_prefix("-Zmiri-num-cpus=") {
let num_cpus = match param.parse::<u32>() {
Ok(i) => i,
Err(err) => show_error!("-Zmiri-num-cpus requires a `u32`: {}", err),
};
miri_config.num_cpus = num_cpus;
} else {
// Forward to rustc.
rustc_args.push(arg);

View File

@ -132,6 +132,8 @@ pub struct MiriConfig {
pub external_so_file: Option<PathBuf>,
/// Run a garbage collector for SbTags every N basic blocks.
pub gc_interval: u32,
/// The number of CPUs to be reported by miri.
pub num_cpus: u32,
}
impl Default for MiriConfig {
@ -164,6 +166,7 @@ impl Default for MiriConfig {
retag_fields: false,
external_so_file: None,
gc_interval: 10_000,
num_cpus: 1,
}
}
}

View File

@ -104,7 +104,7 @@ pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt};
pub use crate::intptrcast::ProvenanceMode;
pub use crate::machine::{
AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, Provenance,
ProvenanceExtra, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;

View File

@ -35,7 +35,6 @@ use crate::{
pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever
pub const NUM_CPUS: u64 = 1;
/// Extra data stored with each stack frame
pub struct FrameData<'tcx> {
@ -410,6 +409,8 @@ pub struct MiriMachine<'mir, 'tcx> {
pub(crate) gc_interval: u32,
/// The number of blocks that passed since the last SbTag GC pass.
pub(crate) since_gc: u32,
/// The number of CPUs to be reported by miri.
pub(crate) num_cpus: u32,
}
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
@ -489,6 +490,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
}),
gc_interval: config.gc_interval,
since_gc: 0,
num_cpus: config.num_cpus,
}
}

View File

@ -225,13 +225,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"sysconf" => {
let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let name = this.read_scalar(name)?.to_i32()?;
// FIXME: Which of these are POSIX, and which are GNU/Linux?
// At least the names seem to all also exist on macOS.
let sysconfs: &[(&str, fn(&MiriInterpCx<'_, '_>) -> Scalar<Provenance>)] = &[
("_SC_PAGESIZE", |this| Scalar::from_int(PAGE_SIZE, this.pointer_size())),
("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())),
("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())),
("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
// 512 seems to be a reasonable default. The value is not critical, in
// the sense that getpwuid_r takes and checks the buffer length.
("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size()))

View File

@ -163,7 +163,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
)?;
// Set number of processors.
let num_cpus = system_info.offset(field_offsets[6], dword_layout, &this.tcx)?;
this.write_scalar(Scalar::from_int(NUM_CPUS, dword_layout.size), &num_cpus.into())?;
this.write_scalar(
Scalar::from_int(this.machine.num_cpus, dword_layout.size),
&num_cpus.into(),
)?;
}
// Thread-local storage

View File

@ -0,0 +1,8 @@
//@compile-flags: -Zmiri-num-cpus=1024
use std::num::NonZeroUsize;
use std::thread::available_parallelism;
fn main() {
assert_eq!(available_parallelism().unwrap(), NonZeroUsize::new(1024).unwrap());
}