Skip to content

Commit 2cd61e6

Browse files
committed
condvar, parking and yielding
1 parent dfc12b2 commit 2cd61e6

File tree

13 files changed

+392
-63
lines changed

13 files changed

+392
-63
lines changed

src/machine.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ pub struct PrimitiveLayouts<'tcx> {
207207
pub u8: TyAndLayout<'tcx>,
208208
pub u16: TyAndLayout<'tcx>,
209209
pub u32: TyAndLayout<'tcx>,
210+
pub u64: TyAndLayout<'tcx>,
210211
pub usize: TyAndLayout<'tcx>,
211212
pub bool: TyAndLayout<'tcx>,
212213
pub mut_raw_ptr: TyAndLayout<'tcx>,
@@ -225,6 +226,7 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
225226
u8: layout_cx.layout_of(tcx.types.u8)?,
226227
u16: layout_cx.layout_of(tcx.types.u16)?,
227228
u32: layout_cx.layout_of(tcx.types.u32)?,
229+
u64: layout_cx.layout_of(tcx.types.u64)?,
228230
usize: layout_cx.layout_of(tcx.types.usize)?,
229231
bool: layout_cx.layout_of(tcx.types.bool)?,
230232
mut_raw_ptr: layout_cx.layout_of(mut_raw_ptr)?,

src/shims/unix/linux/sync.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ pub fn futex<'tcx>(
183183
if val == futex_val {
184184
// The value still matches, so we block the thread make it wait for FUTEX_WAKE.
185185
this.block_thread(thread);
186-
this.futex_wait(addr_usize, thread, bitset);
186+
this.futex_wait(addr_usize, thread, bitset, None);
187187
// Succesfully waking up from FUTEX_WAIT always returns zero.
188188
this.write_scalar(Scalar::from_machine_isize(0, this), dest)?;
189189
// Register a timeout callback if a timeout was specified.
@@ -243,9 +243,9 @@ pub fn futex<'tcx>(
243243
this.atomic_fence(&[], AtomicFenceOrd::SeqCst)?;
244244
let mut n = 0;
245245
for _ in 0..val {
246-
if let Some(thread) = this.futex_wake(addr_usize, bitset) {
247-
this.unblock_thread(thread);
248-
this.unregister_timeout_callback_if_exists(thread);
246+
if let Some(waiter) = this.futex_wake(addr_usize, bitset) {
247+
this.unblock_thread(waiter.thread);
248+
this.unregister_timeout_callback_if_exists(waiter.thread);
249249
n += 1;
250250
} else {
251251
break;

src/shims/unix/sync.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -753,8 +753,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
753753
fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
754754
let this = self.eval_context_mut();
755755
let id = cond_get_or_create_id(this, cond_op)?;
756-
if let Some((thread, mutex)) = this.condvar_signal(id) {
757-
post_cond_signal(this, thread, mutex)?;
756+
if let Some((thread, mutex, _)) = this.condvar_signal(id) {
757+
post_cond_signal(this, thread, MutexId::from_u32(mutex))?;
758758
}
759759

760760
Ok(0)
@@ -764,8 +764,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
764764
let this = self.eval_context_mut();
765765
let id = cond_get_or_create_id(this, cond_op)?;
766766

767-
while let Some((thread, mutex)) = this.condvar_signal(id) {
768-
post_cond_signal(this, thread, mutex)?;
767+
while let Some((thread, mutex, _)) = this.condvar_signal(id) {
768+
post_cond_signal(this, thread, MutexId::from_u32(mutex))?;
769769
}
770770

771771
Ok(0)
@@ -783,7 +783,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
783783
let active_thread = this.get_active_thread();
784784

785785
release_cond_mutex_and_block(this, active_thread, mutex_id)?;
786-
this.condvar_wait(id, active_thread, mutex_id);
786+
this.condvar_wait(id, active_thread, mutex_id.to_u32(), false);
787787

788788
Ok(0)
789789
}
@@ -823,7 +823,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
823823
};
824824

825825
release_cond_mutex_and_block(this, active_thread, mutex_id)?;
826-
this.condvar_wait(id, active_thread, mutex_id);
826+
this.condvar_wait(id, active_thread, mutex_id.to_u32(), false);
827827

828828
// We return success for now and override it in the timeout callback.
829829
this.write_scalar(Scalar::from_i32(0), dest)?;

src/shims/windows/dlsym.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ use log::trace;
66

77
use crate::helpers::check_arg_count;
88
use crate::shims::windows::handle::Handle;
9+
use crate::shims::windows::sync::EvalContextExt as _;
910
use crate::*;
1011

1112
#[derive(Debug, Copy, Clone)]
1213
pub enum Dlsym {
1314
NtWriteFile,
1415
SetThreadDescription,
16+
WaitOnAddress,
17+
WakeByAddressSingle,
1518
}
1619

1720
impl Dlsym {
@@ -20,9 +23,10 @@ impl Dlsym {
2023
pub fn from_str<'tcx>(name: &str) -> InterpResult<'tcx, Option<Dlsym>> {
2124
Ok(match name {
2225
"GetSystemTimePreciseAsFileTime" => None,
23-
"SetThreadDescription" => None,
2426
"NtWriteFile" => Some(Dlsym::NtWriteFile),
2527
"SetThreadDescription" => Some(Dlsym::SetThreadDescription),
28+
"WaitOnAddress" => Some(Dlsym::WaitOnAddress),
29+
"WakeByAddressSingle" => Some(Dlsym::WakeByAddressSingle),
2630
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
2731
})
2832
}
@@ -125,6 +129,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
125129

126130
this.write_null(dest)?;
127131
}
132+
Dlsym::WaitOnAddress => {
133+
let [ptr_op, compare_op, size_op, timeout_op] = check_arg_count(args)?;
134+
135+
this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?;
136+
}
137+
Dlsym::WakeByAddressSingle => {
138+
let [ptr_op] = check_arg_count(args)?;
139+
140+
this.WakeByAddressSingle(ptr_op)?;
141+
}
128142
}
129143

130144
trace!("{:?}", this.dump_place(**dest));

src/shims/windows/foreign_items.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
286286
let ret = this.TryAcquireSRWLockShared(ptr)?;
287287
this.write_scalar(Scalar::from_u8(ret), dest)?;
288288
}
289+
"SleepConditionVariableSRW" => {
290+
let [condvar, lock, timeout, flags] =
291+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
292+
293+
this.SleepConditionVariableSRW(condvar, lock, timeout, flags, dest)?;
294+
}
295+
"WakeConditionVariable" => {
296+
let [condvar] =
297+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
298+
299+
this.WakeConditionVariable(condvar)?;
300+
}
301+
"WakeAllConditionVariable" => {
302+
let [condvar] =
303+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
304+
305+
this.WakeAllConditionVariable(condvar)?;
306+
}
289307

290308
// Dynamic symbol loading
291309
"GetProcAddress" => {
@@ -353,10 +371,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
353371
// FIXME: we should set last_error, but to what?
354372
this.write_null(dest)?;
355373
}
356-
"SwitchToThread" => {
374+
// this is only callable from std because we know that std ignores the return value
375+
"SwitchToThread" if this.frame_in_std() => {
357376
let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
358-
// Note that once Miri supports concurrency, this will need to return a nonzero
359-
// value if this call does result in switching to another thread.
377+
378+
this.yield_active_thread();
379+
380+
// FIXME: this should return a nonzero value if this call does result in switching to another thread.
360381
this.write_null(dest)?;
361382
}
362383
"GetStdHandle" => {
@@ -469,10 +490,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
469490
// There is only one thread, so this always succeeds and returns TRUE.
470491
this.write_scalar(Scalar::from_i32(1), dest)?;
471492
}
472-
"GetCurrentThread" if this.frame_in_std() => {
473-
let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
474-
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
475-
}
476493
"GetCurrentProcessId" if this.frame_in_std() => {
477494
let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
478495
let result = this.GetCurrentProcessId()?;

0 commit comments

Comments
 (0)