just some cleanup as usual
This commit is contained in:
+15
-13
@@ -12,9 +12,10 @@ public:
|
||||
virtual void Halt( bool Kill ) = 0;
|
||||
virtual void Resume() = 0;
|
||||
|
||||
/* Get the identifier for this thread. The actual meaning of this is implementation-
|
||||
* defined, except that each thread has exactly one ID and each ID corresponds to
|
||||
* one thread. (This means that Win32 thread handles are not acceptable as ThreadIds.) */
|
||||
/* Get the identifier for this thread. The actual meaning of this is
|
||||
* implementation-defined, except that each thread has exactly one ID
|
||||
* and each ID corresponds to one thread. (This means that Win32
|
||||
* thread handles are not acceptable as ThreadIds.) */
|
||||
virtual uint64_t GetThreadId() const = 0;
|
||||
|
||||
virtual int Wait() = 0;
|
||||
@@ -28,19 +29,20 @@ public:
|
||||
MutexImpl( RageMutex *pParent ): m_Parent(pParent) {}
|
||||
virtual ~MutexImpl() { }
|
||||
|
||||
/* Lock the mutex. If mutex timeouts are implemented, and the mutex times out,
|
||||
* return false and do not lock the mutex. No other failure return is allowed;
|
||||
* all other errors should fail with an assertion. */
|
||||
/* Lock the mutex. If mutex timeouts are implemented, and the mutex
|
||||
* times out, return false and do not lock the mutex. No other failure
|
||||
* return is allowed; all other errors should fail with an assertion. */
|
||||
virtual bool Lock() = 0;
|
||||
|
||||
/* Non-blocking lock. If locking the mutex would block because the mutex is already
|
||||
* locked by another thread, return false; otherwise return true and lock the mutex. */
|
||||
/* Non-blocking lock. If locking the mutex would block because the mutex
|
||||
* is already locked by another thread, return false; otherwise
|
||||
* return true and lock the mutex. */
|
||||
virtual bool TryLock() = 0;
|
||||
|
||||
/* Unlock the mutex. This must only be called when the mutex is locked; implementations
|
||||
* may fail with an assertion if the mutex is not locked. */
|
||||
/* Unlock the mutex. This must only be called when the mutex is locked;
|
||||
* implementations may fail with an assertion if the mutex is not locked. */
|
||||
virtual void Unlock() = 0;
|
||||
|
||||
|
||||
private:
|
||||
MutexImpl(const MutexImpl& rhs);
|
||||
MutexImpl& operator=(const MutexImpl& rhs);
|
||||
@@ -74,8 +76,8 @@ EventImpl *MakeEvent( MutexImpl *pMutex );
|
||||
SemaImpl *MakeSemaphore( int iInitialValue );
|
||||
uint64_t GetThisThreadId();
|
||||
|
||||
/* Since ThreadId is implementation-defined, we can't define a universal invalid
|
||||
* value. Return the invalid value for this implementation. */
|
||||
/* Since ThreadId is implementation-defined, we can't define a universal
|
||||
* invalid value. Return the invalid value for this implementation. */
|
||||
uint64_t GetInvalidThreadId();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,19 +17,17 @@
|
||||
void ThreadImpl_Pthreads::Halt( bool Kill )
|
||||
{
|
||||
/* Linux:
|
||||
* Send a SIGSTOP to the thread. If we send a SIGKILL, pthreads will
|
||||
* Send a SIGSTOP to the thread. If we send a SIGKILL, pthreads will
|
||||
* "helpfully" propagate it to the other threads, and we'll get killed, too.
|
||||
*
|
||||
* This isn't ideal, since it can cause the process to background as far as
|
||||
* the shell is concerned, so the shell prompt can display before the crash
|
||||
* handler actually displays a message.
|
||||
*/
|
||||
* handler actually displays a message. */
|
||||
SuspendThread( threadHandle );
|
||||
}
|
||||
|
||||
void ThreadImpl_Pthreads::Resume()
|
||||
{
|
||||
/* Linux: Send a SIGCONT to the thread. */
|
||||
// Linux: Send a SIGCONT to the thread.
|
||||
ResumeThread( threadHandle );
|
||||
}
|
||||
|
||||
@@ -65,12 +63,12 @@ static void *StartThread( void *pData )
|
||||
|
||||
pThis->threadHandle = GetCurrentThreadId();
|
||||
*pThis->m_piThreadID = pThis->threadHandle;
|
||||
|
||||
/* Tell MakeThread that we've set m_piThreadID, so it's safe to return. */
|
||||
|
||||
// Tell MakeThread that we've set m_piThreadID, so it's safe to return.
|
||||
pThis->m_StartFinishedSem->Post();
|
||||
|
||||
int iRet = pThis->m_pFunc( pThis->m_pData );
|
||||
|
||||
|
||||
return new int(iRet);
|
||||
}
|
||||
|
||||
@@ -86,10 +84,10 @@ ThreadImpl *MakeThread( int (*pFunc)(void *pData), void *pData, uint64_t *piThre
|
||||
int ret = pthread_create( &thread->thread, NULL, StartThread, thread );
|
||||
ASSERT_M( ret == 0, ssprintf( "MakeThread: pthread_create: %s", strerror(errno)) );
|
||||
|
||||
/* Don't return until StartThread sets m_piThreadID. */
|
||||
// Don't return until StartThread sets m_piThreadID.
|
||||
thread->m_StartFinishedSem->Wait();
|
||||
delete thread->m_StartFinishedSem;
|
||||
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
@@ -105,12 +103,11 @@ MutexImpl_Pthreads::~MutexImpl_Pthreads()
|
||||
ASSERT_M( ret == 0, ssprintf("Error deleting mutex: %s", strerror(errno)) );
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK) || defined(HAVE_PTHREAD_COND_TIMEDWAIT)
|
||||
static bool UseTimedlock()
|
||||
{
|
||||
#if defined(LINUX)
|
||||
/* Valgrind crashes and burns on pthread_mutex_timedlock. */
|
||||
// Valgrind crashes and burns on pthread_mutex_timedlock.
|
||||
if( RunningUnderValgrind() )
|
||||
return false;
|
||||
#endif
|
||||
@@ -124,12 +121,12 @@ bool MutexImpl_Pthreads::Lock()
|
||||
#if defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
|
||||
if( UseTimedlock() )
|
||||
{
|
||||
int len = 10; /* seconds */
|
||||
int len = 10; // seconds
|
||||
int tries = 2;
|
||||
|
||||
while( tries-- )
|
||||
{
|
||||
/* Wait for ten seconds. If it takes longer than that, we're
|
||||
/* Wait for ten seconds. If it takes longer than that, we're
|
||||
* probably deadlocked. */
|
||||
timeval tv;
|
||||
gettimeofday( &tv, NULL );
|
||||
@@ -149,9 +146,9 @@ bool MutexImpl_Pthreads::Lock()
|
||||
continue;
|
||||
|
||||
case ETIMEDOUT:
|
||||
/* Timed out. Probably deadlocked. Try again one more time, with a smaller
|
||||
* timeout, just in case we're debugging and happened to stop while waiting
|
||||
* on the mutex. */
|
||||
/* Timed out. Probably deadlocked. Try again one more time,
|
||||
* with a smaller timeout, just in case we're debugging
|
||||
* and happened to stop while waiting on the mutex. */
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
@@ -205,8 +202,8 @@ MutexImpl *MakeMutex( RageMutex *pParent )
|
||||
return new MutexImpl_Pthreads( pParent );
|
||||
}
|
||||
|
||||
/* Check if condattr_setclock is supported, and supports the clock that RageTimer
|
||||
* selected. */
|
||||
/* Check if condattr_setclock is supported, and supports the clock that
|
||||
* RageTimer selected. */
|
||||
#if defined(UNIX)
|
||||
#include <dlfcn.h>
|
||||
#include "arch/ArchHooks/ArchHooks_Unix.h"
|
||||
@@ -247,7 +244,7 @@ namespace
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure that we can set up the clock attribute. */
|
||||
// Make sure that we can set up the clock attribute.
|
||||
pthread_condattr_t condattr;
|
||||
pthread_condattr_init( &condattr );
|
||||
|
||||
@@ -314,21 +311,21 @@ bool EventImpl_Pthreads::Wait( RageTimer *pTimeout )
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If the clock is not CLOCK_MONOTONIC, or we can't change the wait clock (no
|
||||
* condattr_setclock), pthread_cond_timedwait has an inherent race condition:
|
||||
* the system clock may change before we call it. */
|
||||
/* If the clock is not CLOCK_MONOTONIC, or we can't change the wait clock
|
||||
* (no condattr_setclock), pthread_cond_timedwait has an inherent race
|
||||
* condition: the system clock may change before we call it. */
|
||||
timespec abstime;
|
||||
if( g_CondattrSetclock != NULL || GetClock() == CLOCK_REALTIME )
|
||||
{
|
||||
/* If we support condattr_setclock, we'll set the condition to use the same
|
||||
* clock as RageTimer and can use it directly. If the clock is CLOCK_REALTIME,
|
||||
* that's the default anyway. */
|
||||
/* If we support condattr_setclock, we'll set the condition to use
|
||||
* the same clock as RageTimer and can use it directly. If the
|
||||
* clock is CLOCK_REALTIME, that's the default anyway. */
|
||||
abstime.tv_sec = pTimeout->m_secs;
|
||||
abstime.tv_nsec = pTimeout->m_us * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The RageTimer clock is different than the wait clock; convert it. */
|
||||
// The RageTimer clock is different than the wait clock; convert it.
|
||||
timeval tv;
|
||||
gettimeofday( &tv, NULL );
|
||||
|
||||
@@ -427,7 +424,7 @@ bool SemaImpl_Pthreads::TryWait()
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
/* Use conditions, to work around OS X "forgetting" to implement semaphores. */
|
||||
// Use conditions, to work around OS X "forgetting" to implement semaphores.
|
||||
SemaImpl_Pthreads::SemaImpl_Pthreads( int iInitialValue )
|
||||
{
|
||||
int ret = pthread_cond_init( &m_Cond, NULL );
|
||||
@@ -480,9 +477,9 @@ bool SemaImpl_Pthreads::Wait()
|
||||
break;
|
||||
|
||||
case ETIMEDOUT:
|
||||
/* Timed out. Probably deadlocked. Try again one more time, with a smaller
|
||||
* timeout, just in case we're debugging and happened to stop while waiting
|
||||
* on the mutex. */
|
||||
/* Timed out. Probably deadlocked. Try again one more time,
|
||||
* with a smaller timeout, just in case we're debugging and
|
||||
* happened to stop while waiting on the mutex. */
|
||||
++ts.tv_sec;
|
||||
tries--;
|
||||
break;
|
||||
@@ -525,7 +522,7 @@ bool SemaImpl_Pthreads::TryWait()
|
||||
pthread_mutex_unlock( &m_Mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
--m_iValue;
|
||||
pthread_mutex_unlock( &m_Mutex);
|
||||
|
||||
|
||||
@@ -12,13 +12,12 @@ public:
|
||||
pthread_t thread;
|
||||
|
||||
/* Linux:
|
||||
* Keep a list of child PIDs, so we can send them SIGKILL. This has an
|
||||
* added bonus: if this is corrupted, we'll just send signals and they'll
|
||||
* fail; we won't blow up (unless we're root).
|
||||
*/
|
||||
* Keep a list of child PIDs, so we can send them SIGKILL. This has
|
||||
* an added bonus: if this is corrupted, we'll just send signals and
|
||||
* they'll fail; we won't blow up (unless we're root). */
|
||||
uint64_t threadHandle;
|
||||
|
||||
/* These are only used during initialization. */
|
||||
// These are only used during initialization.
|
||||
int (*m_pFunc)( void *pData );
|
||||
void *m_pData;
|
||||
uint64_t *m_piThreadID;
|
||||
|
||||
@@ -219,9 +219,9 @@ bool MutexImpl_Win32::Lock()
|
||||
if( SimpleWaitForSingleObject( mutex, len ) )
|
||||
return true;
|
||||
|
||||
/* Timed out; probably deadlocked. Try a couple more times, with a smaller
|
||||
* timeout, just in case we're debugging and happened to stop while waiting
|
||||
* on the mutex. */
|
||||
/* Timed out; probably deadlocked. Try a couple more times, with
|
||||
* a smaller timeout, just in case we're debugging and happened
|
||||
* to stop while waiting on the mutex. */
|
||||
len = 1000;
|
||||
}
|
||||
|
||||
@@ -238,8 +238,8 @@ void MutexImpl_Win32::Unlock()
|
||||
{
|
||||
const bool ret = !!ReleaseMutex( mutex );
|
||||
|
||||
/* We can't ASSERT here, since this is called from checkpoints, which is
|
||||
* called from ASSERT. */
|
||||
/* We can't ASSERT here, since this is called from checkpoints,
|
||||
* which is called from ASSERT. */
|
||||
if( !ret )
|
||||
sm_crash( werr_ssprintf( GetLastError(), "ReleaseMutex failed" ) );
|
||||
}
|
||||
@@ -278,10 +278,11 @@ EventImpl_Win32::~EventImpl_Win32()
|
||||
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. */
|
||||
/* 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 bSignalObjectAndWaitUnavailable = false;
|
||||
@@ -364,8 +365,9 @@ bool EventImpl_Win32::Wait( RageTimer *pTimeout )
|
||||
EnterCriticalSection( &m_iNumWaitingLock );
|
||||
if( !bSuccess )
|
||||
{
|
||||
/* Avoid a race condition: someone may have signalled the object between PortableSignalObjectAndWait
|
||||
* and EnterCriticalSection. While we hold m_iNumWaitingLock, poll (with a zero timeout) the
|
||||
/* Avoid a race condition: someone may have signalled the object
|
||||
* between PortableSignalObjectAndWait and EnterCriticalSection.
|
||||
* While we hold m_iNumWaitingLock, poll (with a zero timeout) the
|
||||
* object one last time. */
|
||||
if( WaitForSingleObject( m_WakeupSema, 0 ) == WAIT_OBJECT_0 )
|
||||
bSuccess = true;
|
||||
@@ -374,8 +376,8 @@ bool EventImpl_Win32::Wait( RageTimer *pTimeout )
|
||||
bool bLastWaiting = m_iNumWaiting == 0;
|
||||
LeaveCriticalSection( &m_iNumWaitingLock );
|
||||
|
||||
/* If we're the last waiter to wake up, and we were actually woken by another
|
||||
* thread (not by timeout), wake up the signaller. */
|
||||
/* If we're the last waiter to wake up, and we were actually woken by
|
||||
* another thread (not by timeout), wake up the signaller. */
|
||||
if( bLastWaiting && bSuccess )
|
||||
PortableSignalObjectAndWait( m_WaitersDone, m_pParent->mutex, false );
|
||||
else
|
||||
@@ -416,8 +418,8 @@ void EventImpl_Win32::Broadcast()
|
||||
|
||||
LeaveCriticalSection( &m_iNumWaitingLock );
|
||||
|
||||
/* The last waiter will touch m_WaitersDone, so we wait for all waiters to
|
||||
* wake up and start waiting for the mutex before returning. */
|
||||
/* The last waiter will touch m_WaitersDone, so we wait for all waiters
|
||||
* to wake up and start waiting for the mutex before returning. */
|
||||
WaitForSingleObject( m_WaitersDone, INFINITE );
|
||||
}
|
||||
|
||||
@@ -452,7 +454,7 @@ bool SemaImpl_Win32::Wait()
|
||||
|
||||
while( tries-- )
|
||||
{
|
||||
/* Wait for 15 seconds. If it takes longer than that, we're
|
||||
/* Wait for 15 seconds. If it takes longer than that, we're
|
||||
* probably deadlocked. */
|
||||
if( SimpleWaitForSingleObject( sem, len ) )
|
||||
{
|
||||
@@ -460,9 +462,9 @@ bool SemaImpl_Win32::Wait()
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Timed out; probably deadlocked. Try again a few more times, with a smaller
|
||||
* timeout, just in case we're debugging and happened to stop while waiting
|
||||
* on the mutex. */
|
||||
/* Timed out; probably deadlocked. Try again a few more times,
|
||||
* with a smaller timeout, just in case we're debugging and
|
||||
* happened to stop while waiting on the mutex. */
|
||||
len = 1000;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user