@@ -19,55 +19,71 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
19
19
) -> InterpResult < ' tcx , ThreadId > {
20
20
let this = self . eval_context_mut ( ) ;
21
21
22
- if !this. ptr_is_null ( this. read_pointer ( security_op) ?) ? {
23
- throw_unsup_format ! ( "non-null `lpThreadAttributes` in `CreateThread`" )
24
- }
22
+ let security = this. read_pointer ( security_op) ?;
25
23
26
24
// stacksize is ignored, but still needs to be a valid usize
27
- let _ = this. read_scalar ( stacksize_op) ?. to_machine_usize ( this) ?;
25
+ this. read_scalar ( stacksize_op) ?. to_machine_usize ( this) ?;
26
+
27
+ let start_routine = this. read_pointer ( start_op) ?;
28
+
29
+ let func_arg = this. read_immediate ( arg_op) ?;
28
30
29
31
let flags = this. read_scalar ( flags_op) ?. to_u32 ( ) ?;
30
32
33
+ let thread = if this. ptr_is_null ( this. read_pointer ( thread_op) ?) ? {
34
+ None
35
+ } else {
36
+ let thread_info_place = this. deref_operand ( thread_op) ?;
37
+ Some ( thread_info_place)
38
+ } ;
39
+
31
40
let stack_size_param_is_a_reservation =
32
41
this. eval_windows ( "c" , "STACK_SIZE_PARAM_IS_A_RESERVATION" ) ?. to_u32 ( ) ?;
33
42
43
+ // We ignore the stack size, so we also ignore the
44
+ // `STACK_SIZE_PARAM_IS_A_RESERVATION` flag.
34
45
if flags != 0 && flags != stack_size_param_is_a_reservation {
35
46
throw_unsup_format ! ( "unsupported `dwCreationFlags` {} in `CreateThread`" , flags)
36
47
}
37
48
38
- let thread =
39
- if this. ptr_is_null ( this. read_pointer ( thread_op) ?) ? { None } else { Some ( thread_op) } ;
49
+ if !this. ptr_is_null ( security) ? {
50
+ throw_unsup_format ! ( "non-null `lpThreadAttributes` in `CreateThread`" )
51
+ }
40
52
41
53
this. start_thread (
42
54
thread,
43
- start_op ,
55
+ start_routine ,
44
56
Abi :: System { unwind : false } ,
45
- arg_op ,
57
+ func_arg ,
46
58
this. layout_of ( this. tcx . types . u32 ) ?,
47
59
)
48
60
}
49
61
50
62
fn WaitForSingleObject (
51
63
& mut self ,
52
- handle : & OpTy < ' tcx , Provenance > ,
53
- timeout : & OpTy < ' tcx , Provenance > ,
54
- ) -> InterpResult < ' tcx > {
64
+ handle_op : & OpTy < ' tcx , Provenance > ,
65
+ timeout_op : & OpTy < ' tcx , Provenance > ,
66
+ ) -> InterpResult < ' tcx , u32 > {
55
67
let this = self . eval_context_mut ( ) ;
56
68
57
- let thread = match Handle :: from_scalar ( this. read_scalar ( handle) ?. check_init ( ) ?, this) ? {
69
+ let handle = this. read_scalar ( handle_op) ?. check_init ( ) ?;
70
+
71
+ let timeout = this. read_scalar ( timeout_op) ?. to_u32 ( ) ?;
72
+
73
+ let thread = match Handle :: from_scalar ( handle, this) ? {
58
74
Some ( Handle :: Thread ( thread) ) => thread,
59
- // Unlike on posix, joining the current thread is not UB on windows .
60
- // It will just deadlock .
75
+ // Unlike on posix, the outcome of joining the current thread is not documented .
76
+ // On current Windows, it just deadlocks .
61
77
Some ( Handle :: Pseudo ( PseudoHandle :: CurrentThread ) ) => this. get_active_thread ( ) ,
62
78
_ => this. invalid_handle ( "WaitForSingleObject" ) ?,
63
79
} ;
64
80
65
- if this . read_scalar ( timeout) ? . to_u32 ( ) ? != this. eval_windows ( "c" , "INFINITE" ) ?. to_u32 ( ) ? {
81
+ if timeout != this. eval_windows ( "c" , "INFINITE" ) ?. to_u32 ( ) ? {
66
82
throw_unsup_format ! ( "`WaitForSingleObject` with non-infinite timeout" ) ;
67
83
}
68
84
69
85
this. join_thread ( thread) ?;
70
86
71
- Ok ( ( ) )
87
+ Ok ( 0 )
72
88
}
73
89
}
0 commit comments