summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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) {
System::ResultStatus System::RunLoop(bool tight_loop) {
status = ResultStatus::Success;
+ // Update thread_to_cpu in case Core 0 is run from a different host thread
+ thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0];
+
if (GDBStub::IsServerEnabled()) {
GDBStub::HandlePacket();
@@ -186,17 +189,21 @@ void System::Shutdown() {
gpu_core.reset();
// Close all CPU/threading state
- thread_to_cpu.clear();
- for (auto& cpu_core : cpu_cores) {
- cpu_core.reset();
- }
+ cpu_barrier->NotifyEnd();
for (auto& thread : cpu_core_threads) {
thread->join();
thread.reset();
}
+ thread_to_cpu.clear();
+ for (auto& cpu_core : cpu_cores) {
+ cpu_core.reset();
+ }
+ cpu_barrier.reset();
+ // Close core timing
CoreTiming::Shutdown();
+ // Close app loader
app_loader.reset();
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:
* @returns True if the emulated system is powered on, otherwise false.
*/
bool IsPoweredOn() const {
- return cpu_cores[0] != nullptr;
+ return cpu_barrier && cpu_barrier->IsAlive();
}
/**
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 @@
namespace Core {
+void CpuBarrier::NotifyEnd() {
+ std::unique_lock<std::mutex> lock(mutex);
+ end = true;
+ condition.notify_all();
+}
+
+bool CpuBarrier::Rendezvous() {
+ if (end) {
+ return false;
+ } else {
+ std::unique_lock<std::mutex> lock(mutex);
+
+ --cores_waiting;
+ if (!cores_waiting) {
+ cores_waiting = NUM_CPU_CORES;
+ condition.notify_all();
+ return true;
+ }
+
+ condition.wait(lock);
+ return true;
+ }
+}
+
Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
: cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} {
@@ -38,7 +62,10 @@ Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
void Cpu::RunLoop(bool tight_loop) {
// Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
- cpu_barrier->Rendezvous();
+ if (!cpu_barrier->Rendezvous()) {
+ // If rendezvous failed, session has been killed
+ return;
+ }
// If we don't have a currently active thread then don't execute instructions,
// 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 @@
#pragma once
+#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
@@ -22,23 +23,19 @@ constexpr unsigned NUM_CPU_CORES{4};
class CpuBarrier {
public:
- void Rendezvous() {
- std::unique_lock<std::mutex> lock(mutex);
+ bool IsAlive() const {
+ return !end;
+ }
- --cores_waiting;
- if (!cores_waiting) {
- cores_waiting = NUM_CPU_CORES;
- condition.notify_all();
- return;
- }
+ void NotifyEnd();
- condition.wait(lock);
- }
+ bool Rendezvous();
private:
unsigned cores_waiting{NUM_CPU_CORES};
std::mutex mutex;
std::condition_variable condition;
+ std::atomic<bool> end{};
};
class Cpu {