Fernando Sahmkow 6 лет назад
Родитель
Сommit
15a79eb0d7

+ 1 - 2
src/core/cpu_manager.cpp

@@ -81,8 +81,7 @@ void CpuManager::RunGuestThread() {
     while (true) {
         auto& physical_core = kernel.CurrentPhysicalCore();
         if (!physical_core.IsInterrupted()) {
-            physical_core.Idle();
-            // physical_core.Run();
+            physical_core.Run();
         }
         auto& scheduler = physical_core.Scheduler();
         scheduler.TryDoContextSwitch();

+ 14 - 10
src/core/hle/kernel/hle_ipc.cpp

@@ -14,6 +14,7 @@
 #include "common/common_types.h"
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/errors.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/hle_ipc.h"
 #include "core/hle/kernel/kernel.h"
@@ -21,7 +22,9 @@
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/server_session.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/time_manager.h"
 #include "core/hle/kernel/writable_event.h"
 #include "core/memory.h"
 
@@ -46,11 +49,10 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
     const std::string& reason, u64 timeout, WakeupCallback&& callback,
     std::shared_ptr<WritableEvent> writable_event) {
     // Put the client thread to sleep until the wait event is signaled or the timeout expires.
-    thread->SetWakeupCallback(
+    thread->SetHLECallback(
         [context = *this, callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
                                     std::shared_ptr<SynchronizationObject> object,
                                     std::size_t index) mutable -> bool {
-            ASSERT(thread->GetStatus() == ThreadStatus::WaitHLEEvent);
             callback(thread, context, reason);
             context.WriteToOutgoingCommandBuffer(*thread);
             return true;
@@ -62,14 +64,16 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
         writable_event = pair.writable;
     }
 
-    const auto readable_event{writable_event->GetReadableEvent()};
-    writable_event->Clear();
-    thread->SetStatus(ThreadStatus::WaitHLEEvent);
-    thread->SetSynchronizationObjects({readable_event});
-    readable_event->AddWaitingThread(thread);
-
-    if (timeout > 0) {
-        thread->WakeAfterDelay(timeout);
+    {
+        Handle event_handle = InvalidHandle;
+        SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
+        const auto readable_event{writable_event->GetReadableEvent()};
+        writable_event->Clear();
+        thread->SetStatus(ThreadStatus::WaitHLEEvent);
+        thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
+        readable_event->AddWaitingThread(thread);
+        lock.Release();
+        thread->SetHLETimeEvent(event_handle);
     }
 
     is_thread_waiting = true;

+ 9 - 0
src/core/hle/kernel/scheduler.cpp

@@ -715,4 +715,13 @@ SchedulerLockAndSleep::~SchedulerLockAndSleep() {
     time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
 }
 
+void SchedulerLockAndSleep::Release() {
+    if (sleep_cancelled) {
+        return;
+    }
+    auto& time_manager = kernel.TimeManager();
+    time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
+    sleep_cancelled = true;
+}
+
 } // namespace Kernel

+ 2 - 0
src/core/hle/kernel/scheduler.h

@@ -279,6 +279,8 @@ public:
         sleep_cancelled = true;
     }
 
+    void Release();
+
 private:
     Handle& event_handle;
     Thread* time_task;

+ 10 - 5
src/core/hle/kernel/server_session.cpp

@@ -19,6 +19,7 @@
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/server_session.h"
 #include "core/hle/kernel/session.h"
+#include "core/hle/kernel/scheduler.h"
 #include "core/hle/kernel/thread.h"
 #include "core/memory.h"
 
@@ -168,9 +169,12 @@ ResultCode ServerSession::CompleteSyncRequest() {
     }
 
     // Some service requests require the thread to block
-    if (!context.IsThreadWaiting()) {
-        context.GetThread().ResumeFromWait();
-        context.GetThread().SetWaitSynchronizationResult(result);
+    {
+        SchedulerLock lock(kernel);
+        if (!context.IsThreadWaiting()) {
+            context.GetThread().ResumeFromWait();
+            context.GetThread().SetSynchronizationResults(nullptr, result);
+        }
     }
 
     request_queue.Pop();
@@ -180,8 +184,9 @@ ResultCode ServerSession::CompleteSyncRequest() {
 
 ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
                                             Core::Memory::Memory& memory) {
-    Core::System::GetInstance().CoreTiming().ScheduleEvent(20000, request_event, {});
-    return QueueSyncRequest(std::move(thread), memory);
+    ResultCode result = QueueSyncRequest(std::move(thread), memory);
+    Core::System::GetInstance().CoreTiming().ScheduleEvent(0, request_event, {});
+    return result;
 }
 
 } // namespace Kernel

+ 17 - 4
src/core/hle/kernel/svc.cpp

@@ -38,6 +38,7 @@
 #include "core/hle/kernel/svc_wrap.h"
 #include "core/hle/kernel/synchronization.h"
 #include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/time_manager.h"
 #include "core/hle/kernel/transfer_memory.h"
 #include "core/hle/kernel/writable_event.h"
 #include "core/hle/lock.h"
@@ -318,11 +319,23 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
     LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
 
     auto thread = system.CurrentScheduler().GetCurrentThread();
-    thread->InvalidateWakeupCallback();
-    thread->SetStatus(ThreadStatus::WaitIPC);
-    system.PrepareReschedule(thread->GetProcessorID());
+    {
+        SchedulerLock lock(system.Kernel());
+        thread->InvalidateHLECallback();
+        thread->SetStatus(ThreadStatus::WaitIPC);
+        session->SendSyncRequest(SharedFrom(thread), system.Memory());
+    }
+    ResultCode result = thread->GetSignalingResult();
+    if (thread->HasHLECallback()) {
+        Handle event_handle = thread->GetHLETimeEvent();
+        if (event_handle != InvalidHandle) {
+            auto& time_manager = system.Kernel().TimeManager();
+            time_manager.UnscheduleTimeEvent(event_handle);
+        }
+        thread->InvokeHLECallback(ThreadWakeupReason::Timeout, SharedFrom(thread), nullptr, 0);
+    }
 
-    return session->SendSyncRequest(SharedFrom(thread), system.Memory());
+    return result;
 }
 
 static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {

+ 10 - 4
src/core/hle/kernel/thread.cpp

@@ -96,7 +96,7 @@ void Thread::ResumeFromWait() {
     case ThreadStatus::Ready:
         // The thread's wakeup callback must have already been cleared when the thread was first
         // awoken.
-        ASSERT(wakeup_callback == nullptr);
+        ASSERT(hle_callback == nullptr);
         // If the thread is waiting on multiple wait objects, it might be awoken more than once
         // before actually resuming. We can ignore subsequent wakeups if the thread status has
         // already been set to ThreadStatus::Ready.
@@ -112,7 +112,7 @@ void Thread::ResumeFromWait() {
         return;
     }
 
-    wakeup_callback = nullptr;
+    hle_callback = nullptr;
 
     if (activity == ThreadActivity::Paused) {
         SetStatus(ThreadStatus::Paused);
@@ -398,8 +398,14 @@ bool Thread::AllSynchronizationObjectsReady() const {
 bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
                                   std::shared_ptr<SynchronizationObject> object,
                                   std::size_t index) {
-    ASSERT(wakeup_callback);
-    return wakeup_callback(reason, std::move(thread), std::move(object), index);
+    ASSERT(hle_callback);
+    return hle_callback(reason, std::move(thread), std::move(object), index);
+}
+
+bool Thread::InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
+                               std::shared_ptr<SynchronizationObject> object, std::size_t index) {
+    ASSERT(hle_callback);
+    return hle_callback(reason, std::move(thread), std::move(object), index);
 }
 
 void Thread::SetActivity(ThreadActivity value) {

+ 53 - 29
src/core/hle/kernel/thread.h

@@ -31,12 +31,12 @@ class Process;
 class Scheduler;
 
 enum ThreadPriority : u32 {
-    THREADPRIO_HIGHEST = 0,             ///< Highest thread priority
-    THREADPRIO_MAX_CORE_MIGRATION = 2,  ///< Highest priority for a core migration
-    THREADPRIO_USERLAND_MAX = 24,       ///< Highest thread priority for userland apps
-    THREADPRIO_DEFAULT = 44,            ///< Default thread priority for userland apps
-    THREADPRIO_LOWEST = 63,             ///< Lowest thread priority
-    THREADPRIO_COUNT = 64,              ///< Total number of possible thread priorities.
+    THREADPRIO_HIGHEST = 0,            ///< Highest thread priority
+    THREADPRIO_MAX_CORE_MIGRATION = 2, ///< Highest priority for a core migration
+    THREADPRIO_USERLAND_MAX = 24,      ///< Highest thread priority for userland apps
+    THREADPRIO_DEFAULT = 44,           ///< Default thread priority for userland apps
+    THREADPRIO_LOWEST = 63,            ///< Lowest thread priority
+    THREADPRIO_COUNT = 64,             ///< Total number of possible thread priorities.
 };
 
 enum ThreadType : u32 {
@@ -129,23 +129,24 @@ public:
     using WakeupCallback =
         std::function<bool(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
                            std::shared_ptr<SynchronizationObject> object, std::size_t index)>;
+    using HLECallback = std::function<bool(std::shared_ptr<Thread> thread)>;
 
-   /**
-    * Creates and returns a new thread. The new thread is immediately scheduled
-    * @param system The instance of the whole system
-    * @param name The friendly name desired for the thread
-    * @param entry_point The address at which the thread should start execution
-    * @param priority The thread's priority
-    * @param arg User data to pass to the thread
-    * @param processor_id The ID(s) of the processors on which the thread is desired to be run
-    * @param stack_top The address of the thread's stack top
-    * @param owner_process The parent process for the thread, if null, it's a kernel thread
-    * @return A shared pointer to the newly created thread
-    */
-   static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags, std::string name,
-                                                    VAddr entry_point, u32 priority, u64 arg,
-                                                    s32 processor_id, VAddr stack_top,
-                                                    Process* owner_process);
+    /**
+     * Creates and returns a new thread. The new thread is immediately scheduled
+     * @param system The instance of the whole system
+     * @param name The friendly name desired for the thread
+     * @param entry_point The address at which the thread should start execution
+     * @param priority The thread's priority
+     * @param arg User data to pass to the thread
+     * @param processor_id The ID(s) of the processors on which the thread is desired to be run
+     * @param stack_top The address of the thread's stack top
+     * @param owner_process The parent process for the thread, if null, it's a kernel thread
+     * @return A shared pointer to the newly created thread
+     */
+    static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags,
+                                                     std::string name, VAddr entry_point,
+                                                     u32 priority, u64 arg, s32 processor_id,
+                                                     VAddr stack_top, Process* owner_process);
 
     /**
      * Creates and returns a new thread. The new thread is immediately scheduled
@@ -161,10 +162,10 @@ public:
      * @param thread_start_parameter The parameter which will passed to host context on init
      * @return A shared pointer to the newly created thread
      */
-    static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags, std::string name,
-                                                     VAddr entry_point, u32 priority, u64 arg,
-                                                     s32 processor_id, VAddr stack_top,
-                                                     Process* owner_process,
+    static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags,
+                                                     std::string name, VAddr entry_point,
+                                                     u32 priority, u64 arg, s32 processor_id,
+                                                     VAddr stack_top, Process* owner_process,
                                                      std::function<void(void*)>&& thread_start_func,
                                                      void* thread_start_parameter);
 
@@ -447,17 +448,37 @@ public:
     }
 
     bool HasWakeupCallback() const {
-        return wakeup_callback != nullptr;
+        return hle_callback != nullptr;
+    }
+
+    bool HasHLECallback() const {
+        return hle_callback != nullptr;
     }
 
     void SetWakeupCallback(WakeupCallback callback) {
-        wakeup_callback = std::move(callback);
+        hle_callback = std::move(callback);
+    }
+
+    void SetHLECallback(WakeupCallback callback) {
+        hle_callback = std::move(callback);
+    }
+
+    void SetHLETimeEvent(Handle time_event) {
+        hle_time_event = time_event;
+    }
+
+    Handle GetHLETimeEvent() const {
+        return hle_time_event;
     }
 
     void InvalidateWakeupCallback() {
         SetWakeupCallback(nullptr);
     }
 
+    void InvalidateHLECallback() {
+        SetHLECallback(nullptr);
+    }
+
     /**
      * Invokes the thread's wakeup callback.
      *
@@ -466,6 +487,8 @@ public:
      */
     bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
                               std::shared_ptr<SynchronizationObject> object, std::size_t index);
+    bool InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
+                           std::shared_ptr<SynchronizationObject> object, std::size_t index);
 
     u32 GetIdealCore() const {
         return ideal_core;
@@ -600,7 +623,8 @@ private:
     /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
     /// was waiting via WaitSynchronization then the object will be the last object that became
     /// available. In case of a timeout, the object will be nullptr.
-    WakeupCallback wakeup_callback;
+    WakeupCallback hle_callback;
+    Handle hle_time_event;
 
     Scheduler* scheduler = nullptr;