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::thread::ThreadInit;
12use crate::time::Duration;
13use crate::{io, ptr};
14
15pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
16
17pub struct Thread {
18 handle: Handle,
19}
20
21impl Thread {
22 #[cfg_attr(miri, track_caller)] pub unsafe fn new(stack: usize, init: Box<ThreadInit>) -> io::Result<Thread> {
25 let data = Box::into_raw(init);
26
27 let ret = unsafe {
32 let ret = c::CreateThread(
33 ptr::null_mut(),
34 stack,
35 Some(thread_start),
36 data as *mut _,
37 c::STACK_SIZE_PARAM_IS_A_RESERVATION,
38 ptr::null_mut(),
39 );
40 HandleOrNull::from_raw_handle(ret)
41 };
42 return if let Ok(handle) = ret.try_into() {
43 Ok(Thread { handle: Handle::from_inner(handle) })
44 } else {
45 unsafe { drop(Box::from_raw(data)) };
48 Err(io::Error::last_os_error())
49 };
50
51 unsafe extern "system" fn thread_start(data: *mut c_void) -> u32 {
52 let init = unsafe { Box::from_raw(data as *mut ThreadInit) };
54 let rust_start = init.init();
55
56 stack_overflow::reserve_stack();
58
59 rust_start();
60 0
61 }
62 }
63
64 pub fn join(self) {
65 let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
66 if rc == c::WAIT_FAILED {
67 panic!("failed to join on thread: {}", io::Error::last_os_error());
68 }
69 }
70
71 pub fn handle(&self) -> &Handle {
72 &self.handle
73 }
74
75 pub fn into_handle(self) -> Handle {
76 self.handle
77 }
78}
79
80pub fn available_parallelism() -> io::Result<NonZero<usize>> {
81 let res = unsafe {
82 let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed();
83 c::GetSystemInfo(&mut sysinfo);
84 sysinfo.dwNumberOfProcessors as usize
85 };
86 match res {
87 0 => Err(io::Error::UNKNOWN_THREAD_COUNT),
88 cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
89 }
90}
91
92pub fn current_os_id() -> Option<u64> {
93 let id: u32 = unsafe { c::GetCurrentThreadId() };
95
96 if id == 0 { None } else { Some(id.into()) }
98}
99
100pub fn set_name(name: &CStr) {
101 if let Ok(utf8) = name.to_str() {
102 if let Ok(utf16) = to_u16s(utf8) {
103 unsafe {
104 set_name_wide(&utf16)
106 }
107 };
108 };
109}
110
111pub unsafe fn set_name_wide(name: &[u16]) {
115 unsafe { c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr()) };
116}
117
118pub fn sleep(dur: Duration) {
119 fn high_precision_sleep(dur: Duration) -> Result<(), ()> {
120 let timer = WaitableTimer::high_resolution()?;
121 timer.set(dur)?;
122 timer.wait()
123 }
124 if dur.is_zero() || high_precision_sleep(dur).is_err() {
128 unsafe { c::Sleep(dur2timeout(dur)) }
129 }
130}
131
132pub fn yield_now() {
133 unsafe {
137 c::SwitchToThread();
138 }
139}