diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/lib.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sys/pal/common/thread_local/fast_local.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sys/pal/uefi/time.rs | 116 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/thread.rs | 30 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/c/README.md | 9 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/c/bindings.txt (renamed from library/std/src/sys/pal/windows/c/windows_sys.lst) | 3 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/c/windows_sys.rs | 7 |
7 files changed, 157 insertions, 15 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index cab3e399ffa..c6cd2c6786a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -263,6 +263,10 @@ #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_os = "xous", feature(slice_ptr_len))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] +#![cfg_attr( + all(any(target_arch = "x86_64", target_arch = "x86"), target_os = "uefi"), + feature(stdarch_x86_has_cpuid) +)] // // Language features: // tidy-alphabetical-start diff --git a/library/std/src/sys/pal/common/thread_local/fast_local.rs b/library/std/src/sys/pal/common/thread_local/fast_local.rs index 0fdca27852c..04c0dd6f750 100644 --- a/library/std/src/sys/pal/common/thread_local/fast_local.rs +++ b/library/std/src/sys/pal/common/thread_local/fast_local.rs @@ -94,7 +94,8 @@ pub macro thread_local_inner { if let $crate::option::Option::Some(init) = init { if let $crate::option::Option::Some(value) = init.take() { return value; - } else if $crate::cfg!(debug_assertions) { + } + if $crate::cfg!(debug_assertions) { $crate::unreachable!("missing default value"); } } diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index 68f428c38fb..76562cf9f51 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -14,6 +14,15 @@ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); impl Instant { pub fn now() -> Instant { + // If we have a timestamp protocol, use it. + if let Some(x) = instant_internal::timestamp_protocol() { + return x; + } + + if let Some(x) = instant_internal::platform_specific() { + return x; + } + panic!("time not implemented on this platform") } @@ -103,3 +112,110 @@ pub(crate) mod system_time_internal { Duration::new(utc_epoch, t.nanosecond) } } + +pub(crate) mod instant_internal { + use super::super::helpers; + use super::*; + use crate::mem::MaybeUninit; + use crate::ptr::NonNull; + use crate::sync::atomic::{AtomicPtr, Ordering}; + use crate::sys_common::mul_div_u64; + use r_efi::protocols::timestamp; + + const NS_PER_SEC: u64 = 1_000_000_000; + + pub fn timestamp_protocol() -> Option<Instant> { + fn try_handle(handle: NonNull<crate::ffi::c_void>) -> Option<u64> { + let protocol: NonNull<timestamp::Protocol> = + helpers::open_protocol(handle, timestamp::PROTOCOL_GUID).ok()?; + let mut properties: MaybeUninit<timestamp::Properties> = MaybeUninit::uninit(); + + let r = unsafe { ((*protocol.as_ptr()).get_properties)(properties.as_mut_ptr()) }; + if r.is_error() { + return None; + } + + let freq = unsafe { properties.assume_init().frequency }; + let ts = unsafe { ((*protocol.as_ptr()).get_timestamp)() }; + Some(mul_div_u64(ts, NS_PER_SEC, freq)) + } + + static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> = + AtomicPtr::new(crate::ptr::null_mut()); + + if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { + if let Some(ns) = try_handle(handle) { + return Some(Instant(Duration::from_nanos(ns))); + } + } + + if let Ok(handles) = helpers::locate_handles(timestamp::PROTOCOL_GUID) { + for handle in handles { + if let Some(ns) = try_handle(handle) { + LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release); + return Some(Instant(Duration::from_nanos(ns))); + } + } + } + + None + } + + pub fn platform_specific() -> Option<Instant> { + cfg_if::cfg_if! { + if #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] { + timestamp_rdtsc().map(Instant) + } else { + None + } + } + } + + #[cfg(target_arch = "x86_64")] + fn timestamp_rdtsc() -> Option<Duration> { + if !crate::arch::x86_64::has_cpuid() { + return None; + } + + static FREQUENCY: crate::sync::OnceLock<u64> = crate::sync::OnceLock::new(); + + // Get Frequency in Mhz + // Inspired by [`edk2/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c`](https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c) + let freq = FREQUENCY + .get_or_try_init(|| { + let cpuid = unsafe { crate::arch::x86_64::__cpuid(0x15) }; + if cpuid.eax == 0 || cpuid.ebx == 0 || cpuid.ecx == 0 { + return Err(()); + } + Ok(mul_div_u64(cpuid.ecx as u64, cpuid.ebx as u64, cpuid.eax as u64)) + }) + .ok()?; + + let ts = unsafe { crate::arch::x86_64::_rdtsc() }; + let ns = mul_div_u64(ts, 1000, *freq); + Some(Duration::from_nanos(ns)) + } + + #[cfg(target_arch = "x86")] + fn timestamp_rdtsc() -> Option<Duration> { + if !crate::arch::x86::has_cpuid() { + return None; + } + + static FREQUENCY: crate::sync::OnceLock<u64> = crate::sync::OnceLock::new(); + + let freq = FREQUENCY + .get_or_try_init(|| { + let cpuid = unsafe { crate::arch::x86::__cpuid(0x15) }; + if cpuid.eax == 0 || cpuid.ebx == 0 || cpuid.ecx == 0 { + return Err(()); + } + Ok(mul_div_u64(cpuid.ecx as u64, cpuid.ebx as u64, cpuid.eax as u64)) + }) + .ok()?; + + let ts = unsafe { crate::arch::x86::_rdtsc() }; + let ns = mul_div_u64(ts, 1000, *freq); + Some(Duration::from_nanos(ns)) + } +} diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 767f269dbea..97976407bb4 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -847,11 +847,31 @@ pub mod guard { let stackptr = get_stack_start_aligned()?; let guardaddr = stackptr.addr(); // Technically the number of guard pages is tunable and controlled - // by the security.bsd.stack_guard_page sysctl, but there are - // few reasons to change it from the default. The default value has - // been 1 ever since FreeBSD 11.1 and 10.4. - const GUARD_PAGES: usize = 1; - let guard = guardaddr..guardaddr + GUARD_PAGES * page_size; + // by the security.bsd.stack_guard_page sysctl. + // By default it is 1, checking once is enough since it is + // a boot time config value. + static LOCK: crate::sync::OnceLock<usize> = crate::sync::OnceLock::new(); + let guard = guardaddr + ..guardaddr + + *LOCK.get_or_init(|| { + use crate::sys::weak::dlsym; + dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int); + let mut guard: usize = 0; + let mut size = crate::mem::size_of_val(&guard); + let oid = crate::ffi::CStr::from_bytes_with_nul( + b"security.bsd.stack_guard_page\0", + ) + .unwrap(); + match sysctlbyname.get() { + Some(fcn) => { + if fcn(oid.as_ptr(), &mut guard as *mut _ as *mut _, &mut size as *mut _ as *mut _, crate::ptr::null_mut(), 0) == 0 { + return guard; + } + return 1; + }, + _ => { return 1; } + } + }) * page_size; Some(guard) } else if cfg!(target_os = "openbsd") { // OpenBSD stack already includes a guard page, and stack is diff --git a/library/std/src/sys/pal/windows/c/README.md b/library/std/src/sys/pal/windows/c/README.md new file mode 100644 index 00000000000..d458e55efbc --- /dev/null +++ b/library/std/src/sys/pal/windows/c/README.md @@ -0,0 +1,9 @@ +The `windows_sys.rs` file is autogenerated from `bindings.txt` and must not +be edited manually. + +To add bindings, edit `bindings.txt` then regenerate using the following command: + + ./x run generate-windows-sys && ./x fmt library/std + +If you need to override generated functions or types then add them to +`library/std/src/sys/pal/windows/c.rs`. diff --git a/library/std/src/sys/pal/windows/c/windows_sys.lst b/library/std/src/sys/pal/windows/c/bindings.txt index f91e1054a04..726f1c3df82 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.lst +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -1,7 +1,6 @@ --out windows_sys.rs --config flatten std --filter -// tidy-alphabetical-start !Windows.Win32.Foundation.INVALID_HANDLE_VALUE Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED Windows.Wdk.Storage.FileSystem.FILE_CONTAINS_EXTENDED_CREATE_INFORMATION @@ -2592,5 +2591,3 @@ Windows.Win32.System.Threading.WakeAllConditionVariable Windows.Win32.System.Threading.WakeConditionVariable Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE Windows.Win32.UI.Shell.GetUserProfileDirectoryW -// tidy-alphabetical-end - 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 b38b70c8983..c386b66a722 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -1,9 +1,3 @@ -// This file is autogenerated. -// -// To add bindings, edit windows_sys.lst then use `./x run generate-windows-sys` to -// regenerate the bindings. -// -// ignore-tidy-filelength // Bindings generated by `windows-bindgen` 0.52.0 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] @@ -4351,3 +4345,4 @@ impl ::core::clone::Clone for XSAVE_FORMAT { *self } } +// ignore-tidy-filelength |
