From 9031502974fa25c9c8521ad96ecc8126fcac51c6 Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Fri, 29 Mar 2019 17:11:25 -0400
Subject: [PATCH] Correct Supervisor Calls to work with the new scheduler,

---
 src/core/hle/kernel/svc.cpp | 67 +++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 26 deletions(-)

diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 1fd1a732a9..ee1e9f006a 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -534,6 +534,8 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
     }
 
     thread->CancelWait();
+    if (thread->GetProcessorID() >= 0)
+        Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
     return RESULT_SUCCESS;
 }
 
@@ -1066,6 +1068,9 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act
     }
 
     thread->SetActivity(static_cast<ThreadActivity>(activity));
+
+    if (thread->GetProcessorID() >= 0)
+        Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
     return RESULT_SUCCESS;
 }
 
@@ -1147,7 +1152,8 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri
 
     thread->SetPriority(priority);
 
-    system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
+    if (thread->GetProcessorID() >= 0)
+        Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
     return RESULT_SUCCESS;
 }
 
@@ -1503,7 +1509,8 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
     thread->SetName(
         fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle));
 
-    system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
+    if (thread->GetProcessorID() >= 0)
+        Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
 
     return RESULT_SUCCESS;
 }
@@ -1525,7 +1532,10 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
     thread->ResumeFromWait();
 
     if (thread->GetStatus() == ThreadStatus::Ready) {
-        system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
+        if (thread->GetProcessorID() >= 0)
+            Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
+        else
+            Core::System::GetInstance().GlobalScheduler().SetReselectionPending();
     }
 
     return RESULT_SUCCESS;
@@ -1537,7 +1547,7 @@ static void ExitThread(Core::System& system) {
 
     auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
     current_thread->Stop();
-    system.CurrentScheduler().RemoveThread(current_thread);
+    system.GlobalScheduler().RemoveThread(current_thread);
     system.PrepareReschedule();
 }
 
@@ -1557,13 +1567,13 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
     if (nanoseconds <= 0) {
         switch (static_cast<SleepType>(nanoseconds)) {
         case SleepType::YieldWithoutLoadBalancing:
-            scheduler.YieldWithoutLoadBalancing(current_thread);
+            current_thread->YieldType0();
             break;
         case SleepType::YieldWithLoadBalancing:
-            scheduler.YieldWithLoadBalancing(current_thread);
+            current_thread->YieldType1();
             break;
         case SleepType::YieldAndWaitForLoadBalancing:
-            scheduler.YieldAndWaitForLoadBalancing(current_thread);
+            current_thread->YieldType2();
             break;
         default:
             UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
@@ -1632,24 +1642,16 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
     LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
               condition_variable_addr, target);
 
-    const auto RetrieveWaitingThreads = [&system](std::size_t core_index,
-                                                  std::vector<SharedPtr<Thread>>& waiting_threads,
-                                                  VAddr condvar_addr) {
-        const auto& scheduler = system.Scheduler(core_index);
-        const auto& thread_list = scheduler.GetThreadList();
-
-        for (const auto& thread : thread_list) {
-            if (thread->GetCondVarWaitAddress() == condvar_addr)
-                waiting_threads.push_back(thread);
-        }
-    };
-
     // Retrieve a list of all threads that are waiting for this condition variable.
     std::vector<SharedPtr<Thread>> waiting_threads;
-    RetrieveWaitingThreads(0, waiting_threads, condition_variable_addr);
-    RetrieveWaitingThreads(1, waiting_threads, condition_variable_addr);
-    RetrieveWaitingThreads(2, waiting_threads, condition_variable_addr);
-    RetrieveWaitingThreads(3, waiting_threads, condition_variable_addr);
+    const auto& scheduler = Core::System::GetInstance().GlobalScheduler();
+    const auto& thread_list = scheduler.GetThreadList();
+
+    for (const auto& thread : thread_list) {
+        if (thread->GetCondVarWaitAddress() == condition_variable_addr)
+            waiting_threads.push_back(thread);
+    }
+
     // Sort them by priority, such that the highest priority ones come first.
     std::sort(waiting_threads.begin(), waiting_threads.end(),
               [](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
@@ -1704,7 +1706,8 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
             thread->SetLockOwner(nullptr);
             thread->SetMutexWaitAddress(0);
             thread->SetWaitHandle(0);
-            system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
+            if (thread->GetProcessorID() >= 0)
+                Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
         } else {
             // Atomically signal that the mutex now has a waiting thread.
             do {
@@ -1728,6 +1731,8 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
             thread->SetStatus(ThreadStatus::WaitMutex);
 
             owner->AddMutexWaiter(thread);
+            if (thread->GetProcessorID() >= 0)
+                Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
         }
     }
 
@@ -1753,8 +1758,14 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type,
     }
 
     const auto arbitration_type = static_cast<AddressArbiter::ArbitrationType>(type);
-    auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter();
-    return address_arbiter.WaitForAddress(address, arbitration_type, value, timeout);
+    auto& address_arbiter =
+        system.Kernel().CurrentProcess()->GetAddressArbiter();
+    ResultCode result = address_arbiter.WaitForAddress(address, arbitration_type, value, timeout);
+    if (result == RESULT_SUCCESS)
+        Core::System::GetInstance()
+            .CpuCore(GetCurrentThread()->GetProcessorID())
+            .PrepareReschedule();
+    return result;
 }
 
 // Signals to an address (via Address Arbiter)
@@ -2040,7 +2051,10 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
         return ERR_INVALID_HANDLE;
     }
 
+    Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
     thread->ChangeCore(core, affinity_mask);
+    if (thread->GetProcessorID() >= 0)
+        Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
     return RESULT_SUCCESS;
 }
 
@@ -2151,6 +2165,7 @@ static ResultCode SignalEvent(Core::System& system, Handle handle) {
     }
 
     writable_event->Signal();
+    Core::System::GetInstance().PrepareReschedule();
     return RESULT_SUCCESS;
 }