miri/shims/windows/
thread.rs
1use rustc_abi::ExternAbi;
2use rustc_middle::ty::layout::LayoutOf;
3
4use self::shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle};
5use crate::*;
6
7impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
8
9#[allow(non_snake_case)]
10pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
11 fn CreateThread(
12 &mut self,
13 security_op: &OpTy<'tcx>,
14 stacksize_op: &OpTy<'tcx>,
15 start_op: &OpTy<'tcx>,
16 arg_op: &OpTy<'tcx>,
17 flags_op: &OpTy<'tcx>,
18 thread_op: &OpTy<'tcx>,
19 ) -> InterpResult<'tcx, ThreadId> {
20 let this = self.eval_context_mut();
21
22 let security = this.read_pointer(security_op)?;
23 this.read_target_usize(stacksize_op)?;
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()?;
28
29 let thread = if this.ptr_is_null(this.read_pointer(thread_op)?)? {
30 None
31 } else {
32 let thread_info_place = this.deref_pointer_as(thread_op, this.machine.layouts.u32)?;
33 Some(thread_info_place)
34 };
35
36 let stack_size_param_is_a_reservation =
37 this.eval_windows_u32("c", "STACK_SIZE_PARAM_IS_A_RESERVATION");
38
39 if flags != 0 && flags != stack_size_param_is_a_reservation {
42 throw_unsup_format!("unsupported `dwCreationFlags` {} in `CreateThread`", flags)
43 }
44
45 if !this.ptr_is_null(security)? {
46 throw_unsup_format!("non-null `lpThreadAttributes` in `CreateThread`")
47 }
48
49 this.start_regular_thread(
50 thread,
51 start_routine,
52 ExternAbi::System { unwind: false },
53 func_arg,
54 this.layout_of(this.tcx.types.u32)?,
55 )
56 }
57
58 fn WaitForSingleObject(
59 &mut self,
60 handle_op: &OpTy<'tcx>,
61 timeout_op: &OpTy<'tcx>,
62 ) -> InterpResult<'tcx, Scalar> {
63 let this = self.eval_context_mut();
64
65 let handle = this.read_scalar(handle_op)?;
66 let timeout = this.read_scalar(timeout_op)?.to_u32()?;
67
68 let thread = match Handle::try_from_scalar(handle, this)? {
69 Ok(Handle::Thread(thread)) => thread,
70 Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.active_thread(),
73 _ => this.invalid_handle("WaitForSingleObject")?,
74 };
75
76 if timeout != this.eval_windows_u32("c", "INFINITE") {
77 throw_unsup_format!("`WaitForSingleObject` with non-infinite timeout");
78 }
79
80 this.join_thread(thread)?;
81
82 interp_ok(this.eval_windows("c", "WAIT_OBJECT_0"))
83 }
84}