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;
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(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
24 let p = Box::into_raw(Box::new(p));
25
26 let ret = unsafe {
31 let ret = c::CreateThread(
32 ptr::null_mut(),
33 stack,
34 Some(thread_start),
35 p as *mut _,
36 c::STACK_SIZE_PARAM_IS_A_RESERVATION,
37 ptr::null_mut(),
38 );
39 HandleOrNull::from_raw_handle(ret)
40 };
41 return if let Ok(handle) = ret.try_into() {
42 Ok(Thread { handle: Handle::from_inner(handle) })
43 } else {
44 unsafe { drop(Box::from_raw(p)) };
47 Err(io::Error::last_os_error())
48 };
49
50 unsafe extern "system" fn thread_start(main: *mut c_void) -> u32 {
51 stack_overflow::reserve_stack();
53 unsafe { Box::from_raw(main as *mut Box<dyn FnOnce()>)() };
57 0
58 }
59 }
60
61 pub fn set_name(name: &CStr) {
62 if let Ok(utf8) = name.to_str() {
63 if let Ok(utf16) = to_u16s(utf8) {
64 unsafe {
65 Self::set_name_wide(&utf16)
67 }
68 };
69 };
70 }
71
72 pub unsafe fn set_name_wide(name: &[u16]) {
76 unsafe { c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr()) };
77 }
78
79 pub fn join(self) {
80 let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
81 if rc == c::WAIT_FAILED {
82 panic!("failed to join on thread: {}", io::Error::last_os_error());
83 }
84 }
85
86 pub fn yield_now() {
87 unsafe {
91 c::SwitchToThread();
92 }
93 }
94
95 pub fn sleep(dur: Duration) {
96 fn high_precision_sleep(dur: Duration) -> Result<(), ()> {
97 let timer = WaitableTimer::high_resolution()?;
98 timer.set(dur)?;
99 timer.wait()
100 }
101 if dur.is_zero() || high_precision_sleep(dur).is_err() {
105 unsafe { c::Sleep(super::dur2timeout(dur)) }
106 }
107 }
108
109 pub fn handle(&self) -> &Handle {
110 &self.handle
111 }
112
113 pub fn into_handle(self) -> Handle {
114 self.handle
115 }
116}
117
118pub fn available_parallelism() -> io::Result<NonZero<usize>> {
119 let res = unsafe {
120 let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed();
121 c::GetSystemInfo(&mut sysinfo);
122 sysinfo.dwNumberOfProcessors as usize
123 };
124 match res {
125 0 => Err(io::Error::UNKNOWN_THREAD_COUNT),
126 cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
127 }
128}