Skip to content

Commit

Permalink
Auto merge of #81250 - sivadeilra:remove_xp_compat, r=joshtriplett,m-…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
bors committed Jan 24, 2021
2 parents 72c7b70 + 59855e0 commit 9a9477f
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 145 deletions.
116 changes: 63 additions & 53 deletions library/std/src/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,77 +1020,87 @@ extern "system" {
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 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,
// but we still use them and just provide some form of a fallback implementation.
compat_fn! {
"kernel32":

pub fn CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
_lpTargetFileName: LPCWSTR,
_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
}
// >= Win10 1607
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
pub fn SetThreadDescription(hThread: HANDLE,
lpThreadDescription: LPCWSTR) -> HRESULT {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
}
pub fn SetFileInformationByHandle(_hFile: HANDLE,
_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
_lpFileInformation: LPVOID,
_dwBufferSize: DWORD) -> BOOL {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
}

// >= Win8 / Server 2012
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
-> () {
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! {
"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(
Address: LPVOID,
CompareAddress: LPVOID,
Expand Down
110 changes: 18 additions & 92 deletions library/std/src/sys/windows/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,13 @@
//!
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
//! 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::mem::{self, MaybeUninit};
use crate::sync::atomic::{AtomicUsize, Ordering};

use crate::cell::UnsafeCell;
use crate::mem::MaybeUninit;
use crate::sys::c;

pub struct Mutex {
// This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
lock: AtomicUsize,
srwlock: UnsafeCell<c::SRWLOCK>,
}

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

struct Inner {
remutex: ReentrantMutex,
held: Cell<bool>,
}

#[derive(Clone, Copy)]
enum Kind {
SRWLock,
CriticalSection,
}

#[inline]
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
debug_assert!(mem::size_of::<c::SRWLOCK>() <= mem::size_of_val(&m.lock));
&m.lock as *const _ as *mut _
m.srwlock.get()
}

impl Mutex {
pub const fn new() -> Mutex {
Mutex {
// This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
// initializing an SRWLOCK here.
lock: AtomicUsize::new(0),
}
Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
}
#[inline]
pub unsafe fn init(&mut self) {}

#[inline]
pub unsafe fn lock(&self) {
match kind() {
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");
}
}
}
c::AcquireSRWLockExclusive(raw(self));
}

#[inline]
pub unsafe fn try_lock(&self) -> bool {
match kind() {
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
}
}
}
c::TryAcquireSRWLockExclusive(raw(self)) != 0
}

#[inline]
pub unsafe fn unlock(&self) {
match kind() {
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();
}
}
}
pub unsafe fn destroy(&self) {
match kind() {
Kind::SRWLock => {}
Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
0 => {}
n => Box::from_raw(n as *mut Inner).remutex.destroy(),
},
}
c::ReleaseSRWLockExclusive(raw(self));
}

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 _
}
}
#[inline]
pub unsafe fn destroy(&self) {
// SRWLock does not need to be destroyed.
}
}

fn kind() -> Kind {
if c::AcquireSRWLockExclusive::is_available() { Kind::SRWLock } else { Kind::CriticalSection }
}

pub struct ReentrantMutex {
inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
}
Expand Down

0 comments on commit 9a9477f

Please sign in to comment.