kern: implement SvcSleepThread for ns > 0

This commit is contained in:
Michael Scire 2020-07-10 23:30:15 -07:00
parent f37eda6b86
commit ca9327a120
5 changed files with 79 additions and 3 deletions

View file

@ -122,8 +122,11 @@ namespace ams::kern {
static NOINLINE void OnThreadPriorityChanged(KThread *thread, s32 old_priority);
static NOINLINE void OnThreadAffinityMaskChanged(KThread *thread, const KAffinityMask &old_affinity, s32 old_core);
/* TODO: Yield operations */
static NOINLINE void RotateScheduledQueue(s32 priority, s32 core_id);
static NOINLINE void YieldWithoutCoreMigration();
static NOINLINE void YieldWithCoreMigration();
static NOINLINE void YieldToAnyThread();
private:
/* Instanced private API. */
void ScheduleImpl();

View file

@ -385,6 +385,8 @@ namespace ams::kern {
Result Run();
void Exit();
Result Sleep(s64 timeout);
ALWAYS_INLINE void *GetStackTop() const { return reinterpret_cast<StackParameters *>(this->kernel_stack_top) - 1; }
ALWAYS_INLINE void *GetKernelStackTop() const { return this->kernel_stack_top; }

View file

@ -401,5 +401,16 @@ namespace ams::kern {
SetSchedulerUpdateNeeded();
}
void KScheduler::YieldWithoutCoreMigration() {
MESOSPHERE_UNIMPLEMENTED();
}
void KScheduler::YieldWithCoreMigration() {
MESOSPHERE_UNIMPLEMENTED();
}
void KScheduler::YieldToAnyThread() {
MESOSPHERE_UNIMPLEMENTED();
}
}

View file

@ -664,6 +664,35 @@ namespace ams::kern {
MESOSPHERE_PANIC("KThread::Exit() would return");
}
Result KThread::Sleep(s64 timeout) {
MESOSPHERE_ASSERT_THIS();
MESOSPHERE_ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread());
MESOSPHERE_ASSERT(this == GetCurrentThreadPointer());
MESOSPHERE_ASSERT(timeout > 0);
KHardwareTimer *timer;
{
/* Setup the scheduling lock and sleep. */
KScopedSchedulerLockAndSleep slp(std::addressof(timer), this, timeout);
/* Check if the thread should terminate. */
if (this->IsTerminationRequested()) {
slp.CancelSleep();
return svc::ResultTerminationRequested();
}
/* Mark the thread as waiting. */
this->SetState(KThread::ThreadState_Waiting);
}
/* The lock/sleep is done. */
/* Cancel the timer. */
timer->CancelTask(this);
return ResultSuccess();
}
void KThread::SetState(ThreadState state) {
MESOSPHERE_ASSERT_THIS();

View file

@ -86,6 +86,37 @@ namespace ams::kern::svc {
MESOSPHERE_PANIC("Process survived call to exit");
}
void SleepThread(int64_t ns) {
/* When the input tick is positive, sleep. */
if (AMS_LIKELY(ns > 0)) {
/* Convert the timeout from nanoseconds to ticks. */
/* NOTE: Nintendo does not use this conversion logic in WaitSynchronization... */
s64 timeout;
const ams::svc::Tick offset_tick(TimeSpan::FromNanoSeconds(ns));
if (AMS_LIKELY(offset_tick > 0)) {
timeout = KHardwareTimer::GetTick() + offset_tick + 2;
if (AMS_UNLIKELY(timeout <= 0)) {
timeout = std::numeric_limits<s64>::max();
}
} else {
timeout = std::numeric_limits<s64>::max();
}
/* Sleep. */
/* NOTE: Nintendo does not check the result of this sleep. */
GetCurrentThread().Sleep(timeout);
} else if (ns == ams::svc::YieldType_WithoutCoreMigration) {
KScheduler::YieldWithoutCoreMigration();
} else if (ns == ams::svc::YieldType_WithCoreMigration) {
KScheduler::YieldWithCoreMigration();
} else if (ns == ams::svc::YieldType_ToAnyThread) {
KScheduler::YieldToAnyThread();
} else {
/* Nintendo does nothing at all if an otherwise invalid value is passed. */
}
}
Result GetThreadPriority(int32_t *out_priority, ams::svc::Handle thread_handle) {
/* Get the thread from its handle. */
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle);
@ -123,7 +154,7 @@ namespace ams::kern::svc {
}
void SleepThread64(int64_t ns) {
MESOSPHERE_PANIC("Stubbed SvcSleepThread64 was called.");
return SleepThread(ns);
}
Result GetThreadPriority64(int32_t *out_priority, ams::svc::Handle thread_handle) {
@ -177,7 +208,7 @@ namespace ams::kern::svc {
}
void SleepThread64From32(int64_t ns) {
MESOSPHERE_PANIC("Stubbed SvcSleepThread64From32 was called.");
return SleepThread(ns);
}
Result GetThreadPriority64From32(int32_t *out_priority, ams::svc::Handle thread_handle) {