Skip to content

Commit 9a9477f

Browse files
committed
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" rust-lang/compiler-team#378 * "Firefox has ended support for Windows XP and Vista" https://support.mozilla.org/en-US/kb/end-support-windows-xp-and-vista
2 parents 72c7b70 + 59855e0 commit 9a9477f

File tree

2 files changed

+81
-145
lines changed

2 files changed

+81
-145
lines changed

library/std/src/sys/windows/c.rs

+63-53
Original file line numberDiff line numberDiff line change
@@ -1020,77 +1020,87 @@ extern "system" {
10201020
pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
10211021
pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
10221022
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
1023+
1024+
// >= Vista / Server 2008
1025+
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinka
1026+
pub fn CreateSymbolicLinkW(
1027+
lpSymlinkFileName: LPCWSTR,
1028+
lpTargetFileName: LPCWSTR,
1029+
dwFlags: DWORD,
1030+
) -> BOOLEAN;
1031+
1032+
// >= Vista / Server 2008
1033+
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
1034+
pub fn GetFinalPathNameByHandleW(
1035+
hFile: HANDLE,
1036+
lpszFilePath: LPCWSTR,
1037+
cchFilePath: DWORD,
1038+
dwFlags: DWORD,
1039+
) -> DWORD;
1040+
1041+
// >= Vista / Server 2003
1042+
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadstackguarantee
1043+
#[cfg(not(target_vendor = "uwp"))]
1044+
pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL;
1045+
1046+
// >= Vista / Server 2008
1047+
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle
1048+
pub fn SetFileInformationByHandle(
1049+
hFile: HANDLE,
1050+
FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
1051+
lpFileInformation: LPVOID,
1052+
dwBufferSize: DWORD,
1053+
) -> BOOL;
1054+
1055+
// >= Vista / Server 2008
1056+
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleepconditionvariablesrw
1057+
pub fn SleepConditionVariableSRW(
1058+
ConditionVariable: PCONDITION_VARIABLE,
1059+
SRWLock: PSRWLOCK,
1060+
dwMilliseconds: DWORD,
1061+
Flags: ULONG,
1062+
) -> BOOL;
1063+
1064+
// >= Vista / Server 2008
1065+
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakeconditionvariable
1066+
pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
1067+
pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
1068+
1069+
// >= Vista / Server 2008
1070+
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-acquiresrwlockexclusive
1071+
pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK);
1072+
pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK);
1073+
pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK);
1074+
pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
1075+
pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
1076+
pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
10231077
}
10241078

10251079
// Functions that aren't available on every version of Windows that we support,
10261080
// but we still use them and just provide some form of a fallback implementation.
10271081
compat_fn! {
10281082
"kernel32":
10291083

1030-
pub fn CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
1031-
_lpTargetFileName: LPCWSTR,
1032-
_dwFlags: DWORD) -> BOOLEAN {
1033-
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
1034-
}
1035-
pub fn GetFinalPathNameByHandleW(_hFile: HANDLE,
1036-
_lpszFilePath: LPCWSTR,
1037-
_cchFilePath: DWORD,
1038-
_dwFlags: DWORD) -> DWORD {
1039-
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
1040-
}
1041-
#[cfg(not(target_vendor = "uwp"))]
1042-
pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
1043-
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
1044-
}
1084+
// >= Win10 1607
1085+
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
10451086
pub fn SetThreadDescription(hThread: HANDLE,
10461087
lpThreadDescription: LPCWSTR) -> HRESULT {
10471088
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
10481089
}
1049-
pub fn SetFileInformationByHandle(_hFile: HANDLE,
1050-
_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
1051-
_lpFileInformation: LPVOID,
1052-
_dwBufferSize: DWORD) -> BOOL {
1053-
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
1054-
}
1090+
1091+
// >= Win8 / Server 2012
1092+
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
10551093
pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
10561094
-> () {
10571095
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
10581096
}
1059-
pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
1060-
SRWLock: PSRWLOCK,
1061-
dwMilliseconds: DWORD,
1062-
Flags: ULONG) -> BOOL {
1063-
panic!("condition variables not available")
1064-
}
1065-
pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
1066-
-> () {
1067-
panic!("condition variables not available")
1068-
}
1069-
pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
1070-
-> () {
1071-
panic!("condition variables not available")
1072-
}
1073-
pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
1074-
panic!("rwlocks not available")
1075-
}
1076-
pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK) -> () {
1077-
panic!("rwlocks not available")
1078-
}
1079-
pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
1080-
panic!("rwlocks not available")
1081-
}
1082-
pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK) -> () {
1083-
panic!("rwlocks not available")
1084-
}
1085-
pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN {
1086-
panic!("rwlocks not available")
1087-
}
1088-
pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN {
1089-
panic!("rwlocks not available")
1090-
}
10911097
}
1098+
10921099
compat_fn! {
10931100
"api-ms-win-core-synch-l1-2-0":
1101+
1102+
// >= Windows 8 / Server 2012
1103+
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress
10941104
pub fn WaitOnAddress(
10951105
Address: LPVOID,
10961106
CompareAddress: LPVOID,

library/std/src/sys/windows/mutex.rs

+18-92
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,13 @@
1313
//!
1414
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
1515
//! is that there are no guarantees of fairness.
16-
//!
17-
//! The downside of this approach, however, is that SRWLock is not available on
18-
//! Windows XP, so we continue to have a fallback implementation where
19-
//! CriticalSection is used and we keep track of who's holding the mutex to
20-
//! detect recursive locks.
21-
22-
use crate::cell::{Cell, UnsafeCell};
23-
use crate::mem::{self, MaybeUninit};
24-
use crate::sync::atomic::{AtomicUsize, Ordering};
16+
17+
use crate::cell::UnsafeCell;
18+
use crate::mem::MaybeUninit;
2519
use crate::sys::c;
2620

2721
pub struct Mutex {
28-
// This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
29-
lock: AtomicUsize,
22+
srwlock: UnsafeCell<c::SRWLOCK>,
3023
}
3124

3225
// Windows SRW Locks are movable (while not borrowed).
@@ -37,106 +30,39 @@ pub type MovableMutex = Mutex;
3730
unsafe impl Send for Mutex {}
3831
unsafe impl Sync for Mutex {}
3932

40-
struct Inner {
41-
remutex: ReentrantMutex,
42-
held: Cell<bool>,
43-
}
44-
45-
#[derive(Clone, Copy)]
46-
enum Kind {
47-
SRWLock,
48-
CriticalSection,
49-
}
50-
5133
#[inline]
5234
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
53-
debug_assert!(mem::size_of::<c::SRWLOCK>() <= mem::size_of_val(&m.lock));
54-
&m.lock as *const _ as *mut _
35+
m.srwlock.get()
5536
}
5637

5738
impl Mutex {
5839
pub const fn new() -> Mutex {
59-
Mutex {
60-
// This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
61-
// initializing an SRWLOCK here.
62-
lock: AtomicUsize::new(0),
63-
}
40+
Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
6441
}
6542
#[inline]
6643
pub unsafe fn init(&mut self) {}
44+
45+
#[inline]
6746
pub unsafe fn lock(&self) {
68-
match kind() {
69-
Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
70-
Kind::CriticalSection => {
71-
let inner = &*self.inner();
72-
inner.remutex.lock();
73-
if inner.held.replace(true) {
74-
// It was already locked, so we got a recursive lock which we do not want.
75-
inner.remutex.unlock();
76-
panic!("cannot recursively lock a mutex");
77-
}
78-
}
79-
}
47+
c::AcquireSRWLockExclusive(raw(self));
8048
}
49+
50+
#[inline]
8151
pub unsafe fn try_lock(&self) -> bool {
82-
match kind() {
83-
Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
84-
Kind::CriticalSection => {
85-
let inner = &*self.inner();
86-
if !inner.remutex.try_lock() {
87-
false
88-
} else if inner.held.replace(true) {
89-
// It was already locked, so we got a recursive lock which we do not want.
90-
inner.remutex.unlock();
91-
false
92-
} else {
93-
true
94-
}
95-
}
96-
}
52+
c::TryAcquireSRWLockExclusive(raw(self)) != 0
9753
}
54+
55+
#[inline]
9856
pub unsafe fn unlock(&self) {
99-
match kind() {
100-
Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
101-
Kind::CriticalSection => {
102-
let inner = &*(self.lock.load(Ordering::SeqCst) as *const Inner);
103-
inner.held.set(false);
104-
inner.remutex.unlock();
105-
}
106-
}
107-
}
108-
pub unsafe fn destroy(&self) {
109-
match kind() {
110-
Kind::SRWLock => {}
111-
Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
112-
0 => {}
113-
n => Box::from_raw(n as *mut Inner).remutex.destroy(),
114-
},
115-
}
57+
c::ReleaseSRWLockExclusive(raw(self));
11658
}
11759

118-
unsafe fn inner(&self) -> *const Inner {
119-
match self.lock.load(Ordering::SeqCst) {
120-
0 => {}
121-
n => return n as *const _,
122-
}
123-
let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
124-
inner.remutex.init();
125-
let inner = Box::into_raw(inner);
126-
match self.lock.compare_exchange(0, inner as usize, Ordering::SeqCst, Ordering::SeqCst) {
127-
Ok(_) => inner,
128-
Err(n) => {
129-
Box::from_raw(inner).remutex.destroy();
130-
n as *const _
131-
}
132-
}
60+
#[inline]
61+
pub unsafe fn destroy(&self) {
62+
// SRWLock does not need to be destroyed.
13363
}
13464
}
13565

136-
fn kind() -> Kind {
137-
if c::AcquireSRWLockExclusive::is_available() { Kind::SRWLock } else { Kind::CriticalSection }
138-
}
139-
14066
pub struct ReentrantMutex {
14167
inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
14268
}

0 commit comments

Comments
 (0)