* Redid console logging to use stdout instead of the buffered queue (probably less buggy).

* Removed some hacks from cpuDetectInit's use of cpuId.
 * Improved assertion checking for thread affinity.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2327 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-12-07 22:43:16 +00:00
parent 94cdfb6a8b
commit ba473e0a7f
13 changed files with 206 additions and 146 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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.

View File

@ -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:

View File

@ -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.

View File

@ -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)( &regsave );
}
__except(EXCEPTION_EXECUTE_HANDLER) {
return false;

View File

@ -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
}
}
if ((cmds >= 0x00000004) && !strcmp("GenuineIntel",x86caps.VendorName))
{
iCpuId( 0x00000004, regs );
PhysicalCoresPerPhysicalCPU += ( regs[0] >> 26) & 0x3f;
}
// detect multicore for AMD cpu
iCpuId( 0x80000000, regs );
cmds = regs[ 0 ];
if ( cmds >= 0x80000001 )
{
iCpuId( 0x80000001, regs );
if ((cmds >= 0x80000008) && !strcmp("AuthenticAMD",x86caps.VendorName))
{
if ( iCpuId( 0x80000008, regs ) != -1 )
{
PhysicalCoresPerPhysicalCPU += ( regs[2] ) & 0xff;
}
}
}
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

View File

@ -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 );

View File

@ -37,21 +37,21 @@ const Pcsx2Config EmuConfig;
Pcsx2Config::GSOptions& SetGSConfig()
{
//DbgCon.WriteLn( "Direct modification of EmuConfig.GS detected" );
AllowFromMainThreadOnly();
AffinityAssert_AllowFromMain();
return const_cast<Pcsx2Config::GSOptions&>(EmuConfig.GS);
}
ConsoleLogFilters& SetConsoleConfig()
{
//DbgCon.WriteLn( "Direct modification of EmuConfig.Log detected" );
AllowFromMainThreadOnly();
AffinityAssert_AllowFromMain();
return const_cast<ConsoleLogFilters&>(EmuConfig.Log);
}
TraceLogFilters& SetTraceConfig()
{
//DbgCon.WriteLn( "Direct modification of EmuConfig.TraceLog detected" );
AllowFromMainThreadOnly();
AffinityAssert_AllowFromMain();
return const_cast<TraceLogFilters&>(EmuConfig.Trace);
}

View File

@ -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;

View File

@ -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 );

View File

@ -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<ConsoleWriter_Null>,
ConsoleToWindow_DoSetColor<ConsoleWriter_Null>,
ConsoleToWindow_DoWrite<ConsoleWriter_Null>,
ConsoleToWindow_Newline<ConsoleWriter_Null>,
ConsoleToWindow_SetTitle<ConsoleWriter_Null>,
};
@ -809,6 +813,7 @@ static const IConsoleWriter ConsoleWriter_WindowAndFile =
ConsoleToWindow_DoWriteLn<ConsoleWriter_File>,
ConsoleToWindow_DoSetColor<ConsoleWriter_File>,
ConsoleToWindow_DoWrite<ConsoleWriter_File>,
ConsoleToWindow_Newline<ConsoleWriter_File>,
ConsoleToWindow_SetTitle<ConsoleWriter_File>,
};
@ -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 );
}

View File

@ -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;
}
}