about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-24 10:17:55 +0000
committerbors <bors@rust-lang.org>2024-07-24 10:17:55 +0000
commit12cb742e8258d32afefe304a8c2402a56d4a05ee (patch)
tree3b682c3656192d814d8aca44da9b7c7e8b97c1e6
parent0b22f0c13d3151622200c62726600f1a805ac37e (diff)
parenta0088d7a813a1f63e5af4d6edc5d2c50a0b3702e (diff)
downloadrust-12cb742e8258d32afefe304a8c2402a56d4a05ee.tar.gz
rust-12cb742e8258d32afefe304a8c2402a56d4a05ee.zip
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
-rw-r--r--src/tools/miri/src/shims/env.rs5
-rw-r--r--src/tools/miri/src/shims/unix/env.rs17
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs5
-rw-r--r--src/tools/miri/src/shims/windows/env.rs3
-rw-r--r--src/tools/miri/tests/pass-dep/libc/gettid.rs22
-rw-r--r--src/tools/miri/tests/pass/getpid.rs15
6 files changed, 60 insertions, 7 deletions
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index 7ad395cccb7..6586ea8e48c 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 405431f4327..3b8ad65195b 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 95bee38cd78..20c6a234794 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 ed3eb697986..77ae06bd5c2 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 00000000000..87405b02ac3
--- /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 733545462eb..f350fafff4a 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);
 }