summaryrefslogtreecommitdiff
path: root/src/core/cpu_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/cpu_manager.cpp')
-rw-r--r--src/core/cpu_manager.cpp127
1 files changed, 30 insertions, 97 deletions
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index b4718fbbe..271e1ba04 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -16,31 +16,28 @@
16 16
17namespace Core { 17namespace Core {
18 18
19CpuManager::CpuManager(System& system_) 19CpuManager::CpuManager(System& system_) : system{system_} {}
20 : pause_barrier{std::make_unique<Common::Barrier>(1)}, system{system_} {}
21CpuManager::~CpuManager() = default; 20CpuManager::~CpuManager() = default;
22 21
23void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, 22void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
24 std::size_t core) { 23 std::size_t core) {
25 cpu_manager.RunThread(stop_token, core); 24 cpu_manager.RunThread(core);
26} 25}
27 26
28void CpuManager::Initialize() { 27void CpuManager::Initialize() {
29 running_mode = true; 28 num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
30 if (is_multicore) { 29
31 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 30 for (std::size_t core = 0; core < num_cores; core++) {
32 core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); 31 core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
33 }
34 pause_barrier = std::make_unique<Common::Barrier>(Core::Hardware::NUM_CPU_CORES + 1);
35 } else {
36 core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0);
37 pause_barrier = std::make_unique<Common::Barrier>(2);
38 } 32 }
39} 33}
40 34
41void CpuManager::Shutdown() { 35void CpuManager::Shutdown() {
42 running_mode = false; 36 for (std::size_t core = 0; core < num_cores; core++) {
43 Pause(false); 37 if (core_data[core].host_thread.joinable()) {
38 core_data[core].host_thread.join();
39 }
40 }
44} 41}
45 42
46std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() { 43std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() {
@@ -51,8 +48,8 @@ std::function<void(void*)> CpuManager::GetIdleThreadStartFunc() {
51 return IdleThreadFunction; 48 return IdleThreadFunction;
52} 49}
53 50
54std::function<void(void*)> CpuManager::GetSuspendThreadStartFunc() { 51std::function<void(void*)> CpuManager::GetShutdownThreadStartFunc() {
55 return SuspendThreadFunction; 52 return ShutdownThreadFunction;
56} 53}
57 54
58void CpuManager::GuestThreadFunction(void* cpu_manager_) { 55void CpuManager::GuestThreadFunction(void* cpu_manager_) {
@@ -82,17 +79,12 @@ void CpuManager::IdleThreadFunction(void* cpu_manager_) {
82 } 79 }
83} 80}
84 81
85void CpuManager::SuspendThreadFunction(void* cpu_manager_) { 82void CpuManager::ShutdownThreadFunction(void* cpu_manager) {
86 CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_); 83 static_cast<CpuManager*>(cpu_manager)->ShutdownThread();
87 if (cpu_manager->is_multicore) {
88 cpu_manager->MultiCoreRunSuspendThread();
89 } else {
90 cpu_manager->SingleCoreRunSuspendThread();
91 }
92} 84}
93 85
94void* CpuManager::GetStartFuncParamater() { 86void* CpuManager::GetStartFuncParameter() {
95 return static_cast<void*>(this); 87 return this;
96} 88}
97 89
98/////////////////////////////////////////////////////////////////////////////// 90///////////////////////////////////////////////////////////////////////////////
@@ -134,21 +126,6 @@ void CpuManager::MultiCoreRunIdleThread() {
134 } 126 }
135} 127}
136 128
137void CpuManager::MultiCoreRunSuspendThread() {
138 auto& kernel = system.Kernel();
139 kernel.CurrentScheduler()->OnThreadStart();
140 while (true) {
141 auto core = kernel.CurrentPhysicalCoreIndex();
142 auto& scheduler = *kernel.CurrentScheduler();
143 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
144 current_thread->DisableDispatch();
145
146 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
147 ASSERT(core == kernel.CurrentPhysicalCoreIndex());
148 scheduler.RescheduleCurrentCore();
149 }
150}
151
152/////////////////////////////////////////////////////////////////////////////// 129///////////////////////////////////////////////////////////////////////////////
153/// SingleCore /// 130/// SingleCore ///
154/////////////////////////////////////////////////////////////////////////////// 131///////////////////////////////////////////////////////////////////////////////
@@ -194,21 +171,6 @@ void CpuManager::SingleCoreRunIdleThread() {
194 } 171 }
195} 172}
196 173
197void CpuManager::SingleCoreRunSuspendThread() {
198 auto& kernel = system.Kernel();
199 kernel.CurrentScheduler()->OnThreadStart();
200 while (true) {
201 auto core = kernel.GetCurrentHostThreadID();
202 auto& scheduler = *kernel.CurrentScheduler();
203 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
204 current_thread->DisableDispatch();
205
206 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[0].host_context);
207 ASSERT(core == kernel.GetCurrentHostThreadID());
208 scheduler.RescheduleCurrentCore();
209 }
210}
211
212void CpuManager::PreemptSingleCore(bool from_running_enviroment) { 174void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
213 { 175 {
214 auto& kernel = system.Kernel(); 176 auto& kernel = system.Kernel();
@@ -241,24 +203,16 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
241 } 203 }
242} 204}
243 205
244void CpuManager::Pause(bool paused) { 206void CpuManager::ShutdownThread() {
245 std::scoped_lock lk{pause_lock}; 207 auto& kernel = system.Kernel();
246 208 auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0;
247 if (pause_state == paused) { 209 auto* current_thread = kernel.GetCurrentEmuThread();
248 return;
249 }
250
251 // Set the new state
252 pause_state.store(paused);
253
254 // Wake up any waiting threads
255 pause_state.notify_all();
256 210
257 // Wait for all threads to successfully change state before returning 211 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
258 pause_barrier->Sync(); 212 UNREACHABLE();
259} 213}
260 214
261void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { 215void CpuManager::RunThread(std::size_t core) {
262 /// Initialization 216 /// Initialization
263 system.RegisterCoreThread(core); 217 system.RegisterCoreThread(core);
264 std::string name; 218 std::string name;
@@ -272,8 +226,6 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
272 Common::SetCurrentThreadPriority(Common::ThreadPriority::High); 226 Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
273 auto& data = core_data[core]; 227 auto& data = core_data[core];
274 data.host_context = Common::Fiber::ThreadToFiber(); 228 data.host_context = Common::Fiber::ThreadToFiber();
275 const bool sc_sync = !is_async_gpu && !is_multicore;
276 bool sc_sync_first_use = sc_sync;
277 229
278 // Cleanup 230 // Cleanup
279 SCOPE_EXIT({ 231 SCOPE_EXIT({
@@ -281,32 +233,13 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
281 MicroProfileOnThreadExit(); 233 MicroProfileOnThreadExit();
282 }); 234 });
283 235
284 /// Running 236 // Running
285 while (running_mode) { 237 if (!is_async_gpu && !is_multicore) {
286 if (pause_state.load(std::memory_order_relaxed)) { 238 system.GPU().ObtainContext();
287 // Wait for caller to acknowledge pausing
288 pause_barrier->Sync();
289
290 // Wait until unpaused
291 pause_state.wait(true, std::memory_order_relaxed);
292
293 // Wait for caller to acknowledge unpausing
294 pause_barrier->Sync();
295 }
296
297 if (sc_sync_first_use) {
298 system.GPU().ObtainContext();
299 sc_sync_first_use = false;
300 }
301
302 // Emulation was stopped
303 if (stop_token.stop_requested()) {
304 return;
305 }
306
307 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
308 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
309 } 239 }
240
241 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
242 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
310} 243}
311 244
312} // namespace Core 245} // namespace Core