kern SvcGetCurrentProcessorNumber, SvcSetProcessActivity, half of SvcSetThreadActivity

This commit is contained in:
Michael Scire 2020-07-23 03:04:43 -07:00 committed by SciresM
parent 23eed522d3
commit 1d4d637818
6 changed files with 148 additions and 7 deletions

View file

@ -158,6 +158,10 @@ namespace ams::kern {
return this->is_suspended; return this->is_suspended;
} }
constexpr void SetSuspended(bool suspended) {
this->is_suspended = suspended;
}
Result Terminate(); Result Terminate();
constexpr bool IsTerminated() const { constexpr bool IsTerminated() const {
@ -257,6 +261,8 @@ namespace ams::kern {
Result Reset(); Result Reset();
Result SetActivity(ams::svc::ProcessActivity activity);
void SetPreemptionState(); void SetPreemptionState();
Result SignalToAddress(KProcessAddress address) { Result SignalToAddress(KProcessAddress address) {

View file

@ -433,11 +433,14 @@ namespace ams::kern {
constexpr u32 GetSuspendFlags() const { return this->suspend_allowed_flags & this->suspend_request_flags; } constexpr u32 GetSuspendFlags() const { return this->suspend_allowed_flags & this->suspend_request_flags; }
constexpr bool IsSuspended() const { return this->GetSuspendFlags() != 0; } constexpr bool IsSuspended() const { return this->GetSuspendFlags() != 0; }
constexpr bool IsSuspendRequested(SuspendType type) const { return (this->suspend_request_flags & (1u << (ThreadState_SuspendShift + type))) != 0; }
void RequestSuspend(SuspendType type); void RequestSuspend(SuspendType type);
void Resume(SuspendType type); void Resume(SuspendType type);
void TrySuspend(); void TrySuspend();
void Continue(); void Continue();
Result SetActivity(ams::svc::ThreadActivity activity);
void ContinueIfHasKernelWaiters() { void ContinueIfHasKernelWaiters() {
if (this->GetNumKernelWaiters() > 0) { if (this->GetNumKernelWaiters() > 0) {
this->Continue(); this->Continue();

View file

@ -879,6 +879,48 @@ namespace ams::kern {
return ResultSuccess(); return ResultSuccess();
} }
Result KProcess::SetActivity(ams::svc::ProcessActivity activity) {
/* Lock ourselves and the scheduler. */
KScopedLightLock lk(this->state_lock);
KScopedLightLock list_lk(this->list_lock);
KScopedSchedulerLock sl;
/* Validate our state. */
R_UNLESS(this->state != State_Terminating, svc::ResultInvalidState());
R_UNLESS(this->state != State_Terminated, svc::ResultInvalidState());
/* Either pause or resume. */
if (activity == ams::svc::ProcessActivity_Paused) {
/* Verify that we're not suspended. */
R_UNLESS(!this->is_suspended, svc::ResultInvalidState());
/* Suspend all threads. */
auto end = this->GetThreadList().end();
for (auto it = this->GetThreadList().begin(); it != end; ++it) {
it->RequestSuspend(KThread::SuspendType_Process);
}
/* Set ourselves as suspended. */
this->SetSuspended(true);
} else {
MESOSPHERE_ASSERT(activity == ams::svc::ProcessActivity_Runnable);
/* Verify that we're suspended. */
R_UNLESS(this->is_suspended, svc::ResultInvalidState());
/* Resume all threads. */
auto end = this->GetThreadList().end();
for (auto it = this->GetThreadList().begin(); it != end; ++it) {
it->Resume(KThread::SuspendType_Process);
}
/* Set ourselves as resumed. */
this->SetSuspended(false);
}
return ResultSuccess();
}
KProcess::State KProcess::SetDebugObject(void *debug_object) { KProcess::State KProcess::SetDebugObject(void *debug_object) {
/* Attaching should only happen to non-null objects while the scheduler is locked. */ /* Attaching should only happen to non-null objects while the scheduler is locked. */
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread()); MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());

View file

@ -450,6 +450,7 @@ namespace ams::kern {
MESOSPHERE_ASSERT(this->parent != nullptr); MESOSPHERE_ASSERT(this->parent != nullptr);
MESOSPHERE_ASSERT(affinity_mask != 0); MESOSPHERE_ASSERT(affinity_mask != 0);
{ {
KScopedLightLock lk(this->activity_pause_lock);
KScopedSchedulerLock sl; KScopedSchedulerLock sl;
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0); MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
@ -491,6 +492,8 @@ namespace ams::kern {
} }
} }
/* TODO: Paused waiter list. */
return ResultSuccess(); return ResultSuccess();
} }
@ -610,6 +613,38 @@ namespace ams::kern {
KScheduler::OnThreadStateChanged(this, old_state); KScheduler::OnThreadStateChanged(this, old_state);
} }
Result KThread::SetActivity(ams::svc::ThreadActivity activity) {
/* Lock ourselves and the scheduler. */
KScopedLightLock lk(this->activity_pause_lock);
KScopedSchedulerLock sl;
/* Verify our state. */
const auto cur_state = this->GetState();
R_UNLESS((cur_state == ThreadState_Waiting || cur_state == ThreadState_Runnable), svc::ResultInvalidState());
/* Either pause or resume. */
if (activity == ams::svc::ThreadActivity_Paused) {
/* Verify that we're not suspended. */
R_UNLESS(!this->IsSuspendRequested(SuspendType_Thread), svc::ResultInvalidState());
/* Suspend. */
this->RequestSuspend(SuspendType_Thread);
/* TODO: Paused waiter list. */
MESOSPHERE_UNIMPLEMENTED();
} else {
MESOSPHERE_ASSERT(activity == ams::svc::ThreadActivity_Runnable);
/* Verify that we're suspended. */
R_UNLESS(this->IsSuspendRequested(SuspendType_Thread), svc::ResultInvalidState());
/* Resume. */
this->Resume(SuspendType_Thread);
}
return ResultSuccess();
}
void KThread::AddWaiterImpl(KThread *thread) { void KThread::AddWaiterImpl(KThread *thread) {
MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT_THIS();
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread()); MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());

View file

@ -21,28 +21,81 @@ namespace ams::kern::svc {
namespace { namespace {
constexpr bool IsValidThreadActivity(ams::svc::ThreadActivity thread_activity) {
switch (thread_activity) {
case ams::svc::ThreadActivity_Runnable:
case ams::svc::ThreadActivity_Paused:
return true;
default:
return false;
}
}
constexpr bool IsValidProcessActivity(ams::svc::ProcessActivity process_activity) {
switch (process_activity) {
case ams::svc::ProcessActivity_Runnable:
case ams::svc::ProcessActivity_Paused:
return true;
default:
return false;
}
}
Result SetThreadActivity(ams::svc::Handle thread_handle, ams::svc::ThreadActivity thread_activity) {
/* Validate the activity. */
R_UNLESS(IsValidThreadActivity(thread_activity), svc::ResultInvalidEnumValue());
/* Get the thread from its handle. */
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle());
/* Check that the activity is being set on a non-current thread for the current process. */
R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(), svc::ResultInvalidHandle());
R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(), svc::ResultBusy());
/* Set the activity. */
R_TRY(thread->SetActivity(thread_activity));
return ResultSuccess();
}
Result SetProcessActivity(ams::svc::Handle process_handle, ams::svc::ProcessActivity process_activity) {
/* Validate the activity. */
R_UNLESS(IsValidProcessActivity(process_activity), svc::ResultInvalidEnumValue());
/* Get the process from its handle. */
KScopedAutoObject process = GetCurrentProcess().GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle());
/* Check that the activity isn't being set on the current process. */
R_UNLESS(process.GetPointerUnsafe() != GetCurrentProcessPointer(), svc::ResultBusy());
/* Set the activity. */
R_TRY(process->SetActivity(process_activity));
return ResultSuccess();
}
} }
/* ============================= 64 ABI ============================= */ /* ============================= 64 ABI ============================= */
Result SetThreadActivity64(ams::svc::Handle thread_handle, ams::svc::ThreadActivity thread_activity) { Result SetThreadActivity64(ams::svc::Handle thread_handle, ams::svc::ThreadActivity thread_activity) {
MESOSPHERE_PANIC("Stubbed SvcSetThreadActivity64 was called."); return SetThreadActivity(thread_handle, thread_activity);
} }
Result SetProcessActivity64(ams::svc::Handle process_handle, ams::svc::ProcessActivity process_activity) { Result SetProcessActivity64(ams::svc::Handle process_handle, ams::svc::ProcessActivity process_activity) {
MESOSPHERE_PANIC("Stubbed SvcSetProcessActivity64 was called."); return SetProcessActivity(process_handle, process_activity);
} }
/* ============================= 64From32 ABI ============================= */ /* ============================= 64From32 ABI ============================= */
Result SetThreadActivity64From32(ams::svc::Handle thread_handle, ams::svc::ThreadActivity thread_activity) { Result SetThreadActivity64From32(ams::svc::Handle thread_handle, ams::svc::ThreadActivity thread_activity) {
MESOSPHERE_PANIC("Stubbed SvcSetThreadActivity64From32 was called."); return SetThreadActivity(thread_handle, thread_activity);
} }
Result SetProcessActivity64From32(ams::svc::Handle process_handle, ams::svc::ProcessActivity process_activity) { Result SetProcessActivity64From32(ams::svc::Handle process_handle, ams::svc::ProcessActivity process_activity) {
MESOSPHERE_PANIC("Stubbed SvcSetProcessActivity64From32 was called."); return SetProcessActivity(process_handle, process_activity);
} }
} }

View file

@ -21,20 +21,22 @@ namespace ams::kern::svc {
namespace { namespace {
int32_t GetCurrentProcessorNumber() {
return GetCurrentCoreId();
}
} }
/* ============================= 64 ABI ============================= */ /* ============================= 64 ABI ============================= */
int32_t GetCurrentProcessorNumber64() { int32_t GetCurrentProcessorNumber64() {
MESOSPHERE_PANIC("Stubbed SvcGetCurrentProcessorNumber64 was called."); return GetCurrentProcessorNumber();
} }
/* ============================= 64From32 ABI ============================= */ /* ============================= 64From32 ABI ============================= */
int32_t GetCurrentProcessorNumber64From32() { int32_t GetCurrentProcessorNumber64From32() {
MESOSPHERE_PANIC("Stubbed SvcGetCurrentProcessorNumber64From32 was called."); return GetCurrentProcessorNumber();
} }
} }