diff --git a/stepmania/src/RageThreads.cpp b/stepmania/src/RageThreads.cpp index 88f19d1f63..ad63b486d6 100644 --- a/stepmania/src/RageThreads.cpp +++ b/stepmania/src/RageThreads.cpp @@ -124,6 +124,7 @@ static int FindEmptyThreadSlot() if( g_ThreadSlots[entry].used ) continue; + g_ThreadSlots[entry].used = true; return entry; } @@ -154,7 +155,6 @@ static void InitThreads() strcpy( g_ThreadSlots[slot].name, "Unknown thread" ); g_ThreadSlots[slot].id = GetInvalidThreadId(); sprintf( g_ThreadSlots[slot].ThreadFormattedOutput, "Unknown thread" ); - g_ThreadSlots[slot].used = true; g_pUnknownThreadSlot = &g_ThreadSlots[slot]; g_ThreadSlotsLock.Unlock(); @@ -227,14 +227,12 @@ void RageThread::Create( int (*fn)(void *), void *data ) strcpy( m_pSlot->name, name.c_str() ); } - /* Start a thread using our own startup function. */ - m_pSlot->pImpl = MakeThread( fn, data ); - m_pSlot->id = m_pSlot->pImpl->GetThreadId(); sprintf( m_pSlot->ThreadFormattedOutput, "Thread: %s", name.c_str() ); - /* Only after everything in the slot is valid, mark the slot used, so all - * "used" slots have a valid pImpl. */ - g_ThreadSlots[slotno].used = true; + /* Start a thread using our own startup function. We pass the id to fill in, + * to make sure it's set before the thread actually starts. (Otherwise, early + * checkpoints might not have a completely set-up thread slot.) */ + m_pSlot->pImpl = MakeThread( fn, data, &m_pSlot->id ); } /* On startup, register the main thread's slot. We do this in a static constructor, @@ -249,7 +247,6 @@ static struct SetupMainThread sprintf( g_ThreadSlots[slot].ThreadFormattedOutput, "Thread: %s", g_ThreadSlots[slot].name ); g_ThreadSlots[slot].pImpl = MakeThisThread(); g_ThreadSlots[slot].id = RageThread::GetCurrentThreadID(); - g_ThreadSlots[slot].used = true; } } SetupMainThreadObj; @@ -552,7 +549,7 @@ void RageMutex::Lock() #if defined(CRASH_HANDLER) && !defined(DARWIN) /* Don't leave g_ThreadSlotsLock when we call ForceCrashHandlerDeadlock. */ g_ThreadSlotsLock.Lock(); - uint64_t CrashHandle = OtherSlot? OtherSlot->pImpl->GetCrashHandle():0; + uint64_t CrashHandle = OtherSlot && OtherSlot->pImpl? OtherSlot->pImpl->GetCrashHandle():0; g_ThreadSlotsLock.Unlock(); /* Pass the crash handle of the other thread, so it can backtrace that thread. */ diff --git a/stepmania/src/arch/Threads/Threads.h b/stepmania/src/arch/Threads/Threads.h index 9b2943d8d4..03f91099b7 100644 --- a/stepmania/src/arch/Threads/Threads.h +++ b/stepmania/src/arch/Threads/Threads.h @@ -55,7 +55,7 @@ public: }; /* These functions must be implemented by the thread implementation. */ -ThreadImpl *MakeThread( int (*fn)(void *), void *data ); +ThreadImpl *MakeThread( int (*fn)(void *), void *data, uint64_t *piThreadID ); ThreadImpl *MakeThisThread(); MutexImpl *MakeMutex( RageMutex *pParent ); SemaImpl *MakeSemaphore( int iInitialValue ); diff --git a/stepmania/src/arch/Threads/Threads_Pthreads.cpp b/stepmania/src/arch/Threads/Threads_Pthreads.cpp index 30cb1bfe0f..a36db4f468 100644 --- a/stepmania/src/arch/Threads/Threads_Pthreads.cpp +++ b/stepmania/src/arch/Threads/Threads_Pthreads.cpp @@ -93,20 +93,32 @@ static void *StartThread( void *pData ) pThis->MachThreadHandle = mach_thread_self(); #endif + *pThis->m_piThreadID = pThis->GetThreadId(); + + fprintf(stderr, "set %i\n", (int) pThis->GetThreadId() ); + /* Tell MakeThread that we've set m_piThreadID, so it's safe to return. */ + sem_post( &pThis->m_StartFinishedSem ); + return (void *) pThis->m_pFunc( pThis->m_pData ); } -ThreadImpl *MakeThread( int (*pFunc)(void *pData), void *pData ) +ThreadImpl *MakeThread( int (*pFunc)(void *pData), void *pData, uint64_t *piThreadID ) { ThreadImpl_Pthreads *thread = new ThreadImpl_Pthreads; thread->m_pFunc = pFunc; thread->m_pData = pData; + thread->m_piThreadID = piThreadID; + sem_init( &thread->m_StartFinishedSem, 0, 0 ); int ret = pthread_create( &thread->thread, NULL, StartThread, thread ); if( ret ) RageException::Throw( "pthread_create: %s", strerror(ret) ); - /* XXX: don't return until StartThread sets pid, etc */ + /* Don't return until StartThread sets m_piThreadID. */ + ret = sem_wait( &thread->m_StartFinishedSem ); + if( ret ) + RageException::Throw( "MakeThread(): sem_wait: %s", strerror(ret) ); + sem_destroy( &thread->m_StartFinishedSem ); return thread; } @@ -168,7 +180,6 @@ bool MutexImpl_Pthreads::Lock() int ret; do { - CHECKPOINT; ret = pthread_mutex_lock( &mutex ); } while( ret == -1 && ret == EINTR ); @@ -240,7 +251,6 @@ bool SemaImpl_Pthreads::Wait() int ret; do { - CHECKPOINT; ret = sem_wait( &sem ); } while( ret == -1 && errno == EINTR ); diff --git a/stepmania/src/arch/Threads/Threads_Pthreads.h b/stepmania/src/arch/Threads/Threads_Pthreads.h index bb29500b92..e5387e9272 100644 --- a/stepmania/src/arch/Threads/Threads_Pthreads.h +++ b/stepmania/src/arch/Threads/Threads_Pthreads.h @@ -26,8 +26,11 @@ public: thread_act_t MachThreadHandle; #endif + /* These are only used during initialization. */ int (*m_pFunc)( void *pData ); void *m_pData; + uint64_t *m_piThreadID; + sem_t m_StartFinishedSem; void Halt( bool Kill ); void Resume(); diff --git a/stepmania/src/arch/Threads/Threads_Win32.cpp b/stepmania/src/arch/Threads/Threads_Win32.cpp index 0ce4f0f2e2..40ba8ed6d7 100644 --- a/stepmania/src/arch/Threads/Threads_Win32.cpp +++ b/stepmania/src/arch/Threads/Threads_Win32.cpp @@ -66,7 +66,7 @@ ThreadImpl *MakeThisThread() return thread; } -ThreadImpl *MakeThread( int (*pFunc)(void *pData), void *pData ) +ThreadImpl *MakeThread( int (*pFunc)(void *pData), void *pData, uint64_t *piThreadID ) { ThreadImpl_Win32 *thread = new ThreadImpl_Win32; thread->m_pFunc = pFunc;