std\sys\pal\windows/
thread.rs1use core::ffi::c_void;
2
3use super::time::WaitableTimer;
4use super::to_u16s;
5use crate::ffi::CStr;
6use crate::num::NonZero;
7use crate::os::windows::io::{AsRawHandle, HandleOrNull};
8use crate::sys::handle::Handle;
9use crate::sys::{c, stack_overflow};
10use crate::sys_common::FromInner;
11use crate::time::{Duration, Instant};
12use crate::{io, ptr};
13
14pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
15
16pub struct Thread {
17 handle: Handle,
18}
19
20impl Thread {
21 #[cfg_attr(miri, track_caller)] pub unsafe fn new(
24 stack: usize,
25 _name: Option<&str>,
26 p: Box<dyn FnOnce()>,
27 ) -> io::Result<Thread> {
28 let p = Box::into_raw(Box::new(p));
29
30 let ret = unsafe {
35 let ret = c::CreateThread(
36 ptr::null_mut(),
37 stack,
38 Some(thread_start),
39 p as *mut _,
40 c::STACK_SIZE_PARAM_IS_A_RESERVATION,
41 ptr::null_mut(),
42 );
43 HandleOrNull::from_raw_handle(ret)
44 };
45 return if let Ok(handle) = ret.try_into() {
46 Ok(Thread { handle: Handle::from_inner(handle) })
47 } else {
48 unsafe { drop(Box::from_raw(p)) };
51 Err(io::Error::last_os_error())
52 };
53
54 unsafe extern "system" fn thread_start(main: *mut c_void) -> u32 {
55 stack_overflow::reserve_stack();
57 unsafe { Box::from_raw(main as *mut Box<dyn FnOnce()>)() };
61 0
62 }
63 }
64
65 pub fn set_name(name: &CStr) {
66 if let Ok(utf8) = name.to_str() {
67 if let Ok(utf16) = to_u16s(utf8) {
68 unsafe {
69 Self::set_name_wide(&utf16)
71 }
72 };
73 };
74 }
75
76 pub unsafe fn set_name_wide(name: &[u16]) {
80 unsafe { c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr()) };
81 }
82
83 pub fn join(self) {
84 let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
85 if rc == c::WAIT_FAILED {
86 panic!("failed to join on thread: {}", io::Error::last_os_error());
87 }
88 }
89
90 pub fn yield_now() {
91 unsafe {
95 c::SwitchToThread();
96 }
97 }
98
99 pub fn sleep(dur: Duration) {
100 fn high_precision_sleep(dur: Duration) -> Result<(), ()> {
101 let timer = WaitableTimer::high_resolution()?;
102 timer.set(dur)?;
103 timer.wait()
104 }
105 if dur.is_zero() || high_precision_sleep(dur).is_err() {
109 unsafe { c::Sleep(super::dur2timeout(dur)) }
110 }
111 }
112
113 pub fn sleep_until(deadline: Instant) {
114 let now = Instant::now();
115
116 if let Some(delay) = deadline.checked_duration_since(now) {
117 Self::sleep(delay);
118 }
119 }
120
121 pub fn handle(&self) -> &Handle {
122 &self.handle
123 }
124
125 pub fn into_handle(self) -> Handle {
126 self.handle
127 }
128}
129
130pub(crate) fn current_os_id() -> Option<u64> {
131 let id: u32 = unsafe { c::GetCurrentThreadId() };
133
134 if id == 0 { None } else { Some(id.into()) }
136}
137
138pub fn available_parallelism() -> io::Result<NonZero<usize>> {
139 let res = unsafe {
140 let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed();
141 c::GetSystemInfo(&mut sysinfo);
142 sysinfo.dwNumberOfProcessors as usize
143 };
144 match res {
145 0 => Err(io::Error::UNKNOWN_THREAD_COUNT),
146 cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
147 }
148}