diff options
| author | The rustc-josh-sync Cronjob Bot <github-actions@github.com> | 2025-08-18 04:22:24 +0000 |
|---|---|---|
| committer | The rustc-josh-sync Cronjob Bot <github-actions@github.com> | 2025-08-18 04:22:24 +0000 |
| commit | 5818cbdd441bba57d509d549807af42f004ed21b (patch) | |
| tree | f79760d147848a6b9f97563a5a80dab46c7dd2d1 /library/std/src/sys | |
| parent | a3510c7199806c153f927f25e2bff2c095aa60df (diff) | |
| parent | 425a9c0a0e365c0b8c6cfd00c2ded83a73bed9a0 (diff) | |
Merge ref '425a9c0a0e36' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref: 425a9c0a0e365c0b8c6cfd00c2ded83a73bed9a0 Filtered ref: 26b9fd24259f4fc5fd7634a99dd6dda2821fb2d0 This merge was created using https://github.com/rust-lang/josh-sync.
Diffstat (limited to 'library/std/src/sys')
31 files changed, 681 insertions, 99 deletions
diff --git a/library/std/src/sys/configure_builtins.rs b/library/std/src/sys/configure_builtins.rs new file mode 100644 index 00000000000..9d776b778dc --- /dev/null +++ b/library/std/src/sys/configure_builtins.rs @@ -0,0 +1,22 @@ +/// Hook into .init_array to enable LSE atomic operations at startup, if +/// supported. +#[cfg(all(target_arch = "aarch64", target_os = "linux", not(feature = "compiler-builtins-c")))] +#[used] +#[unsafe(link_section = ".init_array.90")] +static RUST_LSE_INIT: extern "C" fn() = { + extern "C" fn init_lse() { + use crate::arch; + + // This is provided by compiler-builtins::aarch64_linux. + unsafe extern "C" { + fn __rust_enable_lse(); + } + + if arch::is_aarch64_feature_detected!("lse") { + unsafe { + __rust_enable_lse(); + } + } + } + init_lse +}; diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 9b674a25165..bb3e4bc30ca 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -80,7 +80,7 @@ pub struct OpenOptions { attributes: u32, share_mode: u32, security_qos_flags: u32, - security_attributes: *mut c::SECURITY_ATTRIBUTES, + inherit_handle: bool, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -203,7 +203,7 @@ impl OpenOptions { share_mode: c::FILE_SHARE_READ | c::FILE_SHARE_WRITE | c::FILE_SHARE_DELETE, attributes: 0, security_qos_flags: 0, - security_attributes: ptr::null_mut(), + inherit_handle: false, } } @@ -243,8 +243,8 @@ impl OpenOptions { // receive is `SECURITY_ANONYMOUS = 0x0`, which we can't check for later on. self.security_qos_flags = flags | c::SECURITY_SQOS_PRESENT; } - pub fn security_attributes(&mut self, attrs: *mut c::SECURITY_ATTRIBUTES) { - self.security_attributes = attrs; + pub fn inherit_handle(&mut self, inherit: bool) { + self.inherit_handle = inherit; } fn get_access_mode(&self) -> io::Result<u32> { @@ -307,12 +307,17 @@ impl File { fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result<File> { let creation = opts.get_creation_mode()?; + let sa = c::SECURITY_ATTRIBUTES { + nLength: size_of::<c::SECURITY_ATTRIBUTES>() as u32, + lpSecurityDescriptor: ptr::null_mut(), + bInheritHandle: opts.inherit_handle as c::BOOL, + }; let handle = unsafe { c::CreateFileW( path.as_ptr(), opts.get_access_mode()?, opts.share_mode, - opts.security_attributes, + if opts.inherit_handle { &sa } else { ptr::null() }, creation, opts.get_flags_and_attributes(), ptr::null_mut(), @@ -1601,7 +1606,7 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { }; unsafe { let ptr = header.PathBuffer.as_mut_ptr(); - ptr.copy_from(abs_path.as_ptr().cast::<MaybeUninit<u16>>(), abs_path.len()); + ptr.copy_from(abs_path.as_ptr().cast_uninit(), abs_path.len()); let mut ret = 0; cvt(c::DeviceIoControl( diff --git a/library/std/src/sys/io/io_slice/uefi.rs b/library/std/src/sys/io/io_slice/uefi.rs new file mode 100644 index 00000000000..909cfbea0b7 --- /dev/null +++ b/library/std/src/sys/io/io_slice/uefi.rs @@ -0,0 +1,74 @@ +//! A buffer type used with `Write::write_vectored` for UEFI Networking APIs. Vectored writing to +//! File is not supported as of UEFI Spec 2.11. + +use crate::marker::PhantomData; +use crate::slice; + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct IoSlice<'a> { + len: u32, + data: *const u8, + _p: PhantomData<&'a [u8]>, +} + +impl<'a> IoSlice<'a> { + #[inline] + pub fn new(buf: &'a [u8]) -> IoSlice<'a> { + let len = buf.len().try_into().unwrap(); + Self { len, data: buf.as_ptr(), _p: PhantomData } + } + + #[inline] + pub fn advance(&mut self, n: usize) { + self.len = u32::try_from(n) + .ok() + .and_then(|n| self.len.checked_sub(n)) + .expect("advancing IoSlice beyond its length"); + unsafe { self.data = self.data.add(n) }; + } + + #[inline] + pub const fn as_slice(&self) -> &'a [u8] { + unsafe { slice::from_raw_parts(self.data, self.len as usize) } + } +} + +#[repr(C)] +pub struct IoSliceMut<'a> { + len: u32, + data: *mut u8, + _p: PhantomData<&'a mut [u8]>, +} + +impl<'a> IoSliceMut<'a> { + #[inline] + pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { + let len = buf.len().try_into().unwrap(); + Self { len, data: buf.as_mut_ptr(), _p: PhantomData } + } + + #[inline] + pub fn advance(&mut self, n: usize) { + self.len = u32::try_from(n) + .ok() + .and_then(|n| self.len.checked_sub(n)) + .expect("advancing IoSlice beyond its length"); + unsafe { self.data = self.data.add(n) }; + } + + #[inline] + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.data, self.len as usize) } + } + + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) } + } +} diff --git a/library/std/src/sys/io/mod.rs b/library/std/src/sys/io/mod.rs index 4d0365d42fd..ae75f4d97b4 100644 --- a/library/std/src/sys/io/mod.rs +++ b/library/std/src/sys/io/mod.rs @@ -11,6 +11,9 @@ mod io_slice { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use wasi::*; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + pub use uefi::*; } else { mod unsupported; pub use unsupported::*; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index f9a02b522e5..8ec0a0e3302 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -1,5 +1,10 @@ #![allow(unsafe_op_in_unsafe_fn)] +/// The configure builtins provides runtime support compiler-builtin features +/// which require dynamic intialization to work as expected, e.g. aarch64 +/// outline-atomics. +mod configure_builtins; + /// The PAL (platform abstraction layer) contains platform-specific abstractions /// for implementing the features in the other submodules, e.g. UNIX file /// descriptors. diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 95fe4f902d3..cc4734b6819 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -115,6 +115,10 @@ impl Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { unsafe { Ok(NonZero::new_unchecked(hermit_abi::available_parallelism())) } } diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index f76a5f96c87..89a427ab88b 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -25,8 +25,15 @@ impl Timespec { Timespec { t: timespec { tv_sec, tv_nsec } } } - fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { - if self >= other { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { + // FIXME: const PartialOrd + let mut cmp = self.t.tv_sec - other.t.tv_sec; + if cmp == 0 { + cmp = self.t.tv_nsec as i64 - other.t.tv_nsec as i64; + } + + if cmp >= 0 { Ok(if self.t.tv_nsec >= other.t.tv_nsec { Duration::new( (self.t.tv_sec - other.t.tv_sec) as u64, @@ -46,20 +53,22 @@ impl Timespec { } } - fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. - let mut nsec = other.subsec_nanos() + u32::try_from(self.t.tv_nsec).unwrap(); - if nsec >= NSEC_PER_SEC.try_into().unwrap() { - nsec -= u32::try_from(NSEC_PER_SEC).unwrap(); + let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; + if nsec >= NSEC_PER_SEC as u32 { + nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; } Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } }) } - fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. @@ -213,15 +222,18 @@ impl SystemTime { SystemTime(time) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { self.0.sub_timespec(&other.0) } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add_duration(other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub_duration(other)?)) } } diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs index 0d28051fcc4..4e14cb3cbca 100644 --- a/library/std/src/sys/pal/itron/thread.rs +++ b/library/std/src/sys/pal/itron/thread.rs @@ -361,6 +361,10 @@ unsafe fn terminate_and_delete_current_task() -> ! { unsafe { crate::hint::unreachable_unchecked() }; } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { super::unsupported() } diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index a236c362706..1f613badcd7 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -1,6 +1,6 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? -use super::abi::usercalls; +use super::abi::{thread, usercalls}; use super::unsupported; use crate::ffi::CStr; use crate::io; @@ -149,6 +149,10 @@ impl Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + Some(thread::current().addr().get() as u64) +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { unsupported() } diff --git a/library/std/src/sys/pal/sgx/time.rs b/library/std/src/sys/pal/sgx/time.rs index db4cf2804bf..603dae952ab 100644 --- a/library/std/src/sys/pal/sgx/time.rs +++ b/library/std/src/sys/pal/sgx/time.rs @@ -32,15 +32,22 @@ impl SystemTime { SystemTime(usercalls::insecure_time()) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/pal/solid/time.rs b/library/std/src/sys/pal/solid/time.rs index c39d715c6a6..e35e60df1a0 100644 --- a/library/std/src/sys/pal/solid/time.rs +++ b/library/std/src/sys/pal/solid/time.rs @@ -39,7 +39,8 @@ impl SystemTime { Self(t) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { if self.0 >= other.0 { Ok(Duration::from_secs((self.0 as u64).wrapping_sub(other.0 as u64))) } else { @@ -47,11 +48,13 @@ impl SystemTime { } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add_unsigned(other.as_secs())?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub_unsigned(other.as_secs())?)) } } diff --git a/library/std/src/sys/pal/teeos/thread.rs b/library/std/src/sys/pal/teeos/thread.rs index a91d95626e7..1812d11e692 100644 --- a/library/std/src/sys/pal/teeos/thread.rs +++ b/library/std/src/sys/pal/teeos/thread.rs @@ -144,6 +144,10 @@ impl Drop for Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + // Note: Both `sched_getaffinity` and `sysconf` are available but not functional on // teeos, so this function always returns an Error! pub fn available_parallelism() -> io::Result<NonZero<usize>> { diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index 38658cc4e9a..56ca999cc7e 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,7 +1,13 @@ +//! These tests are not run automatically right now. Please run these tests manually by copying them +//! to a separate project when modifying any related code. + use super::alloc::*; -use super::time::*; +use super::time::system_time_internal::{from_uefi, to_uefi}; +use crate::io::{IoSlice, IoSliceMut}; use crate::time::Duration; +const SECS_IN_MINUTE: u64 = 60; + #[test] fn align() { // UEFI ABI specifies that allocation alignment minimum is always 8. So this can be @@ -23,19 +29,177 @@ fn align() { } #[test] -fn epoch() { - let t = r_efi::system::Time { - year: 1970, +fn systemtime_start() { + let t = r_efi::efi::Time { + year: 1900, month: 1, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0, - timezone: r_efi::efi::UNSPECIFIED_TIMEZONE, + timezone: -1440, daylight: 0, + pad2: 0, + }; + assert_eq!(from_uefi(&t), Duration::new(0, 0)); + assert_eq!(t, to_uefi(&from_uefi(&t), -1440, 0).unwrap()); + assert!(to_uefi(&from_uefi(&t), 0, 0).is_none()); +} + +#[test] +fn systemtime_utc_start() { + let t = r_efi::efi::Time { + year: 1900, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, pad1: 0, + nanosecond: 0, + timezone: 0, + daylight: 0, pad2: 0, }; - assert_eq!(system_time_internal::uefi_time_to_duration(t), Duration::new(0, 0)); + assert_eq!(from_uefi(&t), Duration::new(1440 * SECS_IN_MINUTE, 0)); + assert_eq!(t, to_uefi(&from_uefi(&t), 0, 0).unwrap()); + assert!(to_uefi(&from_uefi(&t), -1440, 0).is_some()); +} + +#[test] +fn systemtime_end() { + let t = r_efi::efi::Time { + year: 9999, + month: 12, + day: 31, + hour: 23, + minute: 59, + second: 59, + pad1: 0, + nanosecond: 0, + timezone: 1440, + daylight: 0, + pad2: 0, + }; + assert!(to_uefi(&from_uefi(&t), 1440, 0).is_some()); + assert!(to_uefi(&from_uefi(&t), 1439, 0).is_none()); +} + +// UEFI IoSlice and IoSliceMut Tests +// +// Strictly speaking, vectored read/write types for UDP4, UDP6, TCP4, TCP6 are defined +// separately in the UEFI Spec. However, they have the same signature. These tests just ensure +// that `IoSlice` and `IoSliceMut` are compatible with the vectored types for all the +// networking protocols. + +unsafe fn to_slice<T>(val: &T) -> &[u8] { + let len = size_of_val(val); + unsafe { crate::slice::from_raw_parts(crate::ptr::from_ref(val).cast(), len) } +} + +#[test] +fn io_slice_single() { + let mut data = [0, 1, 2, 3, 4]; + + let tcp4_frag = r_efi::protocols::tcp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let tcp6_frag = r_efi::protocols::tcp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp4_frag = r_efi::protocols::udp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp6_frag = r_efi::protocols::udp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let io_slice = IoSlice::new(&data); + + unsafe { + assert_eq!(to_slice(&io_slice), to_slice(&tcp4_frag)); + assert_eq!(to_slice(&io_slice), to_slice(&tcp6_frag)); + assert_eq!(to_slice(&io_slice), to_slice(&udp4_frag)); + assert_eq!(to_slice(&io_slice), to_slice(&udp6_frag)); + } +} + +#[test] +fn io_slice_mut_single() { + let mut data = [0, 1, 2, 3, 4]; + + let tcp4_frag = r_efi::protocols::tcp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let tcp6_frag = r_efi::protocols::tcp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp4_frag = r_efi::protocols::udp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let udp6_frag = r_efi::protocols::udp6::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let io_slice_mut = IoSliceMut::new(&mut data); + + unsafe { + assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp4_frag)); + assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp6_frag)); + assert_eq!(to_slice(&io_slice_mut), to_slice(&udp4_frag)); + assert_eq!(to_slice(&io_slice_mut), to_slice(&udp6_frag)); + } +} + +#[test] +fn io_slice_multi() { + let mut data = [0, 1, 2, 3, 4]; + + let tcp4_frag = r_efi::protocols::tcp4::FragmentData { + fragment_length: data.len().try_into().unwrap(), + fragment_buffer: data.as_mut_ptr().cast(), + }; + let rhs = + [tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag]; + let lhs = [ + IoSlice::new(&data), + IoSlice::new(&data), + IoSlice::new(&data), + IoSlice::new(&data), + IoSlice::new(&data), + ]; + + unsafe { + assert_eq!(to_slice(&lhs), to_slice(&rhs)); + } +} + +#[test] +fn io_slice_basic() { + let data = [0, 1, 2, 3, 4]; + let mut io_slice = IoSlice::new(&data); + + assert_eq!(data, io_slice.as_slice()); + io_slice.advance(2); + assert_eq!(&data[2..], io_slice.as_slice()); +} + +#[test] +fn io_slice_mut_basic() { + let data = [0, 1, 2, 3, 4]; + let mut data_clone = [0, 1, 2, 3, 4]; + let mut io_slice_mut = IoSliceMut::new(&mut data_clone); + + assert_eq!(data, io_slice_mut.as_slice()); + assert_eq!(data, io_slice_mut.as_mut_slice()); + + io_slice_mut.advance(2); + assert_eq!(&data[2..], io_slice_mut.into_slice()); } diff --git a/library/std/src/sys/pal/uefi/thread.rs b/library/std/src/sys/pal/uefi/thread.rs index 75c364362b2..47a48008c76 100644 --- a/library/std/src/sys/pal/uefi/thread.rs +++ b/library/std/src/sys/pal/uefi/thread.rs @@ -56,6 +56,10 @@ impl Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { // UEFI is single threaded Ok(NonZero::new(1).unwrap()) diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index eeb2c35ffbb..df5611b2ddd 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -1,16 +1,42 @@ use crate::time::Duration; -const SECS_IN_MINUTE: u64 = 60; -const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; -const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); +/// When a Timezone is specified, the stored Duration is in UTC. If timezone is unspecified, then +/// the timezone is assumed to be in UTC. +/// +/// UEFI SystemTime is stored as Duration from 1900-01-01-00:00:00 with timezone -1440 as anchor #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct SystemTime(Duration); -pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); +pub const UNIX_EPOCH: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: 0, + daylight: 0, + pad1: 0, + pad2: 0, +}); + +const MAX_UEFI_TIME: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 9999, + month: 12, + day: 31, + hour: 23, + minute: 59, + second: 59, + nanosecond: 999_999_999, + timezone: 1440, + daylight: 0, + pad1: 0, + pad2: 0, +}); impl Instant { pub fn now() -> Instant { @@ -40,20 +66,45 @@ impl Instant { } impl SystemTime { + pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Self { + Self(system_time_internal::from_uefi(&t)) + } + + #[expect(dead_code)] + pub(crate) const fn to_uefi(self, timezone: i16, daylight: u8) -> Option<r_efi::efi::Time> { + system_time_internal::to_uefi(&self.0, timezone, daylight) + } + pub fn now() -> SystemTime { system_time_internal::now() .unwrap_or_else(|| panic!("time not implemented on this platform")) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { - Some(SystemTime(self.0.checked_add(*other)?)) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + let temp = self.0.checked_add(*other)?; + + // Check if can be represented in UEFI + // FIXME: const PartialOrd + let mut cmp = temp.as_secs() - MAX_UEFI_TIME.0.as_secs(); + if cmp == 0 { + cmp = temp.subsec_nanos() as u64 - MAX_UEFI_TIME.0.subsec_nanos() as u64; + } + + if cmp <= 0 { Some(SystemTime(temp)) } else { None } } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } @@ -66,51 +117,132 @@ pub(crate) mod system_time_internal { use crate::mem::MaybeUninit; use crate::ptr::NonNull; + const SECS_IN_MINUTE: u64 = 60; + const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; + const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + const TIMEZONE_DELTA: u64 = 1440 * SECS_IN_MINUTE; + pub fn now() -> Option<SystemTime> { let runtime_services: NonNull<RuntimeServices> = helpers::runtime_services()?; let mut t: MaybeUninit<Time> = MaybeUninit::uninit(); let r = unsafe { ((*runtime_services.as_ptr()).get_time)(t.as_mut_ptr(), crate::ptr::null_mut()) }; - if r.is_error() { return None; } let t = unsafe { t.assume_init() }; - Some(SystemTime(uefi_time_to_duration(t))) + Some(SystemTime::from_uefi(t)) } - // This algorithm is based on the one described in the post - // https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html - pub(crate) const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration { - assert!(t.month <= 12); - assert!(t.month != 0); + /// This algorithm is a modified form of the one described in the post + /// https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html + /// + /// The changes are to use 1900-01-01-00:00:00 with timezone -1440 as anchor instead of UNIX + /// epoch used in the original algorithm. + pub(crate) const fn from_uefi(t: &Time) -> Duration { + assert!(t.month <= 12 && t.month != 0); + assert!(t.year >= 1900 && t.year <= 9999); + assert!(t.day <= 31 && t.day != 0); + + assert!(t.second < 60); + assert!(t.minute < 60); + assert!(t.hour < 24); + assert!(t.nanosecond < 1_000_000_000); + + assert!( + (t.timezone <= 1440 && t.timezone >= -1440) + || t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE + ); const YEAR_BASE: u32 = 4800; /* Before min year, multiple of 400. */ - // Calculate the number of days since 1/1/1970 + // Calculate the number of days since 1/1/1900. This is the earliest supported date in UEFI + // time. // Use 1 March as the start let (m_adj, overflow): (u32, bool) = (t.month as u32).overflowing_sub(3); let (carry, adjust): (u32, u32) = if overflow { (1, 12) } else { (0, 0) }; let y_adj: u32 = (t.year as u32) + YEAR_BASE - carry; let month_days: u32 = (m_adj.wrapping_add(adjust) * 62719 + 769) / 2048; let leap_days: u32 = y_adj / 4 - y_adj / 100 + y_adj / 400; - let days: u32 = y_adj * 365 + leap_days + month_days + (t.day as u32 - 1) - 2472632; + let days: u32 = y_adj * 365 + leap_days + month_days + (t.day as u32 - 1) - 2447065; let localtime_epoch: u64 = (days as u64) * SECS_IN_DAY + (t.second as u64) + (t.minute as u64) * SECS_IN_MINUTE + (t.hour as u64) * SECS_IN_HOUR; - let utc_epoch: u64 = if t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE { - localtime_epoch + // Calculate the offset from 1/1/1900 at timezone -1440 min + let adjusted_localtime_epoc: u64 = localtime_epoch + TIMEZONE_DELTA; + + let epoch: u64 = if t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE { + adjusted_localtime_epoc } else { - (localtime_epoch as i64 + (t.timezone as i64) * SECS_IN_MINUTE as i64) as u64 + adjusted_localtime_epoc + .checked_add_signed((t.timezone as i64) * SECS_IN_MINUTE as i64) + .unwrap() }; - Duration::new(utc_epoch, t.nanosecond) + Duration::new(epoch, t.nanosecond) + } + + /// This algorithm is a modifed version of the one described in the post: + /// https://howardhinnant.github.io/date_algorithms.html#clive_from_days + /// + /// The changes are to use 1900-01-01-00:00:00 with timezone -1440 as anchor instead of UNIX + /// epoch used in the original algorithm. + pub(crate) const fn to_uefi(dur: &Duration, timezone: i16, daylight: u8) -> Option<Time> { + // Check timzone validity + assert!(timezone <= 1440 && timezone >= -1440); + + // FIXME(#126043): use checked_sub_signed once stablized + let secs = + dur.as_secs().checked_add_signed((-timezone as i64) * SECS_IN_MINUTE as i64).unwrap(); + + // Convert to seconds since 1900-01-01-00:00:00 in timezone. + let Some(secs) = secs.checked_sub(TIMEZONE_DELTA) else { return None }; + + let days = secs / SECS_IN_DAY; + let remaining_secs = secs % SECS_IN_DAY; + + let z = days + 693901; + let era = z / 146097; + let doe = z - (era * 146097); + let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; + let mut y = yoe + era * 400; + let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + let mp = (5 * doy + 2) / 153; + let d = doy - (153 * mp + 2) / 5 + 1; + let m = if mp < 10 { mp + 3 } else { mp - 9 }; + + if m <= 2 { + y += 1; + } + + let hour = (remaining_secs / SECS_IN_HOUR) as u8; + let minute = ((remaining_secs % SECS_IN_HOUR) / SECS_IN_MINUTE) as u8; + let second = (remaining_secs % SECS_IN_MINUTE) as u8; + + // Check Bounds + if y >= 1900 && y <= 9999 { + Some(Time { + year: y as u16, + month: m as u8, + day: d as u8, + hour, + minute, + second, + nanosecond: dur.subsec_nanos(), + timezone, + daylight, + pad1: 0, + pad2: 0, + }) + } else { + None + } } } diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index d89100e6919..0d2100d66bc 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -119,7 +119,8 @@ mod imp { && thread_info.guard_page_range.contains(&fault_addr) { let name = thread_info.thread_name.as_deref().unwrap_or("<unknown>"); - rtprintpanic!("\nthread '{name}' has overflowed its stack\n"); + let tid = crate::thread::current_os_id(); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); rtabort!("stack overflow"); } }) @@ -696,7 +697,8 @@ mod imp { if code == c::EXCEPTION_STACK_OVERFLOW { crate::thread::with_current_name(|name| { let name = name.unwrap_or("<unknown>"); - rtprintpanic!("\nthread '{name}' has overflowed its stack\n"); + let tid = crate::thread::current_os_id(); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); }); } c::EXCEPTION_CONTINUE_SEARCH diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 7f6440152d4..24b65c11fd2 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -77,7 +77,18 @@ impl Thread { let page_size = os::page_size(); let stack_size = (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); - assert_eq!(libc::pthread_attr_setstacksize(attr.as_mut_ptr(), stack_size), 0); + + // Some libc implementations, e.g. musl, place an upper bound + // on the stack size, in which case we can only gracefully return + // an error here. + if libc::pthread_attr_setstacksize(attr.as_mut_ptr(), stack_size) != 0 { + assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0); + drop(Box::from_raw(data)); + return Err(io::const_error!( + io::ErrorKind::InvalidInput, + "invalid stack size" + )); + } } }; } @@ -398,6 +409,62 @@ impl Drop for Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + // Most Unix platforms have a way to query an integer ID of the current thread, all with + // slightly different spellings. + // + // The OS thread ID is used rather than `pthread_self` so as to match what will be displayed + // for process inspection (debuggers, trace, `top`, etc.). + cfg_if::cfg_if! { + // Most platforms have a function returning a `pid_t` or int, which is an `i32`. + if #[cfg(any(target_os = "android", target_os = "linux"))] { + use crate::sys::weak::syscall; + + // `libc::gettid` is only available on glibc 2.30+, but the syscall is available + // since Linux 2.4.11. + syscall!(fn gettid() -> libc::pid_t;); + + // SAFETY: FFI call with no preconditions. + let id: libc::pid_t = unsafe { gettid() }; + Some(id as u64) + } else if #[cfg(target_os = "nto")] { + // SAFETY: FFI call with no preconditions. + let id: libc::pid_t = unsafe { libc::gettid() }; + Some(id as u64) + } else if #[cfg(target_os = "openbsd")] { + // SAFETY: FFI call with no preconditions. + let id: libc::pid_t = unsafe { libc::getthrid() }; + Some(id as u64) + } else if #[cfg(target_os = "freebsd")] { + // SAFETY: FFI call with no preconditions. + let id: libc::c_int = unsafe { libc::pthread_getthreadid_np() }; + Some(id as u64) + } else if #[cfg(target_os = "netbsd")] { + // SAFETY: FFI call with no preconditions. + let id: libc::lwpid_t = unsafe { libc::_lwp_self() }; + Some(id as u64) + } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] { + // On Illumos and Solaris, the `pthread_t` is the same as the OS thread ID. + // SAFETY: FFI call with no preconditions. + let id: libc::pthread_t = unsafe { libc::pthread_self() }; + Some(id as u64) + } else if #[cfg(target_vendor = "apple")] { + // Apple allows querying arbitrary thread IDs, `thread=NULL` queries the current thread. + let mut id = 0u64; + // SAFETY: `thread_id` is a valid pointer, no other preconditions. + let status: libc::c_int = unsafe { libc::pthread_threadid_np(0, &mut id) }; + if status == 0 { + Some(id) + } else { + None + } + } else { + // Other platforms don't have an OS thread ID or don't have a way to access it. + None + } + } +} + #[cfg(any( target_os = "linux", target_os = "nto", diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index bd7f74fea6a..328fe0bc960 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -38,15 +38,18 @@ impl SystemTime { SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) } } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { self.t.sub_timespec(&other.t) } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime { t: self.t.checked_add_duration(other)? }) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime { t: self.t.checked_sub_duration(other)? }) } } @@ -133,8 +136,15 @@ impl Timespec { Timespec::new(t.tv_sec as i64, t.tv_nsec as i64).unwrap() } - pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { - if self >= other { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { + // FIXME: const PartialOrd + let mut cmp = self.tv_sec - other.tv_sec; + if cmp == 0 { + cmp = self.tv_nsec.as_inner() as i64 - other.tv_nsec.as_inner() as i64; + } + + if cmp >= 0 { // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM // to optimize it into a branchless form (see also #75545): // @@ -169,7 +179,8 @@ impl Timespec { } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.tv_sec.checked_add_unsigned(other.as_secs())?; // Nano calculations can't overflow because nanos are <1B which fit @@ -179,10 +190,11 @@ impl Timespec { nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; } - Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) }) + Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) }) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. @@ -191,7 +203,7 @@ impl Timespec { nsec += NSEC_PER_SEC as i32; secs = secs.checked_sub(1)?; } - Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) }) + Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) }) } #[allow(dead_code)] diff --git a/library/std/src/sys/pal/unsupported/thread.rs b/library/std/src/sys/pal/unsupported/thread.rs index 5a1e3fde986..34d9b5ec70c 100644 --- a/library/std/src/sys/pal/unsupported/thread.rs +++ b/library/std/src/sys/pal/unsupported/thread.rs @@ -39,6 +39,10 @@ impl Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { unsupported() } diff --git a/library/std/src/sys/pal/unsupported/time.rs b/library/std/src/sys/pal/unsupported/time.rs index 6d67b538a96..0c387917044 100644 --- a/library/std/src/sys/pal/unsupported/time.rs +++ b/library/std/src/sys/pal/unsupported/time.rs @@ -31,15 +31,22 @@ impl SystemTime { panic!("time not implemented on this platform") } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index a46c74630c9..4755e2ef5da 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -194,6 +194,10 @@ impl Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { diff --git a/library/std/src/sys/pal/wasi/time.rs b/library/std/src/sys/pal/wasi/time.rs index 0d8d0b59ac1..892661b312b 100644 --- a/library/std/src/sys/pal/wasi/time.rs +++ b/library/std/src/sys/pal/wasi/time.rs @@ -43,23 +43,34 @@ impl SystemTime { SystemTime(current_time(wasi::CLOCKID_REALTIME)) } - pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { SystemTime(Duration::from_nanos(ts)) } - pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> { - self.0.as_nanos().try_into().ok() + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> { + // FIXME: const TryInto + let ns = self.0.as_nanos(); + if ns <= u64::MAX as u128 { Some(ns as u64) } else { None } } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs index ebfabaafc79..42a7dbdf8b8 100644 --- a/library/std/src/sys/pal/wasm/atomics/thread.rs +++ b/library/std/src/sys/pal/wasm/atomics/thread.rs @@ -56,6 +56,10 @@ impl Thread { pub fn join(self) {} } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { unsupported() } diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 827d96e73db..abc1c19827f 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2158,6 +2158,7 @@ GetCurrentDirectoryW GetCurrentProcess GetCurrentProcessId GetCurrentThread +GetCurrentThreadId GetEnvironmentStringsW GetEnvironmentVariableW GetExitCodeProcess diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index b2e3aabc633..989a1246650 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -38,6 +38,7 @@ windows_targets::link!("kernel32.dll" "system" fn GetCurrentDirectoryW(nbufferle windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcess() -> HANDLE); windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcessId() -> u32); windows_targets::link!("kernel32.dll" "system" fn GetCurrentThread() -> HANDLE); +windows_targets::link!("kernel32.dll" "system" fn GetCurrentThreadId() -> u32); windows_targets::link!("kernel32.dll" "system" fn GetEnvironmentStringsW() -> PWSTR); windows_targets::link!("kernel32.dll" "system" fn GetEnvironmentVariableW(lpname : PCWSTR, lpbuffer : PWSTR, nsize : u32) -> u32); windows_targets::link!("kernel32.dll" "system" fn GetExitCodeProcess(hprocess : HANDLE, lpexitcode : *mut u32) -> BOOL); diff --git a/library/std/src/sys/pal/windows/stack_overflow.rs b/library/std/src/sys/pal/windows/stack_overflow.rs index 734cd30bed0..9a40551b985 100644 --- a/library/std/src/sys/pal/windows/stack_overflow.rs +++ b/library/std/src/sys/pal/windows/stack_overflow.rs @@ -20,7 +20,8 @@ unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POIN if code == c::EXCEPTION_STACK_OVERFLOW { thread::with_current_name(|name| { let name = name.unwrap_or("<unknown>"); - rtprintpanic!("\nthread '{name}' has overflowed its stack\n"); + let tid = thread::current_os_id(); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); }); } c::EXCEPTION_CONTINUE_SEARCH diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs index b45f76fb546..b0e38220a2d 100644 --- a/library/std/src/sys/pal/windows/thread.rs +++ b/library/std/src/sys/pal/windows/thread.rs @@ -127,6 +127,14 @@ impl Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + // SAFETY: FFI call with no preconditions. + let id: u32 = unsafe { c::GetCurrentThreadId() }; + + // A return value of 0 indicates failed lookup. + if id == 0 { None } else { Some(id.into()) } +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { let res = unsafe { let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed(); diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs index 68126bd8d2f..a948c07e0a3 100644 --- a/library/std/src/sys/pal/windows/time.rs +++ b/library/std/src/sys/pal/windows/time.rs @@ -72,7 +72,8 @@ impl SystemTime { } } - fn from_intervals(intervals: i64) -> SystemTime { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn from_intervals(intervals: i64) -> SystemTime { SystemTime { t: c::FILETIME { dwLowDateTime: intervals as u32, @@ -81,11 +82,13 @@ impl SystemTime { } } - fn intervals(&self) -> i64 { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn intervals(&self) -> i64 { (self.t.dwLowDateTime as i64) | ((self.t.dwHighDateTime as i64) << 32) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { let me = self.intervals(); let other = other.intervals(); if me >= other { @@ -95,12 +98,14 @@ impl SystemTime { } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?; Some(SystemTime::from_intervals(intervals)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?; Some(SystemTime::from_intervals(intervals)) } @@ -150,15 +155,18 @@ impl Hash for SystemTime { } } -fn checked_dur2intervals(dur: &Duration) -> Option<i64> { - dur.as_secs() +#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] +const fn checked_dur2intervals(dur: &Duration) -> Option<i64> { + // FIXME: const TryInto + let secs = dur + .as_secs() .checked_mul(INTERVALS_PER_SEC)? - .checked_add(dur.subsec_nanos() as u64 / 100)? - .try_into() - .ok() + .checked_add(dur.subsec_nanos() as u64 / 100)?; + if secs <= i64::MAX as u64 { Some(secs.cast_signed()) } else { None } } -fn intervals2dur(intervals: u64) -> Duration { +#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] +const fn intervals2dur(intervals: u64) -> Duration { Duration::new(intervals / INTERVALS_PER_SEC, ((intervals % INTERVALS_PER_SEC) * 100) as u32) } diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs index f2404a62abf..92803c94c6e 100644 --- a/library/std/src/sys/pal/xous/thread.rs +++ b/library/std/src/sys/pal/xous/thread.rs @@ -145,6 +145,10 @@ impl Thread { } } +pub(crate) fn current_os_id() -> Option<u64> { + None +} + pub fn available_parallelism() -> io::Result<NonZero<usize>> { // We're unicore right now. Ok(unsafe { NonZero::new_unchecked(1) }) diff --git a/library/std/src/sys/pal/xous/time.rs b/library/std/src/sys/pal/xous/time.rs index ae8be81c0b7..d737416436e 100644 --- a/library/std/src/sys/pal/xous/time.rs +++ b/library/std/src/sys/pal/xous/time.rs @@ -43,15 +43,22 @@ impl SystemTime { SystemTime { 0: Duration::from_millis((upper as u64) << 32 | lower as u64) } } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/process/windows.rs b/library/std/src/sys/process/windows.rs index 1ee3fbd285f..f9e15b82475 100644 --- a/library/std/src/sys/process/windows.rs +++ b/library/std/src/sys/process/windows.rs @@ -623,16 +623,10 @@ impl Stdio { // permissions as well as the ability to be inherited to child // processes (as this is about to be inherited). Stdio::Null => { - let size = size_of::<c::SECURITY_ATTRIBUTES>(); - let mut sa = c::SECURITY_ATTRIBUTES { - nLength: size as u32, - lpSecurityDescriptor: ptr::null_mut(), - bInheritHandle: 1, - }; let mut opts = OpenOptions::new(); opts.read(stdio_id == c::STD_INPUT_HANDLE); opts.write(stdio_id != c::STD_INPUT_HANDLE); - opts.security_attributes(&mut sa); + opts.inherit_handle(true); File::open(Path::new(r"\\.\NUL"), &opts).map(|file| file.into_inner()) } } |
