mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-10 06:01:52 +00:00
kern: update pinning semantics for terminating threads
This commit is contained in:
parent
afb1d68d06
commit
6faa3534bf
4 changed files with 48 additions and 15 deletions
|
@ -127,14 +127,14 @@ namespace ams::kern {
|
||||||
Result StartTermination();
|
Result StartTermination();
|
||||||
void FinishTermination();
|
void FinishTermination();
|
||||||
|
|
||||||
void PinThread(s32 core_id, KThread *thread) {
|
ALWAYS_INLINE void PinThread(s32 core_id, KThread *thread) {
|
||||||
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
|
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
|
||||||
MESOSPHERE_ASSERT(thread != nullptr);
|
MESOSPHERE_ASSERT(thread != nullptr);
|
||||||
MESOSPHERE_ASSERT(m_pinned_threads[core_id] == nullptr);
|
MESOSPHERE_ASSERT(m_pinned_threads[core_id] == nullptr);
|
||||||
m_pinned_threads[core_id] = thread;
|
m_pinned_threads[core_id] = thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnpinThread(s32 core_id, KThread *thread) {
|
ALWAYS_INLINE void UnpinThread(s32 core_id, KThread *thread) {
|
||||||
MESOSPHERE_UNUSED(thread);
|
MESOSPHERE_UNUSED(thread);
|
||||||
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
|
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
|
||||||
MESOSPHERE_ASSERT(thread != nullptr);
|
MESOSPHERE_ASSERT(thread != nullptr);
|
||||||
|
@ -340,6 +340,7 @@ namespace ams::kern {
|
||||||
|
|
||||||
void PinCurrentThread();
|
void PinCurrentThread();
|
||||||
void UnpinCurrentThread();
|
void UnpinCurrentThread();
|
||||||
|
void UnpinThread(KThread *thread);
|
||||||
|
|
||||||
Result SignalToAddress(KProcessAddress address) {
|
Result SignalToAddress(KProcessAddress address) {
|
||||||
return m_cond_var.SignalToAddress(address);
|
return m_cond_var.SignalToAddress(address);
|
||||||
|
|
|
@ -521,6 +521,11 @@ namespace ams::kern::arch::arm64 {
|
||||||
{
|
{
|
||||||
KScopedInterruptEnable ei;
|
KScopedInterruptEnable ei;
|
||||||
|
|
||||||
|
/* Terminate the thread, if we should. */
|
||||||
|
if (GetCurrentThread().IsTerminationRequested()) {
|
||||||
|
GetCurrentThread().Exit();
|
||||||
|
}
|
||||||
|
|
||||||
HandleUserException(context, esr, far, afsr0, afsr1, data);
|
HandleUserException(context, esr, far, afsr0, afsr1, data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -34,6 +34,13 @@ namespace ams::kern {
|
||||||
KScopedLightLock proc_lk(process->GetListLock());
|
KScopedLightLock proc_lk(process->GetListLock());
|
||||||
KScopedSchedulerLock sl;
|
KScopedSchedulerLock sl;
|
||||||
|
|
||||||
|
if (thread_to_not_terminate != nullptr && process->GetPinnedThread(GetCurrentCoreId()) == thread_to_not_terminate) {
|
||||||
|
/* NOTE: Here Nintendo unpins the current thread instead of the thread_to_not_terminate. */
|
||||||
|
/* This is valid because the only caller which uses non-nullptr as argument uses GetCurrentThreadPointer(), */
|
||||||
|
/* but it's still notable because it seems incorrect at first glance. */
|
||||||
|
process->UnpinCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
auto &thread_list = process->GetThreadList();
|
auto &thread_list = process->GetThreadList();
|
||||||
for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
|
for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
|
||||||
if (KThread *thread = std::addressof(*it); thread != thread_to_not_terminate) {
|
if (KThread *thread = std::addressof(*it); thread != thread_to_not_terminate) {
|
||||||
|
@ -1020,12 +1027,15 @@ namespace ams::kern {
|
||||||
const s32 core_id = GetCurrentCoreId();
|
const s32 core_id = GetCurrentCoreId();
|
||||||
KThread *cur_thread = GetCurrentThreadPointer();
|
KThread *cur_thread = GetCurrentThreadPointer();
|
||||||
|
|
||||||
/* Pin it. */
|
/* If the thread isn't terminated, pin it. */
|
||||||
this->PinThread(core_id, cur_thread);
|
if (!cur_thread->IsTerminationRequested()) {
|
||||||
cur_thread->Pin();
|
/* Pin it. */
|
||||||
|
this->PinThread(core_id, cur_thread);
|
||||||
|
cur_thread->Pin();
|
||||||
|
|
||||||
/* An update is needed. */
|
/* An update is needed. */
|
||||||
KScheduler::SetSchedulerUpdateNeeded();
|
KScheduler::SetSchedulerUpdateNeeded();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KProcess::UnpinCurrentThread() {
|
void KProcess::UnpinCurrentThread() {
|
||||||
|
@ -1043,6 +1053,20 @@ namespace ams::kern {
|
||||||
KScheduler::SetSchedulerUpdateNeeded();
|
KScheduler::SetSchedulerUpdateNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KProcess::UnpinThread(KThread *thread) {
|
||||||
|
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||||
|
|
||||||
|
/* Get the thread's core id. */
|
||||||
|
const auto core_id = thread->GetActiveCore();
|
||||||
|
|
||||||
|
/* Unpin it. */
|
||||||
|
this->UnpinThread(core_id, thread);
|
||||||
|
thread->Unpin();
|
||||||
|
|
||||||
|
/* An update is needed. */
|
||||||
|
KScheduler::SetSchedulerUpdateNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
Result KProcess::GetThreadList(s32 *out_num_threads, ams::kern::svc::KUserPointer<u64 *> out_thread_ids, s32 max_out_count) {
|
Result KProcess::GetThreadList(s32 *out_num_threads, ams::kern::svc::KUserPointer<u64 *> out_thread_ids, s32 max_out_count) {
|
||||||
/* Lock the list. */
|
/* Lock the list. */
|
||||||
KScopedLightLock lk(m_list_lock);
|
KScopedLightLock lk(m_list_lock);
|
||||||
|
|
|
@ -483,19 +483,17 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow performing thread suspension (if termination hasn't been requested). */
|
/* Allow performing thread suspension (if termination hasn't been requested). */
|
||||||
{
|
if (!this->IsTerminationRequested()) {
|
||||||
/* Update our allow flags. */
|
/* Update our allow flags. */
|
||||||
if (!this->IsTerminationRequested()) {
|
m_suspend_allowed_flags |= (1 << (SuspendType_Thread + ThreadState_SuspendShift));
|
||||||
m_suspend_allowed_flags |= (1 << (SuspendType_Thread + ThreadState_SuspendShift));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update our state. */
|
/* Update our state. */
|
||||||
this->UpdateState();
|
this->UpdateState();
|
||||||
}
|
|
||||||
|
|
||||||
/* Update our SVC access permissions. */
|
/* Update our SVC access permissions. */
|
||||||
MESOSPHERE_ASSERT(m_parent != nullptr);
|
MESOSPHERE_ASSERT(m_parent != nullptr);
|
||||||
m_parent->CopyUnpinnedSvcPermissionsTo(this->GetStackParameters());
|
m_parent->CopyUnpinnedSvcPermissionsTo(this->GetStackParameters());
|
||||||
|
}
|
||||||
|
|
||||||
/* Resume any threads that began waiting on us while we were pinned. */
|
/* Resume any threads that began waiting on us while we were pinned. */
|
||||||
for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) {
|
for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) {
|
||||||
|
@ -1218,6 +1216,11 @@ namespace ams::kern {
|
||||||
/* Register the terminating dpc. */
|
/* Register the terminating dpc. */
|
||||||
this->RegisterDpc(DpcFlag_Terminating);
|
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 the thread is suspended, continue it. */
|
||||||
if (this->IsSuspended()) {
|
if (this->IsSuspended()) {
|
||||||
m_suspend_allowed_flags = 0;
|
m_suspend_allowed_flags = 0;
|
||||||
|
|
Loading…
Reference in a new issue