From 0a308e224c5242949dc2a82789db8ad75dba41d8 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 20 Jul 2017 23:18:56 -0500 Subject: [PATCH] Kernel/Threads: Add a new thread status that will allow using a Kernel::Event to put a guest thread to sleep inside an HLE handler until said event is signaled. --- src/citra_qt/debugger/wait_tree.cpp | 7 ++++++- src/core/hle/kernel/thread.cpp | 1 + src/core/hle/kernel/thread.h | 1 + src/core/hle/kernel/wait_object.cpp | 3 ++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp index 8c244b6b2c..9b489b62d7 100644 --- a/src/citra_qt/debugger/wait_tree.cpp +++ b/src/citra_qt/debugger/wait_tree.cpp @@ -158,6 +158,9 @@ QString WaitTreeThread::GetText() const { case THREADSTATUS_WAIT_SYNCH_ANY: status = tr("waiting for objects"); break; + case THREADSTATUS_WAIT_HLE_EVENT: + status = tr("waiting for HLE return"); + break; case THREADSTATUS_DORMANT: status = tr("dormant"); break; @@ -184,6 +187,7 @@ QColor WaitTreeThread::GetColor() const { return QColor(Qt::GlobalColor::darkYellow); case THREADSTATUS_WAIT_SYNCH_ALL: case THREADSTATUS_WAIT_SYNCH_ANY: + case THREADSTATUS_WAIT_HLE_EVENT: return QColor(Qt::GlobalColor::red); case THREADSTATUS_DORMANT: return QColor(Qt::GlobalColor::darkCyan); @@ -232,7 +236,8 @@ std::vector> WaitTreeThread::GetChildren() const { list.push_back(std::make_unique(thread.held_mutexes)); } if (thread.status == THREADSTATUS_WAIT_SYNCH_ANY || - thread.status == THREADSTATUS_WAIT_SYNCH_ALL) { + thread.status == THREADSTATUS_WAIT_SYNCH_ALL || + thread.status == THREADSTATUS_WAIT_HLE_EVENT) { list.push_back(std::make_unique(thread.wait_objects, thread.IsSleepingOnWaitAll())); } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 2614a260ce..a457b99ee7 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -276,6 +276,7 @@ void Thread::ResumeFromWait() { switch (status) { case THREADSTATUS_WAIT_SYNCH_ALL: case THREADSTATUS_WAIT_SYNCH_ANY: + case THREADSTATUS_WAIT_HLE_EVENT: case THREADSTATUS_WAIT_ARB: case THREADSTATUS_WAIT_SLEEP: break; diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 4679c2022e..abe5c084ce 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -37,6 +37,7 @@ enum ThreadStatus { THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true + THREADSTATUS_WAIT_HLE_EVENT, ///< Waiting due to an HLE handler pausing the thread THREADSTATUS_DORMANT, ///< Created but not yet made ready THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated }; diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index 4695549081..320e16d07f 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -39,7 +39,8 @@ SharedPtr WaitObject::GetHighestPriorityReadyThread() { for (const auto& thread : waiting_threads) { // The list of waiting threads must not contain threads that are not waiting to be awakened. ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || - thread->status == THREADSTATUS_WAIT_SYNCH_ALL, + thread->status == THREADSTATUS_WAIT_SYNCH_ALL || + thread->status == THREADSTATUS_WAIT_HLE_EVENT, "Inconsistent thread statuses in waiting_threads"); if (thread->current_priority >= candidate_priority)