Пример #1
0
static void InitThreads()
{
	/* We don't have to worry about two threads calling this at once, since it's
	 * called when we create a thread. */
	static bool bInitialized = false;
	if( bInitialized )
		return;

	g_ThreadSlotsLock.Lock();

	/* Libraries might start threads on their own, which might call user callbacks,
	 * which could come back here.  Make sure we don't accidentally initialize twice. */
	if( bInitialized )
	{
		g_ThreadSlotsLock.Unlock();
		return;
	}

	bInitialized = true;

	/* Register the "unknown thread" slot. */
	int slot = FindEmptyThreadSlot();
	strcpy( g_ThreadSlots[slot].name, "Unknown thread" );
	g_ThreadSlots[slot].id = GetInvalidThreadId();
	sprintf( g_ThreadSlots[slot].ThreadFormattedOutput, "Unknown thread" );
	g_pUnknownThreadSlot = &g_ThreadSlots[slot];

	g_ThreadSlotsLock.Unlock();
}
void CrashHandler::ForceDeadlock( RString reason, uint64_t iID )
{
	CrashData crash;
	memset( &crash, 0, sizeof(crash) );

	crash.type = CrashData::FORCE_CRASH;

	GetBacktrace( crash.BacktracePointers[0], BACKTRACE_MAX_SIZE, NULL );

	if( iID == GetInvalidThreadId() )
	{
		/* Backtrace all threads. */
		BacktraceAllThreads( crash );
	}
	else
	{
		BacktraceContext ctx;
		if( !GetThreadBacktraceContext( iID, &ctx ) )
			reason += "; GetThreadBacktraceContext failed";
		else
			GetBacktrace( crash.BacktracePointers[1], BACKTRACE_MAX_SIZE, &ctx );
		strncpy( crash.m_ThreadName[1], RageThread::GetThreadNameByID(iID), sizeof(crash.m_ThreadName[0])-1 );
	}

	strncpy( crash.m_ThreadName[0], RageThread::GetCurrentThreadName(), sizeof(crash.m_ThreadName[0])-1 );

	strncpy( crash.reason, reason, min(sizeof(crash.reason) - 1, reason.length()) );
	crash.reason[ sizeof(crash.reason)-1 ] = 0;

	RunCrashHandler( &crash );

	_exit( 1 );
}
Пример #3
0
	void Init()
	{
		id = GetInvalidThreadId();
		CurCheckpoint = NumCheckpoints = 0;
		pImpl = NULL;

		/* Reset used last; otherwise, a thread creation might pick up the slot. */
		used = false;
	}
Пример #4
0
void RageMutex::Unlock()
{
	if( m_LockCnt )
	{
		--m_LockCnt;
		return;
	}

	m_LockedBy = GetInvalidThreadId();

	m_pMutex->Unlock();
}
Пример #5
0
bool RageThread::EnumThreadIDs( int n, uint64_t &iID )
{
	if( n >= MAX_THREADS )
		return false;

	LockMut(g_ThreadSlotsLock);
	const ThreadSlot *slot = &g_ThreadSlots[n];

	if( slot->used )
		iID = slot->id;
	else
		iID = GetInvalidThreadId();

	return true;
}
Пример #6
0
void RageSemaphore::Wait( bool bFailOnTimeout )
{
retry:
	if( m_pSema->Wait() )
		return;

	if( !bFailOnTimeout || Dialog::IsShowingDialog() )
		goto retry;

	/* We waited too long.  We're probably deadlocked, though unlike mutexes, we can't
	 * tell which thread we're stuck on. */
	const ThreadSlot *ThisSlot = GetThreadSlotFromID( GetThisThreadId() );
	const CString sReason = ssprintf( "Semaphore timeout on mutex %s on thread %s",
		GetName().c_str(), ThisSlot? ThisSlot->GetThreadName(): "(???" ")" ); // stupid trigraph warnings
#if defined(CRASH_HANDLER)
	ForceCrashHandlerDeadlock( sReason, GetInvalidThreadId() );
#else
	RageException::Throw( "%s", sReason.c_str() );
#endif
}
static void BacktraceAllThreads( CrashData& crash )
{
	int iCnt = 1;
	uint64_t iID;
	
	for( int i = 0; RageThread::EnumThreadIDs(i, iID); ++i )
	{
		if( iID == GetInvalidThreadId() || iID == RageThread::GetCurrentThreadID() )
			continue;
		
		BacktraceContext ctx;
		if( GetThreadBacktraceContext( iID, &ctx ) )
			GetBacktrace( crash.BacktracePointers[iCnt], BACKTRACE_MAX_SIZE, &ctx );
		strncpy( crash.m_ThreadName[iCnt], RageThread::GetThreadNameByID(iID), sizeof(crash.m_ThreadName[0])-1 );
		
		++iCnt;
		
		if( iCnt == CrashData::MAX_BACKTRACE_THREADS )
			break;
	}
}
Пример #8
0
RageMutex::RageMutex( const CString name ):
	m_sName( name )
{
	m_pMutex = MakeMutex( this );
	m_LockedBy = GetInvalidThreadId();
	m_LockCnt = 0;


/*	if( g_FreeMutexIDs == NULL )
	{
		g_FreeMutexIDs = new set<int>;
		for( int i = 0; i < MAX_MUTEXES; ++i )
			g_FreeMutexIDs->insert( i );
	}

	if( g_FreeMutexIDs->empty() )
	{
		ASSERT_M( g_MutexList, "!g_FreeMutexIDs but !g_MutexList?" ); // doesn't make sense to be out of mutexes yet never created any
		CString s;
		for( unsigned i = 0; i < g_MutexList->size(); ++i )
		{
			if( i )
				s += ", ";
			s += ssprintf( "\"%s\"", (*g_MutexList)[i]->GetName().c_str() );
		}
		LOG->Trace( "%s", s.c_str() );
		FAIL_M( ssprintf("MAX_MUTEXES exceeded creating \"%s\"", name.c_str() ) );
	}

	m_UniqueID = *g_FreeMutexIDs->begin();

	g_FreeMutexIDs->erase( g_FreeMutexIDs->begin() );

	if( g_MutexList == NULL )
		g_MutexList = new vector<RageMutex*>;

	g_MutexList->push_back( this );
*/
}