@@ -19,55 +19,71 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1919 ) -> InterpResult < ' tcx , ThreadId > {
2020 let this = self . eval_context_mut ( ) ;
2121
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) ?;
2523
2624 // 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) ?;
2830
2931 let flags = this. read_scalar ( flags_op) ?. to_u32 ( ) ?;
3032
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+
3140 let stack_size_param_is_a_reservation =
3241 this. eval_windows ( "c" , "STACK_SIZE_PARAM_IS_A_RESERVATION" ) ?. to_u32 ( ) ?;
3342
43+ // We ignore the stack size, so we also ignore the
44+ // `STACK_SIZE_PARAM_IS_A_RESERVATION` flag.
3445 if flags != 0 && flags != stack_size_param_is_a_reservation {
3546 throw_unsup_format ! ( "unsupported `dwCreationFlags` {} in `CreateThread`" , flags)
3647 }
3748
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+ }
4052
4153 this. start_thread (
4254 thread,
43- start_op ,
55+ start_routine ,
4456 Abi :: System { unwind : false } ,
45- arg_op ,
57+ func_arg ,
4658 this. layout_of ( this. tcx . types . u32 ) ?,
4759 )
4860 }
4961
5062 fn WaitForSingleObject (
5163 & 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 > {
5567 let this = self . eval_context_mut ( ) ;
5668
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) ? {
5874 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 .
6177 Some ( Handle :: Pseudo ( PseudoHandle :: CurrentThread ) ) => this. get_active_thread ( ) ,
6278 _ => this. invalid_handle ( "WaitForSingleObject" ) ?,
6379 } ;
6480
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 ( ) ? {
6682 throw_unsup_format ! ( "`WaitForSingleObject` with non-infinite timeout" ) ;
6783 }
6884
6985 this. join_thread ( thread) ?;
7086
71- Ok ( ( ) )
87+ Ok ( 0 )
7288 }
7389}
0 commit comments