early-access version 3029
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include "core/hle/kernel/k_worker_task_manager.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
#include "core/hle/kernel/svc_types.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
@@ -38,6 +39,9 @@
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline s32 TerminatingThreadPriority = Kernel::Svc::SystemThreadPriorityHighest - 1;
|
||||
|
||||
static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top,
|
||||
u32 entry_point, u32 arg) {
|
||||
context = {};
|
||||
@@ -241,7 +245,7 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack
|
||||
}
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg,
|
||||
@@ -254,7 +258,7 @@ Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_
|
||||
thread->host_context = std::make_shared<Common::Fiber>(std::move(init_func));
|
||||
thread->is_single_core = !Settings::values.use_multi_core.GetValue();
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KThread::InitializeDummyThread(KThread* thread) {
|
||||
@@ -264,31 +268,32 @@ Result KThread::InitializeDummyThread(KThread* thread) {
|
||||
// Initialize emulation parameters.
|
||||
thread->stack_parameters.disable_count = 0;
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KThread::InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core) {
|
||||
return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main,
|
||||
system.GetCpuManager().GetGuestActivateFunc());
|
||||
R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {},
|
||||
ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc()));
|
||||
}
|
||||
|
||||
Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) {
|
||||
return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main,
|
||||
system.GetCpuManager().GetIdleThreadStartFunc());
|
||||
R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {},
|
||||
ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc()));
|
||||
}
|
||||
|
||||
Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread,
|
||||
KThreadFunction func, uintptr_t arg, s32 virt_core) {
|
||||
return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority,
|
||||
system.GetCpuManager().GetShutdownThreadStartFunc());
|
||||
R_RETURN(InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr,
|
||||
ThreadType::HighPriority,
|
||||
system.GetCpuManager().GetShutdownThreadStartFunc()));
|
||||
}
|
||||
|
||||
Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func,
|
||||
uintptr_t arg, VAddr user_stack_top, s32 prio, s32 virt_core,
|
||||
KProcess* owner) {
|
||||
system.Kernel().GlobalSchedulerContext().AddThread(thread);
|
||||
return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner,
|
||||
ThreadType::User, system.GetCpuManager().GetGuestThreadFunc());
|
||||
R_RETURN(InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner,
|
||||
ThreadType::User, system.GetCpuManager().GetGuestThreadFunc()));
|
||||
}
|
||||
|
||||
void KThread::PostDestroy(uintptr_t arg) {
|
||||
@@ -538,7 +543,7 @@ Result KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
|
||||
*out_ideal_core = virtual_ideal_core_id;
|
||||
*out_affinity_mask = virtual_affinity_mask;
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
|
||||
@@ -554,7 +559,7 @@ Result KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask)
|
||||
*out_affinity_mask = original_physical_affinity_mask.GetAffinityMask();
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) {
|
||||
@@ -666,7 +671,7 @@ Result KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) {
|
||||
} while (retry_update);
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void KThread::SetBasePriority(s32 value) {
|
||||
@@ -839,7 +844,7 @@ Result KThread::SetActivity(Svc::ThreadActivity activity) {
|
||||
} while (thread_is_current);
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result KThread::GetThreadContext3(std::vector<u8>& out) {
|
||||
@@ -874,7 +879,7 @@ Result KThread::GetThreadContext3(std::vector<u8>& out) {
|
||||
}
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void KThread::AddWaiterImpl(KThread* thread) {
|
||||
@@ -1038,7 +1043,7 @@ Result KThread::Run() {
|
||||
// Set our state and finish.
|
||||
SetState(ThreadState::Runnable);
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,6 +1078,78 @@ void KThread::Exit() {
|
||||
UNREACHABLE_MSG("KThread::Exit() would return");
|
||||
}
|
||||
|
||||
Result KThread::Terminate() {
|
||||
ASSERT(this != GetCurrentThreadPointer(kernel));
|
||||
|
||||
// Request the thread terminate if it hasn't already.
|
||||
if (const auto new_state = this->RequestTerminate(); new_state != ThreadState::Terminated) {
|
||||
// If the thread isn't terminated, wait for it to terminate.
|
||||
s32 index;
|
||||
KSynchronizationObject* objects[] = {this};
|
||||
R_TRY(KSynchronizationObject::Wait(kernel, std::addressof(index), objects, 1,
|
||||
Svc::WaitInfinite));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
ThreadState KThread::RequestTerminate() {
|
||||
ASSERT(this != GetCurrentThreadPointer(kernel));
|
||||
|
||||
KScopedSchedulerLock sl{kernel};
|
||||
|
||||
// Determine if this is the first termination request.
|
||||
const bool first_request = [&]() -> bool {
|
||||
// Perform an atomic compare-and-swap from false to true.
|
||||
bool expected = false;
|
||||
return termination_requested.compare_exchange_strong(expected, true);
|
||||
}();
|
||||
|
||||
// If this is the first request, start termination procedure.
|
||||
if (first_request) {
|
||||
// If the thread is in initialized state, just change state to terminated.
|
||||
if (this->GetState() == ThreadState::Initialized) {
|
||||
thread_state = ThreadState::Terminated;
|
||||
return ThreadState::Terminated;
|
||||
}
|
||||
|
||||
// Register the terminating dpc.
|
||||
this->RegisterDpc(DpcFlag::Terminating);
|
||||
|
||||
// If the thread is pinned, unpin it.
|
||||
if (this->GetStackParameters().is_pinned) {
|
||||
this->GetOwnerProcess()->UnpinThread(this);
|
||||
}
|
||||
|
||||
// If the thread is suspended, continue it.
|
||||
if (this->IsSuspended()) {
|
||||
suspend_allowed_flags = 0;
|
||||
this->UpdateState();
|
||||
}
|
||||
|
||||
// Change the thread's priority to be higher than any system thread's.
|
||||
if (this->GetBasePriority() >= Svc::SystemThreadPriorityHighest) {
|
||||
this->SetBasePriority(TerminatingThreadPriority);
|
||||
}
|
||||
|
||||
// If the thread is runnable, send a termination interrupt to other cores.
|
||||
if (this->GetState() == ThreadState::Runnable) {
|
||||
if (const u64 core_mask =
|
||||
physical_affinity_mask.GetAffinityMask() & ~(1ULL << GetCurrentCoreId(kernel));
|
||||
core_mask != 0) {
|
||||
Kernel::KInterruptManager::SendInterProcessorInterrupt(kernel, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake up the thread.
|
||||
if (this->GetState() == ThreadState::Waiting) {
|
||||
wait_queue->CancelWait(this, ResultTerminationRequested, true);
|
||||
}
|
||||
}
|
||||
|
||||
return this->GetState();
|
||||
}
|
||||
|
||||
Result KThread::Sleep(s64 timeout) {
|
||||
ASSERT(!kernel.GlobalSchedulerContext().IsLocked());
|
||||
ASSERT(this == GetCurrentThreadPointer(kernel));
|
||||
@@ -1086,7 +1163,7 @@ Result KThread::Sleep(s64 timeout) {
|
||||
// Check if the thread should terminate.
|
||||
if (this->IsTerminationRequested()) {
|
||||
slp.CancelSleep();
|
||||
return ResultTerminationRequested;
|
||||
R_THROW(ResultTerminationRequested);
|
||||
}
|
||||
|
||||
// Wait for the sleep to end.
|
||||
@@ -1094,7 +1171,7 @@ Result KThread::Sleep(s64 timeout) {
|
||||
SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep);
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void KThread::IfDummyThreadTryWait() {
|
||||
|
||||
Reference in New Issue
Block a user