Skip to content

Commit e68cc6d

Browse files
committed
Auto merge of #121956 - ChrisDenton:srwlock, r=joboet
Windows: Implement condvar, mutex and rwlock using futex Well, the Windows equivalent: [`WaitOnAddress`,](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress) [`WakeByAddressSingle`](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddresssingle) and [`WakeByAddressAll`](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddressall). Note that Windows flavoured futexes can be different sizes (1, 2, 4 or 8 bytes). I took advantage of that in the `Mutex` implementation. I also edited the Mutex implementation a bit more than necessary. I was having trouble keeping in my head what 0, 1 and 2 meant so I replaced them with consts. I *think* we're maybe spinning a bit much. `WaitOnAddress` seems to be looping quite a bit too. But for now I've keep the implementations the same. I do wonder if it'd be worth reducing or removing our spinning on Windows. This also adds a new shim to miri, because of course it does. Fixes #121949
2 parents 6aeab96 + 1c12c21 commit e68cc6d

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

src/shims/windows/foreign_items.rs

+6
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

+15
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)