Просмотр исходного кода

hle: kernel: KLightConditionVariable: Migrate to updated KThreadQueue.

bunnei 4 лет назад
Родитель
Сommit
5dff28290f

+ 1 - 0
src/core/CMakeLists.txt

@@ -185,6 +185,7 @@ add_library(core STATIC
     hle/kernel/k_event.h
     hle/kernel/k_event.h
     hle/kernel/k_handle_table.cpp
     hle/kernel/k_handle_table.cpp
     hle/kernel/k_handle_table.h
     hle/kernel/k_handle_table.h
+    hle/kernel/k_light_condition_variable.cpp
     hle/kernel/k_light_condition_variable.h
     hle/kernel/k_light_condition_variable.h
     hle/kernel/k_light_lock.cpp
     hle/kernel/k_light_lock.cpp
     hle/kernel/k_light_lock.h
     hle/kernel/k_light_lock.h

+ 80 - 0
src/core/hle/kernel/k_light_condition_variable.cpp

@@ -0,0 +1,80 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/k_light_condition_variable.h"
+#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
+#include "core/hle/kernel/k_thread_queue.h"
+#include "core/hle/kernel/svc_results.h"
+
+namespace Kernel {
+
+namespace {
+
+class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue {
+private:
+    KThread::WaiterList* m_wait_list;
+    bool m_allow_terminating_thread;
+
+public:
+    ThreadQueueImplForKLightConditionVariable(KernelCore& kernel_, KThread::WaiterList* wl,
+                                              bool term)
+        : KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {}
+
+    virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result,
+                            bool cancel_timer_task) override {
+        // Only process waits if we're allowed to.
+        if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) {
+            return;
+        }
+
+        // Remove the thread from the waiting thread from the light condition variable.
+        m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread));
+
+        // Invoke the base cancel wait handler.
+        KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task);
+    }
+};
+
+} // namespace
+
+void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {
+    // Create thread queue.
+    KThread* owner = GetCurrentThreadPointer(kernel);
+
+    ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list),
+                                                         allow_terminating_thread);
+
+    // Sleep the thread.
+    {
+        KScopedSchedulerLockAndSleep lk(kernel, owner, timeout);
+
+        if (!allow_terminating_thread && owner->IsTerminationRequested()) {
+            lk.CancelSleep();
+            return;
+        }
+
+        lock->Unlock();
+
+        // Add the thread to the queue.
+        wait_list.push_back(*owner);
+
+        // Begin waiting.
+        owner->BeginWait(std::addressof(wait_queue));
+    }
+
+    // Re-acquire the lock.
+    lock->Lock();
+}
+
+void KLightConditionVariable::Broadcast() {
+    KScopedSchedulerLock lk(kernel);
+
+    // Signal all threads.
+    for (auto it = wait_list.begin(); it != wait_list.end(); it = wait_list.erase(it)) {
+        it->EndWait(ResultSuccess);
+    }
+}
+
+} // namespace Kernel

+ 6 - 54
src/core/hle/kernel/k_light_condition_variable.h

@@ -1,73 +1,25 @@
-// Copyright 2020 yuzu Emulator Project
+// Copyright 2021 yuzu Emulator Project
 // Licensed under GPLv2 or any later version
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 // Refer to the license.txt file included.
 
 
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
 #pragma once
 #pragma once
 
 
 #include "common/common_types.h"
 #include "common/common_types.h"
-#include "core/hle/kernel/k_scheduler.h"
-#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
-#include "core/hle/kernel/time_manager.h"
+#include "core/hle/kernel/k_thread.h"
 
 
 namespace Kernel {
 namespace Kernel {
+
 class KernelCore;
 class KernelCore;
+class KLightLock;
 
 
 class KLightConditionVariable {
 class KLightConditionVariable {
 public:
 public:
     explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {}
     explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {}
 
 
-    void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) {
-        WaitImpl(lock, timeout, allow_terminating_thread);
-    }
-
-    void Broadcast() {
-        KScopedSchedulerLock lk{kernel};
-
-        // Signal all threads.
-        for (auto& thread : wait_list) {
-            thread.SetState(ThreadState::Runnable);
-        }
-    }
+    void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true);
+    void Broadcast();
 
 
 private:
 private:
-    void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {
-        KThread* owner = GetCurrentThreadPointer(kernel);
-
-        // Sleep the thread.
-        {
-            KScopedSchedulerLockAndSleep lk{kernel, owner, timeout};
-
-            if (!allow_terminating_thread && owner->IsTerminationRequested()) {
-                lk.CancelSleep();
-                return;
-            }
-
-            lock->Unlock();
-
-            // Set the thread as waiting.
-            GetCurrentThread(kernel).SetState(ThreadState::Waiting);
-
-            // Add the thread to the queue.
-            wait_list.push_back(GetCurrentThread(kernel));
-        }
-
-        // Remove the thread from the wait list.
-        {
-            KScopedSchedulerLock sl{kernel};
-
-            wait_list.erase(wait_list.iterator_to(GetCurrentThread(kernel)));
-        }
-
-        // Cancel the task that the sleep setup.
-        kernel.TimeManager().UnscheduleTimeEvent(owner);
-
-        // Re-acquire the lock.
-        lock->Lock();
-    }
-
     KernelCore& kernel;
     KernelCore& kernel;
     KThread::WaiterList wait_list{};
     KThread::WaiterList wait_list{};
 };
 };