|
1 | 1 | use std::iter; |
| 2 | +use std::time::{Duration, Instant}; |
2 | 3 |
|
3 | 4 | use rustc_middle::mir; |
| 5 | +use rustc_middle::ty::layout::LayoutOf; |
4 | 6 | use rustc_span::Symbol; |
5 | 7 | use rustc_target::abi::Size; |
6 | 8 | use rustc_target::spec::abi::Abi; |
7 | 9 |
|
| 10 | +use crate::thread::Time; |
8 | 11 | use crate::*; |
9 | 12 | use shims::foreign_items::EmulateByNameResult; |
| 13 | +use shims::windows::handle::Handle; |
10 | 14 | use shims::windows::sync::EvalContextExt as _; |
| 15 | +use shims::windows::thread::EvalContextExt as _; |
| 16 | + |
11 | 17 | use smallvec::SmallVec; |
12 | 18 |
|
13 | 19 | impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} |
@@ -230,6 +236,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx |
230 | 236 | let result = this.QueryPerformanceFrequency(lpFrequency)?; |
231 | 237 | this.write_scalar(Scalar::from_i32(result), dest)?; |
232 | 238 | } |
| 239 | + "Sleep" => { |
| 240 | + let [timeout] = |
| 241 | + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; |
| 242 | + |
| 243 | + this.check_no_isolation("`Sleep`")?; |
| 244 | + |
| 245 | + let timeout_ms = this.read_scalar(timeout)?.to_u32()?; |
| 246 | + |
| 247 | + let duration = Duration::from_millis(timeout_ms as u64); |
| 248 | + let timeout_time = Time::Monotonic(Instant::now().checked_add(duration).unwrap()); |
| 249 | + |
| 250 | + let active_thread = this.get_active_thread(); |
| 251 | + this.block_thread(active_thread); |
| 252 | + |
| 253 | + this.register_timeout_callback( |
| 254 | + active_thread, |
| 255 | + timeout_time, |
| 256 | + Box::new(move |ecx| { |
| 257 | + ecx.unblock_thread(active_thread); |
| 258 | + Ok(()) |
| 259 | + }), |
| 260 | + ); |
| 261 | + } |
233 | 262 |
|
234 | 263 | // Synchronization primitives |
235 | 264 | "AcquireSRWLockExclusive" => { |
@@ -340,14 +369,48 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx |
340 | 369 | // std-only shim. |
341 | 370 | this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?; |
342 | 371 | } |
| 372 | + "CloseHandle" => { |
| 373 | + let [handle] = |
| 374 | + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; |
| 375 | + |
| 376 | + match Handle::from_scalar(this.read_scalar(handle)?.check_init()?, this)? { |
| 377 | + Some(Handle::Thread(thread)) => this.detach_thread(thread)?, |
| 378 | + _ => throw_ub_format!("invalid handle"), |
| 379 | + }; |
343 | 380 |
|
344 | | - // Better error for attempts to create a thread |
| 381 | + this.write_scalar(Scalar::from_u32(1), dest)?; |
| 382 | + } |
| 383 | + |
| 384 | + // Threading |
345 | 385 | "CreateThread" => { |
346 | | - let [_, _, _, _, _, _] = |
| 386 | + let [_security, _stacksize, start, arg, _flags, thread] = |
| 387 | + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; |
| 388 | + |
| 389 | + let thread = |
| 390 | + if this.ptr_is_null(this.read_pointer(thread)?)? { None } else { Some(thread) }; |
| 391 | + |
| 392 | + let thread_id = this.start_thread( |
| 393 | + thread, |
| 394 | + start, |
| 395 | + Abi::System { unwind: false }, |
| 396 | + arg, |
| 397 | + this.layout_of(this.tcx.types.u32)?, |
| 398 | + )?; |
| 399 | + |
| 400 | + this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; |
| 401 | + } |
| 402 | + "WaitForSingleObject" => { |
| 403 | + let [handle, timeout] = |
347 | 404 | this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; |
348 | 405 |
|
349 | | - this.handle_unsupported("can't create threads on Windows")?; |
350 | | - return Ok(EmulateByNameResult::AlreadyJumped); |
| 406 | + this.WaitForSingleObject(handle, timeout)?; |
| 407 | + |
| 408 | + this.write_scalar(Scalar::from_u32(0), dest)?; |
| 409 | + } |
| 410 | + "GetCurrentThread" => { |
| 411 | + let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; |
| 412 | + |
| 413 | + this.write_scalar(Handle::CurrentThread.to_scalar(this), dest)?; |
351 | 414 | } |
352 | 415 |
|
353 | 416 | // Incomplete shims that we "stub out" just to get pre-main initialization code to work. |
|
0 commit comments