1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-12-18 00:12:03 +00:00

kern: implement SvcCreateThread, SvcStartThread

This commit is contained in:
Michael Scire 2020-07-09 18:54:09 -07:00
parent 9503aae522
commit 7f4c6ae9e7
5 changed files with 95 additions and 6 deletions

View file

@ -66,6 +66,14 @@ namespace ams::kern::arch::arm64 {
static void FpuContextSwitchHandler(KThread *thread); static void FpuContextSwitchHandler(KThread *thread);
u32 GetFpcr() const { return this->fpcr; }
u32 GetFpsr() const { return this->fpsr; }
void SetFpcr(u32 v) { this->fpcr = v; }
void SetFpsr(u32 v) { this->fpsr = v; }
void CloneFpuStatus();
/* TODO: More methods (especially FPU management) */ /* TODO: More methods (especially FPU management) */
}; };

View file

@ -64,7 +64,7 @@ namespace ams::kern {
size_t system_resource_num_pages{}; size_t system_resource_num_pages{};
size_t memory_release_hint{}; size_t memory_release_hint{};
State state{}; State state{};
KLightLock lock{}; KLightLock state_lock{};
KLightLock list_lock{}; KLightLock list_lock{};
KConditionVariable cond_var{}; KConditionVariable cond_var{};
KAddressArbiter address_arbiter{}; KAddressArbiter address_arbiter{};
@ -133,8 +133,11 @@ namespace ams::kern {
constexpr u64 GetCoreMask() const { return this->capabilities.GetCoreMask(); } constexpr u64 GetCoreMask() const { return this->capabilities.GetCoreMask(); }
constexpr u64 GetPriorityMask() const { return this->capabilities.GetPriorityMask(); } constexpr u64 GetPriorityMask() const { return this->capabilities.GetPriorityMask(); }
constexpr s32 GetIdealCoreId() const { return this->ideal_core_id; }
constexpr void SetIdealCoreId(s32 core_id) { this->ideal_core_id = core_id; } constexpr void SetIdealCoreId(s32 core_id) { this->ideal_core_id = core_id; }
constexpr bool CheckThreadPriority(s32 prio) const { return ((1ul << prio) & this->GetPriorityMask()) != 0; }
constexpr bool Is64Bit() const { return this->flags & ams::svc::CreateProcessFlag_Is64Bit; } constexpr bool Is64Bit() const { return this->flags & ams::svc::CreateProcessFlag_Is64Bit; }
constexpr KProcessAddress GetEntryPoint() const { return this->code_address; } constexpr KProcessAddress GetEntryPoint() const { return this->code_address; }
@ -159,6 +162,9 @@ namespace ams::kern {
void ReleaseResource(ams::svc::LimitableResource which, s64 value); void ReleaseResource(ams::svc::LimitableResource which, s64 value);
void ReleaseResource(ams::svc::LimitableResource which, s64 value, s64 hint); void ReleaseResource(ams::svc::LimitableResource which, s64 value, s64 hint);
constexpr KLightLock &GetStateLock() { return this->state_lock; }
constexpr KLightLock &GetListLock() { return this->list_lock; }
constexpr KProcessPageTable &GetPageTable() { return this->page_table; } constexpr KProcessPageTable &GetPageTable() { return this->page_table; }
constexpr const KProcessPageTable &GetPageTable() const { return this->page_table; } constexpr const KProcessPageTable &GetPageTable() const { return this->page_table; }

View file

@ -173,4 +173,19 @@ namespace ams::kern::arch::arm64 {
} }
} }
void KThreadContext::CloneFpuStatus() {
u64 pcr, psr;
cpu::InstructionMemoryBarrier();
if (IsFpuEnabled()) {
__asm__ __volatile__("mrs %[pcr], fpcr" : [pcr]"=r"(pcr) :: "memory");
__asm__ __volatile__("mrs %[psr], fpsr" : [psr]"=r"(psr) :: "memory");
} else {
pcr = GetCurrentThread().GetContext().GetFpcr();
psr = GetCurrentThread().GetContext().GetFpsr();
}
this->SetFpcr(pcr);
this->SetFpsr(psr);
}
} }

View file

@ -306,7 +306,7 @@ namespace ams::kern {
MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT_THIS();
/* Lock ourselves, to prevent concurrent access. */ /* Lock ourselves, to prevent concurrent access. */
KScopedLightLock lk(this->lock); KScopedLightLock lk(this->state_lock);
/* Validate that we're in a state where we can initialize. */ /* Validate that we're in a state where we can initialize. */
const auto state = this->state; const auto state = this->state;

View file

@ -21,6 +21,66 @@ namespace ams::kern::svc {
namespace { namespace {
constexpr bool IsValidCoreId(int32_t core_id) {
return (0 <= core_id && core_id < static_cast<int32_t>(cpu::NumCores));
}
Result CreateThread(ams::svc::Handle *out, ams::svc::ThreadFunc f, uintptr_t arg, uintptr_t stack_bottom, int32_t priority, int32_t core_id) {
/* Adjust core id, if it's the default magic. */
KProcess &process = GetCurrentProcess();
if (core_id == ams::svc::IdealCoreUseProcessValue) {
core_id = process.GetIdealCoreId();
}
/* Validate arguments. */
R_UNLESS(IsValidCoreId(core_id), svc::ResultInvalidCoreId());
R_UNLESS(((1ul << core_id) & process.GetCoreMask()) != 0, svc::ResultInvalidCoreId());
R_UNLESS(ams::svc::HighestThreadPriority <= priority && priority <= ams::svc::LowestThreadPriority, svc::ResultInvalidPriority());
R_UNLESS(process.CheckThreadPriority(priority), svc::ResultInvalidPriority());
/* Reserve a new session from the process resource limit (waiting up to 100ms). */
KScopedResourceReservation thread_reservation(std::addressof(process), ams::svc::LimitableResource_ThreadCountMax, 1, KHardwareTimer::GetTick() + ams::svc::Tick(TimeSpan::FromMilliSeconds(100)));
R_UNLESS(thread_reservation.Succeeded(), svc::ResultLimitReached());
/* Create the thread. */
KScopedAutoObject thread = KThread::Create();
R_UNLESS(thread.IsNotNull(), svc::ResultOutOfResource());
/* Initialize the thread. */
{
KScopedLightLock lk(process.GetStateLock());
R_TRY(KThread::InitializeUserThread(thread.GetPointerUnsafe(), reinterpret_cast<KThreadFunction>(static_cast<uintptr_t>(f)), arg, stack_bottom, priority, core_id, std::addressof(process)));
}
/* Commit the thread reservation. */
thread_reservation.Commit();
/* Clone the current fpu status to the new thread. */
thread->GetContext().CloneFpuStatus();
/* Register the new thread. */
R_TRY(KThread::Register(thread.GetPointerUnsafe()));
/* Add the thread to the handle table. */
R_TRY(process.GetHandleTable().Add(out, thread.GetPointerUnsafe()));
return ResultSuccess();
}
Result StartThread(ams::svc::Handle thread_handle) {
/* Get the thread from its handle. */
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle());
/* Try to start the thread. */
R_TRY(thread->Run());
/* If we succeeded, persist a reference to the thread. */
thread->Open();
return ResultSuccess();
}
Result GetThreadPriority(int32_t *out_priority, ams::svc::Handle thread_handle) { Result GetThreadPriority(int32_t *out_priority, ams::svc::Handle thread_handle) {
/* Get the thread from its handle. */ /* Get the thread from its handle. */
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle); KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle);
@ -46,11 +106,11 @@ namespace ams::kern::svc {
/* ============================= 64 ABI ============================= */ /* ============================= 64 ABI ============================= */
Result CreateThread64(ams::svc::Handle *out_handle, ams::svc::ThreadFunc func, ams::svc::Address arg, ams::svc::Address stack_bottom, int32_t priority, int32_t core_id) { Result CreateThread64(ams::svc::Handle *out_handle, ams::svc::ThreadFunc func, ams::svc::Address arg, ams::svc::Address stack_bottom, int32_t priority, int32_t core_id) {
MESOSPHERE_PANIC("Stubbed SvcCreateThread64 was called."); return CreateThread(out_handle, func, arg, stack_bottom, priority, core_id);
} }
Result StartThread64(ams::svc::Handle thread_handle) { Result StartThread64(ams::svc::Handle thread_handle) {
MESOSPHERE_PANIC("Stubbed SvcStartThread64 was called."); return StartThread(thread_handle);
} }
void ExitThread64() { void ExitThread64() {
@ -100,11 +160,11 @@ namespace ams::kern::svc {
/* ============================= 64From32 ABI ============================= */ /* ============================= 64From32 ABI ============================= */
Result CreateThread64From32(ams::svc::Handle *out_handle, ams::svc::ThreadFunc func, ams::svc::Address arg, ams::svc::Address stack_bottom, int32_t priority, int32_t core_id) { Result CreateThread64From32(ams::svc::Handle *out_handle, ams::svc::ThreadFunc func, ams::svc::Address arg, ams::svc::Address stack_bottom, int32_t priority, int32_t core_id) {
MESOSPHERE_PANIC("Stubbed SvcCreateThread64From32 was called."); return CreateThread(out_handle, func, arg, stack_bottom, priority, core_id);
} }
Result StartThread64From32(ams::svc::Handle thread_handle) { Result StartThread64From32(ams::svc::Handle thread_handle) {
MESOSPHERE_PANIC("Stubbed SvcStartThread64From32 was called."); return StartThread(thread_handle);
} }
void ExitThread64From32() { void ExitThread64From32() {