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

Kernel: Fixes, corrections and asserts to scheduler and different svcs.

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

+ 12 - 15
src/core/hle/kernel/address_arbiter.cpp

@@ -34,19 +34,9 @@ void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& wai
 
     // Signal the waiting threads.
     for (std::size_t i = 0; i < last; i++) {
-        if (waiting_threads[i]->GetStatus() != ThreadStatus::WaitArb) {
-            last++;
-            last = std::min(waiting_threads.size(), last);
-            continue;
-        }
-
-        time_manager.CancelTimeEvent(waiting_threads[i].get());
-
-        ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb);
         waiting_threads[i]->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
         RemoveThread(waiting_threads[i]);
         waiting_threads[i]->WaitForArbitration(false);
-        waiting_threads[i]->SetArbiterWaitAddress(0);
         waiting_threads[i]->ResumeFromWait();
     }
 }
@@ -172,20 +162,25 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
     {
         SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
 
+        if (current_thread->IsPendingTermination()) {
+            lock.CancelSleep();
+            return ERR_THREAD_TERMINATING;
+        }
+
         // Ensure that we can read the address.
         if (!memory.IsValidVirtualAddress(address)) {
             lock.CancelSleep();
             return ERR_INVALID_ADDRESS_STATE;
         }
 
-        /// TODO(Blinkhawk): Check termination pending.
-
         s32 current_value = static_cast<s32>(memory.Read32(address));
         if (current_value >= value) {
             lock.CancelSleep();
             return ERR_INVALID_STATE;
         }
 
+        current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
+
         s32 decrement_value;
 
         const std::size_t current_core = system.CurrentCoreIndex();
@@ -207,7 +202,6 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
             return RESULT_TIMEOUT;
         }
 
-        current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
         current_thread->SetArbiterWaitAddress(address);
         InsertThread(SharedFrom(current_thread));
         current_thread->SetStatus(ThreadStatus::WaitArb);
@@ -239,14 +233,17 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
     {
         SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
 
+        if (current_thread->IsPendingTermination()) {
+            lock.CancelSleep();
+            return ERR_THREAD_TERMINATING;
+        }
+
         // Ensure that we can read the address.
         if (!memory.IsValidVirtualAddress(address)) {
             lock.CancelSleep();
             return ERR_INVALID_ADDRESS_STATE;
         }
 
-        /// TODO(Blinkhawk): Check termination pending.
-
         s32 current_value = static_cast<s32>(memory.Read32(address));
         if (current_value != value) {
             lock.CancelSleep();

+ 1 - 0
src/core/hle/kernel/kernel.cpp

@@ -49,6 +49,7 @@ namespace Kernel {
  * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
  */
 static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) {
+    UNREACHABLE();
     const auto proper_handle = static_cast<Handle>(thread_handle);
     const auto& system = Core::System::GetInstance();
 

+ 2 - 1
src/core/hle/kernel/scheduler.cpp

@@ -133,6 +133,7 @@ u32 GlobalScheduler::SelectThreads() {
     u32 cores_needing_context_switch{};
     for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
         Scheduler& sched = kernel.Scheduler(core);
+        ASSERT(top_threads[core] == nullptr || top_threads[core]->GetProcessorID() == core);
         if (update_thread(top_threads[core], sched)) {
             cores_needing_context_switch |= (1ul << core);
         }
@@ -244,7 +245,7 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread
             winner = yielding_thread;
         }
     } else {
-        winner = scheduled_queue[i].front();
+        winner = scheduled_queue[core_id].front();
     }
 
     if (kernel.GetCurrentHostThreadID() != core_id) {

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

@@ -16,7 +16,7 @@
 #include "core/hle/kernel/thread.h"
 
 namespace Common {
-    class Fiber;
+class Fiber;
 }
 
 namespace Core {
@@ -133,7 +133,8 @@ private:
     /// and reschedules current core if needed.
     void Unlock();
 
-    void EnableInterruptAndSchedule(u32 cores_pending_reschedule, Core::EmuThreadHandle global_thread);
+    void EnableInterruptAndSchedule(u32 cores_pending_reschedule,
+                                    Core::EmuThreadHandle global_thread);
 
     /**
      * Add a thread to the suggested queue of a cpu core. Suggested threads may be

+ 14 - 13
src/core/hle/kernel/svc.cpp

@@ -1562,6 +1562,11 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
 
         current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
 
+        if (thread->IsPendingTermination()) {
+            lock.CancelSleep();
+            return ERR_THREAD_TERMINATING;
+        }
+
         const auto release_result = current_process->GetMutex().Release(mutex_addr);
         if (release_result.IsError()) {
             lock.CancelSleep();
@@ -1588,6 +1593,11 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
     {
         SchedulerLock lock(kernel);
 
+        auto* owner = current_thread->GetLockOwner();
+        if (owner != nullptr) {
+            owner->RemoveMutexWaiter(SharedFrom(current_thread));
+        }
+
         current_process->RemoveConditionVariableThread(SharedFrom(current_thread));
     }
     // Note: Deliberately don't attempt to inherit the lock owner's priority.
@@ -1618,19 +1628,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
     for (std::size_t index = 0; index < last; ++index) {
         auto& thread = waiting_threads[index];
 
-        if (thread->GetStatus() != ThreadStatus::WaitCondVar) {
-            last++;
-            last = std::min(waiting_threads.size(), last);
-            continue;
-        }
-
-        time_manager.CancelTimeEvent(thread.get());
-
         ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr);
 
         // liberate Cond Var Thread.
         current_process->RemoveConditionVariableThread(thread);
-        thread->SetCondVarWaitAddress(0);
 
         const std::size_t current_core = system.CurrentCoreIndex();
         auto& monitor = system.Monitor();
@@ -1655,9 +1656,6 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
         monitor.ClearExclusive();
         if (mutex_val == 0) {
             // We were able to acquire the mutex, resume this thread.
-            ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar);
-            thread->ResumeFromWait();
-
             auto* const lock_owner = thread->GetLockOwner();
             if (lock_owner != nullptr) {
                 lock_owner->RemoveMutexWaiter(thread);
@@ -1665,13 +1663,16 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
 
             thread->SetLockOwner(nullptr);
             thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
+            thread->ResumeFromWait();
         } else {
             // The mutex is already owned by some other thread, make this thread wait on it.
             const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
             const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
             auto owner = handle_table.Get<Thread>(owner_handle);
             ASSERT(owner);
-            thread->SetStatus(ThreadStatus::WaitMutex);
+            if (thread->GetStatus() == ThreadStatus::WaitCondVar) {
+                thread->SetStatus(ThreadStatus::WaitMutex);
+            }
 
             owner->AddMutexWaiter(thread);
         }

+ 6 - 4
src/core/hle/kernel/synchronization.cpp

@@ -23,9 +23,10 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const {
     if (obj.IsSignaled()) {
         for (auto thread : obj.GetWaitingThreads()) {
             if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) {
+                ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
+                ASSERT(thread->IsWaitingSync());
                 thread->SetSynchronizationResults(&obj, RESULT_SUCCESS);
                 thread->ResumeFromWait();
-                time_manager.CancelTimeEvent(thread.get());
             }
         }
         obj.ClearWaitingThreads();
@@ -91,10 +92,11 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
         ResultCode signaling_result = thread->GetSignalingResult();
         SynchronizationObject* signaling_object = thread->GetSignalingObject();
         thread->SetSynchronizationObjects(nullptr);
+        auto shared_thread = SharedFrom(thread);
         for (auto& obj : sync_objects) {
-            obj->RemoveWaitingThread(SharedFrom(thread));
+            obj->RemoveWaitingThread(shared_thread);
         }
-        if (signaling_result == RESULT_SUCCESS) {
+        if (signaling_object != nullptr) {
             const auto itr = std::find_if(
                 sync_objects.begin(), sync_objects.end(),
                 [signaling_object](const std::shared_ptr<SynchronizationObject>& object) {
@@ -103,7 +105,7 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
             ASSERT(itr != sync_objects.end());
             signaling_object->Acquire(thread);
             const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr));
-            return {RESULT_SUCCESS, index};
+            return {signaling_result, index};
         }
         return {signaling_result, -1};
     }

+ 0 - 2
src/core/hle/kernel/time_manager.cpp

@@ -22,7 +22,6 @@ TimeManager::TimeManager(Core::System& system_) : system{system_} {
             if (cancelled_events[proper_handle]) {
                 return;
             }
-            event_fired[proper_handle] = true;
             std::shared_ptr<Thread> thread =
                 this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
             thread->OnWakeUp();
@@ -39,7 +38,6 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64
         event_handle = InvalidHandle;
     }
     cancelled_events[event_handle] = false;
-    event_fired[event_handle] = false;
 }
 
 void TimeManager::UnscheduleTimeEvent(Handle event_handle) {

+ 0 - 1
src/core/hle/kernel/time_manager.h

@@ -42,7 +42,6 @@ private:
     Core::System& system;
     std::shared_ptr<Core::Timing::EventType> time_manager_event_type;
     std::unordered_map<Handle, bool> cancelled_events;
-    std::unordered_map<Handle, bool> event_fired;
 };
 
 } // namespace Kernel