diff options
| author | 2018-05-03 00:16:12 -0400 | |
|---|---|---|
| committer | 2018-05-10 19:34:47 -0400 | |
| commit | cba69fdcd439c5f225bbddf1dad70e6326edd0dc (patch) | |
| tree | b608addf14d16c634cbe99a04e7931adfb2dbf31 /src | |
| parent | core: Implement multicore support. (diff) | |
| download | yuzu-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.cpp | 15 | ||||
| -rw-r--r-- | src/core/core.h | 2 | ||||
| -rw-r--r-- | src/core/core_cpu.cpp | 29 | ||||
| -rw-r--r-- | src/core/core_cpu.h | 17 |
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) { | |||
| 37 | System::ResultStatus System::RunLoop(bool tight_loop) { | 37 | System::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 | ||
| 20 | namespace Core { | 20 | namespace Core { |
| 21 | 21 | ||
| 22 | void CpuBarrier::NotifyEnd() { | ||
| 23 | std::unique_lock<std::mutex> lock(mutex); | ||
| 24 | end = true; | ||
| 25 | condition.notify_all(); | ||
| 26 | } | ||
| 27 | |||
| 28 | bool 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 | |||
| 22 | Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index) | 46 | Cpu::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 | ||
| 39 | void Cpu::RunLoop(bool tight_loop) { | 63 | void 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 | ||
| 23 | class CpuBarrier { | 24 | class CpuBarrier { |
| 24 | public: | 25 | public: |
| 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 | ||
| 38 | private: | 34 | private: |
| 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 | ||
| 44 | class Cpu { | 41 | class Cpu { |