summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-03-19 13:09:32 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:52 -0400
commitf2ade343e2492c213ac93680a55e9bed712dac9a (patch)
tree30bce0eb24a0b2b38310f07fa37c7ba881fc8535 /src
parentGUI: Make multicore only work with Async and add GUI for multicore. (diff)
downloadyuzu-f2ade343e2492c213ac93680a55e9bed712dac9a.tar.gz
yuzu-f2ade343e2492c213ac93680a55e9bed712dac9a.tar.xz
yuzu-f2ade343e2492c213ac93680a55e9bed712dac9a.zip
SingleCore: Move Host Timing from a sepparate thread to main cpu thread.
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/core_timing.cpp20
-rw-r--r--src/core/core_timing.h7
-rw-r--r--src/core/cpu_manager.cpp17
-rw-r--r--src/core/cpu_manager.h1
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/thread.h9
7 files changed, 48 insertions, 10 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 0f0eb885a..2ca9c0be5 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -158,6 +158,8 @@ struct System::Impl {
158 kernel.SetMulticore(is_multicore); 158 kernel.SetMulticore(is_multicore);
159 cpu_manager.SetMulticore(is_multicore); 159 cpu_manager.SetMulticore(is_multicore);
160 cpu_manager.SetAsyncGpu(is_async_gpu); 160 cpu_manager.SetAsyncGpu(is_async_gpu);
161 core_timing.SetMulticore(is_multicore);
162 cpu_manager.SetRenderWindow(emu_window);
161 163
162 core_timing.Initialize([&system]() { system.RegisterHostThread(); }); 164 core_timing.Initialize([&system]() { system.RegisterHostThread(); });
163 kernel.Initialize(); 165 kernel.Initialize();
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 3438f79ce..189d4aa34 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -55,7 +55,9 @@ void CoreTiming::Initialize(std::function<void(void)>&& on_thread_init_) {
55 event_fifo_id = 0; 55 event_fifo_id = 0;
56 const auto empty_timed_callback = [](u64, s64) {}; 56 const auto empty_timed_callback = [](u64, s64) {};
57 ev_lost = CreateEvent("_lost_event", empty_timed_callback); 57 ev_lost = CreateEvent("_lost_event", empty_timed_callback);
58 timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); 58 if (is_multicore) {
59 timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this));
60 }
59} 61}
60 62
61void CoreTiming::Shutdown() { 63void CoreTiming::Shutdown() {
@@ -63,7 +65,9 @@ void CoreTiming::Shutdown() {
63 shutting_down = true; 65 shutting_down = true;
64 pause_event.Set(); 66 pause_event.Set();
65 event.Set(); 67 event.Set();
66 timer_thread->join(); 68 if (timer_thread) {
69 timer_thread->join();
70 }
67 ClearPendingEvents(); 71 ClearPendingEvents();
68 timer_thread.reset(); 72 timer_thread.reset();
69 has_started = false; 73 has_started = false;
@@ -78,12 +82,14 @@ void CoreTiming::SyncPause(bool is_paused) {
78 return; 82 return;
79 } 83 }
80 Pause(is_paused); 84 Pause(is_paused);
81 if (!is_paused) { 85 if (timer_thread) {
82 pause_event.Set(); 86 if (!is_paused) {
87 pause_event.Set();
88 }
89 event.Set();
90 while (paused_set != is_paused)
91 ;
83 } 92 }
84 event.Set();
85 while (paused_set != is_paused)
86 ;
87} 93}
88 94
89bool CoreTiming::IsRunning() const { 95bool CoreTiming::IsRunning() const {
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 032eb08aa..03f9a5c76 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -67,6 +67,11 @@ public:
67 /// Tears down all timing related functionality. 67 /// Tears down all timing related functionality.
68 void Shutdown(); 68 void Shutdown();
69 69
70 /// Sets if emulation is multicore or single core, must be set before Initialize
71 void SetMulticore(bool is_multicore) {
72 this->is_multicore = is_multicore;
73 }
74
70 /// Pauses/Unpauses the execution of the timer thread. 75 /// Pauses/Unpauses the execution of the timer thread.
71 void Pause(bool is_paused); 76 void Pause(bool is_paused);
72 77
@@ -147,6 +152,8 @@ private:
147 std::atomic<bool> has_started{}; 152 std::atomic<bool> has_started{};
148 std::function<void(void)> on_thread_init{}; 153 std::function<void(void)> on_thread_init{};
149 154
155 bool is_multicore{};
156
150 std::array<std::atomic<u64>, Core::Hardware::NUM_CPU_CORES> ticks_count{}; 157 std::array<std::atomic<u64>, Core::Hardware::NUM_CPU_CORES> ticks_count{};
151}; 158};
152 159
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index d7bd162bc..2aea95a25 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -242,8 +242,11 @@ void CpuManager::SingleCoreRunGuestLoop() {
242 break; 242 break;
243 } 243 }
244 } 244 }
245 physical_core.ClearExclusive();
246 system.ExitDynarmicProfile(); 245 system.ExitDynarmicProfile();
246 thread->SetPhantomMode(true);
247 system.CoreTiming().Advance();
248 thread->SetPhantomMode(false);
249 physical_core.ClearExclusive();
247 PreemptSingleCore(); 250 PreemptSingleCore();
248 auto& scheduler = kernel.Scheduler(current_core); 251 auto& scheduler = kernel.Scheduler(current_core);
249 scheduler.TryDoContextSwitch(); 252 scheduler.TryDoContextSwitch();
@@ -255,6 +258,7 @@ void CpuManager::SingleCoreRunIdleThread() {
255 while (true) { 258 while (true) {
256 auto& physical_core = kernel.CurrentPhysicalCore(); 259 auto& physical_core = kernel.CurrentPhysicalCore();
257 PreemptSingleCore(); 260 PreemptSingleCore();
261 idle_count++;
258 auto& scheduler = physical_core.Scheduler(); 262 auto& scheduler = physical_core.Scheduler();
259 scheduler.TryDoContextSwitch(); 263 scheduler.TryDoContextSwitch();
260 } 264 }
@@ -280,15 +284,24 @@ void CpuManager::SingleCoreRunSuspendThread() {
280void CpuManager::PreemptSingleCore() { 284void CpuManager::PreemptSingleCore() {
281 preemption_count = 0; 285 preemption_count = 0;
282 std::size_t old_core = current_core; 286 std::size_t old_core = current_core;
283 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES);
284 auto& scheduler = system.Kernel().Scheduler(old_core); 287 auto& scheduler = system.Kernel().Scheduler(old_core);
285 Kernel::Thread* current_thread = scheduler.GetCurrentThread(); 288 Kernel::Thread* current_thread = scheduler.GetCurrentThread();
289 if (idle_count >= 4) {
290 current_thread->SetPhantomMode(true);
291 system.CoreTiming().Advance();
292 current_thread->SetPhantomMode(false);
293 }
294 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES);
286 scheduler.Unload(); 295 scheduler.Unload();
287 auto& next_scheduler = system.Kernel().Scheduler(current_core); 296 auto& next_scheduler = system.Kernel().Scheduler(current_core);
288 Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); 297 Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext());
289 /// May have changed scheduler 298 /// May have changed scheduler
290 auto& current_scheduler = system.Kernel().Scheduler(current_core); 299 auto& current_scheduler = system.Kernel().Scheduler(current_core);
291 current_scheduler.Reload(); 300 current_scheduler.Reload();
301 auto* currrent_thread2 = current_scheduler.GetCurrentThread();
302 if (!currrent_thread2->IsIdleThread()) {
303 idle_count = 0;
304 }
292} 305}
293 306
294void CpuManager::SingleCorePause(bool paused) { 307void CpuManager::SingleCorePause(bool paused) {
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h
index 37cef2b12..e6b8612f0 100644
--- a/src/core/cpu_manager.h
+++ b/src/core/cpu_manager.h
@@ -104,6 +104,7 @@ private:
104 bool is_multicore{}; 104 bool is_multicore{};
105 std::atomic<std::size_t> current_core{}; 105 std::atomic<std::size_t> current_core{};
106 std::size_t preemption_count{}; 106 std::size_t preemption_count{};
107 std::size_t idle_count{};
107 static constexpr std::size_t max_cycle_runs = 5; 108 static constexpr std::size_t max_cycle_runs = 5;
108 Core::Frontend::EmuWindow* render_window; 109 Core::Frontend::EmuWindow* render_window;
109 110
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index d2f5f9bf2..a19cd7a1f 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -303,7 +303,7 @@ struct KernelCore::Impl {
303 } 303 }
304 const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); 304 const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler();
305 const Kernel::Thread* current = sched.GetCurrentThread(); 305 const Kernel::Thread* current = sched.GetCurrentThread();
306 if (current != nullptr) { 306 if (current != nullptr && !current->IsPhantomMode()) {
307 result.guest_handle = current->GetGlobalHandle(); 307 result.guest_handle = current->GetGlobalHandle();
308 } else { 308 } else {
309 result.guest_handle = InvalidHandle; 309 result.guest_handle = InvalidHandle;
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index f42d7bd13..f998890c4 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -597,6 +597,14 @@ public:
597 is_continuous_on_svc = is_continuous; 597 is_continuous_on_svc = is_continuous;
598 } 598 }
599 599
600 bool IsPhantomMode() const {
601 return is_phantom_mode;
602 }
603
604 void SetPhantomMode(bool phantom) {
605 is_phantom_mode = phantom;
606 }
607
600private: 608private:
601 friend class GlobalScheduler; 609 friend class GlobalScheduler;
602 friend class Scheduler; 610 friend class Scheduler;
@@ -699,6 +707,7 @@ private:
699 bool is_continuous_on_svc = false; 707 bool is_continuous_on_svc = false;
700 708
701 bool will_be_terminated = false; 709 bool will_be_terminated = false;
710 bool is_phantom_mode = false;
702 711
703 bool was_running = false; 712 bool was_running = false;
704 713