1 use rustc_middle::ty::layout::LayoutOf;
2 use rustc_target::spec::abi::Abi;
5 use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle};
7 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
9 #[allow(non_snake_case)]
10 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
13 security_op: &OpTy<'tcx, Provenance>,
14 stacksize_op: &OpTy<'tcx, Provenance>,
15 start_op: &OpTy<'tcx, Provenance>,
16 arg_op: &OpTy<'tcx, Provenance>,
17 flags_op: &OpTy<'tcx, Provenance>,
18 thread_op: &OpTy<'tcx, Provenance>,
19 ) -> InterpResult<'tcx, ThreadId> {
20 let this = self.eval_context_mut();
22 let security = this.read_pointer(security_op)?;
23 // stacksize is ignored, but still needs to be a valid usize
24 this.read_scalar(stacksize_op)?.to_machine_usize(this)?;
25 let start_routine = this.read_pointer(start_op)?;
26 let func_arg = this.read_immediate(arg_op)?;
27 let flags = this.read_scalar(flags_op)?.to_u32()?;
29 let thread = if this.ptr_is_null(this.read_pointer(thread_op)?)? {
32 let thread_info_place = this.deref_operand(thread_op)?;
33 Some(thread_info_place)
36 let stack_size_param_is_a_reservation =
37 this.eval_windows_u32("c", "STACK_SIZE_PARAM_IS_A_RESERVATION");
39 // We ignore the stack size, so we also ignore the
40 // `STACK_SIZE_PARAM_IS_A_RESERVATION` flag.
41 if flags != 0 && flags != stack_size_param_is_a_reservation {
42 throw_unsup_format!("unsupported `dwCreationFlags` {} in `CreateThread`", flags)
45 if !this.ptr_is_null(security)? {
46 throw_unsup_format!("non-null `lpThreadAttributes` in `CreateThread`")
49 this.start_regular_thread(
52 Abi::System { unwind: false },
54 this.layout_of(this.tcx.types.u32)?,
58 fn WaitForSingleObject(
60 handle_op: &OpTy<'tcx, Provenance>,
61 timeout_op: &OpTy<'tcx, Provenance>,
62 ) -> InterpResult<'tcx, u32> {
63 let this = self.eval_context_mut();
65 let handle = this.read_scalar(handle_op)?;
66 let timeout = this.read_scalar(timeout_op)?.to_u32()?;
68 let thread = match Handle::from_scalar(handle, this)? {
69 Some(Handle::Thread(thread)) => thread,
70 // Unlike on posix, the outcome of joining the current thread is not documented.
71 // On current Windows, it just deadlocks.
72 Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(),
73 _ => this.invalid_handle("WaitForSingleObject")?,
76 if timeout != this.eval_windows_u32("c", "INFINITE") {
77 throw_unsup_format!("`WaitForSingleObject` with non-infinite timeout");
80 this.join_thread(thread)?;