1
1
use std:: iter;
2
+ use std:: time:: { Duration , Instant } ;
2
3
3
4
use rustc_middle:: mir;
4
5
use rustc_span:: Symbol ;
5
6
use rustc_target:: abi:: Size ;
6
7
use rustc_target:: spec:: abi:: Abi ;
7
8
9
+ use crate :: thread:: Time ;
8
10
use crate :: * ;
9
11
use shims:: foreign_items:: EmulateByNameResult ;
12
+ use shims:: windows:: handle:: { EvalContextExt as _, Handle } ;
10
13
use shims:: windows:: sync:: EvalContextExt as _;
14
+ use shims:: windows:: thread:: EvalContextExt as _;
15
+
11
16
use smallvec:: SmallVec ;
12
17
13
18
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
@@ -230,6 +235,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
230
235
let result = this. QueryPerformanceFrequency ( lpFrequency) ?;
231
236
this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
232
237
}
238
+ "Sleep" => {
239
+ let [ timeout] =
240
+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
241
+
242
+ this. check_no_isolation ( "`Sleep`" ) ?;
243
+
244
+ let timeout_ms = this. read_scalar ( timeout) ?. to_u32 ( ) ?;
245
+
246
+ let duration = Duration :: from_millis ( timeout_ms as u64 ) ;
247
+ let timeout_time = Time :: Monotonic ( Instant :: now ( ) . checked_add ( duration) . unwrap ( ) ) ;
248
+
249
+ let active_thread = this. get_active_thread ( ) ;
250
+ this. block_thread ( active_thread) ;
251
+
252
+ this. register_timeout_callback (
253
+ active_thread,
254
+ timeout_time,
255
+ Box :: new ( move |ecx| {
256
+ ecx. unblock_thread ( active_thread) ;
257
+ Ok ( ( ) )
258
+ } ) ,
259
+ ) ;
260
+ }
233
261
234
262
// Synchronization primitives
235
263
"AcquireSRWLockExclusive" => {
@@ -325,10 +353,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
325
353
// FIXME: we should set last_error, but to what?
326
354
this. write_null ( dest) ?;
327
355
}
328
- "SwitchToThread" => {
356
+ // this is only callable from std because we know that std ignores the return value
357
+ "SwitchToThread" if this. frame_in_std ( ) => {
329
358
let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
330
- // Note that once Miri supports concurrency, this will need to return a nonzero
331
- // value if this call does result in switching to another thread.
359
+
360
+ this. yield_active_thread ( ) ;
361
+
362
+ // FIXME: this should return a nonzero value if this call does result in switching to another thread.
332
363
this. write_null ( dest) ?;
333
364
}
334
365
"GetStdHandle" => {
@@ -340,14 +371,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
340
371
// std-only shim.
341
372
this. write_scalar ( Scalar :: from_machine_isize ( which. into ( ) , this) , dest) ?;
342
373
}
374
+ "CloseHandle" => {
375
+ let [ handle] =
376
+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
343
377
344
- // Better error for attempts to create a thread
378
+ this. CloseHandle ( handle) ?;
379
+
380
+ this. write_scalar ( Scalar :: from_u32 ( 1 ) , dest) ?;
381
+ }
382
+
383
+ // Threading
345
384
"CreateThread" => {
346
- let [ _ , _ , _ , _ , _ , _ ] =
385
+ let [ security , stacksize , start , arg , flags , thread ] =
347
386
this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
348
387
349
- this. handle_unsupported ( "can't create threads on Windows" ) ?;
350
- return Ok ( EmulateByNameResult :: AlreadyJumped ) ;
388
+ let thread_id =
389
+ this. CreateThread ( security, stacksize, start, arg, flags, thread) ?;
390
+
391
+ this. write_scalar ( Handle :: Thread ( thread_id) . to_scalar ( this) , dest) ?;
392
+ }
393
+ "WaitForSingleObject" => {
394
+ let [ handle, timeout] =
395
+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
396
+
397
+ this. WaitForSingleObject ( handle, timeout) ?;
398
+
399
+ this. write_scalar ( Scalar :: from_u32 ( 0 ) , dest) ?;
400
+ }
401
+ "GetCurrentThread" => {
402
+ let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
403
+
404
+ this. write_scalar ( Handle :: CurrentThread . to_scalar ( this) , dest) ?;
351
405
}
352
406
353
407
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
@@ -385,40 +439,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
385
439
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
386
440
this. write_scalar ( Scalar :: from_u32 ( 1 ) , dest) ?;
387
441
}
388
- | "InitializeCriticalSection"
389
- | "EnterCriticalSection"
390
- | "LeaveCriticalSection"
391
- | "DeleteCriticalSection"
392
- if this. frame_in_std ( ) =>
393
- {
394
- #[ allow( non_snake_case) ]
395
- let [ _lpCriticalSection] =
396
- this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
397
- assert_eq ! (
398
- this. get_total_thread_count( ) ,
399
- 1 ,
400
- "concurrency on Windows is not supported"
401
- ) ;
402
- // Nothing to do, not even a return value.
403
- // (Windows locks are reentrant, and we have only 1 thread,
404
- // so not doing any futher checks here is at least not incorrect.)
405
- }
406
- "TryEnterCriticalSection" if this. frame_in_std ( ) => {
407
- #[ allow( non_snake_case) ]
408
- let [ _lpCriticalSection] =
409
- this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
410
- assert_eq ! (
411
- this. get_total_thread_count( ) ,
412
- 1 ,
413
- "concurrency on Windows is not supported"
414
- ) ;
415
- // There is only one thread, so this always succeeds and returns TRUE.
416
- this. write_scalar ( Scalar :: from_i32 ( 1 ) , dest) ?;
417
- }
418
- "GetCurrentThread" if this. frame_in_std ( ) => {
419
- let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
420
- this. write_scalar ( Scalar :: from_machine_isize ( 1 , this) , dest) ?;
421
- }
422
442
"GetCurrentProcessId" if this. frame_in_std ( ) => {
423
443
let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
424
444
let result = this. GetCurrentProcessId ( ) ?;
0 commit comments