Kernel: Use different thread statuses when a thread calls WaitSynchronization1 and WaitSynchronizationN with wait_all = true.

This commit removes the overly general THREADSTATUS_WAIT_SYNCH and replaces it with two more granular statuses:

THREADSTATUS_WAIT_SYNCH_ANY when a thread waits on objects via WaitSynchronization1 or WaitSynchronizationN with wait_all = false.

THREADSTATUS_WAIT_SYNCH_ALL when a thread waits on objects via WaitSynchronizationN with wait_all = true.
This commit is contained in:
Subv 2017-01-04 10:44:38 -05:00
parent d3ff5b91e1
commit cef5f45de2
4 changed files with 26 additions and 19 deletions

View file

@ -153,7 +153,8 @@ QString WaitTreeThread::GetText() const {
case THREADSTATUS_WAIT_SLEEP: case THREADSTATUS_WAIT_SLEEP:
status = tr("sleeping"); status = tr("sleeping");
break; break;
case THREADSTATUS_WAIT_SYNCH: case THREADSTATUS_WAIT_SYNCH_ALL:
case THREADSTATUS_WAIT_SYNCH_ANY:
status = tr("waiting for objects"); status = tr("waiting for objects");
break; break;
case THREADSTATUS_DORMANT: case THREADSTATUS_DORMANT:
@ -180,7 +181,8 @@ QColor WaitTreeThread::GetColor() const {
return QColor(Qt::GlobalColor::darkRed); return QColor(Qt::GlobalColor::darkRed);
case THREADSTATUS_WAIT_SLEEP: case THREADSTATUS_WAIT_SLEEP:
return QColor(Qt::GlobalColor::darkYellow); return QColor(Qt::GlobalColor::darkYellow);
case THREADSTATUS_WAIT_SYNCH: case THREADSTATUS_WAIT_SYNCH_ALL:
case THREADSTATUS_WAIT_SYNCH_ANY:
return QColor(Qt::GlobalColor::red); return QColor(Qt::GlobalColor::red);
case THREADSTATUS_DORMANT: case THREADSTATUS_DORMANT:
return QColor(Qt::GlobalColor::darkCyan); return QColor(Qt::GlobalColor::darkCyan);
@ -228,7 +230,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
} else { } else {
list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes)); list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes));
} }
if (thread.status == THREADSTATUS_WAIT_SYNCH) { if (thread.status == THREADSTATUS_WAIT_SYNCH_ANY ||
thread.status == THREADSTATUS_WAIT_SYNCH_ALL) {
list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects,
thread.IsSleepingOnWaitAll())); thread.IsSleepingOnWaitAll()));
} }

View file

@ -72,7 +72,8 @@ Thread* GetCurrentThread() {
* @return True if the thread is waiting, false otherwise * @return True if the thread is waiting, false otherwise
*/ */
static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) { static bool CheckWait_WaitObject(const Thread* thread, WaitObject* wait_object) {
if (thread->status != THREADSTATUS_WAIT_SYNCH) if (thread->status != THREADSTATUS_WAIT_SYNCH_ALL &&
thread->status != THREADSTATUS_WAIT_SYNCH_ANY)
return false; return false;
auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object); auto itr = std::find(thread->wait_objects.begin(), thread->wait_objects.end(), wait_object);
@ -253,7 +254,7 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa
Thread* thread = GetCurrentThread(); Thread* thread = GetCurrentThread();
thread->wait_set_output = wait_set_output; thread->wait_set_output = wait_set_output;
thread->wait_objects = std::move(wait_objects); thread->wait_objects = std::move(wait_objects);
thread->status = THREADSTATUS_WAIT_SYNCH; thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
} }
void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) {
@ -281,7 +282,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
return; return;
} }
if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) {
thread->wait_set_output = false; thread->wait_set_output = false;
// Remove the thread from each of its waiting objects' waitlists // Remove the thread from each of its waiting objects' waitlists
for (auto& object : thread->wait_objects) for (auto& object : thread->wait_objects)
@ -306,7 +308,8 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
void Thread::ResumeFromWait() { void Thread::ResumeFromWait() {
switch (status) { switch (status) {
case THREADSTATUS_WAIT_SYNCH: case THREADSTATUS_WAIT_SYNCH_ALL:
case THREADSTATUS_WAIT_SYNCH_ANY:
case THREADSTATUS_WAIT_ARB: case THREADSTATUS_WAIT_ARB:
case THREADSTATUS_WAIT_SLEEP: case THREADSTATUS_WAIT_SLEEP:
break; break;

View file

@ -35,7 +35,8 @@ enum ThreadStatus {
THREADSTATUS_READY, ///< Ready to run THREADSTATUS_READY, ///< Ready to run
THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization 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_DORMANT, ///< Created but not yet made ready THREADSTATUS_DORMANT, ///< Created but not yet made ready
THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
}; };
@ -158,10 +159,10 @@ public:
/** /**
* Returns whether this thread is waiting for all the objects in * Returns whether this thread is waiting for all the objects in
* its wait list to become ready, as a result of a WaitSynchronizationN call * its wait list to become ready, as a result of a WaitSynchronizationN call
* with wait_all = true, or a ReplyAndReceive call. * with wait_all = true.
*/ */
bool IsSleepingOnWaitAll() const { bool IsSleepingOnWaitAll() const {
return !wait_objects.empty(); return status == THREADSTATUS_WAIT_SYNCH_ALL;
} }
ARM_Interface::ThreadContext context; ARM_Interface::ThreadContext context;

View file

@ -278,7 +278,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
return ERR_SYNC_TIMEOUT; return ERR_SYNC_TIMEOUT;
object->AddWaitingThread(thread); object->AddWaitingThread(thread);
thread->status = THREADSTATUS_WAIT_SYNCH; thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
// Create an event to wake the thread up after the specified nanosecond delay has passed // Create an event to wake the thread up after the specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds); thread->WakeAfterDelay(nano_seconds);
@ -351,7 +351,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
return ERR_SYNC_TIMEOUT; return ERR_SYNC_TIMEOUT;
// Put the thread to sleep // Put the thread to sleep
thread->status = THREADSTATUS_WAIT_SYNCH; thread->status = THREADSTATUS_WAIT_SYNCH_ALL;
// Add the thread to each of the objects' waiting threads. // Add the thread to each of the objects' waiting threads.
for (auto& object : objects) { for (auto& object : objects) {
@ -393,7 +393,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
return ERR_SYNC_TIMEOUT; return ERR_SYNC_TIMEOUT;
// Put the thread to sleep // Put the thread to sleep
thread->status = THREADSTATUS_WAIT_SYNCH; thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
// Clear the thread's waitlist, we won't use it for wait_all = false // Clear the thread's waitlist, we won't use it for wait_all = false
thread->wait_objects.clear(); thread->wait_objects.clear();