summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-05-03 00:16:12 -0400
committerGravatar bunnei2018-05-10 19:34:47 -0400
commitcba69fdcd439c5f225bbddf1dad70e6326edd0dc (patch)
treeb608addf14d16c634cbe99a04e7931adfb2dbf31 /src
parentcore: Implement multicore support. (diff)
downloadyuzu-cba69fdcd439c5f225bbddf1dad70e6326edd0dc.tar.gz
yuzu-cba69fdcd439c5f225bbddf1dad70e6326edd0dc.tar.xz
yuzu-cba69fdcd439c5f225bbddf1dad70e6326edd0dc.zip
core: Support session close with multicore.
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp15
-rw-r--r--src/core/core.h2
-rw-r--r--src/core/core_cpu.cpp29
-rw-r--r--src/core/core_cpu.h17
4 files changed, 47 insertions, 16 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 066423f23..1e6be34c8 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -37,6 +37,9 @@ static void RunCpuCore(std::shared_ptr<Cpu> cpu_state) {
37System::ResultStatus System::RunLoop(bool tight_loop) { 37System::ResultStatus System::RunLoop(bool tight_loop) {
38 status = ResultStatus::Success; 38 status = ResultStatus::Success;
39 39
40 // Update thread_to_cpu in case Core 0 is run from a different host thread
41 thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0];
42
40 if (GDBStub::IsServerEnabled()) { 43 if (GDBStub::IsServerEnabled()) {
41 GDBStub::HandlePacket(); 44 GDBStub::HandlePacket();
42 45
@@ -186,17 +189,21 @@ void System::Shutdown() {
186 gpu_core.reset(); 189 gpu_core.reset();
187 190
188 // Close all CPU/threading state 191 // Close all CPU/threading state
189 thread_to_cpu.clear(); 192 cpu_barrier->NotifyEnd();
190 for (auto& cpu_core : cpu_cores) {
191 cpu_core.reset();
192 }
193 for (auto& thread : cpu_core_threads) { 193 for (auto& thread : cpu_core_threads) {
194 thread->join(); 194 thread->join();
195 thread.reset(); 195 thread.reset();
196 } 196 }
197 thread_to_cpu.clear();
198 for (auto& cpu_core : cpu_cores) {
199 cpu_core.reset();
200 }
201 cpu_barrier.reset();
197 202
203 // Close core timing
198 CoreTiming::Shutdown(); 204 CoreTiming::Shutdown();
199 205
206 // Close app loader
200 app_loader.reset(); 207 app_loader.reset();
201 208
202 NGLOG_DEBUG(Core, "Shutdown OK"); 209 NGLOG_DEBUG(Core, "Shutdown OK");
diff --git a/src/core/core.h b/src/core/core.h
index 3e0a7e6a7..561e7b48f 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -92,7 +92,7 @@ public:
92 * @returns True if the emulated system is powered on, otherwise false. 92 * @returns True if the emulated system is powered on, otherwise false.
93 */ 93 */
94 bool IsPoweredOn() const { 94 bool IsPoweredOn() const {
95 return cpu_cores[0] != nullptr; 95 return cpu_barrier && cpu_barrier->IsAlive();
96 } 96 }
97 97
98 /** 98 /**
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index a556f12e9..bd9869d28 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -19,6 +19,30 @@
19 19
20namespace Core { 20namespace Core {
21 21
22void CpuBarrier::NotifyEnd() {
23 std::unique_lock<std::mutex> lock(mutex);
24 end = true;
25 condition.notify_all();
26}
27
28bool CpuBarrier::Rendezvous() {
29 if (end) {
30 return false;
31 } else {
32 std::unique_lock<std::mutex> lock(mutex);
33
34 --cores_waiting;
35 if (!cores_waiting) {
36 cores_waiting = NUM_CPU_CORES;
37 condition.notify_all();
38 return true;
39 }
40
41 condition.wait(lock);
42 return true;
43 }
44}
45
22Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index) 46Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
23 : cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} { 47 : cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} {
24 48
@@ -38,7 +62,10 @@ Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
38 62
39void Cpu::RunLoop(bool tight_loop) { 63void Cpu::RunLoop(bool tight_loop) {
40 // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step 64 // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
41 cpu_barrier->Rendezvous(); 65 if (!cpu_barrier->Rendezvous()) {
66 // If rendezvous failed, session has been killed
67 return;
68 }
42 69
43 // If we don't have a currently active thread then don't execute instructions, 70 // If we don't have a currently active thread then don't execute instructions,
44 // instead advance to the next event and try to yield to the next thread 71 // instead advance to the next event and try to yield to the next thread
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index 06784c4ab..243f0b5e7 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
7#include <condition_variable> 8#include <condition_variable>
8#include <memory> 9#include <memory>
9#include <mutex> 10#include <mutex>
@@ -22,23 +23,19 @@ constexpr unsigned NUM_CPU_CORES{4};
22 23
23class CpuBarrier { 24class CpuBarrier {
24public: 25public:
25 void Rendezvous() { 26 bool IsAlive() const {
26 std::unique_lock<std::mutex> lock(mutex); 27 return !end;
28 }
27 29
28 --cores_waiting; 30 void NotifyEnd();
29 if (!cores_waiting) {
30 cores_waiting = NUM_CPU_CORES;
31 condition.notify_all();
32 return;
33 }
34 31
35 condition.wait(lock); 32 bool Rendezvous();
36 }
37 33
38private: 34private:
39 unsigned cores_waiting{NUM_CPU_CORES}; 35 unsigned cores_waiting{NUM_CPU_CORES};
40 std::mutex mutex; 36 std::mutex mutex;
41 std::condition_variable condition; 37 std::condition_variable condition;
38 std::atomic<bool> end{};
42}; 39};
43 40
44class Cpu { 41class Cpu {