mirror of https://github.com/PCSX2/pcsx2.git
* Improved the framelimiter sleep mode more (less cpu used and more responsive to fps fluctuation near the 60fps line at the same time)
* Added timeBeginPeriod() to improve the Win32 kernel scheduler resolution (improves sleep accuracy and thread responsiveness) * hackfixed some code that made exiting pcsx2 "slow" sometimes. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2041 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
7bf94f9db9
commit
27174c3f5b
|
@ -73,6 +73,11 @@ namespace Threading
|
|||
// For use in spin/wait loops.
|
||||
extern void SpinWait();
|
||||
|
||||
// Optional implementation to enable hires thread/process scheduler for the operating system.
|
||||
// Needed by Windows, but might not be relevant to other platforms.
|
||||
extern void EnableHiresScheduler();
|
||||
extern void DisableHiresScheduler();
|
||||
|
||||
// sleeps the current thread for the given number of milliseconds.
|
||||
extern void Sleep( int ms );
|
||||
|
||||
|
|
|
@ -24,38 +24,44 @@
|
|||
|
||||
static bool isMultiCore = true; // assume more than one CPU (safer)
|
||||
|
||||
namespace Threading
|
||||
// Note: Apparently this solution is Linux/Solaris only.
|
||||
// FreeBSD/OsX need something far more complicated (apparently)
|
||||
void Threading::CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU )
|
||||
{
|
||||
// Note: Apparently this solution is Linux/Solaris only.
|
||||
// FreeBSD/OsX need something far more complicated (apparently)
|
||||
void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU )
|
||||
const uint numCPU = sysconf( _SC_NPROCESSORS_ONLN );
|
||||
if( numCPU > 0 )
|
||||
{
|
||||
const uint numCPU = sysconf( _SC_NPROCESSORS_ONLN );
|
||||
if( numCPU > 0 )
|
||||
{
|
||||
isMultiCore = numCPU > 1;
|
||||
x86caps.LogicalCores = numCPU;
|
||||
x86caps.PhysicalCores = ( numCPU / LogicalCoresPerPhysicalCPU ) * PhysicalCoresPerPhysicalCPU;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indeterminate?
|
||||
x86caps.LogicalCores = 1;
|
||||
x86caps.PhysicalCores = 1;
|
||||
}
|
||||
isMultiCore = numCPU > 1;
|
||||
x86caps.LogicalCores = numCPU;
|
||||
x86caps.PhysicalCores = ( numCPU / LogicalCoresPerPhysicalCPU ) * PhysicalCoresPerPhysicalCPU;
|
||||
}
|
||||
|
||||
__forceinline void Sleep( int ms )
|
||||
else
|
||||
{
|
||||
usleep( 1000*ms );
|
||||
}
|
||||
|
||||
// For use in spin/wait loops, Acts as a hint to Intel CPUs and should, in theory
|
||||
// improve performance and reduce cpu power consumption.
|
||||
__forceinline void SpinWait()
|
||||
{
|
||||
// If this doesn't compile you can just comment it out (it only serves as a
|
||||
// performance hint and isn't required).
|
||||
__asm__ ( "pause" );
|
||||
// Indeterminate?
|
||||
x86caps.LogicalCores = 1;
|
||||
x86caps.PhysicalCores = 1;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void Threading::Sleep( int ms )
|
||||
{
|
||||
usleep( 1000*ms );
|
||||
}
|
||||
|
||||
// For use in spin/wait loops, Acts as a hint to Intel CPUs and should, in theory
|
||||
// improve performance and reduce cpu power consumption.
|
||||
__forceinline void Threading::SpinWait()
|
||||
{
|
||||
// If this doesn't compile you can just comment it out (it only serves as a
|
||||
// performance hint and isn't required).
|
||||
__asm__ ( "pause" );
|
||||
}
|
||||
|
||||
__forceinline void Threading::EnableHiresScheduler()
|
||||
{
|
||||
// Don't know if linux has a customizable scheduler resolution like Windows (doubtful)
|
||||
}
|
||||
|
||||
__forceinline void Threading::DisableHiresScheduler()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -60,7 +60,23 @@ namespace Threading
|
|||
// improve performance and reduce cpu power consumption.
|
||||
__forceinline void SpinWait()
|
||||
{
|
||||
__asm { pause };
|
||||
__asm pause;
|
||||
}
|
||||
|
||||
__forceinline void EnableHiresScheduler()
|
||||
{
|
||||
// This improves accuracy of Sleep() by some amount, and only adds a negligable amount of
|
||||
// overhead on modern CPUs. Typically desktops are already set pretty low, but laptops in
|
||||
// particular may have a scheduler Period of 15 or 20ms to extend battery life.
|
||||
|
||||
// (note: this same trick is used by most multimedia software and games)
|
||||
|
||||
timeBeginPeriod( 1 );
|
||||
}
|
||||
|
||||
__forceinline void DisableHiresScheduler()
|
||||
{
|
||||
timeEndPeriod( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -327,17 +327,16 @@ static __forceinline void frameLimit()
|
|||
if( sDeltaTime >= 0 ) return;
|
||||
|
||||
// If we're way ahead then we can afford to sleep the thread a bit.
|
||||
// (note, sleep(1) thru sleep(2) tend to be the least accurate sleeps, and longer
|
||||
// sleeps tend to be pretty reliable, so that's why the convoluted if/else below)
|
||||
|
||||
s32 msec = (int)((sDeltaTime*-1000) / (s64)GetTickFrequency());
|
||||
if( msec > 2 ) Threading::Sleep( msec - 2 );
|
||||
if( msec > 4 ) Threading::Sleep( msec );
|
||||
else if( msec > 2 ) Threading::Sleep( 1 );
|
||||
|
||||
//
|
||||
while( true )
|
||||
{
|
||||
sDeltaTime = GetCPUTicks() - uExpectedEnd;
|
||||
if( sDeltaTime >= 0 ) break;
|
||||
Timeslice();
|
||||
}
|
||||
// Sleep is not picture-perfect accurate, but it's actually not necessary to
|
||||
// maintain a "perfect" lock to uExpectedEnd anyway. if we're a little ahead
|
||||
// starting this frame, it'll just sleep longer the next to make up for it. :)
|
||||
}
|
||||
|
||||
static __forceinline void VSyncStart(u32 sCycle)
|
||||
|
|
|
@ -460,6 +460,8 @@ void SysCoreThread::CpuExecute()
|
|||
|
||||
void SysCoreThread::ExecuteTaskInThread()
|
||||
{
|
||||
Threading::EnableHiresScheduler();
|
||||
|
||||
tls_coreThread = this;
|
||||
|
||||
m_sem_event.WaitRaw();
|
||||
|
@ -486,6 +488,8 @@ void SysCoreThread::OnResumeInThread( bool isSuspended )
|
|||
// Invoked by the pthread_exit or pthread_cancel
|
||||
void SysCoreThread::OnCleanupInThread()
|
||||
{
|
||||
Threading::DisableHiresScheduler();
|
||||
|
||||
if( g_plugins != NULL )
|
||||
g_plugins->Close();
|
||||
|
||||
|
|
|
@ -273,15 +273,22 @@ bool Pcsx2App::PrepForExit( bool canCancel )
|
|||
throw Exception::CancelEvent( "Savestate in progress, cannot close program (close event delayed)" );
|
||||
}
|
||||
|
||||
/*
|
||||
if( canCancel )
|
||||
{
|
||||
// TODO: Confirm with the user?
|
||||
// Problem: Suspend is often slow because it needs to wait until the current EE frame
|
||||
// has finished processing (if the GS or logging has incurred severe overhead this makes
|
||||
// closing PCSX2 difficult). A non-blocking suspend with modal dialog might suffice
|
||||
// however. --air
|
||||
|
||||
bool resume = CoreThread.Suspend();
|
||||
if( /* TODO: Confirm with the user? */ false )
|
||||
if( false )
|
||||
{
|
||||
if(resume) CoreThread.Resume();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
m_evtsrc_AppStatus.Dispatch( AppStatus_Exiting );
|
||||
CleanupMess();
|
||||
|
|
Loading…
Reference in New Issue