diff --git a/dtool/src/dtoolbase/dtoolbase.h b/dtool/src/dtoolbase/dtoolbase.h index 66142427cc..2207915f28 100644 --- a/dtool/src/dtoolbase/dtoolbase.h +++ b/dtool/src/dtoolbase/dtoolbase.h @@ -118,7 +118,7 @@ #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif -#define _WIN32_WINNT 0x0502 +#define _WIN32_WINNT 0x0600 #ifdef __cplusplus #ifndef __STDC_LIMIT_MACROS diff --git a/dtool/src/dtoolbase/mutexWin32Impl.I b/dtool/src/dtoolbase/mutexWin32Impl.I index b61d314d61..90115aaab9 100644 --- a/dtool/src/dtoolbase/mutexWin32Impl.I +++ b/dtool/src/dtoolbase/mutexWin32Impl.I @@ -11,24 +11,12 @@ * @date 2006-02-07 */ -/** - * - */ -INLINE MutexWin32Impl:: -~MutexWin32Impl() { - // If the lock has been contended, and we use the Windows XP implementation, - // we have a handle to close. Otherwise, this field will be null. - if (_lock[1] != nullptr) { - CloseHandle(_lock[1]); - } -} - /** * */ INLINE void MutexWin32Impl:: lock() { - _funcs._lock(_lock); + AcquireSRWLockExclusive(&_lock); } /** @@ -36,7 +24,7 @@ lock() { */ INLINE bool MutexWin32Impl:: try_lock() { - return (_funcs._try_lock(_lock) != 0); + return (TryAcquireSRWLockExclusive(&_lock) != 0); } /** @@ -44,7 +32,7 @@ try_lock() { */ INLINE void MutexWin32Impl:: unlock() { - _funcs._unlock(_lock); + ReleaseSRWLockExclusive(&_lock); } /** diff --git a/dtool/src/dtoolbase/mutexWin32Impl.cxx b/dtool/src/dtoolbase/mutexWin32Impl.cxx index 4b0e63a357..4488c637ae 100644 --- a/dtool/src/dtoolbase/mutexWin32Impl.cxx +++ b/dtool/src/dtoolbase/mutexWin32Impl.cxx @@ -13,406 +13,13 @@ #include "selectThreadImpl.h" -#if defined(WIN32_VC) && !defined(CPPPARSER) +#ifdef WIN32_VC #include "mutexWin32Impl.h" // The number of spins to do before suspending the thread. static const unsigned int spin_count = 4000; -// Only compile the below nonsense if we're not compiling for a Vista minimum. -#if _WIN32_WINNT < 0x0600 - -// If this is true, we will use SRWLock on Windows Vista and above instead of -// our own implementation. -static const bool prefer_srwlock = true; - -// These configure our own Windows XP implementation. -static const uintptr_t lock_bit = 0x40000000; - -// This gets set to spin_count if we are on a multi-core system. -static unsigned int effective_spin_count = 0; - -/** - * Windows XP implementation of lock(), which uses a combination of a spinlock - * and an event. - */ -static void __stdcall lock_xp(volatile PVOID *lock) { - // In the Windows XP case, lock consists of two words: the first one is a - // number of waiters plus a bit to indicate that it is locked, the second - // one is the handle of an event that is created in case of contention. - // The first word can be in the following states: - // - // lock bit | waiters | meaning - // ---------|---------|--------- - // unset | 0 | unlocked - // set | 0 | locked, nobody waiting on event - // set | >0 | locked, at least one thread waiting on event - // unset | >0 | handing off lock to one of waiters - // - // The last state is a little subtle: at this point, the thread that was - // holding the lock has stopped holding it, but is about to fire off a - // signal to a waiting thread, which will attempt to grab the lock. In this - // case, the waiting thread has first dibs on the lock, and any new threads - // will still treat it as locked and wait until there are no more waiters. - - // First try to acquire the lock without suspending the thread. This only - // works if the waiter count is 0; this way, we give priority to threads - // that are already waiting for the event. - if (InterlockedCompareExchangePointer(lock, (void *)lock_bit, nullptr) == nullptr) { - // Got the lock on the first try. - return; - } - - // On multi-core systems, we keep trying for the configured spin_count. - const unsigned int max_spins = effective_spin_count; - for (unsigned int spins = 0; spins < max_spins; ++spins) { - if (InterlockedCompareExchangePointer(lock, (void *)lock_bit, nullptr) == nullptr) { - // We managed to acquire the lock. - return; - } - - // Emit the pause instruction. This is NOT a thread yield. - YieldProcessor(); - } - - // Looks like we might have to go to sleep for a while using an event. - HANDLE event = lock[1]; - if (event == nullptr) { - // We don't have an event yet. Create an auto-reset event. - HANDLE new_event = CreateEvent(nullptr, false, false, nullptr); - while (new_event == nullptr) { - // Hmm, out of memory? Just yield to another thread for now until the - // lock is either freed or until we can create an event. - Sleep(1); - if (InterlockedCompareExchangePointer(lock, (void *)lock_bit, nullptr) == 0) { - return; - } - new_event = CreateEvent(nullptr, false, false, nullptr); - } - - // Push the new event. - event = InterlockedCompareExchangePointer(lock + 1, new_event, nullptr); - if (event == nullptr) { - // Set successfully. - event = new_event; - } else { - // Another thread created an event; delete ours and use that one instead. - CloseHandle(new_event); - } - } - - // OK, now we have an event. We need to let the unlock() function know that - // we are waiting. - while (true) { - uintptr_t waiters = (uintptr_t)lock[0]; - if (waiters == 0) { - // It became unlocked while we were creating an event. Quick, grab it. - if (InterlockedCompareExchangePointer(lock, (void *)lock_bit, nullptr) == nullptr) { - return; - } - } - - // If the lock bit gets unset while we try this, just keep trying. It - // would be dangerous to increment this while the lock bit is unset. - waiters |= lock_bit; - uintptr_t new_waiters = (uintptr_t)InterlockedCompareExchangePointer(lock, (void *)(waiters + 1), (void *)waiters); - if (new_waiters == waiters) { - // Made the change successfully. - break; - } else if (new_waiters == 0) { - // It just became unlocked. Quick, grab it. - if (InterlockedCompareExchangePointer(lock, (void *)lock_bit, nullptr) == nullptr) { - return; - } - } - YieldProcessor(); - } - - // Sleep well, thread. - while (true) { - WaitForSingleObjectEx(event, INFINITE, FALSE); - - // We were woken up. Does that mean the lock can be ours? - while (true) { - uintptr_t waiters = (uintptr_t)lock[0]; - if (waiters & lock_bit) { - // False alarm. Go back to sleep. - break; - } - assert(waiters > 0); - - // Grab the lock immediately, and simultaneously tell it that we are no - // longer waiting. - uintptr_t new_waiters = (uintptr_t)InterlockedCompareExchangePointer(lock, (void *)((waiters - 1) | lock_bit), (void *)waiters); - if (new_waiters == waiters) { - // The lock is ours. - return; - } else if (new_waiters & lock_bit) { - // Another thread beat us to it. Go back to sleep. - break; - } - YieldProcessor(); - } - } - - // Never supposed to get here. - assert(false); -} - -/** - * Windows XP implementation of try_lock(). - */ -static BOOL __stdcall try_lock_xp(volatile PVOID *lock) { - return (InterlockedCompareExchangePointer(lock, (void *)lock_bit, nullptr) == nullptr); -} - -/** - * Windows XP implementation of unlock(). - */ -static void __stdcall unlock_xp(volatile PVOID *lock) { - // Clear the lock flag. -#ifdef _WIN64 - uintptr_t waiters = _InterlockedAnd64((volatile __int64 *)lock, ~lock_bit); -#else - uintptr_t waiters = _InterlockedAnd((volatile long *)lock, ~lock_bit); -#endif - - // If this triggers, the lock wasn't held to begin with. - assert((waiters & lock_bit) != 0); - - // Have any threads begun to sleep (or are about to) waiting for this lock? - if ((waiters & ~lock_bit) == 0) { - // No contention, nothing to do. - return; - } else { - // By signalling the auto-resetting event, we wake up one waiting thread. - HANDLE event = lock[1]; - assert(event != nullptr); - SetEvent(event); - } -} - -/** - * Windows XP implementation to wait for a condition variable. - */ -static BOOL __stdcall -cvar_wait_xp(volatile PVOID *cvar, volatile PVOID *lock, DWORD timeout, ULONG) { - // Increment the number of waiters. -#ifdef _WIN64 - _InterlockedIncrement64((volatile __int64 *)cvar); -#else - _InterlockedIncrement((volatile long *)cvar); -#endif - - // Make sure we have two events created: one auto-reset event and one - // manual-reset, to handle signal and broadcast, respectively. - if (cvar[1] == nullptr) { - cvar[1] = CreateEvent(nullptr, false, false, nullptr); - } - if (cvar[2] == nullptr) { - cvar[2] = CreateEvent(nullptr, true, false, nullptr); - } - - // It's ok to release the external_mutex here since Win32 manual-reset - // events maintain state when used with SetEvent(). This avoids the "lost - // wakeup" bug... - unlock_xp(lock); - - // Wait for either event to become signaled due to notify() being called or - // notify_all() being called. - int result = WaitForMultipleObjects(2, (const HANDLE *)(cvar + 1), FALSE, timeout); - - // Decrement the counter. If it reached zero, we were the last waiter. -#ifdef _WIN64 - bool nonzero = (_InterlockedDecrement64((volatile __int64 *)cvar) != 0); -#else - bool nonzero = (_InterlockedDecrement((volatile long *)cvar) != 0); -#endif - bool last_waiter = (result == WAIT_OBJECT_0 + 1 && !nonzero); - - // Some thread called notify_all(). - if (last_waiter) { - // We're the last waiter to be notified or to stop waiting, so reset the - // manual event. - ResetEvent(cvar[2]); - } - - // Reacquire the . - lock_xp(lock); - return TRUE; -} - -/** - * Wakes one thread waiting for a condition variable. - */ -static void __stdcall -cvar_notify_one_xp(volatile PVOID *cvar) { - // If there are any waiters, signal one of them to wake up by signalling the - // auto-reset event. - if ((uintptr_t)cvar[0] > 0) { - SetEvent(cvar[1]); - } -} - -/** - * Wakes all threads waiting for a condition variable. - */ -static void __stdcall -cvar_notify_all_xp(volatile PVOID *cvar) { - // If there are any waiters, signal the manual-reset event, which will be - // reset by the last thread to wake up. - if ((uintptr_t)cvar[0] > 0) { - SetEvent(cvar[2]); - } -} - -#endif // _WIN32_WINNT < 0x0600 - -/** - * This is put initially in the _lock slot; it makes sure that the lock - * functions get initialized the first time someone tries to grab a lock. - */ -void __stdcall MutexWin32Impl:: -lock_initially(volatile PVOID *lock) { - MutexWin32Impl::init_lock_funcs(); - MutexWin32Impl::_funcs._lock(lock); -} - -/** - * This is put initially in the _try_lock slot; it makes sure that the lock - * functions get initialized the first time someone tries to grab a lock. - */ -BOOL __stdcall MutexWin32Impl:: -try_lock_initially(volatile PVOID *lock) { - MutexWin32Impl::init_lock_funcs(); - return MutexWin32Impl::_funcs._try_lock(lock); -} - -/** - * This gets put initially in the _unlock slot and should never be called, - * since the initial lock/try_lock implementation will replace the pointers. - */ -void __stdcall MutexWin32Impl:: -unlock_initially(volatile PVOID *) { -#if !defined(NDEBUG) || defined(DEBUG_THREADS) - std::cerr << "Attempt to release a mutex at static init time before acquiring it!\n"; - assert(false); -#endif -} - -/** - * Same as above for condition variables. - */ -static BOOL __stdcall -cvar_wait_initially(volatile PVOID *cvar, volatile PVOID *lock, DWORD timeout, ULONG) { -#if !defined(NDEBUG) || defined(DEBUG_THREADS) - std::cerr << "Attempt to wait for condition variable at static init time before acquiring mutex!\n"; - assert(false); -#endif - return FALSE; -} - -/** - * Does nothing. - */ -static void __stdcall -noop(volatile PVOID *) { -} - -// We initially set the function pointers to functions that do initialization -// first. -MutexWin32Impl::LockFunctions MutexWin32Impl::_funcs = { - &MutexWin32Impl::lock_initially, - &MutexWin32Impl::try_lock_initially, -#ifndef NDEBUG - &MutexWin32Impl::unlock_initially, -#else - &noop, -#endif - - &cvar_wait_initially, -#ifndef NDEBUG - &MutexWin32Impl::unlock_initially, - &MutexWin32Impl::unlock_initially, -#else - &noop, - &noop, -#endif -}; - -/** - * Called the first time a lock is grabbed. - */ -void MutexWin32Impl:: -init_lock_funcs() { - if (MutexWin32Impl::_funcs._lock != &MutexWin32Impl::lock_initially) { - // Already initialized. - return; - } - -#if _WIN32_WINNT >= 0x0600 - _funcs._lock = (LockFunc)AcquireSRWLockExclusive; - _funcs._try_lock = (TryLockFunc)TryAcquireSRWLockExclusive; - _funcs._unlock = (LockFunc)ReleaseSRWLockExclusive; - _funcs._cvar_wait = (CondWaitFunc)SleepConditionVariableSRW; - _funcs._cvar_notify_one = (LockFunc)WakeConditionVariable; - _funcs._cvar_notify_all = (LockFunc)WakeAllConditionVariable; -#else - // We don't need to be very thread safe here. This can only ever be called - // at static init time, when there is still only one thread. - if (prefer_srwlock) { - HMODULE module = GetModuleHandleA("kernel32"); - if (module != nullptr) { - _funcs._lock = (LockFunc)GetProcAddress(module, "AcquireSRWLockExclusive"); - _funcs._try_lock = (TryLockFunc)GetProcAddress(module, "TryAcquireSRWLockExclusive"); - _funcs._unlock = (LockFunc)GetProcAddress(module, "ReleaseSRWLockExclusive"); - _funcs._cvar_wait = (CondWaitFunc)GetProcAddress(module, "SleepConditionVariableSRW"); - _funcs._cvar_notify_one = (LockFunc)GetProcAddress(module, "WakeConditionVariable"); - _funcs._cvar_notify_all = (LockFunc)GetProcAddress(module, "WakeAllConditionVariable"); - if (_funcs._lock != nullptr && - _funcs._try_lock != nullptr && - _funcs._unlock != nullptr && - _funcs._cvar_wait != nullptr && - _funcs._cvar_notify_one != nullptr && - _funcs._cvar_notify_all != nullptr) { - return; - } - } - } - - // Fall back to our custom Event-based implementation on Windows XP. - _funcs._lock = &lock_xp; - _funcs._try_lock = &try_lock_xp; - _funcs._unlock = &unlock_xp; - _funcs._cvar_wait = &cvar_wait_xp; - _funcs._cvar_notify_one = &cvar_notify_one_xp; - _funcs._cvar_notify_all = &cvar_notify_all_xp; - - // Are we on a multi-core system? If so, enable the spinlock. - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - if (sysinfo.dwNumberOfProcessors > 1) { - effective_spin_count = spin_count; - } else { - effective_spin_count = 0; - } -#endif // _WIN32_WINNT < 0x0600 -} - -/** - * Ensures that the lock functions are initialized at static init time. This - * prevents us from having to implement synchronization in our initialization. - */ -class LockFuncsInitializer { -public: - LockFuncsInitializer() { - MutexWin32Impl::init_lock_funcs(); - } -}; - -static LockFuncsInitializer _lock_funcs_init; - /** * */ diff --git a/dtool/src/dtoolbase/mutexWin32Impl.h b/dtool/src/dtoolbase/mutexWin32Impl.h index 47f31a2e8f..0df0808459 100644 --- a/dtool/src/dtoolbase/mutexWin32Impl.h +++ b/dtool/src/dtoolbase/mutexWin32Impl.h @@ -31,7 +31,7 @@ class EXPCL_DTOOL_DTOOLBASE MutexWin32Impl { public: constexpr MutexWin32Impl() = default; MutexWin32Impl(const MutexWin32Impl ©) = delete; - INLINE ~MutexWin32Impl(); + ~MutexWin32Impl() = default; MutexWin32Impl &operator = (const MutexWin32Impl ©) = delete; @@ -40,38 +40,8 @@ public: INLINE bool try_lock(); INLINE void unlock(); - static void init_lock_funcs(); - private: -#ifndef CPPPARSER - // Store function pointers; these point directly to the SRWLock Win32 API - // functions on Vista and above, or to our own implementation on Windows XP. - typedef void (__stdcall *LockFunc)(volatile PVOID *lock); - typedef BOOL (__stdcall *TryLockFunc)(volatile PVOID *lock); - typedef BOOL (__stdcall *CondWaitFunc)(volatile PVOID *cvar, volatile PVOID *lock, DWORD, ULONG); - - struct LockFunctions { - LockFunc _lock; - TryLockFunc _try_lock; - LockFunc _unlock; - - CondWaitFunc _cvar_wait; - LockFunc _cvar_notify_one; - LockFunc _cvar_notify_all; - }; - - static LockFunctions _funcs; - - static void __stdcall lock_initially(volatile PVOID *lock); - static BOOL __stdcall try_lock_initially(volatile PVOID *lock); - static void __stdcall unlock_initially(volatile PVOID *lock); -#endif - -private: - // In the SRWLock implementation, only the first field is used. On Windows - // XP, the first field contains a waiter count and lock bit, and the second - // field contains an Event handle if contention has occurred. - volatile PVOID _lock[2] = {nullptr, nullptr}; + SRWLOCK _lock = SRWLOCK_INIT; friend class ConditionVarWin32Impl; }; diff --git a/dtool/src/parser-inc/synchapi.h b/dtool/src/parser-inc/synchapi.h index 3332ebd6e7..7b81bb9b89 100755 --- a/dtool/src/parser-inc/synchapi.h +++ b/dtool/src/parser-inc/synchapi.h @@ -4,7 +4,9 @@ #include "winnt.h" #define SRWLOCK_INIT RTL_SRWLOCK_INIT +#define CONDITION_VARIABLE_INIT RTL_CONDITION_VARIABLE_INIT typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; +typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE; #endif diff --git a/dtool/src/parser-inc/windows.h b/dtool/src/parser-inc/windows.h index 79c20acefb..948deacb10 100644 --- a/dtool/src/parser-inc/windows.h +++ b/dtool/src/parser-inc/windows.h @@ -20,6 +20,7 @@ #define WINDOWS_H #include +#include #ifdef _WIN64 typedef int HALF_PTR; diff --git a/dtool/src/parser-inc/winnt.h b/dtool/src/parser-inc/winnt.h index 0984c7312f..4d2299835c 100755 --- a/dtool/src/parser-inc/winnt.h +++ b/dtool/src/parser-inc/winnt.h @@ -13,4 +13,6 @@ typedef struct _RTL_CONDITION_VARIABLE { PVOID Ptr; } RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE; +#define RTL_CONDITION_VARIABLE_INIT {0} + #endif diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 743213757b..2daec23e7a 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1034,11 +1034,8 @@ def CompileCxx(obj,src,opts): cmd += "/favor:blend " cmd += "/wd4996 /wd4275 /wd4273 " - # We still target Windows XP. - cmd += "/DWINVER=0x501 " - # Work around a WinXP/2003 bug when using VS 2015+. - if SDK.get("VISUALSTUDIO_VERSION") >= (14,0): - cmd += "/Zc:threadSafeInit- " + # Set the minimum version to Windows Vista. + cmd += "/DWINVER=0x600 " cmd += "/Fo" + obj + " /nologo /c" if GetTargetArch() != 'x64' and (not PkgSkip("SSE2") or 'SSE2' in opts): @@ -1089,7 +1086,7 @@ def CompileCxx(obj,src,opts): if GetTargetArch() == 'x64': cmd += "/favor:blend " cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 " - cmd += "/DWINVER=0x501 " + cmd += "/DWINVER=0x600 " cmd += "/Fo" + obj + " /c" for x in ipath: cmd += " /I" + x for (opt,dir) in INCDIRECTORIES: @@ -1575,9 +1572,9 @@ def CompileLink(dll, obj, opts): subsystem = GetValueOption(opts, "SUBSYSTEM:") or "CONSOLE" cmd += " /SUBSYSTEM:" + subsystem if GetTargetArch() == 'x64': - cmd += ",5.02" + cmd += ",6.00" else: - cmd += ",5.01" + cmd += ",6.00" if dll.endswith(".dll") or dll.endswith(".pyd"): cmd += ' /IMPLIB:' + GetOutputDir() + '/lib/' + os.path.splitext(os.path.basename(dll))[0] + ".lib" diff --git a/panda/src/device/winInputDeviceManager.cxx b/panda/src/device/winInputDeviceManager.cxx index 0d2c69f216..f218d450a6 100644 --- a/panda/src/device/winInputDeviceManager.cxx +++ b/panda/src/device/winInputDeviceManager.cxx @@ -54,7 +54,7 @@ WinInputDeviceManager() : _xinput_device2.local_object(); _xinput_device3.local_object(); - // This function is only available in Vista and later, so we use a wrapper. + // This function is not available in the 7.1A SDK, so we use a wrapper. HMODULE module = LoadLibraryA("cfgmgr32.dll"); if (module) { _CM_Get_DevNode_PropertyW = (pCM_Get_DevNode_Property)GetProcAddress(module, "CM_Get_DevNode_PropertyW"); diff --git a/panda/src/express/trueClock.cxx b/panda/src/express/trueClock.cxx index f60ddc22dc..e2298eb950 100644 --- a/panda/src/express/trueClock.cxx +++ b/panda/src/express/trueClock.cxx @@ -113,27 +113,15 @@ get_short_raw_time() { /** * */ -typedef BOOL (WINAPI * PFNSETPROCESSAFFINITYMASK)(HANDLE, DWORD_PTR); -typedef BOOL (WINAPI * PFNGETPROCESSAFFINITYMASK)(HANDLE, DWORD_PTR*, DWORD_PTR*); - bool TrueClock:: set_cpu_affinity(uint32_t mask) const { - HMODULE hker = GetModuleHandle("kernel32"); - if (hker != 0) { - PFNGETPROCESSAFFINITYMASK gp = (PFNGETPROCESSAFFINITYMASK) - GetProcAddress(hker, "GetProcessAffinityMask"); - PFNSETPROCESSAFFINITYMASK sp = (PFNSETPROCESSAFFINITYMASK) - GetProcAddress(hker, "SetProcessAffinityMask"); - if (gp != 0 && sp != 0) { - DWORD proc_mask; - DWORD sys_mask; - if (gp(GetCurrentProcess(), (PDWORD_PTR)&proc_mask, (PDWORD_PTR)&sys_mask)) { - // make sure we don't reference CPUs that don't exist - proc_mask = mask & sys_mask; - if (proc_mask) { - return sp(GetCurrentProcess(), proc_mask) != 0; - } - } + DWORD proc_mask; + DWORD sys_mask; + if (GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&proc_mask, (PDWORD_PTR)&sys_mask)) { + // make sure we don't reference CPUs that don't exist + proc_mask = mask & sys_mask; + if (proc_mask) { + return SetProcessAffinityMask(GetCurrentProcess(), proc_mask) != 0; } } return false; diff --git a/panda/src/pipeline/conditionVarWin32Impl.I b/panda/src/pipeline/conditionVarWin32Impl.I index 7f2b24a079..275acff593 100644 --- a/panda/src/pipeline/conditionVarWin32Impl.I +++ b/panda/src/pipeline/conditionVarWin32Impl.I @@ -18,27 +18,12 @@ INLINE ConditionVarWin32Impl:: ConditionVarWin32Impl(MutexWin32Impl &mutex) : _mutex(mutex) { } -/** - * - */ -INLINE ConditionVarWin32Impl:: -~ConditionVarWin32Impl() { - // These fields are only set in the Windows XP implementation, when these - // both contain events. - if (_cvar[1] != nullptr) { - CloseHandle(_cvar[1]); - } - if (_cvar[2] != nullptr) { - CloseHandle(_cvar[2]); - } -} - /** * */ INLINE void ConditionVarWin32Impl:: wait() { - MutexWin32Impl::_funcs._cvar_wait(_cvar, _mutex._lock, INFINITE, 0); + SleepConditionVariableSRW(&_cvar, &_mutex._lock, INFINITE, 0); } /** @@ -46,7 +31,7 @@ wait() { */ INLINE void ConditionVarWin32Impl:: wait(double timeout) { - MutexWin32Impl::_funcs._cvar_wait(_cvar, _mutex._lock, (DWORD)(timeout * 1000.0), 0); + SleepConditionVariableSRW(&_cvar, &_mutex._lock, (DWORD)(timeout * 1000.0), 0); } /** @@ -54,7 +39,7 @@ wait(double timeout) { */ INLINE void ConditionVarWin32Impl:: notify() { - MutexWin32Impl::_funcs._cvar_notify_one(_cvar); + WakeConditionVariable(&_cvar); } /** @@ -62,5 +47,5 @@ notify() { */ INLINE void ConditionVarWin32Impl:: notify_all() { - MutexWin32Impl::_funcs._cvar_notify_all(_cvar); + WakeAllConditionVariable(&_cvar); } diff --git a/panda/src/pipeline/conditionVarWin32Impl.h b/panda/src/pipeline/conditionVarWin32Impl.h index 213cacdf9e..b7daa767bd 100644 --- a/panda/src/pipeline/conditionVarWin32Impl.h +++ b/panda/src/pipeline/conditionVarWin32Impl.h @@ -26,23 +26,11 @@ class MutexWin32Impl; /** * Uses Windows native calls to implement a ConditionVar. - * - * On Windows Vista and above, we use the system's native condition variables. - * - * On Windows XP, we follow the "SetEvent" implementation suggested by - * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html . This allows us to - * implement both notify() and notify_all(). - * - * As described by the above reference, this implementation suffers from a few - * weaknesses; in particular, it does not necessarily wake up all threads - * fairly; and it may sometimes incorrectly wake up a thread that was not - * waiting at the time notify() was called. But we figure it's good enough - * for our purposes. */ class EXPCL_PANDA_PIPELINE ConditionVarWin32Impl { public: INLINE ConditionVarWin32Impl(MutexWin32Impl &mutex); - INLINE ~ConditionVarWin32Impl(); + ~ConditionVarWin32Impl() = default; INLINE void wait(); INLINE void wait(double timeout); @@ -51,11 +39,7 @@ public: private: MutexWin32Impl &_mutex; - - // On Windows XP, the first field contains a Signal (auto-reset) event, - // the second field a broadcast (manual reset) event, third a waiter count. - // On Windows Vista and above, the first contains a PCONDITION_VARIABLE. - volatile PVOID _cvar[3] = {nullptr, nullptr, nullptr}; + CONDITION_VARIABLE _cvar = CONDITION_VARIABLE_INIT; }; #include "conditionVarWin32Impl.I" diff --git a/panda/src/windisplay/winDetectDx.h b/panda/src/windisplay/winDetectDx.h index 4b979de6f0..a6da2e143f 100644 --- a/panda/src/windisplay/winDetectDx.h +++ b/panda/src/windisplay/winDetectDx.h @@ -32,8 +32,6 @@ static DISPLAY_FORMAT display_format_array [ ] = { D3DFMT_UNKNOWN, 0, FALSE, }; -typedef BOOL (WINAPI *GlobalMemoryStatusExType) (LPMEMORYSTATUSEX lpBuffer); - static int d3d_format_to_bits_per_pixel (D3DFORMAT d3d_format) { int format_index; int bits_per_pixel; @@ -612,32 +610,17 @@ static int get_display_information (DisplaySearchParameters &display_search_para } // memory - bool memory_state; - HMODULE kernel32_dll; + MEMORYSTATUSEX memory_status; + memory_status.dwLength = sizeof(MEMORYSTATUSEX); - memory_state = false; - kernel32_dll = LoadLibrary ("kernel32.dll"); - if (kernel32_dll) { - GlobalMemoryStatusExType GlobalMemoryStatusExFunction; - - GlobalMemoryStatusExFunction = (GlobalMemoryStatusExType) GetProcAddress (kernel32_dll, "GlobalMemoryStatusEx"); - if (GlobalMemoryStatusExFunction) { - MEMORYSTATUSEX memory_status; - - memory_status.dwLength = sizeof (MEMORYSTATUSEX); - if (GlobalMemoryStatusExFunction (&memory_status)) { - physical_memory = memory_status.ullTotalPhys; - available_physical_memory = memory_status.ullAvailPhys; - memory_state = true; - } - } - FreeLibrary (kernel32_dll); - } - if (memory_state == false) { + if (GlobalMemoryStatusEx(&memory_status)) { + physical_memory = memory_status.ullTotalPhys; + available_physical_memory = memory_status.ullAvailPhys; + } else { MEMORYSTATUS memory_status; + memory_status.dwLength = sizeof(MEMORYSTATUS); - memory_status.dwLength = sizeof (MEMORYSTATUS); - GlobalMemoryStatus (&memory_status); + GlobalMemoryStatus(&memory_status); physical_memory = memory_status.dwTotalPhys; available_physical_memory = memory_status.dwAvailPhys; diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index 7da40c64f1..ece0559426 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -155,23 +155,11 @@ count_number_of_cpus(DisplayInformation *display_information) { int num_cpu_cores = 0; int num_logical_cpus = 0; - // Get a pointer to the GetLogicalProcessorInformation function. - typedef BOOL (WINAPI *LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, - PDWORD); - LPFN_GLPI glpi; - glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), - "GetLogicalProcessorInformation"); - if (glpi == nullptr) { - windisplay_cat.info() - << "GetLogicalProcessorInformation is not supported.\n"; - return; - } - // Allocate a buffer to hold the result of the // GetLogicalProcessorInformation call. PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = nullptr; DWORD buffer_length = 0; - DWORD rc = glpi(buffer, &buffer_length); + DWORD rc = GetLogicalProcessorInformation(buffer, &buffer_length); while (!rc) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (buffer != nullptr) { @@ -186,7 +174,7 @@ count_number_of_cpus(DisplayInformation *display_information) { << "\n"; return; } - rc = glpi(buffer, &buffer_length); + rc = GetLogicalProcessorInformation(buffer, &buffer_length); } // Now get the results.