/[pcsx2_0.9.7]/trunk/pcsx2/System/SysCoreThread.cpp
ViewVC logotype

Contents of /trunk/pcsx2/System/SysCoreThread.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 1 month ago) by william
File size: 8029 byte(s)
re-commit (had local access denied errors when committing)
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17 #include "Common.h"
18
19 #include "IopBios.h"
20
21 #include "Counters.h"
22 #include "GS.h"
23 #include "Elfheader.h"
24 #include "Patch.h"
25 #include "SysThreads.h"
26
27 #include "Utilities/PageFaultSource.h"
28 #include "Utilities/TlsVariable.inl"
29
30 #ifdef __WXMSW__
31 # include <wx/msw/wrapwin.h>
32 #endif
33
34 #include <xmmintrin.h>
35
36 // --------------------------------------------------------------------------------------
37 // SysCoreThread *External Thread* Implementations
38 // (Called from outside the context of this thread)
39 // --------------------------------------------------------------------------------------
40
41 SysCoreThread::SysCoreThread()
42 {
43 m_name = L"EE Core";
44 m_resetRecompilers = true;
45 m_resetProfilers = true;
46 m_resetVsyncTimers = true;
47 m_resetVirtualMachine = true;
48
49 m_hasActiveMachine = false;
50 }
51
52 SysCoreThread::~SysCoreThread() throw()
53 {
54 SysCoreThread::Cancel();
55 }
56
57 void SysCoreThread::Cancel( bool isBlocking )
58 {
59 m_hasActiveMachine = false;
60 _parent::Cancel();
61 }
62
63 bool SysCoreThread::Cancel( const wxTimeSpan& span )
64 {
65 m_hasActiveMachine = false;
66 if( _parent::Cancel( span ) )
67 return true;
68
69 return false;
70 }
71
72 void SysCoreThread::OnStart()
73 {
74 _parent::OnStart();
75 }
76
77 void SysCoreThread::Start()
78 {
79 if( !GetCorePlugins().AreLoaded() ) return;
80 GetCorePlugins().Init();
81 _parent::Start();
82 }
83
84 // Resumes the core execution state, or does nothing is the core is already running. If
85 // settings were changed, resets will be performed as needed and emulation state resumed from
86 // memory savestates.
87 //
88 // Exceptions (can occur on first call only):
89 // PluginInitError - thrown if a plugin fails init (init is performed on the current thread
90 // on the first time the thread is resumed from it's initial idle state)
91 // ThreadCreationError - Insufficient system resources to create thread.
92 //
93 void SysCoreThread::OnResumeReady()
94 {
95 if( m_resetVirtualMachine )
96 m_hasActiveMachine = false;
97
98 if( !m_hasActiveMachine )
99 m_resetRecompilers = true;
100 }
101
102 // This function *will* reset the emulator in order to allow the specified elf file to
103 // take effect. This is because it really doesn't make sense to change the elf file outside
104 // the context of a reset/restart.
105 void SysCoreThread::SetElfOverride( const wxString& elf )
106 {
107 //pxAssertDev( !m_hasValidMachine, "Thread synchronization error while assigning ELF override." );
108 m_elf_override = elf;
109
110
111 Hle_SetElfPath(elf.ToUTF8());
112 }
113
114 // Performs a quicker reset that does not deallocate memory associated with PS2 virtual machines
115 // or cpu providers (recompilers).
116 void SysCoreThread::ResetQuick()
117 {
118 Suspend();
119
120 m_resetVirtualMachine = true;
121 m_hasActiveMachine = false;
122 }
123
124 void SysCoreThread::Reset()
125 {
126 ResetQuick();
127 GetVmMemory().DecommitAll();
128 SysClearExecutionCache();
129 }
130
131
132 // Applies a full suite of new settings, which will automatically facilitate the necessary
133 // resets of the core and components (including plugins, if needed). The scope of resetting
134 // is determined by comparing the current settings against the new settings, so that only
135 // real differences are applied.
136 void SysCoreThread::ApplySettings( const Pcsx2Config& src )
137 {
138 if( src == EmuConfig ) return;
139
140 if( !pxAssertDev( IsPaused(), "CoreThread is not paused; settings cannot be applied." ) ) return;
141
142 m_resetRecompilers = ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
143 m_resetProfilers = ( src.Profiler != EmuConfig.Profiler );
144 m_resetVsyncTimers = ( src.GS != EmuConfig.GS );
145
146 const_cast<Pcsx2Config&>(EmuConfig) = src;
147 }
148
149 void SysCoreThread::UploadStateCopy( const VmStateBuffer& copy )
150 {
151 if( !pxAssertDev( IsPaused(), "CoreThread is not paused; new VM state cannot be uploaded." ) ) return;
152
153 SysClearExecutionCache();
154 memLoadingState( copy ).FreezeAll();
155 m_resetVirtualMachine = false;
156 }
157
158 // --------------------------------------------------------------------------------------
159 // SysCoreThread *Worker* Implementations
160 // (Called from the context of this thread only)
161 // --------------------------------------------------------------------------------------
162 bool SysCoreThread::HasPendingStateChangeRequest() const
163 {
164 return !m_hasActiveMachine || GetMTGS().HasPendingException() || _parent::HasPendingStateChangeRequest();
165 }
166
167 void SysCoreThread::_reset_stuff_as_needed()
168 {
169 // Note that resetting recompilers along with the virtual machine is only really needed
170 // because of changes to the TLB. We don't actually support the TLB, however, so rec
171 // resets aren't in fact *needed* ... yet. But might as well, no harm. --air
172
173 GetVmMemory().CommitAll();
174
175 if( m_resetVirtualMachine || m_resetRecompilers || m_resetProfilers )
176 {
177 SysClearExecutionCache();
178 memBindConditionalHandlers();
179 SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR );
180
181 m_resetRecompilers = false;
182 m_resetProfilers = false;
183 }
184
185 if( m_resetVirtualMachine )
186 {
187 DoCpuReset();
188
189 m_resetVirtualMachine = false;
190 m_resetVsyncTimers = false;
191 }
192
193 if( m_resetVsyncTimers )
194 {
195 UpdateVSyncRate();
196 frameLimitReset();
197
198 m_resetVsyncTimers = false;
199 }
200 }
201
202 void SysCoreThread::DoCpuReset()
203 {
204 AffinityAssert_AllowFromSelf( pxDiagSpot );
205 cpuReset();
206 }
207
208 // This is called from the PS2 VM at the start of every vsync (either 59.94 or 50 hz by PS2
209 // clock scale, which does not correlate to the actual host machine vsync).
210 //
211 // Default tasks: Updates PADs and applies vsync patches. Derived classes can override this
212 // to change either PAD and/or Patching behaviors.
213 //
214 // [TODO]: Should probably also handle profiling and debugging updates, once those are
215 // re-implemented.
216 //
217 void SysCoreThread::VsyncInThread()
218 {
219 if (EmuConfig.EnablePatches) ApplyPatch();
220 if (EmuConfig.EnableCheats) ApplyCheat();
221 }
222
223 void SysCoreThread::GameStartingInThread()
224 {
225 GetMTGS().SendGameCRC(ElfCRC);
226
227 if (EmuConfig.EnablePatches) ApplyPatch(0);
228 if (EmuConfig.EnableCheats) ApplyCheat(0);
229 }
230
231 bool SysCoreThread::StateCheckInThread()
232 {
233 GetMTGS().RethrowException();
234 return _parent::StateCheckInThread() && (_reset_stuff_as_needed(), true);
235 }
236
237 // Runs CPU cycles indefinitely, until the user or another thread requests execution to break.
238 // Rationale: This very short function allows an override point and solves an SEH
239 // "exception-type boundary" problem (can't mix SEH and C++ exceptions in the same function).
240 void SysCoreThread::DoCpuExecute()
241 {
242 m_hasActiveMachine = true;
243 Cpu->Execute();
244 }
245
246 void SysCoreThread::ExecuteTaskInThread()
247 {
248 Threading::EnableHiresScheduler();
249 m_sem_event.WaitWithoutYield();
250
251 m_mxcsr_saved.bitmask = _mm_getcsr();
252
253 PCSX2_PAGEFAULT_PROTECT {
254 while(true) {
255 StateCheckInThread();
256 DoCpuExecute();
257 }
258 } PCSX2_PAGEFAULT_EXCEPT;
259 }
260
261 void SysCoreThread::OnSuspendInThread()
262 {
263 GetCorePlugins().Close();
264 }
265
266 void SysCoreThread::OnResumeInThread( bool isSuspended )
267 {
268 GetCorePlugins().Open();
269 }
270
271
272 // Invoked by the pthread_exit or pthread_cancel.
273 void SysCoreThread::OnCleanupInThread()
274 {
275 m_ExecMode = ExecMode_Closing;
276
277 m_hasActiveMachine = false;
278 m_resetVirtualMachine = true;
279
280 GetCorePlugins().Close();
281 GetCorePlugins().Shutdown();
282
283 _mm_setcsr( m_mxcsr_saved.bitmask );
284 Threading::DisableHiresScheduler();
285 _parent::OnCleanupInThread();
286
287 m_ExecMode = ExecMode_NoThreadYet;
288 }
289

  ViewVC Help
Powered by ViewVC 1.1.22