mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Windows: Support sub-millisecond sleep
Use `CreateWaitableTimerExW` with `CREATE_WAITABLE_TIMER_HIGH_RESOLUTION`. Does not work before Windows 10, version 1803 so in that case we fallback to using `Sleep`.
This commit is contained in:
parent
cae0791da4
commit
fca182b6a0
@ -2503,9 +2503,12 @@ Windows.Win32.System.Threading.CREATE_SEPARATE_WOW_VDM
|
||||
Windows.Win32.System.Threading.CREATE_SHARED_WOW_VDM
|
||||
Windows.Win32.System.Threading.CREATE_SUSPENDED
|
||||
Windows.Win32.System.Threading.CREATE_UNICODE_ENVIRONMENT
|
||||
Windows.Win32.System.Threading.CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
||||
Windows.Win32.System.Threading.CREATE_WAITABLE_TIMER_MANUAL_RESET
|
||||
Windows.Win32.System.Threading.CreateEventW
|
||||
Windows.Win32.System.Threading.CreateProcessW
|
||||
Windows.Win32.System.Threading.CreateThread
|
||||
Windows.Win32.System.Threading.CreateWaitableTimerExW
|
||||
Windows.Win32.System.Threading.DEBUG_ONLY_THIS_PROCESS
|
||||
Windows.Win32.System.Threading.DEBUG_PROCESS
|
||||
Windows.Win32.System.Threading.DeleteProcThreadAttributeList
|
||||
@ -2542,6 +2545,7 @@ Windows.Win32.System.Threading.REALTIME_PRIORITY_CLASS
|
||||
Windows.Win32.System.Threading.ReleaseSRWLockExclusive
|
||||
Windows.Win32.System.Threading.ReleaseSRWLockShared
|
||||
Windows.Win32.System.Threading.SetThreadStackGuarantee
|
||||
Windows.Win32.System.Threading.SetWaitableTimer
|
||||
Windows.Win32.System.Threading.Sleep
|
||||
Windows.Win32.System.Threading.SleepConditionVariableSRW
|
||||
Windows.Win32.System.Threading.SleepEx
|
||||
@ -2568,6 +2572,8 @@ Windows.Win32.System.Threading.TerminateProcess
|
||||
Windows.Win32.System.Threading.THREAD_CREATE_RUN_IMMEDIATELY
|
||||
Windows.Win32.System.Threading.THREAD_CREATE_SUSPENDED
|
||||
Windows.Win32.System.Threading.THREAD_CREATION_FLAGS
|
||||
Windows.Win32.System.Threading.TIMER_ALL_ACCESS
|
||||
Windows.Win32.System.Threading.TIMER_MODIFY_STATE
|
||||
Windows.Win32.System.Threading.TLS_OUT_OF_INDEXES
|
||||
Windows.Win32.System.Threading.TlsAlloc
|
||||
Windows.Win32.System.Threading.TlsFree
|
||||
|
@ -151,6 +151,15 @@ extern "system" {
|
||||
) -> HANDLE;
|
||||
}
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
pub fn CreateWaitableTimerExW(
|
||||
lptimerattributes: *const SECURITY_ATTRIBUTES,
|
||||
lptimername: PCWSTR,
|
||||
dwflags: u32,
|
||||
dwdesiredaccess: u32,
|
||||
) -> HANDLE;
|
||||
}
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
pub fn DeleteFileW(lpfilename: PCWSTR) -> BOOL;
|
||||
}
|
||||
@ -508,6 +517,17 @@ extern "system" {
|
||||
pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL;
|
||||
}
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
pub fn SetWaitableTimer(
|
||||
htimer: HANDLE,
|
||||
lpduetime: *const i64,
|
||||
lperiod: i32,
|
||||
pfncompletionroutine: PTIMERAPCROUTINE,
|
||||
lpargtocompletionroutine: *const ::core::ffi::c_void,
|
||||
fresume: BOOL,
|
||||
) -> BOOL;
|
||||
}
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
pub fn Sleep(dwmilliseconds: u32) -> ();
|
||||
}
|
||||
@ -1164,6 +1184,8 @@ pub const CREATE_SEPARATE_WOW_VDM: PROCESS_CREATION_FLAGS = 2048u32;
|
||||
pub const CREATE_SHARED_WOW_VDM: PROCESS_CREATION_FLAGS = 4096u32;
|
||||
pub const CREATE_SUSPENDED: PROCESS_CREATION_FLAGS = 4u32;
|
||||
pub const CREATE_UNICODE_ENVIRONMENT: PROCESS_CREATION_FLAGS = 1024u32;
|
||||
pub const CREATE_WAITABLE_TIMER_HIGH_RESOLUTION: u32 = 2u32;
|
||||
pub const CREATE_WAITABLE_TIMER_MANUAL_RESET: u32 = 1u32;
|
||||
pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2i32;
|
||||
pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3i32;
|
||||
pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1i32;
|
||||
@ -3774,6 +3796,13 @@ pub const PROFILE_SERVER: PROCESS_CREATION_FLAGS = 1073741824u32;
|
||||
pub const PROFILE_USER: PROCESS_CREATION_FLAGS = 268435456u32;
|
||||
pub const PROGRESS_CONTINUE: u32 = 0u32;
|
||||
pub type PSTR = *mut u8;
|
||||
pub type PTIMERAPCROUTINE = ::core::option::Option<
|
||||
unsafe extern "system" fn(
|
||||
lpargtocompletionroutine: *const ::core::ffi::c_void,
|
||||
dwtimerlowvalue: u32,
|
||||
dwtimerhighvalue: u32,
|
||||
) -> (),
|
||||
>;
|
||||
pub type PWSTR = *mut u16;
|
||||
pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32;
|
||||
pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32;
|
||||
@ -3910,6 +3939,7 @@ pub type SYMBOLIC_LINK_FLAGS = u32;
|
||||
pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: SYMBOLIC_LINK_FLAGS = 2u32;
|
||||
pub const SYMBOLIC_LINK_FLAG_DIRECTORY: SYMBOLIC_LINK_FLAGS = 1u32;
|
||||
pub const SYMLINK_FLAG_RELATIVE: u32 = 1u32;
|
||||
pub type SYNCHRONIZATION_ACCESS_RIGHTS = u32;
|
||||
pub const SYNCHRONIZE: FILE_ACCESS_RIGHTS = 1048576u32;
|
||||
#[repr(C)]
|
||||
pub struct SYSTEM_INFO {
|
||||
@ -3956,6 +3986,8 @@ pub const TCP_NODELAY: i32 = 1i32;
|
||||
pub const THREAD_CREATE_RUN_IMMEDIATELY: THREAD_CREATION_FLAGS = 0u32;
|
||||
pub const THREAD_CREATE_SUSPENDED: THREAD_CREATION_FLAGS = 4u32;
|
||||
pub type THREAD_CREATION_FLAGS = u32;
|
||||
pub const TIMER_ALL_ACCESS: SYNCHRONIZATION_ACCESS_RIGHTS = 2031619u32;
|
||||
pub const TIMER_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32;
|
||||
#[repr(C)]
|
||||
pub struct TIMEVAL {
|
||||
pub tv_sec: i32,
|
||||
|
@ -12,6 +12,7 @@ use crate::time::Duration;
|
||||
|
||||
use libc::c_void;
|
||||
|
||||
use super::time::WaitableTimer;
|
||||
use super::to_u16s;
|
||||
|
||||
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
|
||||
@ -87,8 +88,18 @@ impl Thread {
|
||||
}
|
||||
|
||||
pub fn sleep(dur: Duration) {
|
||||
fn high_precision_sleep(dur: Duration) -> Result<(), ()> {
|
||||
let timer = WaitableTimer::high_resolution()?;
|
||||
timer.set(dur)?;
|
||||
timer.wait()
|
||||
}
|
||||
// Attempt to use high-precision sleep (Windows 10, version 1803+).
|
||||
// On error fallback to the standard `Sleep` function.
|
||||
// Also preserves the zero duration behaviour of `Sleep`.
|
||||
if dur.is_zero() || high_precision_sleep(dur).is_err() {
|
||||
unsafe { c::Sleep(super::dur2timeout(dur)) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&self.handle
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt;
|
||||
use crate::mem;
|
||||
use crate::ptr::{null, null_mut};
|
||||
use crate::sys::c;
|
||||
use crate::sys_common::IntoInner;
|
||||
use crate::time::Duration;
|
||||
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ops::Neg;
|
||||
|
||||
const NANOS_PER_SEC: u64 = 1_000_000_000;
|
||||
const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100;
|
||||
@ -222,3 +224,39 @@ mod perf_counter {
|
||||
qpc_value
|
||||
}
|
||||
}
|
||||
|
||||
/// A timer you can wait on.
|
||||
pub(super) struct WaitableTimer {
|
||||
handle: c::HANDLE,
|
||||
}
|
||||
impl WaitableTimer {
|
||||
/// Create a high-resolution timer. Will fail before Windows 10, version 1803.
|
||||
pub fn high_resolution() -> Result<Self, ()> {
|
||||
let handle = unsafe {
|
||||
c::CreateWaitableTimerExW(
|
||||
null(),
|
||||
null(),
|
||||
c::CREATE_WAITABLE_TIMER_HIGH_RESOLUTION,
|
||||
c::TIMER_ALL_ACCESS,
|
||||
)
|
||||
};
|
||||
if handle != null_mut() { Ok(Self { handle }) } else { Err(()) }
|
||||
}
|
||||
pub fn set(&self, duration: Duration) -> Result<(), ()> {
|
||||
// Convert the Duration to a format similar to FILETIME.
|
||||
// Negative values are relative times whereas positive values are absolute.
|
||||
// Therefore we negate the relative duration.
|
||||
let time = checked_dur2intervals(&duration).ok_or(())?.neg();
|
||||
let result = unsafe { c::SetWaitableTimer(self.handle, &time, 0, None, null(), c::FALSE) };
|
||||
if result != 0 { Ok(()) } else { Err(()) }
|
||||
}
|
||||
pub fn wait(&self) -> Result<(), ()> {
|
||||
let result = unsafe { c::WaitForSingleObject(self.handle, c::INFINITE) };
|
||||
if result != c::WAIT_FAILED { Ok(()) } else { Err(()) }
|
||||
}
|
||||
}
|
||||
impl Drop for WaitableTimer {
|
||||
fn drop(&mut self) {
|
||||
unsafe { c::CloseHandle(self.handle) };
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user