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

Properly remove a thread from its wait_objects' waitlist when it is awoken by a timeout.

Subv 9 лет назад
Родитель
Сommit
406907d570
3 измененных файлов с 11 добавлено и 2 удалено
  1. 6 1
      src/core/hle/kernel/kernel.cpp
  2. 4 0
      src/core/hle/kernel/thread.cpp
  3. 1 1
      src/core/hle/svc.cpp

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

@@ -38,6 +38,11 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
         return thread->status == THREADSTATUS_RUNNING || thread->status == THREADSTATUS_READY;
     });
 
+    // TODO(Subv): This call should be performed inside the loop below to check if an object can be
+    // acquired by a particular thread. This is useful for things like recursive locking of Mutexes.
+    if (ShouldWait())
+        return nullptr;
+
     Thread* candidate = nullptr;
     s32 candidate_priority = THREADPRIO_LOWEST + 1;
 
@@ -67,7 +72,7 @@ void WaitObject::WakeupAllWaitingThreads() {
                 thread->wait_set_output = false;
             }
         } else {
-            for (auto object : thread->wait_objects) {
+            for (auto& object : thread->wait_objects) {
                 object->Acquire();
                 object->RemoveWaitingThread(thread.get());
             }

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

@@ -277,6 +277,10 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
 
     if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
         thread->wait_set_output = false;
+        // Remove the thread from each of its waiting objects' waitlists
+        for (auto& object : thread->wait_objects)
+            object->RemoveWaitingThread(thread.get());
+        thread->wait_objects.clear();
         thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
                                                         ErrorSummary::StatusChanged,
                                                         ErrorLevel::Info));

+ 1 - 1
src/core/hle/svc.cpp

@@ -321,7 +321,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
         });
         if (all_available) {
             // We can acquire all objects right now, do so.
-            for (auto object : objects)
+            for (auto& object : objects)
                 object->Acquire();
             // Note: In this case, the `out` parameter is not set, and retains whatever value it had before.
             return RESULT_SUCCESS;