Skip to content

Commit

Permalink
Feodor2's patch with commented out code removed
Browse files Browse the repository at this point in the history
  • Loading branch information
K4sum1 committed Jul 11, 2024
1 parent d3fb005 commit a7d5b8c
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 171 deletions.
1 change: 1 addition & 0 deletions src/libstd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ fn main() {
println!("cargo:rustc-link-lib=bcrypt");
} else if target.contains("windows") {
println!("cargo:rustc-link-lib=advapi32");
println!("cargo:rustc-link-lib=ntdll");
println!("cargo:rustc-link-lib=ws2_32");
println!("cargo:rustc-link-lib=userenv");
} else if target.contains("fuchsia") {
Expand Down
85 changes: 25 additions & 60 deletions src/libstd/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![unstable(issue = "none", feature = "windows_c")]

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

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

Expand Down Expand Up @@ -37,6 +36,7 @@ pub type LPBYTE = *mut BYTE;
pub type LPCSTR = *const CHAR;
pub type LPCWSTR = *const WCHAR;
pub type LPDWORD = *mut DWORD;
pub type LPLONG = *mut LONG;
pub type LPHANDLE = *mut HANDLE;
pub type LPOVERLAPPED = *mut OVERLAPPED;
pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
Expand All @@ -54,9 +54,7 @@ pub type LPWSABUF = *mut WSABUF;
pub type LPWSAOVERLAPPED = *mut c_void;
pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;

pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
pub type PLARGE_INTEGER = *mut c_longlong;
pub type PSRWLOCK = *mut SRWLOCK;

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

pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002;

pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { ptr: ptr::null_mut() };
pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() };

pub const DETACHED_PROCESS: DWORD = 0x00000008;
pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200;
pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400;
Expand Down Expand Up @@ -245,7 +240,6 @@ pub struct ipv6_mreq {
pub ipv6mr_interface: c_uint,
}

pub const VOLUME_NAME_DOS: DWORD = 0x0;
pub const MOVEFILE_REPLACE_EXISTING: DWORD = 1;

pub const FILE_BEGIN: DWORD = 0;
Expand Down Expand Up @@ -418,14 +412,6 @@ pub type LPPROGRESS_ROUTINE = crate::option::Option<
) -> DWORD,
>;

#[repr(C)]
pub struct CONDITION_VARIABLE {
pub ptr: LPVOID,
}
#[repr(C)]
pub struct SRWLOCK {
pub ptr: LPVOID,
}
#[repr(C)]
pub struct CRITICAL_SECTION {
CriticalSectionDebug: LPVOID,
Expand Down Expand Up @@ -738,6 +724,21 @@ if #[cfg(target_vendor = "uwp")] {
}

// Shared between Desktop & UWP
pub type NTSTATUS = LONG;

#[repr(C)]
union IO_STATUS_BLOCK_u {
Status: NTSTATUS,
Pointer: LPVOID,
}

#[repr(C)]
pub struct IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_u,
Information: ULONG_PTR,
}
pub type PIO_STATUS_BLOCK = *mut IO_STATUS_BLOCK;

extern "system" {
pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int;
pub fn WSACleanup() -> c_int;
Expand Down Expand Up @@ -775,7 +776,7 @@ extern "system" {
dwFlags: DWORD,
) -> SOCKET;
pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int;
pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
pub fn InitializeCriticalSectionAndSpinCount(CriticalSection: *mut CRITICAL_SECTION, dwSpinCount: DWORD) -> BOOL;
pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOL;
pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
Expand Down Expand Up @@ -809,6 +810,10 @@ extern "system" {
lpThreadId: LPDWORD,
) -> HANDLE;
pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
pub fn SetEvent(hEvent: HANDLE) -> BOOL;
pub fn CreateSemaphoreW(lpSemaphoreAttributes: LPSECURITY_ATTRIBUTES, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE;
pub fn ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LPLONG) -> BOOL;
pub fn ResetEvent(hEvent: HANDLE) -> BOOL;
pub fn SwitchToThread() -> BOOL;
pub fn Sleep(dwMilliseconds: DWORD);
pub fn GetProcessId(handle: HANDLE) -> DWORD;
Expand Down Expand Up @@ -1012,6 +1017,10 @@ 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;
pub fn NtSetInformationFile(hFile: HANDLE, IoStatusBlock: PIO_STATUS_BLOCK, FileInformation: LPVOID, Length: ULONG, FileInformationClass: UINT) -> NTSTATUS;
pub fn NtQueryObject(Handle: HANDLE, ObjectInformationClass: UINT, ObjectInformation: LPCWSTR, ObjectInformationLength: ULONG, ReturnLength: *mut ULONG) -> NTSTATUS;
pub fn QueryDosDeviceW(lpDeviceName: LPCWSTR, lpTargetPath: LPWSTR, ucchMax: DWORD) -> DWORD;
pub fn GetLogicalDriveStringsW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD;
}

// Functions that aren't available on every version of Windows that we support,
Expand All @@ -1024,12 +1033,6 @@ compat_fn! {
_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
Expand All @@ -1038,46 +1041,8 @@ compat_fn! {
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
}
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")
}
}
132 changes: 107 additions & 25 deletions src/libstd/sys/windows/condvar.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,138 @@
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::cell::UnsafeCell;
use crate::ptr;
use crate::sys::c;
use crate::sys::mutex::{self, Mutex};
use crate::sys::os;
use crate::sys::mutex::Mutex;
use crate::time::Duration;

pub struct Condvar {
inner: UnsafeCell<c::CONDITION_VARIABLE>,
const WAKEUP_MODE_NONE: usize = 0;
const WAKEUP_MODE_ONE: usize = 0x40000000;
const WAKEUP_MODE_ALL: usize = 0x80000000;
const WAKEUP_MODE_MASK: usize = WAKEUP_MODE_ONE | WAKEUP_MODE_ALL;
const SLEEPERS_COUNT_MASK: usize = !WAKEUP_MODE_MASK;

pub struct Condvar { sleepersCountAndWakeupMode: AtomicUsize,
sleepWakeupSemaphore: UnsafeCell<c::HANDLE>,
wakeOneEvent: UnsafeCell<c::HANDLE>,
wakeAllEvent: UnsafeCell<c::HANDLE>,
}

unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {}

impl Condvar {
pub const fn new() -> Condvar {
Condvar { inner: UnsafeCell::new(c::CONDITION_VARIABLE_INIT) }
Condvar {
sleepersCountAndWakeupMode: AtomicUsize::new(WAKEUP_MODE_NONE),
sleepWakeupSemaphore: UnsafeCell::new(ptr::null_mut()),
wakeOneEvent: UnsafeCell::new(ptr::null_mut()),
wakeAllEvent: UnsafeCell::new(ptr::null_mut()),
}
}

#[inline]
pub unsafe fn init(&mut self) {}
pub unsafe fn init(&mut self) {
*self.sleepWakeupSemaphore.get() = c::CreateSemaphoreW(ptr::null_mut(), 1, 1, ptr::null_mut());
assert!(*self.sleepWakeupSemaphore.get() != ptr::null_mut());
*self.wakeOneEvent.get() = c::CreateEventW(ptr::null_mut(), c::FALSE, c::FALSE, ptr::null_mut());
assert!(*self.wakeOneEvent.get() != ptr::null_mut());
*self.wakeAllEvent.get() = c::CreateEventW(ptr::null_mut(), c::TRUE, c::FALSE, ptr::null_mut());
assert!(*self.wakeAllEvent.get() != ptr::null_mut());
}

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

pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
let r = c::SleepConditionVariableSRW(
self.inner.get(),
mutex::raw(mutex),
super::dur2timeout(dur),
0,
);
if r == 0 {
debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize);
false
let result = c::WaitForSingleObject(*self.sleepWakeupSemaphore.get(), c::INFINITE);
assert!(result == c::WAIT_OBJECT_0);
self.sleepersCountAndWakeupMode.fetch_add(1, Ordering::SeqCst);
let mut wcwm = self.sleepersCountAndWakeupMode.load(Ordering::SeqCst);
assert!((wcwm & WAKEUP_MODE_MASK) == 0);
let mut success = c::ReleaseSemaphore(*self.sleepWakeupSemaphore.get(), 1, ptr::null_mut());
assert!(success != 0);
mutex.unlock();
let handeles = [*self.wakeOneEvent.get(), *self.wakeAllEvent.get()];
let waitResult = c::WaitForMultipleObjects(2, handeles.as_ptr(), c::FALSE, super::dur2timeout(dur));

let sub: i32;
if waitResult == c::WAIT_OBJECT_0 {
sub = 1 | WAKEUP_MODE_ONE as i32;
} else {
sub = 1;
}

wcwm = self.sleepersCountAndWakeupMode.fetch_add(-sub as usize, Ordering::SeqCst) - sub as usize;

let wakeupMode = wcwm & WAKEUP_MODE_MASK;
let sleepersCount = wcwm & SLEEPERS_COUNT_MASK;

let mut releaseSleepWakeupSemaphore = false;

if waitResult == c::WAIT_OBJECT_0 {
releaseSleepWakeupSemaphore = true;
} else if waitResult == c::WAIT_TIMEOUT && wakeupMode == WAKEUP_MODE_ONE && sleepersCount == 0 {
success = c::ResetEvent(*self.wakeOneEvent.get());
assert!(success != 0);
self.sleepersCountAndWakeupMode.store(WAKEUP_MODE_NONE, Ordering::SeqCst);
releaseSleepWakeupSemaphore = true;
} else if wakeupMode == WAKEUP_MODE_ALL && sleepersCount == 0 {
success = c::ResetEvent(*self.wakeAllEvent.get());
assert!(success != 0);
self.sleepersCountAndWakeupMode.store(WAKEUP_MODE_NONE, Ordering::SeqCst);
releaseSleepWakeupSemaphore = true;
} else if waitResult == c::WAIT_TIMEOUT && super::dur2timeout(dur) != c::INFINITE ||
(waitResult == c::WAIT_OBJECT_0 + 1 &&wakeupMode == WAKEUP_MODE_ALL) {
} else {
true
panic!("invalid wakeup condition");
}

if releaseSleepWakeupSemaphore {
success = c::ReleaseSemaphore(*self.sleepWakeupSemaphore.get(), 1, ptr::null_mut());
assert!(success != 0);
}

mutex.lock();

if waitResult == c::WAIT_TIMEOUT {
c::SetLastError(c::ERROR_TIMEOUT);
return false;
}

true
}

#[inline]
pub unsafe fn notify_one(&self) {
c::WakeConditionVariable(self.inner.get())
Condvar::wakeup(self, WAKEUP_MODE_ONE, *self.wakeOneEvent.get());
}

#[inline]
pub unsafe fn notify_all(&self) {
c::WakeAllConditionVariable(self.inner.get())
Condvar::wakeup(self, WAKEUP_MODE_ALL, *self.wakeAllEvent.get());
}

pub unsafe fn destroy(&self) {
// ...
assert!(self.sleepersCountAndWakeupMode.load(Ordering::SeqCst) == 0);
let mut r = c::CloseHandle(*self.sleepWakeupSemaphore.get());
assert!(r != 0);
r = c::CloseHandle(*self.wakeOneEvent.get());
assert!(r != 0);
r = c::CloseHandle(*self.wakeAllEvent.get());
assert!(r != 0);
}

unsafe fn wakeup(&self, wakeupMode: usize, wakeEvent: c::HANDLE) {
let result = c::WaitForSingleObject(*self.sleepWakeupSemaphore.get(), c::INFINITE);
assert!(result == c::WAIT_OBJECT_0);
let wcwm = self.sleepersCountAndWakeupMode.fetch_add(wakeupMode, Ordering::SeqCst);
let sleepersCount = wcwm & SLEEPERS_COUNT_MASK;
if sleepersCount > 0 {
let success = c::SetEvent(wakeEvent);
assert!(success != 0);
} else {
self.sleepersCountAndWakeupMode.store(WAKEUP_MODE_NONE, Ordering::SeqCst);
let success = c::ReleaseSemaphore(*self.sleepWakeupSemaphore.get(), 1, ptr::null_mut());
assert!(success != 0);
}

}
}
Loading

0 comments on commit a7d5b8c

Please sign in to comment.