thread: Convert ThreadStatus into an enum class
Makes the thread status strongly typed, so implicit conversions can't happen. It also makes it easier to catch mistakes at compile time.
This commit is contained in:
parent
2ba62ec196
commit
5dfa7b74b5
|
@ -145,32 +145,32 @@ QString WaitTreeThread::GetText() const {
|
||||||
const auto& thread = static_cast<const Kernel::Thread&>(object);
|
const auto& thread = static_cast<const Kernel::Thread&>(object);
|
||||||
QString status;
|
QString status;
|
||||||
switch (thread.status) {
|
switch (thread.status) {
|
||||||
case THREADSTATUS_RUNNING:
|
case ThreadStatus::Running:
|
||||||
status = tr("running");
|
status = tr("running");
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_READY:
|
case ThreadStatus::Ready:
|
||||||
status = tr("ready");
|
status = tr("ready");
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_WAIT_ARB:
|
case ThreadStatus::WaitArb:
|
||||||
status = tr("waiting for address 0x%1").arg(thread.wait_address, 8, 16, QLatin1Char('0'));
|
status = tr("waiting for address 0x%1").arg(thread.wait_address, 8, 16, QLatin1Char('0'));
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_WAIT_SLEEP:
|
case ThreadStatus::WaitSleep:
|
||||||
status = tr("sleeping");
|
status = tr("sleeping");
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_WAIT_IPC:
|
case ThreadStatus::WaitIPC:
|
||||||
status = tr("waiting for IPC response");
|
status = tr("waiting for IPC response");
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_WAIT_SYNCH_ALL:
|
case ThreadStatus::WaitSynchAll:
|
||||||
case THREADSTATUS_WAIT_SYNCH_ANY:
|
case ThreadStatus::WaitSynchAny:
|
||||||
status = tr("waiting for objects");
|
status = tr("waiting for objects");
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_WAIT_HLE_EVENT:
|
case ThreadStatus::WaitHleEvent:
|
||||||
status = tr("waiting for HLE return");
|
status = tr("waiting for HLE return");
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_DORMANT:
|
case ThreadStatus::Dormant:
|
||||||
status = tr("dormant");
|
status = tr("dormant");
|
||||||
break;
|
break;
|
||||||
case THREADSTATUS_DEAD:
|
case ThreadStatus::Dead:
|
||||||
status = tr("dead");
|
status = tr("dead");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -183,23 +183,23 @@ QString WaitTreeThread::GetText() const {
|
||||||
QColor WaitTreeThread::GetColor() const {
|
QColor WaitTreeThread::GetColor() const {
|
||||||
const auto& thread = static_cast<const Kernel::Thread&>(object);
|
const auto& thread = static_cast<const Kernel::Thread&>(object);
|
||||||
switch (thread.status) {
|
switch (thread.status) {
|
||||||
case THREADSTATUS_RUNNING:
|
case ThreadStatus::Running:
|
||||||
return QColor(Qt::GlobalColor::darkGreen);
|
return QColor(Qt::GlobalColor::darkGreen);
|
||||||
case THREADSTATUS_READY:
|
case ThreadStatus::Ready:
|
||||||
return QColor(Qt::GlobalColor::darkBlue);
|
return QColor(Qt::GlobalColor::darkBlue);
|
||||||
case THREADSTATUS_WAIT_ARB:
|
case ThreadStatus::WaitArb:
|
||||||
return QColor(Qt::GlobalColor::darkRed);
|
return QColor(Qt::GlobalColor::darkRed);
|
||||||
case THREADSTATUS_WAIT_SLEEP:
|
case ThreadStatus::WaitSleep:
|
||||||
return QColor(Qt::GlobalColor::darkYellow);
|
return QColor(Qt::GlobalColor::darkYellow);
|
||||||
case THREADSTATUS_WAIT_IPC:
|
case ThreadStatus::WaitIPC:
|
||||||
return QColor(Qt::GlobalColor::darkCyan);
|
return QColor(Qt::GlobalColor::darkCyan);
|
||||||
case THREADSTATUS_WAIT_SYNCH_ALL:
|
case ThreadStatus::WaitSynchAll:
|
||||||
case THREADSTATUS_WAIT_SYNCH_ANY:
|
case ThreadStatus::WaitSynchAny:
|
||||||
case THREADSTATUS_WAIT_HLE_EVENT:
|
case ThreadStatus::WaitHleEvent:
|
||||||
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);
|
||||||
case THREADSTATUS_DEAD:
|
case ThreadStatus::Dead:
|
||||||
return QColor(Qt::GlobalColor::gray);
|
return QColor(Qt::GlobalColor::gray);
|
||||||
default:
|
default:
|
||||||
return WaitTreeItem::GetColor();
|
return WaitTreeItem::GetColor();
|
||||||
|
@ -243,9 +243,9 @@ 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_ANY ||
|
if (thread.status == ThreadStatus::WaitSynchAny ||
|
||||||
thread.status == THREADSTATUS_WAIT_SYNCH_ALL ||
|
thread.status == ThreadStatus::WaitSynchAll ||
|
||||||
thread.status == THREADSTATUS_WAIT_HLE_EVENT) {
|
thread.status == ThreadStatus::WaitHleEvent) {
|
||||||
list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects,
|
list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects,
|
||||||
thread.IsSleepingOnWaitAll()));
|
thread.IsSleepingOnWaitAll()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace Kernel {
|
||||||
|
|
||||||
void AddressArbiter::WaitThread(SharedPtr<Thread> thread, VAddr wait_address) {
|
void AddressArbiter::WaitThread(SharedPtr<Thread> thread, VAddr wait_address) {
|
||||||
thread->wait_address = wait_address;
|
thread->wait_address = wait_address;
|
||||||
thread->status = THREADSTATUS_WAIT_ARB;
|
thread->status = ThreadStatus::WaitArb;
|
||||||
waiting_threads.emplace_back(std::move(thread));
|
waiting_threads.emplace_back(std::move(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ void AddressArbiter::ResumeAllThreads(VAddr address) {
|
||||||
// Determine which threads are waiting on this address, those should be woken up.
|
// Determine which threads are waiting on this address, those should be woken up.
|
||||||
auto itr = std::stable_partition(waiting_threads.begin(), waiting_threads.end(),
|
auto itr = std::stable_partition(waiting_threads.begin(), waiting_threads.end(),
|
||||||
[address](const auto& thread) {
|
[address](const auto& thread) {
|
||||||
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_ARB,
|
ASSERT_MSG(thread->status == ThreadStatus::WaitArb,
|
||||||
"Inconsistent AddressArbiter state");
|
"Inconsistent AddressArbiter state");
|
||||||
return thread->wait_address != address;
|
return thread->wait_address != address;
|
||||||
});
|
});
|
||||||
|
@ -41,8 +41,7 @@ SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
|
||||||
// Determine which threads are waiting on this address, those should be considered for wakeup.
|
// Determine which threads are waiting on this address, those should be considered for wakeup.
|
||||||
auto matches_start = std::stable_partition(
|
auto matches_start = std::stable_partition(
|
||||||
waiting_threads.begin(), waiting_threads.end(), [address](const auto& thread) {
|
waiting_threads.begin(), waiting_threads.end(), [address](const auto& thread) {
|
||||||
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_ARB,
|
ASSERT_MSG(thread->status == ThreadStatus::WaitArb, "Inconsistent AddressArbiter state");
|
||||||
"Inconsistent AddressArbiter state");
|
|
||||||
return thread->wait_address != address;
|
return thread->wait_address != address;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
||||||
thread->wakeup_callback = [context = *this, callback](ThreadWakeupReason reason,
|
thread->wakeup_callback = [context = *this, callback](ThreadWakeupReason reason,
|
||||||
SharedPtr<Thread> thread,
|
SharedPtr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) mutable {
|
SharedPtr<WaitObject> object) mutable {
|
||||||
ASSERT(thread->status == THREADSTATUS_WAIT_HLE_EVENT);
|
ASSERT(thread->status == ThreadStatus::WaitHleEvent);
|
||||||
callback(thread, context, reason);
|
callback(thread, context, reason);
|
||||||
|
|
||||||
auto& process = thread->owner_process;
|
auto& process = thread->owner_process;
|
||||||
|
@ -56,7 +56,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
|
auto event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
|
||||||
thread->status = THREADSTATUS_WAIT_HLE_EVENT;
|
thread->status = ThreadStatus::WaitHleEvent;
|
||||||
thread->wait_objects = {event};
|
thread->wait_objects = {event};
|
||||||
event->AddWaitingThread(thread);
|
event->AddWaitingThread(thread);
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
||||||
hle_handler->HandleSyncRequest(SharedPtr<ServerSession>(this));
|
hle_handler->HandleSyncRequest(SharedPtr<ServerSession>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->status == THREADSTATUS_RUNNING) {
|
if (thread->status == ThreadStatus::Running) {
|
||||||
// Put the thread to sleep until the server replies, it will be awoken in
|
// Put the thread to sleep until the server replies, it will be awoken in
|
||||||
// svcReplyAndReceive for LLE servers.
|
// svcReplyAndReceive for LLE servers.
|
||||||
thread->status = THREADSTATUS_WAIT_IPC;
|
thread->status = ThreadStatus::WaitIPC;
|
||||||
|
|
||||||
if (hle_handler != nullptr) {
|
if (hle_handler != nullptr) {
|
||||||
// For HLE services, we put the request threads to sleep for a short duration to
|
// For HLE services, we put the request threads to sleep for a short duration to
|
||||||
|
|
|
@ -161,8 +161,8 @@ static void ExitProcess() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO(Subv): When are the other running/ready threads terminated?
|
// TODO(Subv): When are the other running/ready threads terminated?
|
||||||
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
|
ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny ||
|
||||||
thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
|
thread->status == ThreadStatus::WaitSynchAll,
|
||||||
"Exiting processes with non-waiting threads is currently unimplemented");
|
"Exiting processes with non-waiting threads is currently unimplemented");
|
||||||
|
|
||||||
thread->Stop();
|
thread->Stop();
|
||||||
|
@ -283,14 +283,14 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
|
||||||
|
|
||||||
thread->wait_objects = {object};
|
thread->wait_objects = {object};
|
||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(thread);
|
||||||
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
|
thread->status = ThreadStatus::WaitSynchAny;
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
SharedPtr<WaitObject> object) {
|
||||||
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||||
|
|
||||||
if (reason == ThreadWakeupReason::Timeout) {
|
if (reason == ThreadWakeupReason::Timeout) {
|
||||||
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
||||||
|
@ -365,7 +365,7 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand
|
||||||
return RESULT_TIMEOUT;
|
return RESULT_TIMEOUT;
|
||||||
|
|
||||||
// Put the thread to sleep
|
// Put the thread to sleep
|
||||||
thread->status = THREADSTATUS_WAIT_SYNCH_ALL;
|
thread->status = ThreadStatus::WaitSynchAll;
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -379,7 +379,7 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand
|
||||||
|
|
||||||
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
SharedPtr<WaitObject> object) {
|
||||||
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ALL);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAll);
|
||||||
|
|
||||||
if (reason == ThreadWakeupReason::Timeout) {
|
if (reason == ThreadWakeupReason::Timeout) {
|
||||||
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
||||||
|
@ -421,7 +421,7 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand
|
||||||
return RESULT_TIMEOUT;
|
return RESULT_TIMEOUT;
|
||||||
|
|
||||||
// Put the thread to sleep
|
// Put the thread to sleep
|
||||||
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
|
thread->status = ThreadStatus::WaitSynchAny;
|
||||||
|
|
||||||
// Add the thread to each of the objects' waiting threads.
|
// Add the thread to each of the objects' waiting threads.
|
||||||
for (std::size_t i = 0; i < objects.size(); ++i) {
|
for (std::size_t i = 0; i < objects.size(); ++i) {
|
||||||
|
@ -439,7 +439,7 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand
|
||||||
|
|
||||||
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
SharedPtr<WaitObject> object) {
|
||||||
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||||
|
|
||||||
if (reason == ThreadWakeupReason::Timeout) {
|
if (reason == ThreadWakeupReason::Timeout) {
|
||||||
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
|
||||||
|
@ -578,7 +578,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
|
||||||
// No objects were ready to be acquired, prepare to suspend the thread.
|
// No objects were ready to be acquired, prepare to suspend the thread.
|
||||||
|
|
||||||
// Put the thread to sleep
|
// Put the thread to sleep
|
||||||
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
|
thread->status = ThreadStatus::WaitSynchAny;
|
||||||
|
|
||||||
// Add the thread to each of the objects' waiting threads.
|
// Add the thread to each of the objects' waiting threads.
|
||||||
for (std::size_t i = 0; i < objects.size(); ++i) {
|
for (std::size_t i = 0; i < objects.size(); ++i) {
|
||||||
|
@ -590,7 +590,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
|
||||||
|
|
||||||
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
SharedPtr<WaitObject> object) {
|
||||||
ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||||
|
|
||||||
ResultCode result = RESULT_SUCCESS;
|
ResultCode result = RESULT_SUCCESS;
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Kernel {
|
||||||
static CoreTiming::EventType* ThreadWakeupEventType = nullptr;
|
static CoreTiming::EventType* ThreadWakeupEventType = nullptr;
|
||||||
|
|
||||||
bool Thread::ShouldWait(Thread* thread) const {
|
bool Thread::ShouldWait(Thread* thread) const {
|
||||||
return status != THREADSTATUS_DEAD;
|
return status != ThreadStatus::Dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::Acquire(Thread* thread) {
|
void Thread::Acquire(Thread* thread) {
|
||||||
|
@ -75,11 +75,11 @@ void Thread::Stop() {
|
||||||
|
|
||||||
// Clean up thread from ready queue
|
// Clean up thread from ready queue
|
||||||
// This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
|
// This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
|
||||||
if (status == THREADSTATUS_READY) {
|
if (status == ThreadStatus::Ready) {
|
||||||
ready_queue.remove(current_priority, this);
|
ready_queue.remove(current_priority, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = THREADSTATUS_DEAD;
|
status = ThreadStatus::Dead;
|
||||||
|
|
||||||
WakeupAllWaitingThreads();
|
WakeupAllWaitingThreads();
|
||||||
|
|
||||||
|
@ -111,17 +111,17 @@ static void SwitchContext(Thread* new_thread) {
|
||||||
previous_thread->last_running_ticks = CoreTiming::GetTicks();
|
previous_thread->last_running_ticks = CoreTiming::GetTicks();
|
||||||
Core::CPU().SaveContext(previous_thread->context);
|
Core::CPU().SaveContext(previous_thread->context);
|
||||||
|
|
||||||
if (previous_thread->status == THREADSTATUS_RUNNING) {
|
if (previous_thread->status == ThreadStatus::Running) {
|
||||||
// This is only the case when a reschedule is triggered without the current thread
|
// This is only the case when a reschedule is triggered without the current thread
|
||||||
// yielding execution (i.e. an event triggered, system core time-sliced, etc)
|
// yielding execution (i.e. an event triggered, system core time-sliced, etc)
|
||||||
ready_queue.push_front(previous_thread->current_priority, previous_thread);
|
ready_queue.push_front(previous_thread->current_priority, previous_thread);
|
||||||
previous_thread->status = THREADSTATUS_READY;
|
previous_thread->status = ThreadStatus::Ready;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load context of new thread
|
// Load context of new thread
|
||||||
if (new_thread) {
|
if (new_thread) {
|
||||||
ASSERT_MSG(new_thread->status == THREADSTATUS_READY,
|
ASSERT_MSG(new_thread->status == ThreadStatus::Ready,
|
||||||
"Thread must be ready to become running.");
|
"Thread must be ready to become running.");
|
||||||
|
|
||||||
// Cancel any outstanding wakeup events for this thread
|
// Cancel any outstanding wakeup events for this thread
|
||||||
|
@ -132,7 +132,7 @@ static void SwitchContext(Thread* new_thread) {
|
||||||
current_thread = new_thread;
|
current_thread = new_thread;
|
||||||
|
|
||||||
ready_queue.remove(new_thread->current_priority, new_thread);
|
ready_queue.remove(new_thread->current_priority, new_thread);
|
||||||
new_thread->status = THREADSTATUS_RUNNING;
|
new_thread->status = ThreadStatus::Running;
|
||||||
|
|
||||||
if (previous_process != current_thread->owner_process) {
|
if (previous_process != current_thread->owner_process) {
|
||||||
Kernel::g_current_process = current_thread->owner_process;
|
Kernel::g_current_process = current_thread->owner_process;
|
||||||
|
@ -156,7 +156,7 @@ static Thread* PopNextReadyThread() {
|
||||||
Thread* next;
|
Thread* next;
|
||||||
Thread* thread = GetCurrentThread();
|
Thread* thread = GetCurrentThread();
|
||||||
|
|
||||||
if (thread && thread->status == THREADSTATUS_RUNNING) {
|
if (thread && thread->status == ThreadStatus::Running) {
|
||||||
// We have to do better than the current thread.
|
// We have to do better than the current thread.
|
||||||
// This call returns null when that's not possible.
|
// This call returns null when that's not possible.
|
||||||
next = ready_queue.pop_first_better(thread->current_priority);
|
next = ready_queue.pop_first_better(thread->current_priority);
|
||||||
|
@ -173,7 +173,7 @@ static Thread* PopNextReadyThread() {
|
||||||
|
|
||||||
void WaitCurrentThread_Sleep() {
|
void WaitCurrentThread_Sleep() {
|
||||||
Thread* thread = GetCurrentThread();
|
Thread* thread = GetCurrentThread();
|
||||||
thread->status = THREADSTATUS_WAIT_SLEEP;
|
thread->status = ThreadStatus::WaitSleep;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExitCurrentThread() {
|
void ExitCurrentThread() {
|
||||||
|
@ -195,9 +195,9 @@ static void ThreadWakeupCallback(u64 thread_handle, s64 cycles_late) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
|
if (thread->status == ThreadStatus::WaitSynchAny ||
|
||||||
thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB ||
|
thread->status == ThreadStatus::WaitSynchAll || thread->status == ThreadStatus::WaitArb ||
|
||||||
thread->status == THREADSTATUS_WAIT_HLE_EVENT) {
|
thread->status == ThreadStatus::WaitHleEvent) {
|
||||||
|
|
||||||
// Invoke the wakeup callback before clearing the wait objects
|
// Invoke the wakeup callback before clearing the wait objects
|
||||||
if (thread->wakeup_callback)
|
if (thread->wakeup_callback)
|
||||||
|
@ -224,27 +224,27 @@ void Thread::ResumeFromWait() {
|
||||||
ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
|
ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case THREADSTATUS_WAIT_SYNCH_ALL:
|
case ThreadStatus::WaitSynchAll:
|
||||||
case THREADSTATUS_WAIT_SYNCH_ANY:
|
case ThreadStatus::WaitSynchAny:
|
||||||
case THREADSTATUS_WAIT_HLE_EVENT:
|
case ThreadStatus::WaitHleEvent:
|
||||||
case THREADSTATUS_WAIT_ARB:
|
case ThreadStatus::WaitArb:
|
||||||
case THREADSTATUS_WAIT_SLEEP:
|
case ThreadStatus::WaitSleep:
|
||||||
case THREADSTATUS_WAIT_IPC:
|
case ThreadStatus::WaitIPC:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case THREADSTATUS_READY:
|
case ThreadStatus::Ready:
|
||||||
// The thread's wakeup callback must have already been cleared when the thread was first
|
// The thread's wakeup callback must have already been cleared when the thread was first
|
||||||
// awoken.
|
// awoken.
|
||||||
ASSERT(wakeup_callback == nullptr);
|
ASSERT(wakeup_callback == nullptr);
|
||||||
// If the thread is waiting on multiple wait objects, it might be awoken more than once
|
// If the thread is waiting on multiple wait objects, it might be awoken more than once
|
||||||
// before actually resuming. We can ignore subsequent wakeups if the thread status has
|
// before actually resuming. We can ignore subsequent wakeups if the thread status has
|
||||||
// already been set to THREADSTATUS_READY.
|
// already been set to ThreadStatus::Ready.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case THREADSTATUS_RUNNING:
|
case ThreadStatus::Running:
|
||||||
DEBUG_ASSERT_MSG(false, "Thread with object id {} has already resumed.", GetObjectId());
|
DEBUG_ASSERT_MSG(false, "Thread with object id {} has already resumed.", GetObjectId());
|
||||||
return;
|
return;
|
||||||
case THREADSTATUS_DEAD:
|
case ThreadStatus::Dead:
|
||||||
// This should never happen, as threads must complete before being stopped.
|
// This should never happen, as threads must complete before being stopped.
|
||||||
DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.",
|
DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.",
|
||||||
GetObjectId());
|
GetObjectId());
|
||||||
|
@ -254,7 +254,7 @@ void Thread::ResumeFromWait() {
|
||||||
wakeup_callback = nullptr;
|
wakeup_callback = nullptr;
|
||||||
|
|
||||||
ready_queue.push_back(current_priority, this);
|
ready_queue.push_back(current_priority, this);
|
||||||
status = THREADSTATUS_READY;
|
status = ThreadStatus::Ready;
|
||||||
Core::System::GetInstance().PrepareReschedule();
|
Core::System::GetInstance().PrepareReschedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
|
||||||
ready_queue.prepare(priority);
|
ready_queue.prepare(priority);
|
||||||
|
|
||||||
thread->thread_id = NewThreadId();
|
thread->thread_id = NewThreadId();
|
||||||
thread->status = THREADSTATUS_DORMANT;
|
thread->status = ThreadStatus::Dormant;
|
||||||
thread->entry_point = entry_point;
|
thread->entry_point = entry_point;
|
||||||
thread->stack_top = stack_top;
|
thread->stack_top = stack_top;
|
||||||
thread->nominal_priority = thread->current_priority = priority;
|
thread->nominal_priority = thread->current_priority = priority;
|
||||||
|
@ -408,7 +408,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
|
||||||
ResetThreadContext(thread->context, stack_top, entry_point, arg);
|
ResetThreadContext(thread->context, stack_top, entry_point, arg);
|
||||||
|
|
||||||
ready_queue.push_back(thread->current_priority, thread.get());
|
ready_queue.push_back(thread->current_priority, thread.get());
|
||||||
thread->status = THREADSTATUS_READY;
|
thread->status = ThreadStatus::Ready;
|
||||||
|
|
||||||
return MakeResult<SharedPtr<Thread>>(std::move(thread));
|
return MakeResult<SharedPtr<Thread>>(std::move(thread));
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ void Thread::SetPriority(u32 priority) {
|
||||||
ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
|
ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
|
||||||
"Invalid priority value.");
|
"Invalid priority value.");
|
||||||
// If thread was ready, adjust queues
|
// If thread was ready, adjust queues
|
||||||
if (status == THREADSTATUS_READY)
|
if (status == ThreadStatus::Ready)
|
||||||
ready_queue.move(this, current_priority, priority);
|
ready_queue.move(this, current_priority, priority);
|
||||||
else
|
else
|
||||||
ready_queue.prepare(priority);
|
ready_queue.prepare(priority);
|
||||||
|
@ -436,7 +436,7 @@ void Thread::UpdatePriority() {
|
||||||
|
|
||||||
void Thread::BoostPriority(u32 priority) {
|
void Thread::BoostPriority(u32 priority) {
|
||||||
// If thread was ready, adjust queues
|
// If thread was ready, adjust queues
|
||||||
if (status == THREADSTATUS_READY)
|
if (status == ThreadStatus::Ready)
|
||||||
ready_queue.move(this, current_priority, priority);
|
ready_queue.move(this, current_priority, priority);
|
||||||
else
|
else
|
||||||
ready_queue.prepare(priority);
|
ready_queue.prepare(priority);
|
||||||
|
|
|
@ -31,16 +31,16 @@ enum ThreadProcessorId : s32 {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ThreadStatus {
|
enum ThreadStatus {
|
||||||
THREADSTATUS_RUNNING, ///< Currently running
|
Running, ///< Currently running
|
||||||
THREADSTATUS_READY, ///< Ready to run
|
Ready, ///< Ready to run
|
||||||
THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
|
WaitArb, ///< Waiting on an address arbiter
|
||||||
THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
|
WaitSleep, ///< Waiting due to a SleepThread SVC
|
||||||
THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request
|
WaitIPC, ///< Waiting for the reply from an IPC request
|
||||||
THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
|
WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
|
||||||
THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true
|
WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true
|
||||||
THREADSTATUS_WAIT_HLE_EVENT, ///< Waiting due to an HLE handler pausing the thread
|
WaitHleEvent, ///< Waiting due to an HLE handler pausing the thread
|
||||||
THREADSTATUS_DORMANT, ///< Created but not yet made ready
|
Dormant, ///< Created but not yet made ready
|
||||||
THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
|
Dead ///< Run to completion, or forcefully terminated
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ThreadWakeupReason {
|
enum class ThreadWakeupReason {
|
||||||
|
@ -178,16 +178,16 @@ public:
|
||||||
* with wait_all = true.
|
* with wait_all = true.
|
||||||
*/
|
*/
|
||||||
bool IsSleepingOnWaitAll() const {
|
bool IsSleepingOnWaitAll() const {
|
||||||
return status == THREADSTATUS_WAIT_SYNCH_ALL;
|
return status == ThreadStatus::WaitSynchAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ARM_Interface::ThreadContext> context;
|
std::unique_ptr<ARM_Interface::ThreadContext> context;
|
||||||
|
|
||||||
u32 thread_id;
|
u32 thread_id;
|
||||||
|
|
||||||
u32 status;
|
ThreadStatus status;
|
||||||
u32 entry_point;
|
VAddr entry_point;
|
||||||
u32 stack_top;
|
VAddr stack_top;
|
||||||
|
|
||||||
u32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
|
u32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
|
||||||
u32 current_priority; ///< Current thread priority, can be temporarily changed
|
u32 current_priority; ///< Current thread priority, can be temporarily changed
|
||||||
|
|
|
@ -38,9 +38,9 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
|
||||||
|
|
||||||
for (const auto& thread : waiting_threads) {
|
for (const auto& thread : waiting_threads) {
|
||||||
// The list of waiting threads must not contain threads that are not waiting to be awakened.
|
// The list of waiting threads must not contain threads that are not waiting to be awakened.
|
||||||
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
|
ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny ||
|
||||||
thread->status == THREADSTATUS_WAIT_SYNCH_ALL ||
|
thread->status == ThreadStatus::WaitSynchAll ||
|
||||||
thread->status == THREADSTATUS_WAIT_HLE_EVENT,
|
thread->status == ThreadStatus::WaitHleEvent,
|
||||||
"Inconsistent thread statuses in waiting_threads");
|
"Inconsistent thread statuses in waiting_threads");
|
||||||
|
|
||||||
if (thread->current_priority >= candidate_priority)
|
if (thread->current_priority >= candidate_priority)
|
||||||
|
@ -49,10 +49,10 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
|
||||||
if (ShouldWait(thread.get()))
|
if (ShouldWait(thread.get()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// A thread is ready to run if it's either in THREADSTATUS_WAIT_SYNCH_ANY or
|
// A thread is ready to run if it's either in ThreadStatus::WaitSynchAny or
|
||||||
// in THREADSTATUS_WAIT_SYNCH_ALL and the rest of the objects it is waiting on are ready.
|
// in ThreadStatus::WaitSynchAll and the rest of the objects it is waiting on are ready.
|
||||||
bool ready_to_run = true;
|
bool ready_to_run = true;
|
||||||
if (thread->status == THREADSTATUS_WAIT_SYNCH_ALL) {
|
if (thread->status == ThreadStatus::WaitSynchAll) {
|
||||||
ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
|
ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
|
||||||
[&thread](const SharedPtr<WaitObject>& object) {
|
[&thread](const SharedPtr<WaitObject>& object) {
|
||||||
return object->ShouldWait(thread.get());
|
return object->ShouldWait(thread.get());
|
||||||
|
|
|
@ -198,11 +198,11 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
|
||||||
handler_invoker(this, info->handler_callback, context);
|
handler_invoker(this, info->handler_callback, context);
|
||||||
|
|
||||||
auto thread = Kernel::GetCurrentThread();
|
auto thread = Kernel::GetCurrentThread();
|
||||||
ASSERT(thread->status == THREADSTATUS_RUNNING || thread->status == THREADSTATUS_WAIT_HLE_EVENT);
|
ASSERT(thread->status == ThreadStatus::Running || thread->status == ThreadStatus::WaitHleEvent);
|
||||||
// Only write the response immediately if the thread is still running. If the HLE handler put
|
// Only write the response immediately if the thread is still running. If the HLE handler put
|
||||||
// the thread to sleep then the writing of the command buffer will be deferred to the wakeup
|
// the thread to sleep then the writing of the command buffer will be deferred to the wakeup
|
||||||
// callback.
|
// callback.
|
||||||
if (thread->status == THREADSTATUS_RUNNING) {
|
if (thread->status == ThreadStatus::Running) {
|
||||||
context.WriteToOutgoingCommandBuffer(cmd_buf, *Kernel::g_current_process,
|
context.WriteToOutgoingCommandBuffer(cmd_buf, *Kernel::g_current_process,
|
||||||
Kernel::g_handle_table);
|
Kernel::g_handle_table);
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue