diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index 7ad395cccb79..6586ea8e48cf 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -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 } + } } diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs index 405431f4327d..3b8ad65195b8 100644 --- a/src/tools/miri/src/shims/unix/env.rs +++ b/src/tools/miri/src/shims/unix/env.rs @@ -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) } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 95bee38cd783..20c6a2347942 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -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" => { diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs index ed3eb6979863..77ae06bd5c2d 100644 --- a/src/tools/miri/src/shims/windows/env.rs +++ b/src/tools/miri/src/shims/windows/env.rs @@ -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)] diff --git a/src/tools/miri/tests/pass-dep/libc/gettid.rs b/src/tools/miri/tests/pass-dep/libc/gettid.rs new file mode 100644 index 000000000000..87405b02ac35 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/gettid.rs @@ -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() }); +} diff --git a/src/tools/miri/tests/pass/getpid.rs b/src/tools/miri/tests/pass/getpid.rs index 733545462ebc..f350fafff4a2 100644 --- a/src/tools/miri/tests/pass/getpid.rs +++ b/src/tools/miri/tests/pass/getpid.rs @@ -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); }