Skip to content

Commit 12cb742

Browse files
committed
Auto merge of rust-lang#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 rust-lang#3730
2 parents 0b22f0c + a0088d7 commit 12cb742

File tree

6 files changed

+60
-7
lines changed

6 files changed

+60
-7
lines changed

src/tools/miri/src/shims/env.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
108108
EnvVars::Windows(vars) => vars.get(name),
109109
}
110110
}
111+
112+
fn get_pid(&self) -> u32 {
113+
let this = self.eval_context_ref();
114+
if this.machine.communicate() { std::process::id() } else { 1000 }
115+
}
111116
}

src/tools/miri/src/shims/unix/env.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
274274
let this = self.eval_context_mut();
275275
this.assert_target_os_is_unix("getpid");
276276

277-
this.check_no_isolation("`getpid`")?;
278-
279277
// The reason we need to do this wacky of a conversion is because
280278
// `libc::getpid` returns an i32, however, `std::process::id()` return an u32.
281279
// So we un-do the conversion that stdlib does and turn it back into an i32.
282280
#[allow(clippy::cast_possible_wrap)]
283-
Ok(std::process::id() as i32)
281+
Ok(this.get_pid() as i32)
282+
}
283+
284+
fn linux_gettid(&mut self) -> InterpResult<'tcx, i32> {
285+
let this = self.eval_context_ref();
286+
this.assert_target_os("linux", "gettid");
287+
288+
let index = this.machine.threads.active_thread().to_u32();
289+
290+
// Compute a TID for this thread, ensuring that the main thread has PID == TID.
291+
let tid = this.get_pid().strict_add(index);
292+
293+
#[allow(clippy::cast_possible_wrap)]
294+
Ok(tid as i32)
284295
}
285296
}

src/tools/miri/src/shims/unix/linux/foreign_items.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
9494
)?;
9595
this.write_scalar(res, dest)?;
9696
}
97+
"gettid" => {
98+
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
99+
let result = this.linux_gettid()?;
100+
this.write_scalar(Scalar::from_i32(result), dest)?;
101+
}
97102

98103
// Dynamically invoked syscalls
99104
"syscall" => {

src/tools/miri/src/shims/windows/env.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
200200
fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> {
201201
let this = self.eval_context_mut();
202202
this.assert_target_os("windows", "GetCurrentProcessId");
203-
this.check_no_isolation("`GetCurrentProcessId`")?;
204203

205-
Ok(std::process::id())
204+
Ok(this.get_pid())
206205
}
207206

208207
#[allow(non_snake_case)]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@only-target-linux
2+
//@revisions: with_isolation without_isolation
3+
//@[without_isolation] compile-flags: -Zmiri-disable-isolation
4+
5+
use libc::{getpid, gettid};
6+
use std::thread;
7+
8+
fn main() {
9+
thread::spawn(|| {
10+
// Test that in isolation mode a deterministic value will be returned.
11+
// The value 1001 is not important, we only care that whatever the value
12+
// is, won't change from execution to execution.
13+
#[cfg(with_isolation)]
14+
assert_eq!(unsafe { gettid() }, 1001);
15+
16+
assert_ne!(unsafe { gettid() }, unsafe { getpid() });
17+
});
18+
19+
// Test that the thread ID of the main thread is the same as the process
20+
// ID.
21+
assert_eq!(unsafe { gettid() }, unsafe { getpid() });
22+
}

src/tools/miri/tests/pass/getpid.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
//@compile-flags: -Zmiri-disable-isolation
1+
//@revisions: with_isolation without_isolation
2+
//@[without_isolation] compile-flags: -Zmiri-disable-isolation
23

34
fn getpid() -> u32 {
45
std::process::id()
56
}
67

78
fn main() {
8-
getpid();
9+
let pid = getpid();
10+
11+
std::thread::spawn(move || {
12+
assert_eq!(getpid(), pid);
13+
});
14+
15+
// Test that in isolation mode a deterministic value will be returned.
16+
// The value 1000 is not important, we only care that whatever the value
17+
// is, won't change from execution to execution.
18+
#[cfg(with_isolation)]
19+
assert_eq!(pid, 1000);
920
}

0 commit comments

Comments
 (0)