Skip to content

Commit 7fa1be5

Browse files
committed
condvar, parking and yielding
1 parent e2f3e84 commit 7fa1be5

File tree

13 files changed

+414
-74
lines changed

13 files changed

+414
-74
lines changed

src/machine.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ pub struct PrimitiveLayouts<'tcx> {
209209
pub u8: TyAndLayout<'tcx>,
210210
pub u16: TyAndLayout<'tcx>,
211211
pub u32: TyAndLayout<'tcx>,
212+
pub u64: TyAndLayout<'tcx>,
212213
pub usize: TyAndLayout<'tcx>,
213214
pub bool: TyAndLayout<'tcx>,
214215
pub mut_raw_ptr: TyAndLayout<'tcx>,
@@ -227,6 +228,7 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
227228
u8: layout_cx.layout_of(tcx.types.u8)?,
228229
u16: layout_cx.layout_of(tcx.types.u16)?,
229230
u32: layout_cx.layout_of(tcx.types.u32)?,
231+
u64: layout_cx.layout_of(tcx.types.u64)?,
230232
usize: layout_cx.layout_of(tcx.types.usize)?,
231233
bool: layout_cx.layout_of(tcx.types.bool)?,
232234
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
@@ -149,7 +149,7 @@ pub fn futex<'tcx>(
149149
if val == futex_val {
150150
// The value still matches, so we block the trait make it wait for FUTEX_WAKE.
151151
this.block_thread(thread);
152-
this.futex_wait(addr_usize, thread, bitset);
152+
this.futex_wait(addr_usize, thread, bitset, None);
153153
// Succesfully waking up from FUTEX_WAIT always returns zero.
154154
this.write_scalar(Scalar::from_machine_isize(0, this), dest)?;
155155
// Register a timeout callback if a timeout was specified.
@@ -205,9 +205,9 @@ pub fn futex<'tcx>(
205205
}
206206
let mut n = 0;
207207
for _ in 0..val {
208-
if let Some(thread) = this.futex_wake(addr_usize, bitset) {
209-
this.unblock_thread(thread);
210-
this.unregister_timeout_callback_if_exists(thread);
208+
if let Some(waiter) = this.futex_wake(addr_usize, bitset) {
209+
this.unblock_thread(waiter.thread);
210+
this.unregister_timeout_callback_if_exists(waiter.thread);
211211
n += 1;
212212
} else {
213213
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 & 0 deletions
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 {
@@ -23,6 +26,8 @@ impl Dlsym {
2326
"SetThreadDescription" => None,
2427
"NtWriteFile" => Some(Dlsym::NtWriteFile),
2528
"SetThreadDescription" => Some(Dlsym::SetThreadDescription),
29+
"WaitOnAddress" => Some(Dlsym::WaitOnAddress),
30+
"WakeByAddressSingle" => Some(Dlsym::WakeByAddressSingle),
2631
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
2732
})
2833
}
@@ -125,6 +130,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
125130

126131
this.write_null(dest)?;
127132
}
133+
Dlsym::WaitOnAddress => {
134+
let [ptr_op, compare_op, size_op, timeout_op] = check_arg_count(args)?;
135+
136+
this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?;
137+
}
138+
Dlsym::WakeByAddressSingle => {
139+
let [ptr_op] = check_arg_count(args)?;
140+
141+
this.WakeByAddressSingle(ptr_op)?;
142+
}
128143
}
129144

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

src/shims/windows/foreign_items.rs

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

291309
// Dynamic symbol loading
292310
"GetProcAddress" => {
@@ -356,8 +374,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
356374
}
357375
"SwitchToThread" => {
358376
let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
359-
// Note that once Miri supports concurrency, this will need to return a nonzero
360-
// 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.
361381
this.write_null(dest)?;
362382
}
363383
"GetStdHandle" => {

0 commit comments

Comments
 (0)