add miri_spin_loop to make hint::spin_loop work consistently

This commit is contained in:
Folkert de Vries 2025-12-17 12:25:45 +01:00
parent 08de25c4ea
commit c7dd19b8d6
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
3 changed files with 19 additions and 0 deletions

View file

@ -269,6 +269,15 @@ pub const unsafe fn assert_unchecked(cond: bool) {
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
pub fn spin_loop() {
crate::cfg_select! {
miri => {
unsafe extern "Rust" {
safe fn miri_spin_loop();
}
// Miri does support some of the intrinsics that are called below, but to guarantee
// consistent behavior across targets, this custom function is used.
miri_spin_loop();
}
target_arch = "x86" => {
// SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
crate::arch::x86::_mm_pause()

View file

@ -435,6 +435,13 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Return value: 0 on success, otherwise the size it would have needed.
this.write_int(if success { 0 } else { needed_size }, dest)?;
}
// Hint that a loop is spinning indefinitely.
"miri_spin_loop" => {
let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
// Try to run another thread to maximize the chance of finding actual bugs.
this.yield_active_thread();
}
// Obtains the size of a Miri backtrace. See the README for details.
"miri_backtrace_size" => {
this.handle_miri_backtrace_size(abi, link_name, args, dest)?;

View file

@ -155,4 +155,7 @@ extern "Rust" {
/// Blocks the current execution if the argument is false
pub fn miri_genmc_assume(condition: bool);
/// Indicate to Miri that this thread is busy-waiting in a spin loop.
pub fn miri_spin_loop();
}