diff options
author | Subv <subv2112@gmail.com> | 2016-12-14 18:13:02 +0100 |
---|---|---|
committer | Subv <subv2112@gmail.com> | 2016-12-14 18:35:01 +0100 |
commit | 5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2 (patch) | |
tree | b6fbcc194effc5e05a608ebde0ea3c887720d920 | |
parent | Properly remove a thread from its wait_objects' waitlist when it is awoken by a timeout. (diff) | |
download | yuzu-5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2.tar yuzu-5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2.tar.gz yuzu-5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2.tar.bz2 yuzu-5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2.tar.lz yuzu-5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2.tar.xz yuzu-5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2.tar.zst yuzu-5b1edc6ae70972d4a11eee1f1ff8fdff2122b5a2.zip |
-rw-r--r-- | src/citra_qt/debugger/wait_tree.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 10 | ||||
-rw-r--r-- | src/core/hle/svc.cpp | 47 |
4 files changed, 41 insertions, 28 deletions
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp index 8ff094209..b2e7f4a97 100644 --- a/src/citra_qt/debugger/wait_tree.cpp +++ b/src/citra_qt/debugger/wait_tree.cpp @@ -230,7 +230,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes)); } if (thread.status == THREADSTATUS_WAIT_SYNCH) { - list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, thread.IsSleepingOnWaitAll())); + list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, + thread.IsSleepingOnWaitAll())); } return list; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 2ddeffcdd..209d35270 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -50,9 +50,9 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { if (thread->current_priority >= candidate_priority) continue; - bool ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(), [](const SharedPtr<WaitObject>& object) { - return object->ShouldWait(); - }); + bool ready_to_run = + std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(), + [](const SharedPtr<WaitObject>& object) { return object->ShouldWait(); }); if (ready_to_run) { candidate = thread.get(); candidate_priority = thread->current_priority; @@ -83,7 +83,8 @@ void WaitObject::WakeupAllWaitingThreads() { thread->SetWaitSynchronizationResult(RESULT_SUCCESS); thread->ResumeFromWait(); - // Note: Removing the thread from the object's waitlist will be done by GetHighestPriorityReadyThread + // Note: Removing the thread from the object's waitlist will be + // done by GetHighestPriorityReadyThread. } } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 4c254cb9d..238359fc5 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -178,17 +178,19 @@ public: /// Mutexes currently held by this thread, which will be released when it exits. boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; - SharedPtr<Process> owner_process; ///< Process that owns this thread + SharedPtr<Process> owner_process; ///< Process that owns this thread /// Objects that the thread is waiting on. /// This is only populated when the thread should wait for all the objects to become ready. std::vector<SharedPtr<WaitObject>> wait_objects; - boost::container::flat_map<int, s32> wait_objects_index; ///< Mapping of Object ids to their position in the last waitlist that this object waited on. + /// Mapping of Object ids to their position in the last waitlist that this object waited on. + boost::container::flat_map<int, s32> wait_objects_index; - VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address + VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address - bool wait_set_output; ///< True if the WaitSynchronizationN output parameter should be set on thread wakeup + /// True if the WaitSynchronizationN output parameter should be set on thread wakeup. + bool wait_set_output; std::string name; diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index c81c14443..a4a00d9b2 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -264,14 +264,16 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { return ERR_SYNC_TIMEOUT; object->AddWaitingThread(thread); - // TODO(Subv): Perform things like update the mutex lock owner's priority to prevent priority inversion. - // Currently this is done in Mutex::ShouldWait, but it should be moved to a function that is called from here. + // TODO(Subv): Perform things like update the mutex lock owner's priority to + // prevent priority inversion. Currently this is done in Mutex::ShouldWait, + // but it should be moved to a function that is called from here. thread->status = THREADSTATUS_WAIT_SYNCH; // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); - // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a signal in its wait objects. + // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread + // resumes due to a signal in its wait objects. // Otherwise we retain the default value of timeout. return ERR_SYNC_TIMEOUT; } @@ -316,20 +318,22 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou thread->wait_objects_index.clear(); if (wait_all) { - bool all_available = std::all_of(objects.begin(), objects.end(), [](const ObjectPtr& object) { - return !object->ShouldWait(); - }); + bool all_available = + std::all_of(objects.begin(), objects.end(), + [](const ObjectPtr& object) { return !object->ShouldWait(); }); if (all_available) { // We can acquire all objects right now, do so. for (auto& object : objects) object->Acquire(); - // Note: In this case, the `out` parameter is not set, and retains whatever value it had before. + // Note: In this case, the `out` parameter is not set, + // and retains whatever value it had before. return RESULT_SUCCESS; } // Not all objects were available right now, prepare to suspend the thread. - // If a timeout value of 0 was provided, just return the Timeout error code instead of suspending the thread. + // If a timeout value of 0 was provided, just return the Timeout error code instead of + // suspending the thread. if (nano_seconds == 0) return ERR_SYNC_TIMEOUT; @@ -339,8 +343,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou // Add the thread to each of the objects' waiting threads. for (auto& object : objects) { object->AddWaitingThread(thread); - // TODO(Subv): Perform things like update the mutex lock owner's priority to prevent priority inversion. - // Currently this is done in Mutex::ShouldWait, but it should be moved to a function that is called from here. + // TODO(Subv): Perform things like update the mutex lock owner's priority to + // prevent priority inversion. Currently this is done in Mutex::ShouldWait, + // but it should be moved to a function that is called from here. } // Set the thread's waitlist to the list of objects passed to WaitSynchronizationN @@ -351,13 +356,13 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou // This value gets set to -1 by default in this case, it is not modified after this. *out = -1; - // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a signal in one of its wait objects. + // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to + // a signal in one of its wait objects. return ERR_SYNC_TIMEOUT; } else { // Find the first object that is acquirable in the provided list of objects - auto itr = std::find_if(objects.begin(), objects.end(), [](const ObjectPtr& object) { - return !object->ShouldWait(); - }); + auto itr = std::find_if(objects.begin(), objects.end(), + [](const ObjectPtr& object) { return !object->ShouldWait(); }); if (itr != objects.end()) { // We found a ready object, acquire it and set the result value @@ -369,7 +374,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou // No objects were ready to be acquired, prepare to suspend the thread. - // If a timeout value of 0 was provided, just return the Timeout error code instead of suspending the thread. + // If a timeout value of 0 was provided, just return the Timeout error code instead of + // suspending the thread. if (nano_seconds == 0) return ERR_SYNC_TIMEOUT; @@ -385,16 +391,19 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou // Set the index of this object in the mapping of Objects -> index for this thread. thread->wait_objects_index[object->GetObjectId()] = static_cast<int>(i); object->AddWaitingThread(thread); - // TODO(Subv): Perform things like update the mutex lock owner's priority to prevent priority inversion. - // Currently this is done in Mutex::ShouldWait, but it should be moved to a function that is called from here. + // TODO(Subv): Perform things like update the mutex lock owner's priority to + // prevent priority inversion. Currently this is done in Mutex::ShouldWait, + // but it should be moved to a function that is called from here. } - // Note: If no handles and no timeout were given, then the thread will deadlock, this is consistent with hardware behavior. + // Note: If no handles and no timeout were given, then the thread will deadlock, this is + // consistent with hardware behavior. // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); - // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a signal in one of its wait objects. + // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a + // signal in one of its wait objects. // Otherwise we retain the default value of timeout, and -1 in the out parameter thread->wait_set_output = true; *out = -1; |