diff --git a/common/include/Utilities/Console.h b/common/include/Utilities/Console.h index 346a6ed010..032e159157 100644 --- a/common/include/Utilities/Console.h +++ b/common/include/Utilities/Console.h @@ -81,6 +81,10 @@ struct IConsoleWriter // SetColor implementation for internal use only. void (__concall *DoSetColor)( ConsoleColors color ); + // Special implementation of DoWrite that's pretty much for MSVC use only. + // All implementations should map to DoWrite, except Stdio which should map to Null. + void (__concall *DoWriteFromStdout)( const wxString& fmt ); + void (__concall *Newline)(); void (__concall *SetTitle)( const wxString& title ); @@ -111,6 +115,9 @@ struct IConsoleWriter bool Error( const wxChar* fmt, ... ) const; bool Warning( const wxChar* fmt, ... ) const; + bool WriteFromStdout( const char* fmt, ... ) const; + bool WriteFromStdout( ConsoleColors color, const char* fmt, ... ) const; + // internal value for indentation of individual lines. Use the Indent() member to invoke. int _imm_indentation; @@ -209,7 +216,7 @@ extern void ConsoleBuffer_Clear(); extern void ConsoleBuffer_FlushToFile( FILE *fp ); extern const IConsoleWriter ConsoleWriter_Null; -extern const IConsoleWriter ConsoleWriter_Stdio; +extern const IConsoleWriter ConsoleWriter_Stdout; extern const IConsoleWriter ConsoleWriter_Assert; extern const IConsoleWriter ConsoleWriter_Buffered; extern const IConsoleWriter ConsoleWriter_wxError; diff --git a/common/include/Utilities/Threading.h b/common/include/Utilities/Threading.h index 3cb970ef3f..d0ce327de2 100644 --- a/common/include/Utilities/Threading.h +++ b/common/include/Utilities/Threading.h @@ -24,7 +24,7 @@ #undef Yield // release th burden of windows.h global namespace spam. -#define AllowFromMainThreadOnly() \ +#define AffinityAssert_AllowFromMain() \ pxAssertMsg( wxThread::IsMain(), "Thread affinity violation: Call allowed from main thread only." ) class wxTimeSpan; @@ -419,6 +419,9 @@ namespace Threading void FrankenMutex( Mutex& mutex ); + bool AffinityAssert_AllowFromSelf() const; + bool AffinityAssert_DisallowFromSelf() const; + // ---------------------------------------------------------------------------- // Section of methods for internal use only. diff --git a/common/src/Utilities/Console.cpp b/common/src/Utilities/Console.cpp index fd2c2fa993..0cea1191e0 100644 --- a/common/src/Utilities/Console.cpp +++ b/common/src/Utilities/Console.cpp @@ -18,6 +18,9 @@ using namespace Threading; +static wxString m_buffer; // used by ConsoleBuffer +static Mutex m_bufferlock; // used by ConsoleBuffer + // This function re-assigns the console log writer(s) to the specified target. It makes sure // to flush any contents from the buffered console log (which typically accumulates due to // log suspension during log file/window re-init operations) into the new log. @@ -34,8 +37,12 @@ void Console_SetActiveHandler( const IConsoleWriter& writer, FILE* flushfp ) "Invalid IConsoleWriter object! All function pointer interfaces must be implemented." ); - if( !ConsoleBuffer_Get().IsEmpty() ) - writer.DoWriteLn( ConsoleBuffer_Get() ); + if( &writer != &ConsoleWriter_Buffered ) + { + ScopedLock lock( m_bufferlock ); + if( !ConsoleBuffer_Get().IsEmpty() ) + writer.DoWriteLn( ConsoleBuffer_Get() ); + } Console = writer; @@ -64,6 +71,7 @@ const IConsoleWriter ConsoleWriter_Null = ConsoleNull_DoWriteLn, ConsoleNull_DoSetColor, + ConsoleNull_DoWrite, ConsoleNull_Newline, ConsoleNull_SetTitle, @@ -71,7 +79,7 @@ const IConsoleWriter ConsoleWriter_Null = }; // -------------------------------------------------------------------------------------- -// Console_Stdio +// Console_Stdout // -------------------------------------------------------------------------------------- #ifdef __LINUX__ @@ -117,23 +125,23 @@ static __forceinline const wxChar* GetLinuxConsoleColor(ConsoleColors color) #endif // One possible default write action at startup and shutdown is to use the stdout. -static void __concall ConsoleStdio_DoWrite( const wxString& fmt ) +static void __concall ConsoleStdout_DoWrite( const wxString& fmt ) { wxPrintf( fmt ); } // Default write action at startup and shutdown is to use the stdout. -static void __concall ConsoleStdio_DoWriteLn( const wxString& fmt ) +static void __concall ConsoleStdout_DoWriteLn( const wxString& fmt ) { wxPrintf( fmt + L"\n" ); } -static void __concall ConsoleStdio_Newline() +static void __concall ConsoleStdout_Newline() { wxPrintf( L"\n" ); } -static void __concall ConsoleStdio_DoSetColor( ConsoleColors color ) +static void __concall ConsoleStdout_DoSetColor( ConsoleColors color ) { #ifdef __LINUX__ wxPrintf(L"\033[0m"); @@ -141,21 +149,22 @@ static void __concall ConsoleStdio_DoSetColor( ConsoleColors color ) #endif } -static void __concall ConsoleStdio_SetTitle( const wxString& title ) +static void __concall ConsoleStdout_SetTitle( const wxString& title ) { #ifdef __LINUX__ wxPrintf(L"\033]0;" + title + L"\007"); #endif } -const IConsoleWriter ConsoleWriter_Stdio = +const IConsoleWriter ConsoleWriter_Stdout = { - ConsoleStdio_DoWrite, // Writes without newlines go to buffer to avoid error log spam. - ConsoleStdio_DoWriteLn, - ConsoleStdio_DoSetColor, + ConsoleStdout_DoWrite, // Writes without newlines go to buffer to avoid error log spam. + ConsoleStdout_DoWriteLn, + ConsoleStdout_DoSetColor, - ConsoleStdio_Newline, - ConsoleStdio_SetTitle, + ConsoleNull_DoWrite, // writes from stdout are ignored here, lest we create infinite loop hell >_< + ConsoleStdout_Newline, + ConsoleStdout_SetTitle, 0, // instance-level indentation (should always be 0) }; @@ -180,6 +189,7 @@ const IConsoleWriter ConsoleWriter_Assert = ConsoleAssert_DoWriteLn, ConsoleNull_DoSetColor, + ConsoleNull_DoWrite, ConsoleNull_Newline, ConsoleNull_SetTitle, @@ -190,8 +200,6 @@ const IConsoleWriter ConsoleWriter_Assert = // ConsoleBuffer // -------------------------------------------------------------------------------------- -static wxString m_buffer; - const wxString& ConsoleBuffer_Get() { return m_buffer; @@ -199,6 +207,7 @@ const wxString& ConsoleBuffer_Get() void ConsoleBuffer_Clear() { + ScopedLock lock( m_bufferlock ); m_buffer.Clear(); } @@ -206,6 +215,7 @@ void ConsoleBuffer_Clear() // clears the buffer contents to 0. void ConsoleBuffer_FlushToFile( FILE *fp ) { + ScopedLock lock( m_bufferlock ); if( fp == NULL || m_buffer.IsEmpty() ) return; px_fputs( fp, m_buffer.ToUTF8() ); m_buffer.Clear(); @@ -213,11 +223,13 @@ void ConsoleBuffer_FlushToFile( FILE *fp ) static void __concall ConsoleBuffer_DoWrite( const wxString& fmt ) { + ScopedLock lock( m_bufferlock ); m_buffer += fmt; } static void __concall ConsoleBuffer_DoWriteLn( const wxString& fmt ) { + ScopedLock lock( m_bufferlock ); m_buffer += fmt + L"\n"; } @@ -227,6 +239,7 @@ const IConsoleWriter ConsoleWriter_Buffered = ConsoleBuffer_DoWriteLn, ConsoleNull_DoSetColor, + ConsoleBuffer_DoWrite, ConsoleNull_Newline, ConsoleNull_SetTitle, @@ -253,6 +266,7 @@ const IConsoleWriter ConsoleWriter_wxError = Console_wxLogError_DoWriteLn, ConsoleNull_DoSetColor, + ConsoleBuffer_DoWrite, ConsoleNull_Newline, ConsoleNull_SetTitle, @@ -616,6 +630,36 @@ bool IConsoleWriter::Warning( const wxChar* fmt, ... ) const return false; } +// -------------------------------------------------------------------------------------- +// +// -------------------------------------------------------------------------------------- + +bool IConsoleWriter::WriteFromStdout( const char* fmt, ... ) const +{ + if( DoWriteFromStdout == ConsoleNull_DoWrite ) return false; + + va_list args; + va_start(args,fmt); + DoWrite( ascii_format_string(fmt, args) ); + va_end(args); + + return false; +} + +bool IConsoleWriter::WriteFromStdout( ConsoleColors color, const char* fmt, ... ) const +{ + if( DoWriteFromStdout == ConsoleNull_DoWrite ) return false; + + va_list args; + va_start(args,fmt); + ConsoleColorScope cs( color ); + DoWrite( ascii_format_string(fmt, args) ); + va_end(args); + + return false; +} + + // -------------------------------------------------------------------------------------- // Default Writer for C++ init / startup: // -------------------------------------------------------------------------------------- @@ -627,7 +671,7 @@ bool IConsoleWriter::Warning( const wxChar* fmt, ... ) const #if wxUSE_GUI && defined(__WXMSW__) # define _DefaultWriter_ ConsoleWriter_Assert #else -# define _DefaultWriter_ ConsoleWriter_Stdio +# define _DefaultWriter_ ConsoleWriter_Stdout #endif // Important! Only Assert and Null console loggers are allowed for initial console targeting. diff --git a/common/src/Utilities/ThreadTools.cpp b/common/src/Utilities/ThreadTools.cpp index 642a7046e5..3854300fc3 100644 --- a/common/src/Utilities/ThreadTools.cpp +++ b/common/src/Utilities/ThreadTools.cpp @@ -67,12 +67,12 @@ void Threading::PersistentThread::_pt_callback_cleanup( void* handle ) ((PersistentThread*)handle)->_ThreadCleanup(); } -Threading::PersistentThread::PersistentThread() : - m_name( L"PersistentThread" ) -, m_thread() -, m_sem_event() -, m_lock_InThread() -, m_lock_start() +Threading::PersistentThread::PersistentThread() + : m_name( L"PersistentThread" ) + , m_thread() + , m_sem_event() + , m_lock_InThread() + , m_lock_start() { m_detached = true; // start out with m_thread in detached/invalid state m_running = false; @@ -116,6 +116,16 @@ Threading::PersistentThread::~PersistentThread() throw() DESTRUCTOR_CATCHALL } +bool Threading::PersistentThread::AffinityAssert_AllowFromSelf() const +{ + return pxAssertMsg( IsSelf(), wxsFormat( L"Thread affinity violation: Call allowed from '%s' thread only.", m_name ) ); +} + +bool Threading::PersistentThread::AffinityAssert_DisallowFromSelf() const +{ + return pxAssertMsg( !IsSelf(), wxsFormat( L"Thread affinity violation: Call is *not* allowed from '%s' thread.", m_name ) ); +} + void Threading::PersistentThread::FrankenMutex( Mutex& mutex ) { if( mutex.RecreateIfLocked() ) @@ -155,7 +165,7 @@ void Threading::PersistentThread::Start() // This function should not be called from the owner thread. bool Threading::PersistentThread::Detach() { - pxAssertMsg( !IsSelf(), "Thread affinity error." ); // not allowed from our own thread. + AffinityAssert_DisallowFromSelf(); if( _InterlockedExchange( &m_detached, true ) ) return false; pthread_detach( m_thread ); @@ -175,7 +185,7 @@ bool Threading::PersistentThread::Detach() // void Threading::PersistentThread::Cancel( bool isBlocking ) { - pxAssertMsg( !IsSelf(), "Thread affinity error." ); + AffinityAssert_DisallowFromSelf(); { // Prevent simultaneous startup and cancel: @@ -210,8 +220,7 @@ void Threading::PersistentThread::Cancel( bool isBlocking ) // void Threading::PersistentThread::Block() { - pxAssertDev( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." ); - + AffinityAssert_DisallowFromSelf(); m_lock_InThread.Wait(); } @@ -268,7 +277,7 @@ void Threading::PersistentThread::_selfRunningTest( const wxChar* name ) const // void Threading::PersistentThread::WaitOnSelf( Semaphore& sem ) const { - if( !pxAssertDev( !IsSelf(), "WaitOnSelf called from inside the blocking thread (invalid operation!)" ) ) return; + if( !AffinityAssert_DisallowFromSelf() ) return; while( true ) { @@ -292,7 +301,7 @@ void Threading::PersistentThread::WaitOnSelf( Semaphore& sem ) const // void Threading::PersistentThread::WaitOnSelf( Mutex& mutex ) const { - if( !pxAssertDev( !IsSelf(), "WaitOnSelf called from inside the blocking thread (invalid operation!)" ) ) return; + if( !AffinityAssert_DisallowFromSelf() ) return; while( true ) { @@ -305,7 +314,7 @@ static const wxTimeSpan SelfWaitInterval( 0,0,0,333 ); bool Threading::PersistentThread::WaitOnSelf( Semaphore& sem, const wxTimeSpan& timeout ) const { - if( !pxAssertDev( !IsSelf(), "WaitOnSelf called from inside the blocking thread (invalid operation!)" ) ) return true; + if( !AffinityAssert_DisallowFromSelf() ) return true; wxTimeSpan runningout( timeout ); @@ -321,7 +330,7 @@ bool Threading::PersistentThread::WaitOnSelf( Semaphore& sem, const wxTimeSpan& bool Threading::PersistentThread::WaitOnSelf( Mutex& mutex, const wxTimeSpan& timeout ) const { - if( !pxAssertDev( !IsSelf(), "WaitOnSelf called from inside the blocking thread (invalid operation!)" ) ) return true; + if( !AffinityAssert_DisallowFromSelf() ) return true; wxTimeSpan runningout( timeout ); @@ -341,7 +350,7 @@ bool Threading::PersistentThread::WaitOnSelf( Mutex& mutex, const wxTimeSpan& ti // and cleanup, or use the DoThreadCleanup() override to perform resource cleanup). void Threading::PersistentThread::TestCancel() const { - pxAssert( IsSelf() ); + AffinityAssert_AllowFromSelf(); pthread_testcancel(); } @@ -422,10 +431,8 @@ void Threading::PersistentThread::_try_virtual_invoke( void (PersistentThread::* // OnCleanupInThread() to extend cleanup functionality. void Threading::PersistentThread::_ThreadCleanup() { - pxAssertMsg( IsSelf(), "Thread affinity error." ); // only allowed from our own thread, thanks. - + AffinityAssert_AllowFromSelf(); _try_virtual_invoke( &PersistentThread::OnCleanupInThread ); - m_lock_InThread.Release(); } @@ -486,7 +493,7 @@ void Threading::PersistentThread::_DoSetThreadName( const wxString& name ) void Threading::PersistentThread::_DoSetThreadName( const char* name ) { - pxAssertMsg( IsSelf(), "Thread affinity error." ); // only allowed from our own thread, thanks. + if( !AffinityAssert_AllowFromSelf() ) return; // This feature needs Windows headers and MSVC's SEH support: diff --git a/common/src/x86emitter/LnxCpuDetect.cpp b/common/src/x86emitter/LnxCpuDetect.cpp index 2c7d42bcf8..91ca200b85 100644 --- a/common/src/x86emitter/LnxCpuDetect.cpp +++ b/common/src/x86emitter/LnxCpuDetect.cpp @@ -17,13 +17,9 @@ #include "PrecompiledHeader.h" #include "cpudetect_internal.h" -s32 iCpuId( u32 cmd, u32 *regs ) +void iCpuId( u32 cmd, u32 *regs ) { - // ecx should be zero for CPUID(4) - __asm__ __volatile__ ( "xor %ecx, %ecx" ); - __cpuid( (int*)regs, cmd ); - return 0; } // Note: Apparently this solution is Linux/Solaris only. diff --git a/common/src/x86emitter/WinCpuDetect.cpp b/common/src/x86emitter/WinCpuDetect.cpp index 039b12128b..6dd1fd7c99 100644 --- a/common/src/x86emitter/WinCpuDetect.cpp +++ b/common/src/x86emitter/WinCpuDetect.cpp @@ -17,12 +17,10 @@ #include "PrecompiledHeader.h" #include "cpudetect_internal.h" -s32 iCpuId( u32 cmd, u32 *regs ) +void iCpuId( u32 cmd, u32 *regs ) { // ecx should be zero for CPUID(4) - __asm xor ecx, ecx; __cpuid( (int*)regs, cmd ); - return 0; } void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU ) @@ -54,7 +52,8 @@ void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhys bool _test_instruction( void* pfnCall ) { __try { - ((void (*)())pfnCall)(); + u128 regsave; + ((void (__fastcall *)(void*))pfnCall)( ®save ); } __except(EXCEPTION_EXECUTE_HANDLER) { return false; diff --git a/common/src/x86emitter/cpudetect.cpp b/common/src/x86emitter/cpudetect.cpp index 6035d54c36..337a7d15fc 100644 --- a/common/src/x86emitter/cpudetect.cpp +++ b/common/src/x86emitter/cpudetect.cpp @@ -68,79 +68,72 @@ static s64 CPUSpeedHz( u64 time ) //////////////////////////////////////////////////// void cpudetectInit() { - u32 regs[ 4 ]; - u32 cmds; - //AMD 64 STUFF - u32 x86_64_8BITBRANDID; - u32 x86_64_12BITBRANDID; + u32 regs[ 4 ]; + u32 cmds; + //AMD 64 STUFF + u32 x86_64_8BITBRANDID; + u32 x86_64_12BITBRANDID; - memzero( x86caps.VendorName ); - x86caps.FamilyID = 0; - x86caps.Model = 0; - x86caps.TypeID = 0; - x86caps.StepID = 0; - x86caps.Flags = 0; - x86caps.EFlags = 0; + memzero( x86caps.VendorName ); + x86caps.FamilyID = 0; + x86caps.Model = 0; + x86caps.TypeID = 0; + x86caps.StepID = 0; + x86caps.Flags = 0; + x86caps.EFlags = 0; - if ( iCpuId( 0, regs ) == -1 ) return; + //memzero( regs ); + iCpuId( 0, regs ); - cmds = regs[ 0 ]; - ((u32*)x86caps.VendorName)[ 0 ] = regs[ 1 ]; - ((u32*)x86caps.VendorName)[ 1 ] = regs[ 3 ]; - ((u32*)x86caps.VendorName)[ 2 ] = regs[ 2 ]; + cmds = regs[ 0 ]; + ((u32*)x86caps.VendorName)[ 0 ] = regs[ 1 ]; + ((u32*)x86caps.VendorName)[ 1 ] = regs[ 3 ]; + ((u32*)x86caps.VendorName)[ 2 ] = regs[ 2 ]; - u32 LogicalCoresPerPhysicalCPU = 0; - u32 PhysicalCoresPerPhysicalCPU = 1; + u32 LogicalCoresPerPhysicalCPU = 0; + u32 PhysicalCoresPerPhysicalCPU = 1; - if ( cmds >= 0x00000001 ) - { - if ( iCpuId( 0x00000001, regs ) != -1 ) - { - x86caps.StepID = regs[ 0 ] & 0xf; - x86caps.Model = (regs[ 0 ] >> 4) & 0xf; - x86caps.FamilyID = (regs[ 0 ] >> 8) & 0xf; - x86caps.TypeID = (regs[ 0 ] >> 12) & 0x3; - LogicalCoresPerPhysicalCPU = ( regs[1] >> 16 ) & 0xff; - x86_64_8BITBRANDID = regs[ 1 ] & 0xff; - x86caps.Flags = regs[ 3 ]; - x86caps.Flags2 = regs[ 2 ]; - } - } + if ( cmds >= 0x00000001 ) + { + iCpuId( 0x00000001, regs ); - // detect multicore for Intel cpu + x86caps.StepID = regs[ 0 ] & 0xf; + x86caps.Model = (regs[ 0 ] >> 4) & 0xf; + x86caps.FamilyID = (regs[ 0 ] >> 8) & 0xf; + x86caps.TypeID = (regs[ 0 ] >> 12) & 0x3; + x86_64_8BITBRANDID = regs[ 1 ] & 0xff; + x86caps.Flags = regs[ 3 ]; + x86caps.Flags2 = regs[ 2 ]; - if ((cmds >= 0x00000004) && !strcmp("GenuineIntel",x86caps.VendorName)) - { - if ( iCpuId( 0x00000004, regs ) != -1 ) - { - PhysicalCoresPerPhysicalCPU += ( regs[0] >> 26) & 0x3f; - } - } + LogicalCoresPerPhysicalCPU = ( regs[1] >> 16 ) & 0xff; + } - if ( iCpuId( 0x80000000, regs ) != -1 ) - { - cmds = regs[ 0 ]; - if ( cmds >= 0x80000001 ) - { - if ( iCpuId( 0x80000001, regs ) != -1 ) - { - x86_64_12BITBRANDID = regs[1] & 0xfff; - x86caps.EFlags2 = regs[ 2 ]; - x86caps.EFlags = regs[ 3 ]; + // detect multicore for Intel cpu - } - } - - // detect multicore for AMD cpu - - if ((cmds >= 0x80000008) && !strcmp("AuthenticAMD",x86caps.VendorName)) - { - if ( iCpuId( 0x80000008, regs ) != -1 ) - { - PhysicalCoresPerPhysicalCPU += ( regs[2] ) & 0xff; - } - } - } + if ((cmds >= 0x00000004) && !strcmp("GenuineIntel",x86caps.VendorName)) + { + iCpuId( 0x00000004, regs ); + PhysicalCoresPerPhysicalCPU += ( regs[0] >> 26) & 0x3f; + } + + iCpuId( 0x80000000, regs ); + cmds = regs[ 0 ]; + if ( cmds >= 0x80000001 ) + { + iCpuId( 0x80000001, regs ); + + x86_64_12BITBRANDID = regs[1] & 0xfff; + x86caps.EFlags2 = regs[ 2 ]; + x86caps.EFlags = regs[ 3 ]; + } + + // detect multicore for AMD cpu + + if ((cmds >= 0x80000008) && !strcmp("AuthenticAMD",x86caps.VendorName)) + { + iCpuId( 0x80000008, regs ); + PhysicalCoresPerPhysicalCPU += ( regs[2] ) & 0xff; + } switch(x86caps.TypeID) { @@ -245,15 +238,21 @@ void cpudetectInit() if( CanTestInstructionSets() ) { xSetPtr( recSSE ); + xMOVDQU( ptr[ecx], xmm1 ); xMOVSLDUP( xmm1, xmm0 ); + xMOVDQU( xmm1, ptr[ecx] ); xRET(); u8* funcSSSE3 = xGetPtr(); - xPABS.W( xmm0, xmm1 ); + xMOVDQU( ptr[ecx], xmm1 ); + xPABS.W( xmm1, xmm0 ); + xMOVDQU( xmm1, ptr[ecx] ); xRET(); u8* funcSSE41 = xGetPtr(); + xMOVDQU( ptr[ecx], xmm1 ); xBLEND.VPD( xmm1, xmm0 ); + xMOVDQU( xmm1, ptr[ecx] ); xRET(); bool sse3_result = _test_instruction( recSSE ); // sse3 diff --git a/common/src/x86emitter/cpudetect_internal.h b/common/src/x86emitter/cpudetect_internal.h index 6dd14f7935..53831954bb 100644 --- a/common/src/x86emitter/cpudetect_internal.h +++ b/common/src/x86emitter/cpudetect_internal.h @@ -53,4 +53,4 @@ public: extern bool CanTestInstructionSets(); extern bool _test_instruction( void* pfnCall ); -extern s32 iCpuId( u32 cmd, u32 *regs ); +extern void iCpuId( u32 cmd, u32 *regs ); diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 8f4b9c523d..bacb59245d 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -37,21 +37,21 @@ const Pcsx2Config EmuConfig; Pcsx2Config::GSOptions& SetGSConfig() { //DbgCon.WriteLn( "Direct modification of EmuConfig.GS detected" ); - AllowFromMainThreadOnly(); + AffinityAssert_AllowFromMain(); return const_cast(EmuConfig.GS); } ConsoleLogFilters& SetConsoleConfig() { //DbgCon.WriteLn( "Direct modification of EmuConfig.Log detected" ); - AllowFromMainThreadOnly(); + AffinityAssert_AllowFromMain(); return const_cast(EmuConfig.Log); } TraceLogFilters& SetTraceConfig() { //DbgCon.WriteLn( "Direct modification of EmuConfig.TraceLog detected" ); - AllowFromMainThreadOnly(); + AffinityAssert_AllowFromMain(); return const_cast(EmuConfig.Trace); } diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 4a031f721c..1eaab5a48a 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -64,7 +64,7 @@ static int resume_tries = 0; void AppCoreThread::Resume() { // Thread control (suspend / resume) should only be performed from the main/gui thread. - if( !AllowFromMainThreadOnly() ) return; + if( !AffinityAssert_AllowFromMain() ) return; if( m_ExecMode == ExecMode_Opened ) return; if( m_ResumeProtection.IsLocked() ) return; diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 13e277377f..1440b4cc68 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -103,7 +103,7 @@ void Pcsx2App::PostPadKey( wxKeyEvent& evt ) int Pcsx2App::ThreadedModalDialog( DialogIdentifiers dialogId ) { - AllowFromMainThreadOnly(); + AffinityAssert_AllowFromMain(); MsgboxEventResult result; wxCommandEvent joe( pxEVT_OpenModalDialog, dialogId ); @@ -399,7 +399,7 @@ GSFrame& Pcsx2App::GetGSFrame() const void AppApplySettings( const AppConfig* oldconf ) { - AllowFromMainThreadOnly(); + AffinityAssert_AllowFromMain(); g_Conf->Folders.ApplyDefaults(); @@ -452,7 +452,7 @@ AppIniLoader::AppIniLoader() void AppLoadSettings() { - if( !AllowFromMainThreadOnly() ) return; + if( !AffinityAssert_AllowFromMain() ) return; AppIniLoader loader; g_Conf->LoadSave( loader ); @@ -461,7 +461,7 @@ void AppLoadSettings() void AppSaveSettings() { - if( !AllowFromMainThreadOnly() ) return; + if( !AffinityAssert_AllowFromMain() ) return; AppIniSaver saver; g_Conf->LoadSave( saver ); diff --git a/pcsx2/gui/ConsoleLogger.cpp b/pcsx2/gui/ConsoleLogger.cpp index 66cf9b5360..d49e14d87a 100644 --- a/pcsx2/gui/ConsoleLogger.cpp +++ b/pcsx2/gui/ConsoleLogger.cpp @@ -589,9 +589,12 @@ void ConsoleLogFrame::OnIdleEvent( wxIdleEvent& evt ) void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt ) { ScopedLock locker( m_QueueLock ); - m_pendingFlushMsg = false; - //if( m_TextCtrl.HasWriteLock() ) return; + + // recursion guard needed due to Mutex lock/acquire code below. + static int recursion_counter = 0; + RecursionGuard recguard( recursion_counter ); + if( recguard.IsReentrant() ) return; if( m_CurQueuePos != 0 ) { @@ -609,7 +612,9 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt ) locker.Acquire(); } - DoFlushQueue(); + if( m_CurQueuePos != 0 ) + DoFlushQueue(); + //m_TextCtrl.Thaw(); } @@ -618,9 +623,6 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt ) // paperwork. But wxEVT_IDLE doesn't work when you click menus or the title bar of a window, // making it pretty well annoyingly useless for just about anything. >_< - // Workaround: I added a Sleep(1) to the DoWrite method to give the GUI some time to - // do its paperwork. - if( m_WaitingThreadsForFlush > 0 ) { do { @@ -702,7 +704,7 @@ void Pcsx2App::ProgramLog_PostEvent( wxEvent& evt ) static void __concall ConsoleToFile_Newline() { #ifdef __LINUX__ - if (g_Conf->EmuOptions.ConsoleToStdio) ConsoleWriter_Stdio.Newline(); + if (g_Conf->EmuOptions.ConsoleToStdio) ConsoleWriter_Stdout.Newline(); #endif #ifdef __LINUX__ @@ -715,7 +717,7 @@ static void __concall ConsoleToFile_Newline() static void __concall ConsoleToFile_DoWrite( const wxString& fmt ) { #ifdef __LINUX__ - if (g_Conf->EmuOptions.ConsoleToStdio) ConsoleWriter_Stdio.DoWrite(fmt); + if (g_Conf->EmuOptions.ConsoleToStdio) ConsoleWriter_Stdout.DoWrite(fmt); #endif px_fputs( emuLog, fmt.ToUTF8() ); @@ -731,12 +733,12 @@ static void __concall ConsoleToFile_DoWriteLn( const wxString& fmt ) static void __concall ConsoleToFile_SetTitle( const wxString& title ) { - ConsoleWriter_Stdio.SetTitle(title); + ConsoleWriter_Stdout.SetTitle(title); } static void __concall ConsoleToFile_DoSetColor( ConsoleColors color ) { - ConsoleWriter_Stdio.DoSetColor(color); + ConsoleWriter_Stdout.DoSetColor(color); } extern const IConsoleWriter ConsoleWriter_File; @@ -746,6 +748,7 @@ const IConsoleWriter ConsoleWriter_File = ConsoleToFile_DoWriteLn, ConsoleToFile_DoSetColor, + ConsoleToFile_DoWrite, ConsoleToFile_Newline, ConsoleToFile_SetTitle, }; @@ -799,6 +802,7 @@ static const IConsoleWriter ConsoleWriter_Window = ConsoleToWindow_DoWriteLn, ConsoleToWindow_DoSetColor, + ConsoleToWindow_DoWrite, ConsoleToWindow_Newline, ConsoleToWindow_SetTitle, }; @@ -809,6 +813,7 @@ static const IConsoleWriter ConsoleWriter_WindowAndFile = ConsoleToWindow_DoWriteLn, ConsoleToWindow_DoSetColor, + ConsoleToWindow_DoWrite, ConsoleToWindow_Newline, ConsoleToWindow_SetTitle, }; @@ -818,14 +823,14 @@ void Pcsx2App::EnableAllLogging() const if( emuLog ) Console_SetActiveHandler( (m_ProgramLogBox!=NULL) ? (IConsoleWriter&)ConsoleWriter_WindowAndFile : (IConsoleWriter&)ConsoleWriter_File ); else - Console_SetActiveHandler( (m_ProgramLogBox!=NULL) ? (IConsoleWriter&)ConsoleWriter_Window : (IConsoleWriter&)ConsoleWriter_Buffered ); + Console_SetActiveHandler( (m_ProgramLogBox!=NULL) ? (IConsoleWriter&)ConsoleWriter_Window : (IConsoleWriter&)ConsoleWriter_Stdout ); } // Used to disable the emuLog disk logger, typically used when disabling or re-initializing the // emuLog file handle. Call SetConsoleLogging to re-enable the disk logger when finished. void Pcsx2App::DisableDiskLogging() const { - Console_SetActiveHandler( (m_ProgramLogBox!=NULL) ? (IConsoleWriter&)ConsoleWriter_Window : (IConsoleWriter&)ConsoleWriter_Buffered ); + Console_SetActiveHandler( (m_ProgramLogBox!=NULL) ? (IConsoleWriter&)ConsoleWriter_Window : (IConsoleWriter&)ConsoleWriter_Stdout ); // Semi-hack: It's possible, however very unlikely, that a secondary thread could attempt // to write to the logfile just before we disable logging, and would thus have a pending write @@ -834,7 +839,7 @@ void Pcsx2App::DisableDiskLogging() const // when changing settings, so the chance for problems is low. We minimize it further here // by sleeping off 5ms, which should allow any pending log-to-disk events to finish up. // - // (the most ideal solution would be a mutex lock in the Disk logger itself, but for now I + // (the most correct solution would be a mutex lock in the Disk logger itself, but for now I // am going to try and keep the logger lock-free and use this semi-hack instead). Threading::Sleep( 5 ); @@ -842,6 +847,6 @@ void Pcsx2App::DisableDiskLogging() const void Pcsx2App::DisableWindowLogging() const { - Console_SetActiveHandler( (emuLog!=NULL) ? (IConsoleWriter&)ConsoleWriter_File : (IConsoleWriter&)ConsoleWriter_Buffered ); + Console_SetActiveHandler( (emuLog!=NULL) ? (IConsoleWriter&)ConsoleWriter_File : (IConsoleWriter&)ConsoleWriter_Stdout ); Threading::Sleep( 5 ); } diff --git a/pcsx2/windows/WinConsolePipe.cpp b/pcsx2/windows/WinConsolePipe.cpp index ed4e904a0a..eecb18bb61 100644 --- a/pcsx2/windows/WinConsolePipe.cpp +++ b/pcsx2/windows/WinConsolePipe.cpp @@ -84,9 +84,9 @@ protected: const ConsoleColors m_color; public: - WinPipeThread( const HANDLE& outpipe, ConsoleColors color ) : - m_outpipe( outpipe ) - , m_color( color ) + WinPipeThread( const HANDLE& outpipe, ConsoleColors color ) + : m_outpipe( outpipe ) + , m_color( color ) { m_name = (m_color == Color_Red) ? L"Redirect_Stderr" : L"Redirect_Stdout"; } @@ -150,8 +150,7 @@ protected: // ATTENTION: The Console always prints ANSI to the pipe independent if compiled as UNICODE or MBCS! s8_Buf[u32_Read] = 0; - OemToCharA(s8_Buf, s8_Buf); // convert DOS codepage -> ANSI - Console.Write( m_color, s8_Buf ); + Console.WriteFromStdout( m_color, s8_Buf ); TestCancel(); } @@ -187,12 +186,12 @@ public: void Cleanup() throw(); }; -WinPipeRedirection::WinPipeRedirection( FILE* stdstream ) : - m_readpipe(INVALID_HANDLE_VALUE) -, m_writepipe(INVALID_HANDLE_VALUE) -, m_crtFile(-1) -, m_fp(NULL) -, m_Thread( m_readpipe, (stdstream == stderr) ? Color_Red : Color_Black ) +WinPipeRedirection::WinPipeRedirection( FILE* stdstream ) + : m_readpipe(INVALID_HANDLE_VALUE) + , m_writepipe(INVALID_HANDLE_VALUE) + , m_crtFile(-1) + , m_fp(NULL) + , m_Thread( m_readpipe, (stdstream == stderr) ? Color_Red : Color_Black ) { try { @@ -236,6 +235,7 @@ WinPipeRedirection::WinPipeRedirection( FILE* stdstream ) : } catch( ... ) { + Cleanup(); throw; } }