mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-10 06:01:52 +00:00
kern: implement SvcSleepThread for ns > 0
This commit is contained in:
parent
f37eda6b86
commit
ca9327a120
5 changed files with 79 additions and 3 deletions
|
@ -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();
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -401,5 +401,16 @@ namespace ams::kern {
|
|||
SetSchedulerUpdateNeeded();
|
||||
}
|
||||
|
||||
void KScheduler::YieldWithoutCoreMigration() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void KScheduler::YieldWithCoreMigration() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void KScheduler::YieldToAnyThread() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue