mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-19 11:01:09 +00:00
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:
parent
d3ff5b91e1
commit
cef5f45de2
@ -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()));
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -31,13 +31,14 @@ enum ThreadProcessorId : s32 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum ThreadStatus {
|
enum ThreadStatus {
|
||||||
THREADSTATUS_RUNNING, ///< Currently running
|
THREADSTATUS_RUNNING, ///< Currently running
|
||||||
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_DORMANT, ///< Created but not yet made ready
|
THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true
|
||||||
THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
|
THREADSTATUS_DORMANT, ///< Created but not yet made ready
|
||||||
|
THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
@ -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;
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user