1
1
use std:: iter;
2
+ use std:: time:: { Duration , Instant } ;
2
3
3
4
use rustc_span:: Symbol ;
4
5
use rustc_target:: abi:: Size ;
5
6
use rustc_target:: spec:: abi:: Abi ;
6
7
8
+ use crate :: thread:: Time ;
7
9
use crate :: * ;
8
10
use shims:: foreign_items:: EmulateByNameResult ;
11
+ use shims:: windows:: handle:: { EvalContextExt as _, Handle } ;
9
12
use shims:: windows:: sync:: EvalContextExt as _;
13
+ use shims:: windows:: thread:: EvalContextExt as _;
14
+
10
15
use smallvec:: SmallVec ;
11
16
12
17
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
@@ -219,6 +224,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
219
224
let result = this. QueryPerformanceFrequency ( lpFrequency) ?;
220
225
this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
221
226
}
227
+ "Sleep" => {
228
+ let [ timeout] =
229
+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
230
+
231
+ this. check_no_isolation ( "`Sleep`" ) ?;
232
+
233
+ let timeout_ms = this. read_scalar ( timeout) ?. to_u32 ( ) ?;
234
+
235
+ let duration = Duration :: from_millis ( timeout_ms as u64 ) ;
236
+ let timeout_time = Time :: Monotonic ( Instant :: now ( ) . checked_add ( duration) . unwrap ( ) ) ;
237
+
238
+ let active_thread = this. get_active_thread ( ) ;
239
+ this. block_thread ( active_thread) ;
240
+
241
+ this. register_timeout_callback (
242
+ active_thread,
243
+ timeout_time,
244
+ Box :: new ( move |ecx| {
245
+ ecx. unblock_thread ( active_thread) ;
246
+ Ok ( ( ) )
247
+ } ) ,
248
+ ) ;
249
+ }
222
250
223
251
// Synchronization primitives
224
252
"AcquireSRWLockExclusive" => {
@@ -314,10 +342,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
314
342
// FIXME: we should set last_error, but to what?
315
343
this. write_null ( dest) ?;
316
344
}
317
- "SwitchToThread" => {
345
+ // this is only callable from std because we know that std ignores the return value
346
+ "SwitchToThread" if this. frame_in_std ( ) => {
318
347
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.
348
+
349
+ this. yield_active_thread ( ) ;
350
+
351
+ // FIXME: this should return a nonzero value if this call does result in switching to another thread.
321
352
this. write_null ( dest) ?;
322
353
}
323
354
"GetStdHandle" => {
@@ -329,14 +360,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
329
360
// std-only shim.
330
361
this. write_scalar ( Scalar :: from_machine_isize ( which. into ( ) , this) , dest) ?;
331
362
}
363
+ "CloseHandle" => {
364
+ let [ handle] =
365
+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
332
366
333
- // Better error for attempts to create a thread
367
+ this. CloseHandle ( handle) ?;
368
+
369
+ this. write_scalar ( Scalar :: from_u32 ( 1 ) , dest) ?;
370
+ }
371
+
372
+ // Threading
334
373
"CreateThread" => {
335
- let [ _ , _ , _ , _ , _ , _ ] =
374
+ let [ security , stacksize , start , arg , flags , thread ] =
336
375
this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
337
376
338
- this. handle_unsupported ( "can't create threads on Windows" ) ?;
339
- return Ok ( EmulateByNameResult :: AlreadyJumped ) ;
377
+ let thread_id =
378
+ this. CreateThread ( security, stacksize, start, arg, flags, thread) ?;
379
+
380
+ this. write_scalar ( Handle :: Thread ( thread_id) . to_scalar ( this) , dest) ?;
381
+ }
382
+ "WaitForSingleObject" => {
383
+ let [ handle, timeout] =
384
+ this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
385
+
386
+ this. WaitForSingleObject ( handle, timeout) ?;
387
+
388
+ this. write_scalar ( Scalar :: from_u32 ( 0 ) , dest) ?;
389
+ }
390
+ "GetCurrentThread" => {
391
+ let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
392
+
393
+ this. write_scalar ( Handle :: CurrentThread . to_scalar ( this) , dest) ?;
340
394
}
341
395
342
396
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
@@ -374,40 +428,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
374
428
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
375
429
this. write_scalar ( Scalar :: from_u32 ( 1 ) , dest) ?;
376
430
}
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
431
"GetCurrentProcessId" if this. frame_in_std ( ) => {
412
432
let [ ] = this. check_shim ( abi, Abi :: System { unwind : false } , link_name, args) ?;
413
433
let result = this. GetCurrentProcessId ( ) ?;
0 commit comments