void SysExecEvent_CoreThreadPause::InvokeEvent() { #ifdef PCSX2_DEVBUILD bool CorePluginsAreOpen = GetCorePlugins().AreOpen(); ScopedCoreThreadPause paused_core; _post_and_wait(paused_core); // All plugins should be initialized and opened upon resuming from // a paused state. If the thread that puased us changed plugin status, it should // have used Close instead. if( CorePluginsAreOpen ) { CorePluginsAreOpen = GetCorePlugins().AreOpen(); pxAssertDev( CorePluginsAreOpen, "Invalid plugin close/shutdown detected during paused CoreThread; please Stop/Suspend the core instead." ); } paused_core.AllowResume(); #else ScopedCoreThreadPause paused_core; _post_and_wait(paused_core); paused_core.AllowResume(); #endif }
// Invoked by the pthread_exit or pthread_cancel. void SysCoreThread::OnCleanupInThread() { m_ExecMode = ExecMode_Closing; m_hasActiveMachine = false; m_resetVirtualMachine = true; GetCorePlugins().Close(); GetCorePlugins().Shutdown(); _mm_setcsr( m_mxcsr_saved.bitmask ); Threading::DisableHiresScheduler(); _parent::OnCleanupInThread(); m_ExecMode = ExecMode_NoThreadYet; }
// Invoked by the pthread_exit or pthread_cancel. void SysCoreThread::OnCleanupInThread() { m_ExecMode = ExecMode_Closing; m_hasActiveMachine = false; m_resetVirtualMachine = true; // FIXME: temporary workaround for deadlock on exit, which actually should be a crash vu1Thread.WaitVU(); GetCorePlugins().Close(); GetCorePlugins().Shutdown(); _mm_setcsr( m_mxcsr_saved.bitmask ); Threading::DisableHiresScheduler(); _parent::OnCleanupInThread(); m_ExecMode = ExecMode_NoThreadYet; }
void AppCoreThread::Resume() { if( !GetSysExecutorThread().IsSelf() ) { GetSysExecutorThread().PostEvent( SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::Resume) ); return; } GetCorePlugins().Init(); _parent::Resume(); }
void AppCoreThread::OnResumeInThread( bool isSuspended ) { if( m_resetCdvd ) { GetCorePlugins().Close( PluginId_CDVD ); CDVDsys_ChangeSource( g_Conf->CdvdSource ); cdvdCtrlTrayOpen(); m_resetCdvd = false; } _parent::OnResumeInThread( isSuspended ); PostCoreStatus( CoreThread_Resumed ); }
// Resumes the core execution state, or does nothing is the core is already running. If // settings were changed, resets will be performed as needed and emulation state resumed from // memory savestates. // // Note that this is considered a non-blocking action. Most times the state is safely resumed // on return, but in the case of re-entrant or nested message handling the function may return // before the thread has resumed. If you need explicit behavior tied to the completion of the // Resume, you'll need to bind callbacks to either OnResumeReady or OnResumeInThread. // // Exceptions: // PluginInitError - thrown if a plugin fails init (init is performed on the current thread // on the first time the thread is resumed from it's initial idle state) // ThreadCreationError - Insufficient system resources to create thread. // void SysThreadBase::Resume() { if( IsSelf() ) return; if( m_ExecMode == ExecMode_Opened ) return; ScopedLock locker( m_ExecModeMutex ); // Implementation Note: // The entire state coming out of a Wait is indeterminate because of user input // and pending messages being handled. So after each call we do some seemingly redundant // sanity checks against m_ExecMode/m_Running status, and if something doesn't feel // right, we should abort; the user may have canceled the action before it even finished. switch( m_ExecMode ) { case ExecMode_Opened: return; case ExecMode_NoThreadYet: { Start(); if( !m_running || (m_ExecMode == ExecMode_NoThreadYet) ) throw Exception::ThreadCreationError(this); if( m_ExecMode == ExecMode_Opened ) return; } // fall through... case ExecMode_Closing: case ExecMode_Pausing: // we need to make sure and wait for the emuThread to enter a fully suspended // state before continuing... m_RunningLock.Wait(); if( !m_running ) return; if( (m_ExecMode != ExecMode_Closed) && (m_ExecMode != ExecMode_Paused) ) return; if( !GetCorePlugins().AreLoaded() ) return; break; case ExecMode_Paused: case ExecMode_Closed: break; } pxAssertDev( (m_ExecMode == ExecMode_Closed) || (m_ExecMode == ExecMode_Paused), "SysThreadBase is not in a closed/paused state? wtf!" ); OnResumeReady(); m_ExecMode = ExecMode_Opened; m_sem_Resume.Post(); }
void AppCoreThread::ChangeCdvdSource() { if( !GetSysExecutorThread().IsSelf() ) { GetSysExecutorThread().PostEvent( new SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::ChangeCdvdSource) ); return; } CDVD_SourceType cdvdsrc( g_Conf->CdvdSource ); if( cdvdsrc == CDVDsys_GetSourceType() ) return; // Fast change of the CDVD source only -- a Pause will suffice. ScopedCoreThreadPause paused_core; GetCorePlugins().Close( PluginId_CDVD ); CDVDsys_ChangeSource( cdvdsrc ); paused_core.AllowResume(); // TODO: Add a listener for CDVDsource changes? Or should we bother? }
void SysCoreThread::Start() { if( !GetCorePlugins().AreLoaded() ) return; GetCorePlugins().Init(); _parent::Start(); }
void SysCoreThread::OnResumeInThread( bool isSuspended ) { GetCorePlugins().Open(); }
void SysCoreThread::OnSuspendInThread() { GetCorePlugins().Close(); }