|
|
@ -71,26 +71,26 @@ void KSynchronizationObject::Finalize() {
|
|
|
|
KAutoObject::Finalize();
|
|
|
|
KAutoObject::Finalize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
|
|
|
|
Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
|
|
|
|
KSynchronizationObject** objects, const s32 num_objects,
|
|
|
|
KSynchronizationObject** objects, const s32 num_objects,
|
|
|
|
s64 timeout) {
|
|
|
|
s64 timeout) {
|
|
|
|
// Allocate space on stack for thread nodes.
|
|
|
|
// Allocate space on stack for thread nodes.
|
|
|
|
std::vector<ThreadListNode> thread_nodes(num_objects);
|
|
|
|
std::vector<ThreadListNode> thread_nodes(num_objects);
|
|
|
|
|
|
|
|
|
|
|
|
// Prepare for wait.
|
|
|
|
// Prepare for wait.
|
|
|
|
KThread* thread = GetCurrentThreadPointer(kernel_ctx);
|
|
|
|
KThread* thread = GetCurrentThreadPointer(kernel);
|
|
|
|
KHardwareTimer* timer{};
|
|
|
|
KHardwareTimer* timer{};
|
|
|
|
ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel_ctx, objects,
|
|
|
|
ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel, objects, thread_nodes.data(),
|
|
|
|
thread_nodes.data(), num_objects);
|
|
|
|
num_objects);
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Setup the scheduling lock and sleep.
|
|
|
|
// Setup the scheduling lock and sleep.
|
|
|
|
KScopedSchedulerLockAndSleep slp(kernel_ctx, std::addressof(timer), thread, timeout);
|
|
|
|
KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), thread, timeout);
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the thread should terminate.
|
|
|
|
// Check if the thread should terminate.
|
|
|
|
if (thread->IsTerminationRequested()) {
|
|
|
|
if (thread->IsTerminationRequested()) {
|
|
|
|
slp.CancelSleep();
|
|
|
|
slp.CancelSleep();
|
|
|
|
return ResultTerminationRequested;
|
|
|
|
R_THROW(ResultTerminationRequested);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if any of the objects are already signaled.
|
|
|
|
// Check if any of the objects are already signaled.
|
|
|
@ -100,21 +100,21 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
|
|
|
|
if (objects[i]->IsSignaled()) {
|
|
|
|
if (objects[i]->IsSignaled()) {
|
|
|
|
*out_index = i;
|
|
|
|
*out_index = i;
|
|
|
|
slp.CancelSleep();
|
|
|
|
slp.CancelSleep();
|
|
|
|
return ResultSuccess;
|
|
|
|
R_THROW(ResultSuccess);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the timeout is zero.
|
|
|
|
// Check if the timeout is zero.
|
|
|
|
if (timeout == 0) {
|
|
|
|
if (timeout == 0) {
|
|
|
|
slp.CancelSleep();
|
|
|
|
slp.CancelSleep();
|
|
|
|
return ResultTimedOut;
|
|
|
|
R_THROW(ResultTimedOut);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if waiting was canceled.
|
|
|
|
// Check if waiting was canceled.
|
|
|
|
if (thread->IsWaitCancelled()) {
|
|
|
|
if (thread->IsWaitCancelled()) {
|
|
|
|
slp.CancelSleep();
|
|
|
|
slp.CancelSleep();
|
|
|
|
thread->ClearWaitCancelled();
|
|
|
|
thread->ClearWaitCancelled();
|
|
|
|
return ResultCancelled;
|
|
|
|
R_THROW(ResultCancelled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add the waiters.
|
|
|
|
// Add the waiters.
|
|
|
@ -141,7 +141,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
|
|
|
|
*out_index = thread->GetSyncedIndex();
|
|
|
|
*out_index = thread->GetSyncedIndex();
|
|
|
|
|
|
|
|
|
|
|
|
// Get the wait result.
|
|
|
|
// Get the wait result.
|
|
|
|
return thread->GetWaitResult();
|
|
|
|
R_RETURN(thread->GetWaitResult());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_)
|
|
|
|
KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_)
|
|
|
@ -158,7 +158,7 @@ void KSynchronizationObject::NotifyAvailable(Result result) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Iterate over each thread.
|
|
|
|
// Iterate over each thread.
|
|
|
|
for (auto* cur_node = thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
|
|
|
for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
|
|
|
cur_node->thread->NotifyAvailable(this, result);
|
|
|
|
cur_node->thread->NotifyAvailable(this, result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -169,7 +169,7 @@ std::vector<KThread*> KSynchronizationObject::GetWaitingThreadsForDebugging() co
|
|
|
|
// If debugging, dump the list of waiters.
|
|
|
|
// If debugging, dump the list of waiters.
|
|
|
|
{
|
|
|
|
{
|
|
|
|
KScopedSchedulerLock lock(kernel);
|
|
|
|
KScopedSchedulerLock lock(kernel);
|
|
|
|
for (auto* cur_node = thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
|
|
|
for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
|
|
|
threads.emplace_back(cur_node->thread);
|
|
|
|
threads.emplace_back(cur_node->thread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|