about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorChris Denton <chris@chrisdenton.dev>2024-03-03 22:06:00 +0000
committerChris Denton <chris@chrisdenton.dev>2024-03-05 00:19:42 +0000
commitf700641bd9eb7ec3b36b4d44eafae35ba970eea4 (patch)
tree2bcda35248fd9a6b15cd821e97e666549e44c36f /src/tools
parent89b78304e82dc5114e3b2faa0fbec747a28a2b37 (diff)
downloadrust-f700641bd9eb7ec3b36b4d44eafae35ba970eea4.tar.gz
rust-f700641bd9eb7ec3b36b4d44eafae35ba970eea4.zip
Windows: Implement mutex using futex
Well, the Windows equivalent: `WaitOnAddress`, `WakeByAddressSingle` and `WakeByAddressAll`.
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/windows/sync.rs15
2 files changed, 21 insertions, 0 deletions
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 734737a86dd..f56ea06dbe3 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -366,6 +366,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 this.WakeByAddressSingle(ptr_op)?;
             }
+            "WakeByAddressAll" => {
+                let [ptr_op] =
+                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+
+                this.WakeByAddressAll(ptr_op)?;
+            }
 
             // Dynamic symbol loading
             "GetProcAddress" => {
diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs
index 2b9801fea68..1ce385aaaba 100644
--- a/src/tools/miri/src/shims/windows/sync.rs
+++ b/src/tools/miri/src/shims/windows/sync.rs
@@ -384,6 +384,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         Ok(())
     }
+    fn WakeByAddressAll(&mut self, ptr_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        let ptr = this.read_pointer(ptr_op)?;
+
+        // See the Linux futex implementation for why this fence exists.
+        this.atomic_fence(AtomicFenceOrd::SeqCst)?;
+
+        while let Some(thread) = this.futex_wake(ptr.addr().bytes(), u32::MAX) {
+            this.unblock_thread(thread);
+            this.unregister_timeout_callback_if_exists(thread);
+        }
+
+        Ok(())
+    }
 
     fn SleepConditionVariableSRW(
         &mut self,