mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
Drop support for Windows XP
This commit is contained in:
parent
da9d1d6a13
commit
1bb4a032aa
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 <external_mutex>.
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define WINDOWS_H
|
||||
|
||||
#include <wtypes.h>
|
||||
#include <synchapi.h>
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef int HALF_PTR;
|
||||
|
@ -13,4 +13,6 @@ typedef struct _RTL_CONDITION_VARIABLE {
|
||||
PVOID Ptr;
|
||||
} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
|
||||
|
||||
#define RTL_CONDITION_VARIABLE_INIT {0}
|
||||
|
||||
#endif
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user