Auto merge of #3756 - Mandragorian:gettid_support, r=RalfJung
Add `gettid` support Add support for `gettid` in miri. To ensure that the requirement that `getpid() == gettdi()` for the main thread, we use the value returned by `getpid` and add to it the internal thread index. Since `getpid` is only supported when isolation is disabled, and we want `gettid` to be used both in isolated and non-isolated executions, we modify `getpid` to return a hardcoded value (1000) when running in isolation mode. Fixes #3730
This commit is contained in:
commit
12cb742e82
6 changed files with 60 additions and 7 deletions
|
|
@ -108,4 +108,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
EnvVars::Windows(vars) => vars.get(name),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pid(&self) -> u32 {
|
||||
let this = self.eval_context_ref();
|
||||
if this.machine.communicate() { std::process::id() } else { 1000 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,12 +274,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
let this = self.eval_context_mut();
|
||||
this.assert_target_os_is_unix("getpid");
|
||||
|
||||
this.check_no_isolation("`getpid`")?;
|
||||
|
||||
// The reason we need to do this wacky of a conversion is because
|
||||
// `libc::getpid` returns an i32, however, `std::process::id()` return an u32.
|
||||
// So we un-do the conversion that stdlib does and turn it back into an i32.
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
Ok(std::process::id() as i32)
|
||||
Ok(this.get_pid() as i32)
|
||||
}
|
||||
|
||||
fn linux_gettid(&mut self) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_ref();
|
||||
this.assert_target_os("linux", "gettid");
|
||||
|
||||
let index = this.machine.threads.active_thread().to_u32();
|
||||
|
||||
// Compute a TID for this thread, ensuring that the main thread has PID == TID.
|
||||
let tid = this.get_pid().strict_add(index);
|
||||
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
Ok(tid as i32)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"gettid" => {
|
||||
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let result = this.linux_gettid()?;
|
||||
this.write_scalar(Scalar::from_i32(result), dest)?;
|
||||
}
|
||||
|
||||
// Dynamically invoked syscalls
|
||||
"syscall" => {
|
||||
|
|
|
|||
|
|
@ -200,9 +200,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("windows", "GetCurrentProcessId");
|
||||
this.check_no_isolation("`GetCurrentProcessId`")?;
|
||||
|
||||
Ok(std::process::id())
|
||||
Ok(this.get_pid())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
|
|
|||
22
src/tools/miri/tests/pass-dep/libc/gettid.rs
Normal file
22
src/tools/miri/tests/pass-dep/libc/gettid.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//@only-target-linux
|
||||
//@revisions: with_isolation without_isolation
|
||||
//@[without_isolation] compile-flags: -Zmiri-disable-isolation
|
||||
|
||||
use libc::{getpid, gettid};
|
||||
use std::thread;
|
||||
|
||||
fn main() {
|
||||
thread::spawn(|| {
|
||||
// Test that in isolation mode a deterministic value will be returned.
|
||||
// The value 1001 is not important, we only care that whatever the value
|
||||
// is, won't change from execution to execution.
|
||||
#[cfg(with_isolation)]
|
||||
assert_eq!(unsafe { gettid() }, 1001);
|
||||
|
||||
assert_ne!(unsafe { gettid() }, unsafe { getpid() });
|
||||
});
|
||||
|
||||
// Test that the thread ID of the main thread is the same as the process
|
||||
// ID.
|
||||
assert_eq!(unsafe { gettid() }, unsafe { getpid() });
|
||||
}
|
||||
|
|
@ -1,9 +1,20 @@
|
|||
//@compile-flags: -Zmiri-disable-isolation
|
||||
//@revisions: with_isolation without_isolation
|
||||
//@[without_isolation] compile-flags: -Zmiri-disable-isolation
|
||||
|
||||
fn getpid() -> u32 {
|
||||
std::process::id()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
getpid();
|
||||
let pid = getpid();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
assert_eq!(getpid(), pid);
|
||||
});
|
||||
|
||||
// Test that in isolation mode a deterministic value will be returned.
|
||||
// The value 1000 is not important, we only care that whatever the value
|
||||
// is, won't change from execution to execution.
|
||||
#[cfg(with_isolation)]
|
||||
assert_eq!(pid, 1000);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue