@@ -6,7 +6,10 @@ use rustc_target::spec::abi::Abi;
6
6
7
7
use crate :: * ;
8
8
use shims:: foreign_items:: EmulateByNameResult ;
9
+ use shims:: windows:: handle:: { EvalContextExt as _, Handle , PseudoHandle } ;
9
10
use shims:: windows:: sync:: EvalContextExt as _;
11
+ use shims:: windows:: thread:: EvalContextExt as _;
12
+
10
13
use smallvec:: SmallVec ;
11
14
12
15
impl < ' 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
219
222
let result = this. QueryPerformanceFrequency ( lpFrequency) ?;
220
223
this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
221
224
}
225
+ "Sleep" => {
226
+ let [ timeout] =
227
+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
228
+
229
+ this. Sleep ( timeout) ?;
230
+ }
222
231
223
232
// Synchronization primitives
224
233
"AcquireSRWLockExclusive" => {
@@ -314,36 +323,57 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
314
323
// FIXME: we should set last_error, but to what?
315
324
this. write_null ( dest) ?;
316
325
}
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
- }
323
326
"GetStdHandle" => {
324
327
let [ which] =
325
328
this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
326
329
let which = this. read_scalar ( which) ?. to_i32 ( ) ?;
327
330
// We just make this the identity function, so we know later in `NtWriteFile` which
328
331
// one it is. This is very fake, but libtest needs it so we cannot make it a
329
332
// std-only shim.
333
+ // FIXME: this should return real HANDLEs when io support is added
330
334
this. write_scalar ( Scalar :: from_machine_isize ( which. into ( ) , this) , dest) ?;
331
335
}
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
+ }
332
344
333
- // Better error for attempts to create a thread
345
+ // Threading
334
346
"CreateThread" => {
335
- let [ _ , _ , _ , _ , _ , _ ] =
347
+ let [ security , stacksize , start , arg , flags , thread ] =
336
348
this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
337
349
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
+ ) ?;
340
369
}
341
370
342
371
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
343
372
// These shims are enabled only when the caller is in the standard library.
344
373
"GetProcessHeap" if this. frame_in_std ( ) => {
345
374
let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
346
375
// Just fake a HANDLE
376
+ // It's fine to not use the Handle type here because its a stub
347
377
this. write_scalar ( Scalar :: from_machine_isize ( 1 , this) , dest) ?;
348
378
}
349
379
"GetModuleHandleA" if this. frame_in_std ( ) => {
@@ -374,45 +404,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
374
404
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
375
405
this. write_scalar ( Scalar :: from_u32 ( 1 ) , dest) ?;
376
406
}
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
- }
411
407
"GetCurrentProcessId" if this. frame_in_std ( ) => {
412
408
let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
413
409
let result = this. GetCurrentProcessId ( ) ?;
414
410
this. write_scalar ( Scalar :: from_u32 ( result) , dest) ?;
415
411
}
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
+ }
416
421
417
422
_ => return Ok ( EmulateByNameResult :: NotSupported ) ,
418
423
}
0 commit comments