Skip to content

Commit 1c12c21

Browse files
committed
Windows: Implement mutex using futex
Well, the Windows equivalent: `WaitOnAddress`, `WakeByAddressSingle` and `WakeByAddressAll`.
1 parent 6eaf8c5 commit 1c12c21

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

src/shims/windows/foreign_items.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
366366

367367
this.WakeByAddressSingle(ptr_op)?;
368368
}
369+
"WakeByAddressAll" => {
370+
let [ptr_op] =
371+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
372+
373+
this.WakeByAddressAll(ptr_op)?;
374+
}
369375

370376
// Dynamic symbol loading
371377
"GetProcAddress" => {

src/shims/windows/sync.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
384384

385385
Ok(())
386386
}
387+
fn WakeByAddressAll(&mut self, ptr_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
388+
let this = self.eval_context_mut();
389+
390+
let ptr = this.read_pointer(ptr_op)?;
391+
392+
// See the Linux futex implementation for why this fence exists.
393+
this.atomic_fence(AtomicFenceOrd::SeqCst)?;
394+
395+
while let Some(thread) = this.futex_wake(ptr.addr().bytes(), u32::MAX) {
396+
this.unblock_thread(thread);
397+
this.unregister_timeout_callback_if_exists(thread);
398+
}
399+
400+
Ok(())
401+
}
387402

388403
fn SleepConditionVariableSRW(
389404
&mut self,

0 commit comments

Comments
 (0)