Threads_Win32 fixes

From top to bottom,

- Fix incorrect gcc implementation in `SetThreadName`
- Static Cast in `StartThread`
- Fix `MutexImpl_Win32::Lock()`
- Remove unnecessary pre-winXP methods in PortableSignalObjectAndWait()
- Static Cast in `EventImpl_Win32::Wait`
This commit is contained in:
sukibaby
2024-08-06 15:31:24 -07:00
committed by teejusb
parent e2ae82deb2
commit 2fd1bff510
+21 -58
View File
@@ -75,28 +75,29 @@ typedef struct tagTHREADNAME_INFO
static void SetThreadName( DWORD dwThreadID, LPCTSTR szThreadName ) static void SetThreadName( DWORD dwThreadID, LPCTSTR szThreadName )
{ {
#if defined(_MSC_VER)
THREADNAME_INFO info; THREADNAME_INFO info;
info.dwType = 0x1000; info.dwType = 0x1000;
info.szName = szThreadName; info.szName = szThreadName;
info.dwThreadID = dwThreadID; info.dwThreadID = dwThreadID;
info.dwFlags = 0; info.dwFlags = 0;
// FIXME: Need to find a GCC/GDB-friendly way to do this.
#if defined(_MSC_VER)
__try { __try {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info); RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info);
} __except (EXCEPTION_CONTINUE_EXECUTION) { } __except (EXCEPTION_CONTINUE_EXECUTION) {
} }
#elif defined(__GNUC__)
pthread_setname_np(pthread_self(), szThreadName);
#endif #endif
} }
static DWORD WINAPI StartThread( LPVOID pData ) static DWORD WINAPI StartThread( LPVOID pData )
{ {
ThreadImpl_Win32 *pThis = (ThreadImpl_Win32 *) pData; ThreadImpl_Win32 *pThis = static_cast<ThreadImpl_Win32 *>(pData);
SetThreadName( GetCurrentThreadId(), RageThread::GetCurrentThreadName() ); SetThreadName( GetCurrentThreadId(), RageThread::GetCurrentThreadName() );
DWORD ret = (DWORD) pThis->m_pFunc( pThis->m_pData ); DWORD ret = static_cast<DWORD>(pThis->m_pFunc(pThis->m_pData));
for( int i = 0; i < MAX_THREADS; ++i ) for( int i = 0; i < MAX_THREADS; ++i )
{ {
@@ -214,26 +215,24 @@ static bool SimpleWaitForSingleObject( HANDLE h, DWORD ms )
} }
bool MutexImpl_Win32::Lock() bool MutexImpl_Win32::Lock()
{
int len = 15000;
int tries = 5;
while( tries-- )
{ {
// Wait for fifteen seconds. If it takes longer than that, we're probably deadlocked. DWORD dwWaitResult = WaitForSingleObject(mutex, INFINITE);
if( SimpleWaitForSingleObject( mutex, len ) ) switch (dwWaitResult)
{
case WAIT_OBJECT_0:
return true; return true;
/* Timed out; probably deadlocked. Try a couple more times, with case WAIT_TIMEOUT:
* a smaller timeout, just in case we're debugging and happened return false;
* to stop while waiting on the mutex. */
len = 1000; case WAIT_ABANDONED:
return false;
default:
FAIL_M( "WaitForSingleObject failed in a way that shouldn't have been possible" );
}
} }
return false;
}
bool MutexImpl_Win32::TryLock() bool MutexImpl_Win32::TryLock()
{ {
return SimpleWaitForSingleObject( mutex, 0 ); return SimpleWaitForSingleObject( mutex, 0 );
@@ -283,46 +282,8 @@ EventImpl_Win32::~EventImpl_Win32()
CloseHandle( m_WaitersDone ); CloseHandle( m_WaitersDone );
} }
/* SignalObjectAndWait is atomic, which leads to more fair event handling.
* However, we don't guarantee or depend upon fair events, and
* SignalObjectAndWait is only available in NT. I also can't find a single
* function to signal an object like SignalObjectAndWait, so we need to
* know if the object is a mutex or an event. */
static bool PortableSignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, bool bFirstParamIsMutex, unsigned iMilliseconds = INFINITE ) static bool PortableSignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, bool bFirstParamIsMutex, unsigned iMilliseconds = INFINITE )
{ {
static bool bSignalObjectAndWaitUnavailable = false;
// Watch out: SignalObjectAndWait doesn't work when iMilliseconds is zero.
if( !bSignalObjectAndWaitUnavailable && iMilliseconds != 0 )
{
DWORD ret = SignalObjectAndWait( hObjectToSignal, hObjectToWaitOn, iMilliseconds, false );
switch( ret )
{
case WAIT_OBJECT_0:
return true;
case WAIT_ABANDONED:
// The docs aren't particular about what this does, but it should never happen.
FAIL_M( "WAIT_ABANDONED" );
case 1: // bogus Win98 return value
case WAIT_FAILED:
if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
{
// We're probably on 9x.
bSignalObjectAndWaitUnavailable = true;
break;
}
FAIL_M( werr_ssprintf(GetLastError(), "SignalObjectAndWait") );
case WAIT_TIMEOUT:
return false;
default:
FAIL_M( ssprintf("Unexpected code from SignalObjectAndWait: %d",ret ));
}
}
if( bFirstParamIsMutex ) if( bFirstParamIsMutex )
{ {
const bool bRet = !!ReleaseMutex( hObjectToSignal ); const bool bRet = !!ReleaseMutex( hObjectToSignal );
@@ -330,7 +291,9 @@ static bool PortableSignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectT
sm_crash( werr_ssprintf( GetLastError(), "ReleaseMutex failed" ) ); sm_crash( werr_ssprintf( GetLastError(), "ReleaseMutex failed" ) );
} }
else else
{
SetEvent( hObjectToSignal ); SetEvent( hObjectToSignal );
}
DWORD ret = WaitForSingleObject( hObjectToWaitOn, iMilliseconds ); DWORD ret = WaitForSingleObject( hObjectToWaitOn, iMilliseconds );
switch( ret ) switch( ret )
@@ -361,7 +324,7 @@ bool EventImpl_Win32::Wait( RageTimer *pTimeout )
if( pTimeout != nullptr ) if( pTimeout != nullptr )
{ {
float fSecondsInFuture = -pTimeout->Ago(); float fSecondsInFuture = -pTimeout->Ago();
iMilliseconds = (unsigned) std::max( 0, int( fSecondsInFuture * 1000 ) ); iMilliseconds = static_cast<unsigned>(std::max(0, static_cast<int>(fSecondsInFuture * 1000)));
} }
// Unlock the mutex and wait for a signal. // Unlock the mutex and wait for a signal.