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::{FromInner, c, stack_overflow};
10use crate::thread::ThreadInit;
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(stack: usize, init: Box<ThreadInit>) -> io::Result<Thread> {
24 let data = Box::into_raw(init);
25
26 let ret = unsafe {
31 let ret = c::CreateThread(
32 ptr::null_mut(),
33 stack,
34 Some(thread_start),
35 data 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(data)) };
47 Err(io::Error::last_os_error())
48 };
49
50 unsafe extern "system" fn thread_start(data: *mut c_void) -> u32 {
51 let init = unsafe { Box::from_raw(data as *mut ThreadInit) };
53 let rust_start = init.init();
54
55 stack_overflow::reserve_stack();
57
58 rust_start();
59 0
60 }
61 }
62
63 pub fn join(self) {
64 let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
65 if rc == c::WAIT_FAILED {
66 panic!("failed to join on thread: {}", io::Error::last_os_error());
67 }
68 }
69
70 pub fn handle(&self) -> &Handle {
71 &self.handle
72 }
73
74 pub fn into_handle(self) -> Handle {
75 self.handle
76 }
77}
78
79pub fn available_parallelism() -> io::Result<NonZero<usize>> {
80 let res = unsafe {
81 let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed();
82 c::GetSystemInfo(&mut sysinfo);
83 sysinfo.dwNumberOfProcessors as usize
84 };
85 match res {
86 0 => Err(io::Error::UNKNOWN_THREAD_COUNT),
87 cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
88 }
89}
90
91pub fn current_os_id() -> Option<u64> {
92 let id: u32 = unsafe { c::GetCurrentThreadId() };
94
95 if id == 0 { None } else { Some(id.into()) }
97}
98
99pub fn set_name(name: &CStr) {
100 if let Ok(utf8) = name.to_str() {
101 if let Ok(utf16) = to_u16s(utf8) {
102 unsafe {
103 set_name_wide(&utf16)
105 }
106 };
107 };
108}
109
110pub unsafe fn set_name_wide(name: &[u16]) {
114 unsafe { c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr()) };
115}
116
117pub fn sleep(dur: Duration) {
118 fn high_precision_sleep(dur: Duration) -> Result<(), ()> {
119 let timer = WaitableTimer::high_resolution()?;
120 timer.set(dur)?;
121 timer.wait()
122 }
123 if dur.is_zero() {
126 unsafe { c::Sleep(0) };
127 } else if high_precision_sleep(dur).is_err() {
130 let start = Instant::now();
131 unsafe { c::Sleep(dur2timeout(dur)) };
132
133 if start.elapsed() < dur {
143 unsafe { c::Sleep(1) };
144 }
145 }
146}
147
148pub fn yield_now() {
149 unsafe {
153 c::SwitchToThread();
154 }
155}