]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/src/shims/windows/thread.rs
make eval_libc functions ICE on any problem
[rust.git] / src / tools / miri / src / shims / windows / thread.rs
1 use rustc_middle::ty::layout::LayoutOf;
2 use rustc_target::spec::abi::Abi;
3
4 use crate::*;
5 use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle};
6
7 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
8
9 #[allow(non_snake_case)]
10 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
11     fn CreateThread(
12         &mut self,
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();
21
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()?;
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_operand(thread_op)?;
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         // 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)
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             Abi::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, Provenance>,
61         timeout_op: &OpTy<'tcx, Provenance>,
62     ) -> InterpResult<'tcx, u32> {
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::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")?,
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         Ok(0)
83     }
84 }