@@ -6,7 +6,10 @@ use rustc_target::spec::abi::Abi;
66
77use crate :: * ;
88use shims:: foreign_items:: EmulateByNameResult ;
9+ use shims:: windows:: handle:: { EvalContextExt as _, Handle , PseudoHandle } ;
910use shims:: windows:: sync:: EvalContextExt as _;
11+ use shims:: windows:: thread:: EvalContextExt as _;
12+
1013use smallvec:: SmallVec ;
1114
1215impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
@@ -219,6 +222,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
219222 let result = this. QueryPerformanceFrequency ( lpFrequency) ?;
220223 this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
221224 }
225+ "Sleep" => {
226+ let [ timeout] =
227+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
228+
229+ this. Sleep ( timeout) ?;
230+ }
222231
223232 // Synchronization primitives
224233 "AcquireSRWLockExclusive" => {
@@ -314,36 +323,57 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
314323 // FIXME: we should set last_error, but to what?
315324 this. write_null ( dest) ?;
316325 }
317- "SwitchToThread" => {
318- let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
319- // Note that once Miri supports concurrency, this will need to return a nonzero
320- // value if this call does result in switching to another thread.
321- this. write_null ( dest) ?;
322- }
323326 "GetStdHandle" => {
324327 let [ which] =
325328 this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
326329 let which = this. read_scalar ( which) ?. to_i32 ( ) ?;
327330 // We just make this the identity function, so we know later in `NtWriteFile` which
328331 // one it is. This is very fake, but libtest needs it so we cannot make it a
329332 // std-only shim.
333+ // FIXME: this should return real HANDLEs when io support is added
330334 this. write_scalar ( Scalar :: from_machine_isize ( which. into ( ) , this) , dest) ?;
331335 }
336+ "CloseHandle" => {
337+ let [ handle] =
338+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
339+
340+ this. CloseHandle ( handle) ?;
341+
342+ this. write_scalar ( Scalar :: from_u32 ( 1 ) , dest) ?;
343+ }
332344
333- // Better error for attempts to create a thread
345+ // Threading
334346 "CreateThread" => {
335- let [ _ , _ , _ , _ , _ , _ ] =
347+ let [ security , stacksize , start , arg , flags , thread ] =
336348 this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
337349
338- this. handle_unsupported ( "can't create threads on Windows" ) ?;
339- return Ok ( EmulateByNameResult :: AlreadyJumped ) ;
350+ let thread_id =
351+ this. CreateThread ( security, stacksize, start, arg, flags, thread) ?;
352+
353+ this. write_scalar ( Handle :: Thread ( thread_id) . to_scalar ( this) , dest) ?;
354+ }
355+ "WaitForSingleObject" => {
356+ let [ handle, timeout] =
357+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
358+
359+ let ret = this. WaitForSingleObject ( handle, timeout) ?;
360+ this. write_scalar ( Scalar :: from_u32 ( ret) , dest) ?;
361+ }
362+ "GetCurrentThread" => {
363+ let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
364+
365+ this. write_scalar (
366+ Handle :: Pseudo ( PseudoHandle :: CurrentThread ) . to_scalar ( this) ,
367+ dest,
368+ ) ?;
340369 }
341370
342371 // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
343372 // These shims are enabled only when the caller is in the standard library.
344373 "GetProcessHeap" if this. frame_in_std ( ) => {
345374 let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
346375 // Just fake a HANDLE
376+ // It's fine to not use the Handle type here because its a stub
347377 this. write_scalar ( Scalar :: from_machine_isize ( 1 , this) , dest) ?;
348378 }
349379 "GetModuleHandleA" if this. frame_in_std ( ) => {
@@ -374,45 +404,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
374404 // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
375405 this. write_scalar ( Scalar :: from_u32 ( 1 ) , dest) ?;
376406 }
377- | "InitializeCriticalSection"
378- | "EnterCriticalSection"
379- | "LeaveCriticalSection"
380- | "DeleteCriticalSection"
381- if this. frame_in_std ( ) =>
382- {
383- #[ allow( non_snake_case) ]
384- let [ _lpCriticalSection] =
385- this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
386- assert_eq ! (
387- this. get_total_thread_count( ) ,
388- 1 ,
389- "concurrency on Windows is not supported"
390- ) ;
391- // Nothing to do, not even a return value.
392- // (Windows locks are reentrant, and we have only 1 thread,
393- // so not doing any futher checks here is at least not incorrect.)
394- }
395- "TryEnterCriticalSection" if this. frame_in_std ( ) => {
396- #[ allow( non_snake_case) ]
397- let [ _lpCriticalSection] =
398- this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
399- assert_eq ! (
400- this. get_total_thread_count( ) ,
401- 1 ,
402- "concurrency on Windows is not supported"
403- ) ;
404- // There is only one thread, so this always succeeds and returns TRUE.
405- this. write_scalar ( Scalar :: from_i32 ( 1 ) , dest) ?;
406- }
407- "GetCurrentThread" if this. frame_in_std ( ) => {
408- let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
409- this. write_scalar ( Scalar :: from_machine_isize ( 1 , this) , dest) ?;
410- }
411407 "GetCurrentProcessId" if this. frame_in_std ( ) => {
412408 let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
413409 let result = this. GetCurrentProcessId ( ) ?;
414410 this. write_scalar ( Scalar :: from_u32 ( result) , dest) ?;
415411 }
412+ // this is only callable from std because we know that std ignores the return value
413+ "SwitchToThread" if this. frame_in_std ( ) => {
414+ let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
415+
416+ this. yield_active_thread ( ) ;
417+
418+ // FIXME: this should return a nonzero value if this call does result in switching to another thread.
419+ this. write_null ( dest) ?;
420+ }
416421
417422 _ => return Ok ( EmulateByNameResult :: NotSupported ) ,
418423 }
0 commit comments