Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
6e05d61
Synced rust-analyzer configs
YohDeadfall Jun 27, 2025
40ec147
Merge pull request #4415 from YohDeadfall/sync-ra-configs
RalfJung Jun 28, 2025
75e22d5
Preparing for merge from rustc
Jun 29, 2025
7b985d5
Merge from rustc
Jun 29, 2025
03a7b9f
Merge pull request #4420 from rust-lang/rustup-2025-06-29
RalfJung Jun 29, 2025
7be1bf7
make ./miri work on stable again
RalfJung Jun 29, 2025
d01e001
Merge pull request #4423 from RalfJung/miri-script-stable
RalfJung Jun 29, 2025
ea69081
also test on arm-64 linux hosts
RalfJung Jun 29, 2025
651d2f8
Merge pull request #4424 from RalfJung/aarch64-linux-ci
RalfJung Jun 29, 2025
d539e66
Preparing for merge from rustc
RalfJung Jun 29, 2025
9c22372
Merge from rustc
RalfJung Jun 29, 2025
33f1700
Merge pull request #4425 from RalfJung/rustup
RalfJung Jun 29, 2025
ab2443c
fix type mismatches in native-lib/scalar_arguments test
RalfJung Jun 29, 2025
6aaaff8
test on x86-32 and arm-32
RalfJung Jun 29, 2025
e788b3c
also test on s390x via qemu
RalfJung Jun 29, 2025
d559073
remove duplicate clippy check
RalfJung Jun 29, 2025
ec85b70
add a riscv64 test job
RalfJung Jun 29, 2025
d69b8e2
Add shims for `gettid`-esque functions
tgross35 Jun 13, 2025
d1ee0eb
Merge pull request #4422 from RalfJung/more-ci
RalfJung Jun 29, 2025
555553f
Merge pull request #4397 from tgross35/gettid-shims
RalfJung Jun 29, 2025
cd971c6
linux futex: fix for val > i32::MAX
RalfJung Jun 30, 2025
8bb5f8c
Merge pull request #4429 from RalfJung/futex-val-too-big
RalfJung Jun 30, 2025
0c3c9e4
Preparing for merge from rustc
Jul 1, 2025
e6371c9
Merge from rustc
Jul 1, 2025
8958967
fmt
Jul 1, 2025
c52d522
./miri toolchain: no need to run 'cargo metadata'
RalfJung Jul 1, 2025
83d519c
Merge pull request #4431 from rust-lang/rustup-2025-07-01
RalfJung Jul 1, 2025
828f594
re-balance CI jobs
RalfJung Jul 1, 2025
d72b15b
Merge pull request #4432 from RalfJung/no-metadata
RalfJung Jul 1, 2025
b9b8fd2
Merge pull request #4433 from RalfJung/ci-balance
RalfJung Jul 1, 2025
4606afb
Remove leaky synchronisation objects.
LorrensP-2158466 Jun 12, 2025
0ca0671
Merge pull request #4411 from LorrensP-2158466/remove-leaky-syncobj
RalfJung Jul 1, 2025
9d9f0e0
Preparing for merge from rustc
Jul 2, 2025
af5f4be
Merge from rustc
Jul 2, 2025
28900b0
Add tracing feature to enable tracing_chrome support
Stypox Jun 18, 2025
d2f2271
rename show_error -> fatal_error
RalfJung Jul 2, 2025
0234984
Merge pull request #4436 from rust-lang/rustup-2025-07-02
RalfJung Jul 2, 2025
0d43e2f
Merge pull request #4406 from Stypox/tracing
RalfJung Jul 2, 2025
510040f
skip env var memory for leak check
RalfJung Jul 2, 2025
5ce7a04
Merge pull request #4437 from RalfJung/env-cleanup
RalfJung Jul 2, 2025
8fc0fd5
use more clever approach for genmc conditional import
RalfJung Jul 2, 2025
143c05a
Merge pull request #4438 from RalfJung/genmc-conditional-import
RalfJung Jul 2, 2025
db617af
only set host-specific CC; improve and de-duplicate native libs testi…
RalfJung Jul 3, 2025
4be7583
Merge pull request #4439 from RalfJung/ci
RalfJung Jul 3, 2025
2cbbd6c
Preparing for merge from rustc
RalfJung Jul 3, 2025
484c64b
Merge from rustc
RalfJung Jul 3, 2025
3c3f1e4
Merge pull request #4440 from RalfJung/rustup
RalfJung Jul 3, 2025
7ea812f
nanosleep: fix argument name and add a missing argument read
RalfJung Jul 3, 2025
2119b7e
Merge pull request #4441 from RalfJung/nanosleep
RalfJung Jul 3, 2025
04522bb
Preparing for merge from rustc
Jul 4, 2025
f655289
Merge from rustc
Jul 4, 2025
0018401
Merge pull request #4442 from rust-lang/rustup-2025-07-04
oli-obk Jul 4, 2025
0d656e0
declare data race and weak memory support as non-experimental
RalfJung Jul 4, 2025
23b3be5
Merge pull request #4443 from RalfJung/concurrency-ub-detection
RalfJung Jul 4, 2025
1620117
Preparing for merge from rustc
RalfJung Jul 5, 2025
61f3705
Merge from rustc
RalfJung Jul 5, 2025
72043e3
fmt
RalfJung Jul 5, 2025
6e3e05b
Merge pull request #4445 from RalfJung/rustup
RalfJung Jul 5, 2025
a1f4172
update lockfile
RalfJung Jul 5, 2025
44d7238
remove armv5te-unknown-linux-gnueabi target maintainer
koalatux Jul 5, 2025
90762c2
Complete mut_visit.
cjgillot Jul 5, 2025
39ee1b2
Remove yields_in_scope from the scope tree.
cjgillot Jul 5, 2025
8eb9f70
Stop using Key trait randomly
compiler-errors Jul 5, 2025
2d8ffff
Port `#[ignore]` to the new attribute parsing infrastructure
JonathanBrouwer Jun 30, 2025
9a921a3
Rollup merge of #143238 - JonathanBrouwer:ignore_parser, r=jdonszelmann
matthiaskrgr Jul 5, 2025
0311159
Rollup merge of #143441 - compiler-errors:no-key, r=petrochenkov
matthiaskrgr Jul 5, 2025
7ad67e6
Rollup merge of #143478 - RalfJung:miri-sync, r=RalfJung
matthiaskrgr Jul 5, 2025
5aa7be4
Rollup merge of #143486 - husqvarnagroup:af/no-armv5te-target-maintai…
matthiaskrgr Jul 5, 2025
8a5d239
Rollup merge of #143489 - cjgillot:mut-visit-span, r=petrochenkov
matthiaskrgr Jul 5, 2025
c3c4fd7
Rollup merge of #143494 - cjgillot:no-yield-in-scope, r=compiler-errors
matthiaskrgr Jul 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add shims for gettid-esque functions
Various platforms provide a function to return the current OS thread ID,
but they all use a slightly different name. Add shims for these
functions for Apple, FreeBSD, and Windows, with tests to account for
those and a few more platforms that are not yet supported by Miri. The
syscall and extern symbol is included as well on Linux.

These should be useful in general but will also help support printing
the OS thread ID in panic messages [1].

[1]: #115746

Squashed commit from Ralf:

    try_from_scalar: extend comment
  • Loading branch information
tgross35 committed Jun 29, 2025
commit d69b8e2b48cd5e3ac4f8ee7af995241ea7c3a010
1 change: 0 additions & 1 deletion src/tools/miri/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,6 @@ where

/// Check that the number of varargs is at least the minimum what we expect.
/// Fixed args should not be included.
/// Use `check_vararg_fixed_arg_count` to extract the varargs slice from full function arguments.
pub fn check_min_vararg_count<'a, 'tcx, const N: usize>(
name: &'a str,
args: &'a [OpTy<'tcx>],
Expand Down
22 changes: 22 additions & 0 deletions src/tools/miri/src/shims/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
}
}

/// Get the process identifier.
fn get_pid(&self) -> u32 {
let this = self.eval_context_ref();
if this.machine.communicate() { std::process::id() } else { 1000 }
}

/// Get an "OS" thread ID for the current thread.
fn get_current_tid(&self) -> u32 {
let this = self.eval_context_ref();
self.get_tid(this.machine.threads.active_thread())
}

/// Get an "OS" thread ID for any thread.
fn get_tid(&self, thread: ThreadId) -> u32 {
let this = self.eval_context_ref();
let index = thread.to_u32();
let target_os = &this.tcx.sess.target.os;
if target_os == "linux" || target_os == "netbsd" {
// On Linux, the main thread has PID == TID so we uphold this. NetBSD also appears
// to exhibit the same behavior, though I can't find a citation.
this.get_pid().strict_add(index)
} else {
// Other platforms do not display any relationship between PID and TID.
index
}
}
}
2 changes: 1 addition & 1 deletion src/tools/miri/src/shims/extern_static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl<'tcx> MiriMachine<'tcx> {
ecx,
&["__cxa_thread_atexit_impl", "__clock_gettime64"],
)?;
Self::weak_symbol_extern_statics(ecx, &["getrandom", "statx"])?;
Self::weak_symbol_extern_statics(ecx, &["getrandom", "gettid", "statx"])?;
}
"freebsd" => {
Self::null_ptr_extern_statics(ecx, &["__cxa_thread_atexit_impl"])?;
Expand Down
49 changes: 43 additions & 6 deletions src/tools/miri/src/shims/unix/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,15 +274,52 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
interp_ok(Scalar::from_u32(this.get_pid()))
}

fn linux_gettid(&mut self) -> InterpResult<'tcx, Scalar> {
/// The `gettid`-like function for Unix platforms that take no parameters and return a 32-bit
/// integer. It is not always named "gettid".
fn unix_gettid(&mut self, link_name: &str) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_ref();
this.assert_target_os("linux", "gettid");
this.assert_target_os_is_unix(link_name);

let index = this.machine.threads.active_thread().to_u32();
// For most platforms the return type is an `i32`, but some are unsigned. The TID
// will always be positive so we don't need to differentiate.
interp_ok(Scalar::from_u32(this.get_current_tid()))
}

/// The Apple-specific `int pthread_threadid_np(pthread_t thread, uint64_t *thread_id)`, which
/// allows querying the ID for arbitrary threads, identified by their pthread_t.
///
/// API documentation: <https://www.manpagez.com/man/3/pthread_threadid_np/>.
fn apple_pthread_threadip_np(
&mut self,
thread_op: &OpTy<'tcx>,
tid_op: &OpTy<'tcx>,
) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os("macos", "pthread_threadip_np");

let tid_dest = this.read_pointer(tid_op)?;
if this.ptr_is_null(tid_dest)? {
// If NULL is passed, an error is immediately returned
return interp_ok(this.eval_libc("EINVAL"));
}

let thread = this.read_scalar(thread_op)?.to_int(this.libc_ty_layout("pthread_t").size)?;
let thread = if thread == 0 {
// Null thread ID indicates that we are querying the active thread.
this.machine.threads.active_thread()
} else {
// Our pthread_t is just the raw ThreadId.
let Ok(thread) = this.thread_id_try_from(thread) else {
return interp_ok(this.eval_libc("ESRCH"));
};
thread
};

// Compute a TID for this thread, ensuring that the main thread has PID == TID.
let tid = this.get_pid().strict_add(index);
let tid = this.get_tid(thread);
let tid_dest = this.deref_pointer_as(tid_op, this.machine.layouts.u64)?;
this.write_int(tid, &tid_dest)?;

interp_ok(Scalar::from_u32(tid))
// Possible errors have been handled, return success.
interp_ok(Scalar::from_u32(0))
}
}
5 changes: 5 additions & 0 deletions src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
};
this.write_scalar(res, dest)?;
}
"pthread_getthreadid_np" => {
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.unix_gettid(link_name.as_str())?;
this.write_scalar(result, dest)?;
}

"cpuset_getaffinity" => {
// The "same" kind of api as `sched_getaffinity` but more fine grained control for FreeBSD specifically.
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/src/shims/unix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::*;
const TASK_COMM_LEN: u64 = 16;

pub fn is_dyn_sym(name: &str) -> bool {
matches!(name, "statx")
matches!(name, "gettid" | "statx")
}

impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
Expand Down Expand Up @@ -117,7 +117,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
}
"gettid" => {
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.linux_gettid()?;
let result = this.unix_gettid(link_name.as_str())?;
this.write_scalar(result, dest)?;
}

Expand Down
6 changes: 6 additions & 0 deletions src/tools/miri/src/shims/unix/linux_like/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rustc_span::Symbol;
use rustc_target::callconv::FnAbi;

use crate::helpers::check_min_vararg_count;
use crate::shims::unix::env::EvalContextExt;
use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
use crate::shims::unix::linux_like::sync::futex;
use crate::*;
Expand All @@ -24,6 +25,7 @@ pub fn syscall<'tcx>(
let sys_getrandom = ecx.eval_libc("SYS_getrandom").to_target_usize(ecx)?;
let sys_futex = ecx.eval_libc("SYS_futex").to_target_usize(ecx)?;
let sys_eventfd2 = ecx.eval_libc("SYS_eventfd2").to_target_usize(ecx)?;
let sys_gettid = ecx.eval_libc("SYS_gettid").to_target_usize(ecx)?;

match ecx.read_target_usize(op)? {
// `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
Expand Down Expand Up @@ -53,6 +55,10 @@ pub fn syscall<'tcx>(
let result = ecx.eventfd(initval, flags)?;
ecx.write_int(result.to_i32()?, dest)?;
}
num if num == sys_gettid => {
let result = ecx.unix_gettid("SYS_gettid")?;
ecx.write_int(result.to_u32()?, dest)?;
}
num => {
throw_unsup_format!("syscall: unsupported syscall number {num}");
}
Expand Down
5 changes: 5 additions & 0 deletions src/tools/miri/src/shims/unix/macos/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
};
this.write_scalar(res, dest)?;
}
"pthread_threadid_np" => {
let [thread, tid_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let res = this.apple_pthread_threadip_np(thread, tid_ptr)?;
this.write_scalar(res, dest)?;
}

// Synchronization primitives
"os_sync_wait_on_address" => {
Expand Down
17 changes: 17 additions & 0 deletions src/tools/miri/src/shims/windows/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(name, &name_ptr)?;
this.write_scalar(res, dest)?;
}
"GetThreadId" => {
let [handle] = this.check_shim(abi, sys_conv, link_name, args)?;
let handle = this.read_handle(handle, "GetThreadId")?;
let thread = match handle {
Handle::Thread(thread) => thread,
Handle::Pseudo(PseudoHandle::CurrentThread) => this.active_thread(),
_ => this.invalid_handle("GetThreadDescription")?,
};
let tid = this.get_tid(thread);
this.write_scalar(Scalar::from_u32(tid), dest)?;
}
"GetCurrentThreadId" => {
let [] = this.check_shim(abi, sys_conv, link_name, args)?;
let thread = this.active_thread();
let tid = this.get_tid(thread);
this.write_scalar(Scalar::from_u32(tid), dest)?;
}

// Miscellaneous
"ExitProcess" => {
Expand Down
4 changes: 4 additions & 0 deletions src/tools/miri/src/shims/windows/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ impl Handle {
/// Structurally invalid handles return [`HandleError::InvalidHandle`].
/// If the handle is structurally valid but semantically invalid, e.g. a for non-existent thread
/// ID, returns [`HandleError::ThreadNotFound`].
///
/// This function is deliberately private; shims should always use `read_handle`.
/// That enforces handle validity even when Windows does not: for now, we argue invalid
/// handles are always a bug and programmers likely want to know about them.
fn try_from_scalar<'tcx>(
handle: Scalar,
cx: &MiriInterpCx<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Ensure we error if thread functions are called with invalid handles
//@only-target: windows # testing Windows API

use windows_sys::Win32::System::Threading::GetThreadId;

fn main() {
let _tid = unsafe { GetThreadId(std::ptr::dangling_mut()) };
//~^ ERROR: invalid handle
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error: abnormal termination: invalid handle 1 passed to GetThreadId
--> tests/fail-dep/concurrency/windows_thread_invalid.rs:LL:CC
|
LL | let _tid = unsafe { GetThreadId(std::ptr::dangling_mut()) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here
|
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/concurrency/windows_thread_invalid.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

Loading