Skip to content

Commit a7d5b8c

Browse files
committed
Feodor2's patch with commented out code removed
1 parent d3fb005 commit a7d5b8c

File tree

6 files changed

+267
-171
lines changed

6 files changed

+267
-171
lines changed

src/libstd/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ fn main() {
5151
println!("cargo:rustc-link-lib=bcrypt");
5252
} else if target.contains("windows") {
5353
println!("cargo:rustc-link-lib=advapi32");
54+
println!("cargo:rustc-link-lib=ntdll");
5455
println!("cargo:rustc-link-lib=ws2_32");
5556
println!("cargo:rustc-link-lib=userenv");
5657
} else if target.contains("fuchsia") {

src/libstd/sys/windows/c.rs

Lines changed: 25 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#![unstable(issue = "none", feature = "windows_c")]
66

77
use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
8-
use crate::ptr;
98

109
use libc::{c_void, size_t, wchar_t};
1110

@@ -37,6 +36,7 @@ pub type LPBYTE = *mut BYTE;
3736
pub type LPCSTR = *const CHAR;
3837
pub type LPCWSTR = *const WCHAR;
3938
pub type LPDWORD = *mut DWORD;
39+
pub type LPLONG = *mut LONG;
4040
pub type LPHANDLE = *mut HANDLE;
4141
pub type LPOVERLAPPED = *mut OVERLAPPED;
4242
pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
@@ -54,9 +54,7 @@ pub type LPWSABUF = *mut WSABUF;
5454
pub type LPWSAOVERLAPPED = *mut c_void;
5555
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
5656

57-
pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
5857
pub type PLARGE_INTEGER = *mut c_longlong;
59-
pub type PSRWLOCK = *mut SRWLOCK;
6058

6159
pub type SOCKET = crate::os::windows::raw::SOCKET;
6260
pub type socklen_t = c_int;
@@ -198,9 +196,6 @@ pub const INFINITE: DWORD = !0;
198196

199197
pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002;
200198

201-
pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { ptr: ptr::null_mut() };
202-
pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() };
203-
204199
pub const DETACHED_PROCESS: DWORD = 0x00000008;
205200
pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200;
206201
pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400;
@@ -245,7 +240,6 @@ pub struct ipv6_mreq {
245240
pub ipv6mr_interface: c_uint,
246241
}
247242

248-
pub const VOLUME_NAME_DOS: DWORD = 0x0;
249243
pub const MOVEFILE_REPLACE_EXISTING: DWORD = 1;
250244

251245
pub const FILE_BEGIN: DWORD = 0;
@@ -418,14 +412,6 @@ pub type LPPROGRESS_ROUTINE = crate::option::Option<
418412
) -> DWORD,
419413
>;
420414

421-
#[repr(C)]
422-
pub struct CONDITION_VARIABLE {
423-
pub ptr: LPVOID,
424-
}
425-
#[repr(C)]
426-
pub struct SRWLOCK {
427-
pub ptr: LPVOID,
428-
}
429415
#[repr(C)]
430416
pub struct CRITICAL_SECTION {
431417
CriticalSectionDebug: LPVOID,
@@ -738,6 +724,21 @@ if #[cfg(target_vendor = "uwp")] {
738724
}
739725

740726
// Shared between Desktop & UWP
727+
pub type NTSTATUS = LONG;
728+
729+
#[repr(C)]
730+
union IO_STATUS_BLOCK_u {
731+
Status: NTSTATUS,
732+
Pointer: LPVOID,
733+
}
734+
735+
#[repr(C)]
736+
pub struct IO_STATUS_BLOCK {
737+
u: IO_STATUS_BLOCK_u,
738+
Information: ULONG_PTR,
739+
}
740+
pub type PIO_STATUS_BLOCK = *mut IO_STATUS_BLOCK;
741+
741742
extern "system" {
742743
pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int;
743744
pub fn WSACleanup() -> c_int;
@@ -775,7 +776,7 @@ extern "system" {
775776
dwFlags: DWORD,
776777
) -> SOCKET;
777778
pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int;
778-
pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
779+
pub fn InitializeCriticalSectionAndSpinCount(CriticalSection: *mut CRITICAL_SECTION, dwSpinCount: DWORD) -> BOOL;
779780
pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
780781
pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOL;
781782
pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
@@ -809,6 +810,10 @@ extern "system" {
809810
lpThreadId: LPDWORD,
810811
) -> HANDLE;
811812
pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
813+
pub fn SetEvent(hEvent: HANDLE) -> BOOL;
814+
pub fn CreateSemaphoreW(lpSemaphoreAttributes: LPSECURITY_ATTRIBUTES, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE;
815+
pub fn ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LPLONG) -> BOOL;
816+
pub fn ResetEvent(hEvent: HANDLE) -> BOOL;
812817
pub fn SwitchToThread() -> BOOL;
813818
pub fn Sleep(dwMilliseconds: DWORD);
814819
pub fn GetProcessId(handle: HANDLE) -> DWORD;
@@ -1012,6 +1017,10 @@ extern "system" {
10121017
pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
10131018
pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
10141019
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
1020+
pub fn NtSetInformationFile(hFile: HANDLE, IoStatusBlock: PIO_STATUS_BLOCK, FileInformation: LPVOID, Length: ULONG, FileInformationClass: UINT) -> NTSTATUS;
1021+
pub fn NtQueryObject(Handle: HANDLE, ObjectInformationClass: UINT, ObjectInformation: LPCWSTR, ObjectInformationLength: ULONG, ReturnLength: *mut ULONG) -> NTSTATUS;
1022+
pub fn QueryDosDeviceW(lpDeviceName: LPCWSTR, lpTargetPath: LPWSTR, ucchMax: DWORD) -> DWORD;
1023+
pub fn GetLogicalDriveStringsW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD;
10151024
}
10161025

10171026
// Functions that aren't available on every version of Windows that we support,
@@ -1024,12 +1033,6 @@ compat_fn! {
10241033
_dwFlags: DWORD) -> BOOLEAN {
10251034
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
10261035
}
1027-
pub fn GetFinalPathNameByHandleW(_hFile: HANDLE,
1028-
_lpszFilePath: LPCWSTR,
1029-
_cchFilePath: DWORD,
1030-
_dwFlags: DWORD) -> DWORD {
1031-
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
1032-
}
10331036
#[cfg(not(target_vendor = "uwp"))]
10341037
pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
10351038
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
@@ -1038,46 +1041,8 @@ compat_fn! {
10381041
lpThreadDescription: LPCWSTR) -> HRESULT {
10391042
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
10401043
}
1041-
pub fn SetFileInformationByHandle(_hFile: HANDLE,
1042-
_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
1043-
_lpFileInformation: LPVOID,
1044-
_dwBufferSize: DWORD) -> BOOL {
1045-
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
1046-
}
10471044
pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
10481045
-> () {
10491046
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
10501047
}
1051-
pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
1052-
SRWLock: PSRWLOCK,
1053-
dwMilliseconds: DWORD,
1054-
Flags: ULONG) -> BOOL {
1055-
panic!("condition variables not available")
1056-
}
1057-
pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
1058-
-> () {
1059-
panic!("condition variables not available")
1060-
}
1061-
pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE)
1062-
-> () {
1063-
panic!("condition variables not available")
1064-
}
1065-
pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
1066-
panic!("rwlocks not available")
1067-
}
1068-
pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK) -> () {
1069-
panic!("rwlocks not available")
1070-
}
1071-
pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK) -> () {
1072-
panic!("rwlocks not available")
1073-
}
1074-
pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK) -> () {
1075-
panic!("rwlocks not available")
1076-
}
1077-
pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN {
1078-
panic!("rwlocks not available")
1079-
}
1080-
pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN {
1081-
panic!("rwlocks not available")
1082-
}
10831048
}

src/libstd/sys/windows/condvar.rs

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,138 @@
1+
use crate::sync::atomic::{AtomicUsize, Ordering};
12
use crate::cell::UnsafeCell;
3+
use crate::ptr;
24
use crate::sys::c;
3-
use crate::sys::mutex::{self, Mutex};
4-
use crate::sys::os;
5+
use crate::sys::mutex::Mutex;
56
use crate::time::Duration;
67

7-
pub struct Condvar {
8-
inner: UnsafeCell<c::CONDITION_VARIABLE>,
8+
const WAKEUP_MODE_NONE: usize = 0;
9+
const WAKEUP_MODE_ONE: usize = 0x40000000;
10+
const WAKEUP_MODE_ALL: usize = 0x80000000;
11+
const WAKEUP_MODE_MASK: usize = WAKEUP_MODE_ONE | WAKEUP_MODE_ALL;
12+
const SLEEPERS_COUNT_MASK: usize = !WAKEUP_MODE_MASK;
13+
14+
pub struct Condvar { sleepersCountAndWakeupMode: AtomicUsize,
15+
sleepWakeupSemaphore: UnsafeCell<c::HANDLE>,
16+
wakeOneEvent: UnsafeCell<c::HANDLE>,
17+
wakeAllEvent: UnsafeCell<c::HANDLE>,
918
}
1019

1120
unsafe impl Send for Condvar {}
1221
unsafe impl Sync for Condvar {}
1322

1423
impl Condvar {
1524
pub const fn new() -> Condvar {
16-
Condvar { inner: UnsafeCell::new(c::CONDITION_VARIABLE_INIT) }
25+
Condvar {
26+
sleepersCountAndWakeupMode: AtomicUsize::new(WAKEUP_MODE_NONE),
27+
sleepWakeupSemaphore: UnsafeCell::new(ptr::null_mut()),
28+
wakeOneEvent: UnsafeCell::new(ptr::null_mut()),
29+
wakeAllEvent: UnsafeCell::new(ptr::null_mut()),
30+
}
1731
}
1832

19-
#[inline]
20-
pub unsafe fn init(&mut self) {}
33+
pub unsafe fn init(&mut self) {
34+
*self.sleepWakeupSemaphore.get() = c::CreateSemaphoreW(ptr::null_mut(), 1, 1, ptr::null_mut());
35+
assert!(*self.sleepWakeupSemaphore.get() != ptr::null_mut());
36+
*self.wakeOneEvent.get() = c::CreateEventW(ptr::null_mut(), c::FALSE, c::FALSE, ptr::null_mut());
37+
assert!(*self.wakeOneEvent.get() != ptr::null_mut());
38+
*self.wakeAllEvent.get() = c::CreateEventW(ptr::null_mut(), c::TRUE, c::FALSE, ptr::null_mut());
39+
assert!(*self.wakeAllEvent.get() != ptr::null_mut());
40+
}
2141

22-
#[inline]
2342
pub unsafe fn wait(&self, mutex: &Mutex) {
24-
let r = c::SleepConditionVariableSRW(self.inner.get(), mutex::raw(mutex), c::INFINITE, 0);
25-
debug_assert!(r != 0);
43+
Condvar::wait_timeout(self, mutex, Duration::from_secs(1000 * 365 * 86400));
2644
}
2745

2846
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
29-
let r = c::SleepConditionVariableSRW(
30-
self.inner.get(),
31-
mutex::raw(mutex),
32-
super::dur2timeout(dur),
33-
0,
34-
);
35-
if r == 0 {
36-
debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize);
37-
false
47+
let result = c::WaitForSingleObject(*self.sleepWakeupSemaphore.get(), c::INFINITE);
48+
assert!(result == c::WAIT_OBJECT_0);
49+
self.sleepersCountAndWakeupMode.fetch_add(1, Ordering::SeqCst);
50+
let mut wcwm = self.sleepersCountAndWakeupMode.load(Ordering::SeqCst);
51+
assert!((wcwm & WAKEUP_MODE_MASK) == 0);
52+
let mut success = c::ReleaseSemaphore(*self.sleepWakeupSemaphore.get(), 1, ptr::null_mut());
53+
assert!(success != 0);
54+
mutex.unlock();
55+
let handeles = [*self.wakeOneEvent.get(), *self.wakeAllEvent.get()];
56+
let waitResult = c::WaitForMultipleObjects(2, handeles.as_ptr(), c::FALSE, super::dur2timeout(dur));
57+
58+
let sub: i32;
59+
if waitResult == c::WAIT_OBJECT_0 {
60+
sub = 1 | WAKEUP_MODE_ONE as i32;
61+
} else {
62+
sub = 1;
63+
}
64+
65+
wcwm = self.sleepersCountAndWakeupMode.fetch_add(-sub as usize, Ordering::SeqCst) - sub as usize;
66+
67+
let wakeupMode = wcwm & WAKEUP_MODE_MASK;
68+
let sleepersCount = wcwm & SLEEPERS_COUNT_MASK;
69+
70+
let mut releaseSleepWakeupSemaphore = false;
71+
72+
if waitResult == c::WAIT_OBJECT_0 {
73+
releaseSleepWakeupSemaphore = true;
74+
} else if waitResult == c::WAIT_TIMEOUT && wakeupMode == WAKEUP_MODE_ONE && sleepersCount == 0 {
75+
success = c::ResetEvent(*self.wakeOneEvent.get());
76+
assert!(success != 0);
77+
self.sleepersCountAndWakeupMode.store(WAKEUP_MODE_NONE, Ordering::SeqCst);
78+
releaseSleepWakeupSemaphore = true;
79+
} else if wakeupMode == WAKEUP_MODE_ALL && sleepersCount == 0 {
80+
success = c::ResetEvent(*self.wakeAllEvent.get());
81+
assert!(success != 0);
82+
self.sleepersCountAndWakeupMode.store(WAKEUP_MODE_NONE, Ordering::SeqCst);
83+
releaseSleepWakeupSemaphore = true;
84+
} else if waitResult == c::WAIT_TIMEOUT && super::dur2timeout(dur) != c::INFINITE ||
85+
(waitResult == c::WAIT_OBJECT_0 + 1 &&wakeupMode == WAKEUP_MODE_ALL) {
3886
} else {
39-
true
87+
panic!("invalid wakeup condition");
88+
}
89+
90+
if releaseSleepWakeupSemaphore {
91+
success = c::ReleaseSemaphore(*self.sleepWakeupSemaphore.get(), 1, ptr::null_mut());
92+
assert!(success != 0);
4093
}
94+
95+
mutex.lock();
96+
97+
if waitResult == c::WAIT_TIMEOUT {
98+
c::SetLastError(c::ERROR_TIMEOUT);
99+
return false;
100+
}
101+
102+
true
41103
}
42104

43-
#[inline]
44105
pub unsafe fn notify_one(&self) {
45-
c::WakeConditionVariable(self.inner.get())
106+
Condvar::wakeup(self, WAKEUP_MODE_ONE, *self.wakeOneEvent.get());
46107
}
47108

48-
#[inline]
49109
pub unsafe fn notify_all(&self) {
50-
c::WakeAllConditionVariable(self.inner.get())
110+
Condvar::wakeup(self, WAKEUP_MODE_ALL, *self.wakeAllEvent.get());
51111
}
52112

53113
pub unsafe fn destroy(&self) {
54-
// ...
114+
assert!(self.sleepersCountAndWakeupMode.load(Ordering::SeqCst) == 0);
115+
let mut r = c::CloseHandle(*self.sleepWakeupSemaphore.get());
116+
assert!(r != 0);
117+
r = c::CloseHandle(*self.wakeOneEvent.get());
118+
assert!(r != 0);
119+
r = c::CloseHandle(*self.wakeAllEvent.get());
120+
assert!(r != 0);
121+
}
122+
123+
unsafe fn wakeup(&self, wakeupMode: usize, wakeEvent: c::HANDLE) {
124+
let result = c::WaitForSingleObject(*self.sleepWakeupSemaphore.get(), c::INFINITE);
125+
assert!(result == c::WAIT_OBJECT_0);
126+
let wcwm = self.sleepersCountAndWakeupMode.fetch_add(wakeupMode, Ordering::SeqCst);
127+
let sleepersCount = wcwm & SLEEPERS_COUNT_MASK;
128+
if sleepersCount > 0 {
129+
let success = c::SetEvent(wakeEvent);
130+
assert!(success != 0);
131+
} else {
132+
self.sleepersCountAndWakeupMode.store(WAKEUP_MODE_NONE, Ordering::SeqCst);
133+
let success = c::ReleaseSemaphore(*self.sleepWakeupSemaphore.get(), 1, ptr::null_mut());
134+
assert!(success != 0);
135+
}
136+
55137
}
56138
}

0 commit comments

Comments
 (0)