std\sys\thread/
windows.rs1use core::ffi::c_void;
2
3use crate::ffi::CStr;
4use crate::num::NonZero;
5use crate::os::windows::io::{AsRawHandle, HandleOrNull};
6use crate::sys::handle::Handle;
7use crate::sys::pal::time::WaitableTimer;
8use crate::sys::pal::{dur2timeout, to_u16s};
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(
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 join(self) {
66 let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
67 if rc == c::WAIT_FAILED {
68 panic!("failed to join on thread: {}", io::Error::last_os_error());
69 }
70 }
71
72 pub fn handle(&self) -> &Handle {
73 &self.handle
74 }
75
76 pub fn into_handle(self) -> Handle {
77 self.handle
78 }
79}
80
81pub fn available_parallelism() -> io::Result<NonZero<usize>> {
82 let res = unsafe {
83 let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed();
84 c::GetSystemInfo(&mut sysinfo);
85 sysinfo.dwNumberOfProcessors as usize
86 };
87 match res {
88 0 => Err(io::Error::UNKNOWN_THREAD_COUNT),
89 cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
90 }
91}
92
93pub fn current_os_id() -> Option<u64> {
94 let id: u32 = unsafe { c::GetCurrentThreadId() };
96
97 if id == 0 { None } else { Some(id.into()) }
99}
100
101pub fn set_name(name: &CStr) {
102 if let Ok(utf8) = name.to_str() {
103 if let Ok(utf16) = to_u16s(utf8) {
104 unsafe {
105 set_name_wide(&utf16)
107 }
108 };
109 };
110}
111
112pub unsafe fn set_name_wide(name: &[u16]) {
116 unsafe { c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr()) };
117}
118
119pub fn sleep(dur: Duration) {
120 fn high_precision_sleep(dur: Duration) -> Result<(), ()> {
121 let timer = WaitableTimer::high_resolution()?;
122 timer.set(dur)?;
123 timer.wait()
124 }
125 if dur.is_zero() || high_precision_sleep(dur).is_err() {
129 unsafe { c::Sleep(dur2timeout(dur)) }
130 }
131}
132
133pub fn yield_now() {
134 unsafe {
138 c::SwitchToThread();
139 }
140}