mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 16:54:01 +00:00
Auto merge of #81250 - sivadeilra:remove_xp_compat, r=joshtriplett,m-ou-se
Remove delay-binding for Win XP and Vista The minimum supported Windows version is now Windows 7. Windows XP and Windows Vista are no longer supported; both are already broken, and require extra steps to use. This commit removes the delayed-binding support for Windows API functions that are present on all supported Windows targets. This has several benefits: Removes needless complexity. Removes a load and dynamic call on hot paths in mutex acquire / release. This may have performance benefits. * "Drop official support for Windows XP" https://github.com/rust-lang/compiler-team/issues/378 * "Firefox has ended support for Windows XP and Vista" https://support.mozilla.org/en-US/kb/end-support-windows-xp-and-vista
This commit is contained in:
commit
9a9477fada
@ -1020,6 +1020,60 @@ extern "system" {
|
|||||||
pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
|
pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
|
||||||
pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
|
pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
|
||||||
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
|
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
|
||||||
|
|
||||||
|
// >= Vista / Server 2008
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinka
|
||||||
|
pub fn CreateSymbolicLinkW(
|
||||||
|
lpSymlinkFileName: LPCWSTR,
|
||||||
|
lpTargetFileName: LPCWSTR,
|
||||||
|
dwFlags: DWORD,
|
||||||
|
) -> BOOLEAN;
|
||||||
|
|
||||||
|
// >= Vista / Server 2008
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
|
||||||
|
pub fn GetFinalPathNameByHandleW(
|
||||||
|
hFile: HANDLE,
|
||||||
|
lpszFilePath: LPCWSTR,
|
||||||
|
cchFilePath: DWORD,
|
||||||
|
dwFlags: DWORD,
|
||||||
|
) -> DWORD;
|
||||||
|
|
||||||
|
// >= Vista / Server 2003
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadstackguarantee
|
||||||
|
#[cfg(not(target_vendor = "uwp"))]
|
||||||
|
pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL;
|
||||||
|
|
||||||
|
// >= Vista / Server 2008
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle
|
||||||
|
pub fn SetFileInformationByHandle(
|
||||||
|
hFile: HANDLE,
|
||||||
|
FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
|
||||||
|
lpFileInformation: LPVOID,
|
||||||
|
dwBufferSize: DWORD,
|
||||||
|
) -> BOOL;
|
||||||
|
|
||||||
|
// >= Vista / Server 2008
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleepconditionvariablesrw
|
||||||
|
pub fn SleepConditionVariableSRW(
|
||||||
|
ConditionVariable: PCONDITION_VARIABLE,
|
||||||
|
SRWLock: PSRWLOCK,
|
||||||
|
dwMilliseconds: DWORD,
|
||||||
|
Flags: ULONG,
|
||||||
|
) -> BOOL;
|
||||||
|
|
||||||
|
// >= Vista / Server 2008
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakeconditionvariable
|
||||||
|
pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
|
||||||
|
pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
|
||||||
|
|
||||||
|
// >= Vista / Server 2008
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-acquiresrwlockexclusive
|
||||||
|
pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK);
|
||||||
|
pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK);
|
||||||
|
pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK);
|
||||||
|
pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
|
||||||
|
pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
|
||||||
|
pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions that aren't available on every version of Windows that we support,
|
// Functions that aren't available on every version of Windows that we support,
|
||||||
@ -1027,70 +1081,26 @@ extern "system" {
|
|||||||
compat_fn! {
|
compat_fn! {
|
||||||
"kernel32":
|
"kernel32":
|
||||||
|
|
||||||
pub fn CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
|
// >= Win10 1607
|
||||||
_lpTargetFileName: LPCWSTR,
|
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
|
||||||
_dwFlags: DWORD) -> BOOLEAN {
|
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
|
|
||||||
}
|
|
||||||
pub fn GetFinalPathNameByHandleW(_hFile: HANDLE,
|
|
||||||
_lpszFilePath: LPCWSTR,
|
|
||||||
_cchFilePath: DWORD,
|
|
||||||
_dwFlags: DWORD) -> DWORD {
|
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
|
|
||||||
}
|
|
||||||
#[cfg(not(target_vendor = "uwp"))]
|
|
||||||
pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
|
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
|
|
||||||
}
|
|
||||||
pub fn SetThreadDescription(hThread: HANDLE,
|
pub fn SetThreadDescription(hThread: HANDLE,
|
||||||
lpThreadDescription: LPCWSTR) -> HRESULT {
|
lpThreadDescription: LPCWSTR) -> HRESULT {
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
|
||||||
}
|
}
|
||||||
pub fn SetFileInformationByHandle(_hFile: HANDLE,
|
|
||||||
_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
|
// >= Win8 / Server 2012
|
||||||
_lpFileInformation: LPVOID,
|
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
|
||||||
_dwBufferSize: DWORD) -> BOOL {
|
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
|
|
||||||
}
|
|
||||||
pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
|
pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
|
||||||
-> () {
|
-> () {
|
||||||
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
|
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
|
||||||
}
|
}
|
||||||
pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
|
|
||||||
SRWLock: PSRWLOCK,
|
|
||||||
dwMilliseconds: DWORD,
|
|
||||||
Flags: ULONG) -> BOOL {
|
|
||||||
panic!("condition variables not available")
|
|
||||||
}
|
|
||||||
pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
|
|
||||||
-> () {
|
|
||||||
panic!("condition variables not available")
|
|
||||||
}
|
|
||||||
pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
|
|
||||||
-> () {
|
|
||||||
panic!("condition variables not available")
|
|
||||||
}
|
|
||||||
pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
|
|
||||||
panic!("rwlocks not available")
|
|
||||||
}
|
|
||||||
pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK) -> () {
|
|
||||||
panic!("rwlocks not available")
|
|
||||||
}
|
|
||||||
pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
|
|
||||||
panic!("rwlocks not available")
|
|
||||||
}
|
|
||||||
pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK) -> () {
|
|
||||||
panic!("rwlocks not available")
|
|
||||||
}
|
|
||||||
pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN {
|
|
||||||
panic!("rwlocks not available")
|
|
||||||
}
|
|
||||||
pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN {
|
|
||||||
panic!("rwlocks not available")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compat_fn! {
|
compat_fn! {
|
||||||
"api-ms-win-core-synch-l1-2-0":
|
"api-ms-win-core-synch-l1-2-0":
|
||||||
|
|
||||||
|
// >= Windows 8 / Server 2012
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress
|
||||||
pub fn WaitOnAddress(
|
pub fn WaitOnAddress(
|
||||||
Address: LPVOID,
|
Address: LPVOID,
|
||||||
CompareAddress: LPVOID,
|
CompareAddress: LPVOID,
|
||||||
|
@ -13,20 +13,13 @@
|
|||||||
//!
|
//!
|
||||||
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
|
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
|
||||||
//! is that there are no guarantees of fairness.
|
//! is that there are no guarantees of fairness.
|
||||||
//!
|
|
||||||
//! The downside of this approach, however, is that SRWLock is not available on
|
|
||||||
//! Windows XP, so we continue to have a fallback implementation where
|
|
||||||
//! CriticalSection is used and we keep track of who's holding the mutex to
|
|
||||||
//! detect recursive locks.
|
|
||||||
|
|
||||||
use crate::cell::{Cell, UnsafeCell};
|
use crate::cell::UnsafeCell;
|
||||||
use crate::mem::{self, MaybeUninit};
|
use crate::mem::MaybeUninit;
|
||||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
use crate::sys::c;
|
use crate::sys::c;
|
||||||
|
|
||||||
pub struct Mutex {
|
pub struct Mutex {
|
||||||
// This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
|
srwlock: UnsafeCell<c::SRWLOCK>,
|
||||||
lock: AtomicUsize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows SRW Locks are movable (while not borrowed).
|
// Windows SRW Locks are movable (while not borrowed).
|
||||||
@ -37,104 +30,37 @@ pub type MovableMutex = Mutex;
|
|||||||
unsafe impl Send for Mutex {}
|
unsafe impl Send for Mutex {}
|
||||||
unsafe impl Sync for Mutex {}
|
unsafe impl Sync for Mutex {}
|
||||||
|
|
||||||
struct Inner {
|
|
||||||
remutex: ReentrantMutex,
|
|
||||||
held: Cell<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
enum Kind {
|
|
||||||
SRWLock,
|
|
||||||
CriticalSection,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
|
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
|
||||||
debug_assert!(mem::size_of::<c::SRWLOCK>() <= mem::size_of_val(&m.lock));
|
m.srwlock.get()
|
||||||
&m.lock as *const _ as *mut _
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mutex {
|
impl Mutex {
|
||||||
pub const fn new() -> Mutex {
|
pub const fn new() -> Mutex {
|
||||||
Mutex {
|
Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
|
||||||
// This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
|
|
||||||
// initializing an SRWLOCK here.
|
|
||||||
lock: AtomicUsize::new(0),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn init(&mut self) {}
|
pub unsafe fn init(&mut self) {}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub unsafe fn lock(&self) {
|
pub unsafe fn lock(&self) {
|
||||||
match kind() {
|
c::AcquireSRWLockExclusive(raw(self));
|
||||||
Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
|
|
||||||
Kind::CriticalSection => {
|
|
||||||
let inner = &*self.inner();
|
|
||||||
inner.remutex.lock();
|
|
||||||
if inner.held.replace(true) {
|
|
||||||
// It was already locked, so we got a recursive lock which we do not want.
|
|
||||||
inner.remutex.unlock();
|
|
||||||
panic!("cannot recursively lock a mutex");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub unsafe fn try_lock(&self) -> bool {
|
pub unsafe fn try_lock(&self) -> bool {
|
||||||
match kind() {
|
c::TryAcquireSRWLockExclusive(raw(self)) != 0
|
||||||
Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
|
|
||||||
Kind::CriticalSection => {
|
|
||||||
let inner = &*self.inner();
|
|
||||||
if !inner.remutex.try_lock() {
|
|
||||||
false
|
|
||||||
} else if inner.held.replace(true) {
|
|
||||||
// It was already locked, so we got a recursive lock which we do not want.
|
|
||||||
inner.remutex.unlock();
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub unsafe fn unlock(&self) {
|
pub unsafe fn unlock(&self) {
|
||||||
match kind() {
|
c::ReleaseSRWLockExclusive(raw(self));
|
||||||
Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
|
|
||||||
Kind::CriticalSection => {
|
|
||||||
let inner = &*(self.lock.load(Ordering::SeqCst) as *const Inner);
|
|
||||||
inner.held.set(false);
|
|
||||||
inner.remutex.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub unsafe fn destroy(&self) {
|
pub unsafe fn destroy(&self) {
|
||||||
match kind() {
|
// SRWLock does not need to be destroyed.
|
||||||
Kind::SRWLock => {}
|
|
||||||
Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
|
|
||||||
0 => {}
|
|
||||||
n => Box::from_raw(n as *mut Inner).remutex.destroy(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn inner(&self) -> *const Inner {
|
|
||||||
match self.lock.load(Ordering::SeqCst) {
|
|
||||||
0 => {}
|
|
||||||
n => return n as *const _,
|
|
||||||
}
|
|
||||||
let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
|
|
||||||
inner.remutex.init();
|
|
||||||
let inner = Box::into_raw(inner);
|
|
||||||
match self.lock.compare_exchange(0, inner as usize, Ordering::SeqCst, Ordering::SeqCst) {
|
|
||||||
Ok(_) => inner,
|
|
||||||
Err(n) => {
|
|
||||||
Box::from_raw(inner).remutex.destroy();
|
|
||||||
n as *const _
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn kind() -> Kind {
|
|
||||||
if c::AcquireSRWLockExclusive::is_available() { Kind::SRWLock } else { Kind::CriticalSection }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReentrantMutex {
|
pub struct ReentrantMutex {
|
||||||
|
Loading…
Reference in New Issue
Block a user