|
|
@ -534,6 +534,8 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
thread->CancelWait();
|
|
|
|
thread->CancelWait();
|
|
|
|
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1066,6 +1068,9 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
thread->SetActivity(static_cast<ThreadActivity>(activity));
|
|
|
|
thread->SetActivity(static_cast<ThreadActivity>(activity));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1147,7 +1152,8 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri
|
|
|
|
|
|
|
|
|
|
|
|
thread->SetPriority(priority);
|
|
|
|
thread->SetPriority(priority);
|
|
|
|
|
|
|
|
|
|
|
|
system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1503,7 +1509,8 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
|
|
|
|
thread->SetName(
|
|
|
|
thread->SetName(
|
|
|
|
fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle));
|
|
|
|
fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle));
|
|
|
|
|
|
|
|
|
|
|
|
system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
|
|
|
|
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1525,7 +1532,10 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
|
|
|
|
thread->ResumeFromWait();
|
|
|
|
thread->ResumeFromWait();
|
|
|
|
|
|
|
|
|
|
|
|
if (thread->GetStatus() == ThreadStatus::Ready) {
|
|
|
|
if (thread->GetStatus() == ThreadStatus::Ready) {
|
|
|
|
system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
Core::System::GetInstance().GlobalScheduler().SetReselectionPending();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
return RESULT_SUCCESS;
|
|
|
@ -1537,7 +1547,7 @@ static void ExitThread(Core::System& system) {
|
|
|
|
|
|
|
|
|
|
|
|
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
|
|
|
|
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
|
|
|
|
current_thread->Stop();
|
|
|
|
current_thread->Stop();
|
|
|
|
system.CurrentScheduler().RemoveThread(current_thread);
|
|
|
|
system.GlobalScheduler().RemoveThread(current_thread);
|
|
|
|
system.PrepareReschedule();
|
|
|
|
system.PrepareReschedule();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1557,13 +1567,13 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
|
|
|
|
if (nanoseconds <= 0) {
|
|
|
|
if (nanoseconds <= 0) {
|
|
|
|
switch (static_cast<SleepType>(nanoseconds)) {
|
|
|
|
switch (static_cast<SleepType>(nanoseconds)) {
|
|
|
|
case SleepType::YieldWithoutLoadBalancing:
|
|
|
|
case SleepType::YieldWithoutLoadBalancing:
|
|
|
|
scheduler.YieldWithoutLoadBalancing(current_thread);
|
|
|
|
current_thread->YieldType0();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case SleepType::YieldWithLoadBalancing:
|
|
|
|
case SleepType::YieldWithLoadBalancing:
|
|
|
|
scheduler.YieldWithLoadBalancing(current_thread);
|
|
|
|
current_thread->YieldType1();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case SleepType::YieldAndWaitForLoadBalancing:
|
|
|
|
case SleepType::YieldAndWaitForLoadBalancing:
|
|
|
|
scheduler.YieldAndWaitForLoadBalancing(current_thread);
|
|
|
|
current_thread->YieldType2();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
|
|
|
|
UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
|
|
|
@ -1632,24 +1642,16 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
|
|
|
|
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
|
|
|
|
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
|
|
|
|
condition_variable_addr, target);
|
|
|
|
condition_variable_addr, target);
|
|
|
|
|
|
|
|
|
|
|
|
const auto RetrieveWaitingThreads = [&system](std::size_t core_index,
|
|
|
|
|
|
|
|
std::vector<SharedPtr<Thread>>& waiting_threads,
|
|
|
|
|
|
|
|
VAddr condvar_addr) {
|
|
|
|
|
|
|
|
const auto& scheduler = system.Scheduler(core_index);
|
|
|
|
|
|
|
|
const auto& thread_list = scheduler.GetThreadList();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& thread : thread_list) {
|
|
|
|
|
|
|
|
if (thread->GetCondVarWaitAddress() == condvar_addr)
|
|
|
|
|
|
|
|
waiting_threads.push_back(thread);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Retrieve a list of all threads that are waiting for this condition variable.
|
|
|
|
// Retrieve a list of all threads that are waiting for this condition variable.
|
|
|
|
std::vector<SharedPtr<Thread>> waiting_threads;
|
|
|
|
std::vector<SharedPtr<Thread>> waiting_threads;
|
|
|
|
RetrieveWaitingThreads(0, waiting_threads, condition_variable_addr);
|
|
|
|
const auto& scheduler = Core::System::GetInstance().GlobalScheduler();
|
|
|
|
RetrieveWaitingThreads(1, waiting_threads, condition_variable_addr);
|
|
|
|
const auto& thread_list = scheduler.GetThreadList();
|
|
|
|
RetrieveWaitingThreads(2, waiting_threads, condition_variable_addr);
|
|
|
|
|
|
|
|
RetrieveWaitingThreads(3, waiting_threads, condition_variable_addr);
|
|
|
|
for (const auto& thread : thread_list) {
|
|
|
|
|
|
|
|
if (thread->GetCondVarWaitAddress() == condition_variable_addr)
|
|
|
|
|
|
|
|
waiting_threads.push_back(thread);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Sort them by priority, such that the highest priority ones come first.
|
|
|
|
// Sort them by priority, such that the highest priority ones come first.
|
|
|
|
std::sort(waiting_threads.begin(), waiting_threads.end(),
|
|
|
|
std::sort(waiting_threads.begin(), waiting_threads.end(),
|
|
|
|
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
|
|
|
|
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
|
|
|
@ -1704,7 +1706,8 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
|
|
|
|
thread->SetLockOwner(nullptr);
|
|
|
|
thread->SetLockOwner(nullptr);
|
|
|
|
thread->SetMutexWaitAddress(0);
|
|
|
|
thread->SetMutexWaitAddress(0);
|
|
|
|
thread->SetWaitHandle(0);
|
|
|
|
thread->SetWaitHandle(0);
|
|
|
|
system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Atomically signal that the mutex now has a waiting thread.
|
|
|
|
// Atomically signal that the mutex now has a waiting thread.
|
|
|
|
do {
|
|
|
|
do {
|
|
|
@ -1728,6 +1731,8 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
|
|
|
|
thread->SetStatus(ThreadStatus::WaitMutex);
|
|
|
|
thread->SetStatus(ThreadStatus::WaitMutex);
|
|
|
|
|
|
|
|
|
|
|
|
owner->AddMutexWaiter(thread);
|
|
|
|
owner->AddMutexWaiter(thread);
|
|
|
|
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1753,8 +1758,14 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const auto arbitration_type = static_cast<AddressArbiter::ArbitrationType>(type);
|
|
|
|
const auto arbitration_type = static_cast<AddressArbiter::ArbitrationType>(type);
|
|
|
|
auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter();
|
|
|
|
auto& address_arbiter =
|
|
|
|
return address_arbiter.WaitForAddress(address, arbitration_type, value, timeout);
|
|
|
|
system.Kernel().CurrentProcess()->GetAddressArbiter();
|
|
|
|
|
|
|
|
ResultCode result = address_arbiter.WaitForAddress(address, arbitration_type, value, timeout);
|
|
|
|
|
|
|
|
if (result == RESULT_SUCCESS)
|
|
|
|
|
|
|
|
Core::System::GetInstance()
|
|
|
|
|
|
|
|
.CpuCore(GetCurrentThread()->GetProcessorID())
|
|
|
|
|
|
|
|
.PrepareReschedule();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Signals to an address (via Address Arbiter)
|
|
|
|
// Signals to an address (via Address Arbiter)
|
|
|
@ -2040,7 +2051,10 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
|
|
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
return ERR_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
thread->ChangeCore(core, affinity_mask);
|
|
|
|
thread->ChangeCore(core, affinity_mask);
|
|
|
|
|
|
|
|
if (thread->GetProcessorID() >= 0)
|
|
|
|
|
|
|
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -2151,6 +2165,7 @@ static ResultCode SignalEvent(Core::System& system, Handle handle) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
writable_event->Signal();
|
|
|
|
writable_event->Signal();
|
|
|
|
|
|
|
|
Core::System::GetInstance().PrepareReschedule();
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|