Common: reformat (#4720)

* common: format AlignedMalloc.cpp

* common: format AppTrait.h

* common: format Assertions.h

* common: format CheckedStaticBox

* common: format Console

* common: format Dependencies.h

* common: format EmbeddedImage

* common: format EventSource

* common: format Exceptions

* common: format FastFormatString.cpp

* common: format General.h

* common: format InitInterface

* common: format MathUtils.h

* common: format MemsetFast/MemcpyFast

* common: format Mutex.cpp

* common: format PageFaultSource.h

* common: format Path.h

* common: format PathUtils.cpp

* common: format Pcsx2Types.h

* common: format Perf

* common: format PersistentThread.h

* common: format RwMutex

* common: format SafeArray

* common: format ScopedAlloc.h

* common: format ScopedPtrMT.h

* common: format Semaphore.cpp

* common: format StringHelpers

* common: format ThreadTools.cpp

* common: format Threading.h

* common: format ThreadingDialogs

* common: format ThreadingInternal.h

* common: format TraceLog.h

* common: format VirtualMemory.cpp

* common: format pxCheckBox

* common: format pxEvents.h

* common: format pxForwardDefs.h

* common: format pxRadioPanel

* common: format pxStaticText

* common: format pxStreams

* common: format pxTranslate.cpp

* common: format pxWindowTextWriter.cpp

* common: format wxAppWithHelpers

* common: format wxBaseTools.h

* common: format wxGuiTools

* common: format wxHelpers.cpp

* common: format Darwin directory

* common: format Linux directory

* common: format Windows directory

* common: format LnxCpuDetect.cpp

* common: format WinCpuDetect.cpp

* common: format bmi.cpp

* common: format cpudetect.cpp

* common: format cpu_detect_internal.h

* common: format fpu.cpp

* common: format groups.cpp

* common: format instructions.h

* common: format internal.h

* common: format jmp.cpp

* common: format legacy.cpp

* common: format legacy_instructions.h

* common: format legacy_internal.h

* common: format movs.cpp

* common: format simd.cpp

* common: format tools.h

* common: format x86emitter.cpp

* common: format x86types.h

* common: format bmi.h

* common: format dwshift.h

* common: format group1.h group2.h group3.h

* common: format incdec.h

* common: format jmpcall.h

* common: format movs.h

* common: format simd_arithmetic.h

* common: format simd_comparisons.h

* common: format simd_helpers.h

* common: format simd_moremovs.h

* common: format simd_shufflepack.h

* common: format simd_templated_helpers.h

* common: format test.h
This commit is contained in:
Kojin
2021-09-06 14:28:26 -04:00
committed by GitHub
parent f9bf87f50d
commit 13dfceff48
102 changed files with 13189 additions and 12692 deletions
+351 -329
View File
@@ -33,12 +33,12 @@ const wxTimeSpan Threading::def_yieldgui_interval(0, 0, 0, 100);
ConsoleLogSource_Threading::ConsoleLogSource_Threading()
{
static const TraceLogDescriptor myDesc =
{
L"p&xThread", L"pxThread",
pxLt("Threading activity: start, detach, sync, deletion, etc.")};
static const TraceLogDescriptor myDesc =
{
L"p&xThread", L"pxThread",
pxLt("Threading activity: start, detach, sync, deletion, etc.")};
m_Descriptor = &myDesc;
m_Descriptor = &myDesc;
}
ConsoleLogSource_Threading pxConLog_Thread;
@@ -47,18 +47,18 @@ ConsoleLogSource_Threading pxConLog_Thread;
class StaticMutex : public Mutex
{
protected:
bool &m_DeletedFlag;
bool& m_DeletedFlag;
public:
StaticMutex(bool &deletedFlag)
: m_DeletedFlag(deletedFlag)
{
}
StaticMutex(bool& deletedFlag)
: m_DeletedFlag(deletedFlag)
{
}
virtual ~StaticMutex()
{
m_DeletedFlag = true;
}
virtual ~StaticMutex()
{
m_DeletedFlag = true;
}
};
static pthread_key_t curthread_key = 0;
@@ -67,111 +67,115 @@ static s32 total_key_count = 0;
static bool tkl_destructed = false;
static StaticMutex total_key_lock(tkl_destructed);
static void make_curthread_key(const pxThread *thr)
static void make_curthread_key(const pxThread* thr)
{
pxAssumeDev(!tkl_destructed, "total_key_lock is destroyed; program is shutting down; cannot create new thread key.");
pxAssumeDev(!tkl_destructed, "total_key_lock is destroyed; program is shutting down; cannot create new thread key.");
ScopedLock lock(total_key_lock);
if (total_key_count++ != 0)
return;
ScopedLock lock(total_key_lock);
if (total_key_count++ != 0)
return;
if (0 != pthread_key_create(&curthread_key, NULL)) {
pxThreadLog.Error(thr->GetName(), L"Thread key creation failed (probably out of memory >_<)");
curthread_key = 0;
}
if (0 != pthread_key_create(&curthread_key, NULL))
{
pxThreadLog.Error(thr->GetName(), L"Thread key creation failed (probably out of memory >_<)");
curthread_key = 0;
}
}
static void unmake_curthread_key()
{
ScopedLock lock;
if (!tkl_destructed)
lock.AssignAndLock(total_key_lock);
ScopedLock lock;
if (!tkl_destructed)
lock.AssignAndLock(total_key_lock);
if (--total_key_count > 0)
return;
if (--total_key_count > 0)
return;
if (curthread_key)
pthread_key_delete(curthread_key);
if (curthread_key)
pthread_key_delete(curthread_key);
curthread_key = 0;
curthread_key = 0;
}
void Threading::pxTestCancel()
{
pthread_testcancel();
pthread_testcancel();
}
// Returns a handle to the current persistent thread. If the current thread does not belong
// to the pxThread table, NULL is returned. Since the main/ui thread is not created
// through pxThread it will also return NULL. Callers can use wxThread::IsMain() to
// test if the NULL thread is the main thread.
pxThread *Threading::pxGetCurrentThread()
pxThread* Threading::pxGetCurrentThread()
{
return !curthread_key ? NULL : (pxThread *)pthread_getspecific(curthread_key);
return !curthread_key ? NULL : (pxThread*)pthread_getspecific(curthread_key);
}
// returns the name of the current thread, or "Unknown" if the thread is neither a pxThread
// nor the Main/UI thread.
wxString Threading::pxGetCurrentThreadName()
{
if (pxThread *thr = pxGetCurrentThread()) {
return thr->GetName();
} else if (wxThread::IsMain()) {
return L"Main/UI";
}
if (pxThread* thr = pxGetCurrentThread())
{
return thr->GetName();
}
else if (wxThread::IsMain())
{
return L"Main/UI";
}
return L"Unknown";
return L"Unknown";
}
void Threading::pxYield(int ms)
{
if (pxThread *thr = pxGetCurrentThread())
thr->Yield(ms);
else
Sleep(ms);
if (pxThread* thr = pxGetCurrentThread())
thr->Yield(ms);
else
Sleep(ms);
}
// (intended for internal use only)
// Returns true if the Wait is recursive, or false if the Wait is safe and should be
// handled via normal yielding methods.
bool Threading::_WaitGui_RecursionGuard(const wxChar *name)
bool Threading::_WaitGui_RecursionGuard(const wxChar* name)
{
AffinityAssert_AllowFrom_MainUI();
AffinityAssert_AllowFrom_MainUI();
// In order to avoid deadlock we need to make sure we cut some time to handle messages.
// But this can result in recursive yield calls, which would crash the app. Protect
// against them here and, if recursion is detected, perform a standard blocking wait.
// In order to avoid deadlock we need to make sure we cut some time to handle messages.
// But this can result in recursive yield calls, which would crash the app. Protect
// against them here and, if recursion is detected, perform a standard blocking wait.
static int __Guard = 0;
RecursionGuard guard(__Guard);
static int __Guard = 0;
RecursionGuard guard(__Guard);
//if( pxAssertDev( !guard.IsReentrant(), "Recursion during UI-bound threading wait object." ) ) return false;
//if( pxAssertDev( !guard.IsReentrant(), "Recursion during UI-bound threading wait object." ) ) return false;
if (!guard.IsReentrant())
return false;
pxThreadLog.Write(pxGetCurrentThreadName(),
pxsFmt(L"Yield recursion in %s; opening modal dialog.", name));
return true;
if (!guard.IsReentrant())
return false;
pxThreadLog.Write(pxGetCurrentThreadName(),
pxsFmt(L"Yield recursion in %s; opening modal dialog.", name));
return true;
}
__fi void Threading::Timeslice()
{
sched_yield();
sched_yield();
}
void Threading::pxThread::_pt_callback_cleanup(void *handle)
void Threading::pxThread::_pt_callback_cleanup(void* handle)
{
((pxThread *)handle)->_ThreadCleanup();
((pxThread*)handle)->_ThreadCleanup();
}
Threading::pxThread::pxThread(const wxString &name)
: m_name(name)
, m_thread()
, m_native_id(0)
, m_native_handle(0)
, m_detached(true) // start out with m_thread in detached/invalid state
, m_running(false)
Threading::pxThread::pxThread(const wxString& name)
: m_name(name)
, m_thread()
, m_native_id(0)
, m_native_handle(0)
, m_detached(true) // start out with m_thread in detached/invalid state
, m_running(false)
{
}
@@ -184,50 +188,53 @@ Threading::pxThread::pxThread(const wxString &name)
// like marrying your sister, and then cheating on her with your daughter.
Threading::pxThread::~pxThread()
{
try {
pxThreadLog.Write(GetName(), L"Executing default destructor!");
try
{
pxThreadLog.Write(GetName(), L"Executing default destructor!");
if (m_running) {
pxThreadLog.Write(GetName(), L"Waiting for running thread to end...");
m_mtx_InThread.Wait();
pxThreadLog.Write(GetName(), L"Thread ended gracefully.");
}
Threading::Sleep(1);
Detach();
}
DESTRUCTOR_CATCHALL
if (m_running)
{
pxThreadLog.Write(GetName(), L"Waiting for running thread to end...");
m_mtx_InThread.Wait();
pxThreadLog.Write(GetName(), L"Thread ended gracefully.");
}
Threading::Sleep(1);
Detach();
}
DESTRUCTOR_CATCHALL
}
bool Threading::pxThread::AffinityAssert_AllowFromSelf(const DiagnosticOrigin &origin) const
bool Threading::pxThread::AffinityAssert_AllowFromSelf(const DiagnosticOrigin& origin) const
{
if (IsSelf())
return true;
if (IsSelf())
return true;
if (IsDevBuild)
pxOnAssert(origin, pxsFmt(L"Thread affinity violation: Call allowed from '%s' thread only.", WX_STR(GetName())));
if (IsDevBuild)
pxOnAssert(origin, pxsFmt(L"Thread affinity violation: Call allowed from '%s' thread only.", WX_STR(GetName())));
return false;
return false;
}
bool Threading::pxThread::AffinityAssert_DisallowFromSelf(const DiagnosticOrigin &origin) const
bool Threading::pxThread::AffinityAssert_DisallowFromSelf(const DiagnosticOrigin& origin) const
{
if (!IsSelf())
return true;
if (!IsSelf())
return true;
if (IsDevBuild)
pxOnAssert(origin, pxsFmt(L"Thread affinity violation: Call is *not* allowed from '%s' thread.", WX_STR(GetName())));
if (IsDevBuild)
pxOnAssert(origin, pxsFmt(L"Thread affinity violation: Call is *not* allowed from '%s' thread.", WX_STR(GetName())));
return false;
return false;
}
void Threading::pxThread::FrankenMutex(Mutex &mutex)
void Threading::pxThread::FrankenMutex(Mutex& mutex)
{
if (mutex.RecreateIfLocked()) {
// Our lock is bupkis, which means the previous thread probably deadlocked.
// Let's create a new mutex lock to replace it.
if (mutex.RecreateIfLocked())
{
// Our lock is bupkis, which means the previous thread probably deadlocked.
// Let's create a new mutex lock to replace it.
pxThreadLog.Error(GetName(), L"Possible deadlock detected on restarted mutex!");
}
pxThreadLog.Error(GetName(), L"Possible deadlock detected on restarted mutex!");
}
}
// Main entry point for starting or e-starting a persistent thread. This function performs necessary
@@ -238,53 +245,56 @@ void Threading::pxThread::FrankenMutex(Mutex &mutex)
// This function should not be called from the owner thread.
void Threading::pxThread::Start()
{
// Prevents sudden parallel startup, and or parallel startup + cancel:
ScopedLock startlock(m_mtx_start);
if (m_running) {
pxThreadLog.Write(GetName(), L"Start() called on running thread; ignorning...");
return;
}
// Prevents sudden parallel startup, and or parallel startup + cancel:
ScopedLock startlock(m_mtx_start);
if (m_running)
{
pxThreadLog.Write(GetName(), L"Start() called on running thread; ignorning...");
return;
}
Detach(); // clean up previous thread handle, if one exists.
OnStart();
Detach(); // clean up previous thread handle, if one exists.
OnStart();
m_except = NULL;
m_except = NULL;
pxThreadLog.Write(GetName(), L"Calling pthread_create...");
if (pthread_create(&m_thread, NULL, _internal_callback, this) != 0)
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: " + wxString(std::strerror(errno)));
pxThreadLog.Write(GetName(), L"Calling pthread_create...");
if (pthread_create(&m_thread, NULL, _internal_callback, this) != 0)
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: " + wxString(std::strerror(errno)));
#ifdef ASAN_WORKAROUND
// Recent Asan + libc6 do pretty bad stuff on the thread init => https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77982
//
// In our case, the semaphore was posted (counter is 1) but thread is still
// waiting... So waits 100ms and checks the counter value manually
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 0, 100))) {
if (m_sem_startup.Count() == 0)
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: %s thread never posted startup semaphore.");
}
// Recent Asan + libc6 do pretty bad stuff on the thread init => https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77982
//
// In our case, the semaphore was posted (counter is 1) but thread is still
// waiting... So waits 100ms and checks the counter value manually
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 0, 100)))
{
if (m_sem_startup.Count() == 0)
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: %s thread never posted startup semaphore.");
}
#else
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 3, 0))) {
RethrowException();
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 3, 0)))
{
RethrowException();
// And if the thread threw nothing of its own:
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: %s thread never posted startup semaphore.");
}
// And if the thread threw nothing of its own:
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: %s thread never posted startup semaphore.");
}
#endif
// Event Rationale (above): Performing this semaphore wait on the created thread is "slow" in the
// sense that it stalls the calling thread completely until the new thread is created
// (which may not always be desirable). But too bad. In order to safely use 'running' locks
// and detachment management, this *has* to be done. By rule, starting new threads shouldn't
// be done very often anyway, hence the concept of Threadpooling for rapidly rotating tasks.
// (and indeed, this semaphore wait might, in fact, be very swift compared to other kernel
// overhead in starting threads).
// Event Rationale (above): Performing this semaphore wait on the created thread is "slow" in the
// sense that it stalls the calling thread completely until the new thread is created
// (which may not always be desirable). But too bad. In order to safely use 'running' locks
// and detachment management, this *has* to be done. By rule, starting new threads shouldn't
// be done very often anyway, hence the concept of Threadpooling for rapidly rotating tasks.
// (and indeed, this semaphore wait might, in fact, be very swift compared to other kernel
// overhead in starting threads).
// (this could also be done using operating system specific calls, since any threaded OS has
// functions that allow us to see if a thread is running or not, and to block against it even if
// it's been detached -- removing the need for m_mtx_InThread and the semaphore wait above. But
// pthreads kinda lacks that stuff, since pthread_join() has no timeout option making it im-
// possible to safely block against a running thread)
// (this could also be done using operating system specific calls, since any threaded OS has
// functions that allow us to see if a thread is running or not, and to block against it even if
// it's been detached -- removing the need for m_mtx_InThread and the semaphore wait above. But
// pthreads kinda lacks that stuff, since pthread_join() has no timeout option making it im-
// possible to safely block against a running thread)
}
// Returns: TRUE if the detachment was performed, or FALSE if the thread was
@@ -292,26 +302,27 @@ void Threading::pxThread::Start()
// This function should not be called from the owner thread.
bool Threading::pxThread::Detach()
{
AffinityAssert_DisallowFromSelf(pxDiagSpot);
AffinityAssert_DisallowFromSelf(pxDiagSpot);
if (m_detached.exchange(true))
return false;
pthread_detach(m_thread);
return true;
if (m_detached.exchange(true))
return false;
pthread_detach(m_thread);
return true;
}
bool Threading::pxThread::_basecancel()
{
if (!m_running)
return false;
if (!m_running)
return false;
if (m_detached) {
pxThreadLog.Warn(GetName(), L"Ignoring attempted cancellation of detached thread.");
return false;
}
if (m_detached)
{
pxThreadLog.Warn(GetName(), L"Ignoring attempted cancellation of detached thread.");
return false;
}
pthread_cancel(m_thread);
return true;
pthread_cancel(m_thread);
return true;
}
// Remarks:
@@ -330,34 +341,35 @@ bool Threading::pxThread::_basecancel()
//
void Threading::pxThread::Cancel(bool isBlocking)
{
AffinityAssert_DisallowFromSelf(pxDiagSpot);
AffinityAssert_DisallowFromSelf(pxDiagSpot);
// Prevent simultaneous startup and cancel, necessary to avoid
ScopedLock startlock(m_mtx_start);
// Prevent simultaneous startup and cancel, necessary to avoid
ScopedLock startlock(m_mtx_start);
if (!_basecancel())
return;
if (!_basecancel())
return;
if (isBlocking) {
WaitOnSelf(m_mtx_InThread);
Detach();
}
if (isBlocking)
{
WaitOnSelf(m_mtx_InThread);
Detach();
}
}
bool Threading::pxThread::Cancel(const wxTimeSpan &timespan)
bool Threading::pxThread::Cancel(const wxTimeSpan& timespan)
{
AffinityAssert_DisallowFromSelf(pxDiagSpot);
AffinityAssert_DisallowFromSelf(pxDiagSpot);
// Prevent simultaneous startup and cancel:
ScopedLock startlock(m_mtx_start);
// Prevent simultaneous startup and cancel:
ScopedLock startlock(m_mtx_start);
if (!_basecancel())
return true;
if (!_basecancel())
return true;
if (!WaitOnSelf(m_mtx_InThread, timespan))
return false;
Detach();
return true;
if (!WaitOnSelf(m_mtx_InThread, timespan))
return false;
Detach();
return true;
}
@@ -373,32 +385,32 @@ bool Threading::pxThread::Cancel(const wxTimeSpan &timespan)
//
void Threading::pxThread::Block()
{
AffinityAssert_DisallowFromSelf(pxDiagSpot);
WaitOnSelf(m_mtx_InThread);
AffinityAssert_DisallowFromSelf(pxDiagSpot);
WaitOnSelf(m_mtx_InThread);
}
bool Threading::pxThread::Block(const wxTimeSpan &timeout)
bool Threading::pxThread::Block(const wxTimeSpan& timeout)
{
AffinityAssert_DisallowFromSelf(pxDiagSpot);
return WaitOnSelf(m_mtx_InThread, timeout);
AffinityAssert_DisallowFromSelf(pxDiagSpot);
return WaitOnSelf(m_mtx_InThread, timeout);
}
bool Threading::pxThread::IsSelf() const
{
// Detached threads may have their pthread handles recycled as newer threads, causing
// false IsSelf reports.
return !m_detached && (pthread_self() == m_thread);
// Detached threads may have their pthread handles recycled as newer threads, causing
// false IsSelf reports.
return !m_detached && (pthread_self() == m_thread);
}
bool Threading::pxThread::IsRunning() const
{
return m_running;
return m_running;
}
void Threading::pxThread::AddListener(EventListener_Thread &evt)
void Threading::pxThread::AddListener(EventListener_Thread& evt)
{
evt.SetThread(this);
m_evtsrc_OnDelete.Add(evt);
evt.SetThread(this);
m_evtsrc_OnDelete.Add(evt);
}
// Throws an exception if the thread encountered one. Uses the BaseException's Rethrow() method,
@@ -406,49 +418,51 @@ void Threading::pxThread::AddListener(EventListener_Thread &evt)
// the thread will have allowed itself to terminate properly.
void Threading::pxThread::RethrowException() const
{
// Thread safety note: always detach the m_except pointer. If we checked it for NULL, the
// pointer might still be invalid after detachment, so might as well just detach and check
// after.
// Thread safety note: always detach the m_except pointer. If we checked it for NULL, the
// pointer might still be invalid after detachment, so might as well just detach and check
// after.
ScopedExcept ptr(const_cast<pxThread *>(this)->m_except.DetachPtr());
if (ptr)
ptr->Rethrow();
ScopedExcept ptr(const_cast<pxThread*>(this)->m_except.DetachPtr());
if (ptr)
ptr->Rethrow();
}
static bool m_BlockDeletions = false;
bool Threading::AllowDeletions()
{
AffinityAssert_AllowFrom_MainUI();
return !m_BlockDeletions;
AffinityAssert_AllowFrom_MainUI();
return !m_BlockDeletions;
}
void Threading::YieldToMain()
{
m_BlockDeletions = true;
wxTheApp->Yield(true);
m_BlockDeletions = false;
m_BlockDeletions = true;
wxTheApp->Yield(true);
m_BlockDeletions = false;
}
void Threading::pxThread::_selfRunningTest(const wxChar *name) const
void Threading::pxThread::_selfRunningTest(const wxChar* name) const
{
if (HasPendingException()) {
pxThreadLog.Error(GetName(), pxsFmt(L"An exception was thrown while waiting on a %s.", name));
RethrowException();
}
if (HasPendingException())
{
pxThreadLog.Error(GetName(), pxsFmt(L"An exception was thrown while waiting on a %s.", name));
RethrowException();
}
if (!m_running) {
throw Exception::CancelEvent(pxsFmt(
L"Blocking thread %s was terminated while another thread was waiting on a %s.",
WX_STR(GetName()), name));
}
if (!m_running)
{
throw Exception::CancelEvent(pxsFmt(
L"Blocking thread %s was terminated while another thread was waiting on a %s.",
WX_STR(GetName()), name));
}
// Thread is still alive and kicking (for now) -- yield to other messages and hope
// that impending chaos does not ensue. [it shouldn't since we block pxThread
// objects from being deleted until outside the scope of a mutex/semaphore wait).
// Thread is still alive and kicking (for now) -- yield to other messages and hope
// that impending chaos does not ensue. [it shouldn't since we block pxThread
// objects from being deleted until outside the scope of a mutex/semaphore wait).
if ((wxTheApp != NULL) && wxThread::IsMain() && !_WaitGui_RecursionGuard(L"WaitForSelf"))
Threading::YieldToMain();
if ((wxTheApp != NULL) && wxThread::IsMain() && !_WaitGui_RecursionGuard(L"WaitForSelf"))
Threading::YieldToMain();
}
// This helper function is a deadlock-safe method of waiting on a semaphore in a pxThread. If the
@@ -462,16 +476,17 @@ void Threading::pxThread::_selfRunningTest(const wxChar *name) const
// This function will rethrow exceptions raised by the persistent thread, if it throws an error
// while the calling thread is blocking (which also means the persistent thread has terminated).
//
void Threading::pxThread::WaitOnSelf(Semaphore &sem) const
void Threading::pxThread::WaitOnSelf(Semaphore& sem) const
{
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return;
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return;
while (true) {
if (sem.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
return;
_selfRunningTest(L"semaphore");
}
while (true)
{
if (sem.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
return;
_selfRunningTest(L"semaphore");
}
}
// This helper function is a deadlock-safe method of waiting on a mutex in a pxThread.
@@ -487,52 +502,55 @@ void Threading::pxThread::WaitOnSelf(Semaphore &sem) const
// error while the calling thread is blocking (which also means the persistent thread has
// terminated).
//
void Threading::pxThread::WaitOnSelf(Mutex &mutex) const
void Threading::pxThread::WaitOnSelf(Mutex& mutex) const
{
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return;
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return;
while (true) {
if (mutex.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
return;
_selfRunningTest(L"mutex");
}
while (true)
{
if (mutex.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
return;
_selfRunningTest(L"mutex");
}
}
static const wxTimeSpan SelfWaitInterval(0, 0, 0, 333);
bool Threading::pxThread::WaitOnSelf(Semaphore &sem, const wxTimeSpan &timeout) const
bool Threading::pxThread::WaitOnSelf(Semaphore& sem, const wxTimeSpan& timeout) const
{
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return true;
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return true;
wxTimeSpan runningout(timeout);
wxTimeSpan runningout(timeout);
while (runningout.GetMilliseconds() > 0) {
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
if (sem.WaitWithoutYield(interval))
return true;
_selfRunningTest(L"semaphore");
runningout -= interval;
}
return false;
while (runningout.GetMilliseconds() > 0)
{
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
if (sem.WaitWithoutYield(interval))
return true;
_selfRunningTest(L"semaphore");
runningout -= interval;
}
return false;
}
bool Threading::pxThread::WaitOnSelf(Mutex &mutex, const wxTimeSpan &timeout) const
bool Threading::pxThread::WaitOnSelf(Mutex& mutex, const wxTimeSpan& timeout) const
{
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return true;
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return true;
wxTimeSpan runningout(timeout);
wxTimeSpan runningout(timeout);
while (runningout.GetMilliseconds() > 0) {
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
if (mutex.WaitWithoutYield(interval))
return true;
_selfRunningTest(L"mutex");
runningout -= interval;
}
return false;
while (runningout.GetMilliseconds() > 0)
{
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
if (mutex.WaitWithoutYield(interval))
return true;
_selfRunningTest(L"mutex");
runningout -= interval;
}
return false;
}
// Inserts a thread cancellation point. If the thread has received a cancel request, this
@@ -541,36 +559,39 @@ bool Threading::pxThread::WaitOnSelf(Mutex &mutex, const wxTimeSpan &timeout) co
// and cleanup, or use the DoThreadCleanup() override to perform resource cleanup).
void Threading::pxThread::TestCancel() const
{
AffinityAssert_AllowFromSelf(pxDiagSpot);
pthread_testcancel();
AffinityAssert_AllowFromSelf(pxDiagSpot);
pthread_testcancel();
}
// Executes the virtual member method
void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)())
{
try {
(this->*method)();
}
try
{
(this->*method)();
}
// ----------------------------------------------------------------------------
// Neat repackaging for STL Runtime errors...
//
catch (std::runtime_error &ex) {
m_except = new Exception::RuntimeError(ex, WX_STR(GetName()));
}
// ----------------------------------------------------------------------------
// Neat repackaging for STL Runtime errors...
//
catch (std::runtime_error& ex)
{
m_except = new Exception::RuntimeError(ex, WX_STR(GetName()));
}
// ----------------------------------------------------------------------------
catch (Exception::RuntimeError &ex) {
BaseException *woot = ex.Clone();
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
m_except = woot;
}
// ----------------------------------------------------------------------------
catch (Exception::RuntimeError& ex)
{
BaseException* woot = ex.Clone();
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
m_except = woot;
}
#ifndef PCSX2_DEVBUILD
// ----------------------------------------------------------------------------
// Bleh... don't bother with std::exception. runtime_error should catch anything
// useful coming out of the core STL libraries anyway, and these are best handled by
// the MSVC debugger (or by silent random annoying fail on debug-less linux).
/*catch( std::logic_error& ex )
// ----------------------------------------------------------------------------
// Bleh... don't bother with std::exception. runtime_error should catch anything
// useful coming out of the core STL libraries anyway, and these are best handled by
// the MSVC debugger (or by silent random annoying fail on debug-less linux).
/*catch( std::logic_error& ex )
{
throw BaseException( pxsFmt( L"STL Logic Error (thread:%s): %s",
WX_STR(GetName()), WX_STR(fromUTF8( ex.what() )) )
@@ -582,14 +603,15 @@ void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)())
WX_STR(GetName()), WX_STR(fromUTF8( ex.what() )) )
);
}*/
// ----------------------------------------------------------------------------
// BaseException -- same deal as LogicErrors.
//
catch (BaseException &ex) {
BaseException *woot = ex.Clone();
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
m_except = woot;
}
// ----------------------------------------------------------------------------
// BaseException -- same deal as LogicErrors.
//
catch (BaseException& ex)
{
BaseException* woot = ex.Clone();
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
m_except = woot;
}
#endif
}
@@ -597,25 +619,25 @@ void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)())
// OnCleanupInThread() to extend cleanup functionality.
void Threading::pxThread::_ThreadCleanup()
{
AffinityAssert_AllowFromSelf(pxDiagSpot);
_try_virtual_invoke(&pxThread::OnCleanupInThread);
m_mtx_InThread.Release();
AffinityAssert_AllowFromSelf(pxDiagSpot);
_try_virtual_invoke(&pxThread::OnCleanupInThread);
m_mtx_InThread.Release();
// Must set m_running LAST, as thread destructors depend on this value (it is used
// to avoid destruction of the thread until all internal data use has stopped.
m_running = false;
// Must set m_running LAST, as thread destructors depend on this value (it is used
// to avoid destruction of the thread until all internal data use has stopped.
m_running = false;
}
wxString Threading::pxThread::GetName() const
{
ScopedLock lock(m_mtx_ThreadName);
return m_name;
ScopedLock lock(m_mtx_ThreadName);
return m_name;
}
void Threading::pxThread::SetName(const wxString &newname)
void Threading::pxThread::SetName(const wxString& newname)
{
ScopedLock lock(m_mtx_ThreadName);
m_name = newname;
ScopedLock lock(m_mtx_ThreadName);
m_name = newname;
}
// This override is called by PeristentThread when the thread is first created, prior to
@@ -627,82 +649,82 @@ void Threading::pxThread::SetName(const wxString &newname)
//
void Threading::pxThread::OnStartInThread()
{
m_detached = false;
m_running = true;
m_detached = false;
m_running = true;
_platform_specific_OnStartInThread();
_platform_specific_OnStartInThread();
}
void Threading::pxThread::_internal_execute()
{
m_mtx_InThread.Acquire();
m_mtx_InThread.Acquire();
_DoSetThreadName(GetName());
make_curthread_key(this);
if (curthread_key)
pthread_setspecific(curthread_key, this);
_DoSetThreadName(GetName());
make_curthread_key(this);
if (curthread_key)
pthread_setspecific(curthread_key, this);
OnStartInThread();
m_sem_startup.Post();
OnStartInThread();
m_sem_startup.Post();
_try_virtual_invoke(&pxThread::ExecuteTaskInThread);
_try_virtual_invoke(&pxThread::ExecuteTaskInThread);
}
// Called by Start, prior to actual starting of the thread, and after any previous
// running thread has been canceled or detached.
void Threading::pxThread::OnStart()
{
m_native_handle = 0;
m_native_id = 0;
m_native_handle = 0;
m_native_id = 0;
FrankenMutex(m_mtx_InThread);
m_sem_event.Reset();
m_sem_startup.Reset();
FrankenMutex(m_mtx_InThread);
m_sem_event.Reset();
m_sem_startup.Reset();
}
// Extending classes that override this method should always call it last from their
// personal implementations.
void Threading::pxThread::OnCleanupInThread()
{
if (curthread_key)
pthread_setspecific(curthread_key, NULL);
if (curthread_key)
pthread_setspecific(curthread_key, NULL);
unmake_curthread_key();
unmake_curthread_key();
_platform_specific_OnCleanupInThread();
_platform_specific_OnCleanupInThread();
m_native_handle = 0;
m_native_id = 0;
m_native_handle = 0;
m_native_id = 0;
m_evtsrc_OnDelete.Dispatch(0);
m_evtsrc_OnDelete.Dispatch(0);
}
// passed into pthread_create, and is used to dispatch the thread's object oriented
// callback function
void *Threading::pxThread::_internal_callback(void *itsme)
void* Threading::pxThread::_internal_callback(void* itsme)
{
if (!pxAssertDev(itsme != NULL, wxNullChar))
return NULL;
if (!pxAssertDev(itsme != NULL, wxNullChar))
return NULL;
internal_callback_helper(itsme);
return nullptr;
internal_callback_helper(itsme);
return nullptr;
}
// __try is used in pthread_cleanup_push when CLEANUP_SEH is used as the cleanup model.
// That can't be used in a function that has objects that require unwinding (compile
// error C2712), so move it into a separate function.
void Threading::pxThread::internal_callback_helper(void *itsme)
void Threading::pxThread::internal_callback_helper(void* itsme)
{
pxThread &owner = *static_cast<pxThread *>(itsme);
pxThread& owner = *static_cast<pxThread*>(itsme);
pthread_cleanup_push(_pt_callback_cleanup, itsme);
owner._internal_execute();
pthread_cleanup_pop(true);
pthread_cleanup_push(_pt_callback_cleanup, itsme);
owner._internal_execute();
pthread_cleanup_pop(true);
}
void Threading::pxThread::_DoSetThreadName(const wxString &name)
void Threading::pxThread::_DoSetThreadName(const wxString& name)
{
_DoSetThreadName(static_cast<const char *>(name.ToUTF8()));
_DoSetThreadName(static_cast<const char*>(name.ToUTF8()));
}
// --------------------------------------------------------------------------------------
@@ -746,23 +768,23 @@ void Threading::WaitEvent::Wait()
wxString Exception::BaseThreadError::FormatDiagnosticMessage() const
{
wxString null_str(L"Null Thread Object");
return pxsFmt(m_message_diag, (m_thread == NULL) ? WX_STR(null_str) : WX_STR(m_thread->GetName()));
wxString null_str(L"Null Thread Object");
return pxsFmt(m_message_diag, (m_thread == NULL) ? WX_STR(null_str) : WX_STR(m_thread->GetName()));
}
wxString Exception::BaseThreadError::FormatDisplayMessage() const
{
wxString null_str(L"Null Thread Object");
return pxsFmt(m_message_user, (m_thread == NULL) ? WX_STR(null_str) : WX_STR(m_thread->GetName()));
wxString null_str(L"Null Thread Object");
return pxsFmt(m_message_user, (m_thread == NULL) ? WX_STR(null_str) : WX_STR(m_thread->GetName()));
}
pxThread &Exception::BaseThreadError::Thread()
pxThread& Exception::BaseThreadError::Thread()
{
pxAssertDev(m_thread != NULL, "NULL thread object on ThreadError exception.");
return *m_thread;
pxAssertDev(m_thread != NULL, "NULL thread object on ThreadError exception.");
return *m_thread;
}
const pxThread &Exception::BaseThreadError::Thread() const
const pxThread& Exception::BaseThreadError::Thread() const
{
pxAssertDev(m_thread != NULL, "NULL thread object on ThreadError exception.");
return *m_thread;
pxAssertDev(m_thread != NULL, "NULL thread object on ThreadError exception.");
return *m_thread;
}