mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-09 21:51:45 +00:00
kern: mostly implement thread exit
This commit is contained in:
parent
c8f71007ec
commit
4a767c9082
8 changed files with 126 additions and 3 deletions
|
@ -147,6 +147,10 @@ namespace ams::kern {
|
|||
return this->is_suspended;
|
||||
}
|
||||
|
||||
bool EnterUserException();
|
||||
bool LeaveUserException();
|
||||
bool ReleaseUserException(KThread *thread);
|
||||
|
||||
KThread *GetPreemptionStatePinnedThread(s32 core_id) const {
|
||||
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
|
||||
return this->pinned_threads[core_id];
|
||||
|
@ -186,6 +190,14 @@ namespace ams::kern {
|
|||
void IncrementThreadCount();
|
||||
void DecrementThreadCount();
|
||||
|
||||
void ClearRunningThread(KThread *thread) {
|
||||
for (size_t i = 0; i < util::size(this->running_threads); ++i) {
|
||||
if (this->running_threads[i] == thread) {
|
||||
this->running_threads[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterThread(KThread *thread);
|
||||
void UnregisterThread(KThread *thread);
|
||||
|
||||
|
|
|
@ -116,6 +116,8 @@ namespace ams::kern {
|
|||
}
|
||||
}
|
||||
|
||||
static NOINLINE void ClearPreviousThread(KThread *thread);
|
||||
|
||||
static NOINLINE void OnThreadStateChanged(KThread *thread, KThread::ThreadState old_state);
|
||||
static NOINLINE void OnThreadPriorityChanged(KThread *thread, s32 old_priority);
|
||||
static NOINLINE void OnThreadAffinityMaskChanged(KThread *thread, const KAffinityMask &old_affinity, s32 old_core);
|
||||
|
|
|
@ -268,6 +268,9 @@ namespace ams::kern {
|
|||
ALWAYS_INLINE void AddWaiterImpl(KThread *thread);
|
||||
ALWAYS_INLINE void RemoveWaiterImpl(KThread *thread);
|
||||
ALWAYS_INLINE static void RestorePriority(KThread *thread);
|
||||
|
||||
void StartTermination();
|
||||
void FinishTermination();
|
||||
public:
|
||||
constexpr u64 GetThreadId() const { return this->thread_id; }
|
||||
|
||||
|
|
|
@ -94,6 +94,10 @@ namespace ams::kern {
|
|||
static KThread &GetMainThread(s32 core_id);
|
||||
static KThread &GetIdleThread(s32 core_id);
|
||||
|
||||
static ALWAYS_INLINE KCurrentContext &GetCurrentContext(s32 core_id) {
|
||||
return GetCoreLocalContext(core_id).current;
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE KScheduler &GetScheduler() {
|
||||
return GetCoreLocalContext().scheduler;
|
||||
}
|
||||
|
|
|
@ -613,7 +613,7 @@ namespace ams::kern {
|
|||
|
||||
/* Apply the memory block updates. */
|
||||
this->memory_block_manager.Update(std::addressof(src_allocator), src_address, num_pages, src_state, new_src_perm, new_src_attr);
|
||||
this->memory_block_manager.Update(std::addressof(dst_allocator), dst_address, num_pages, KMemoryState_None, KMemoryPermission_UserReadWrite, KMemoryAttribute_None);
|
||||
this->memory_block_manager.Update(std::addressof(dst_allocator), dst_address, num_pages, KMemoryState_Stack, KMemoryPermission_UserReadWrite, KMemoryAttribute_None);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
|
|
@ -272,6 +272,25 @@ namespace ams::kern {
|
|||
}
|
||||
}
|
||||
|
||||
bool KProcess::EnterUserException() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
bool KProcess::LeaveUserException() {
|
||||
return this->ReleaseUserException(GetCurrentThreadPointer());
|
||||
}
|
||||
|
||||
bool KProcess::ReleaseUserException(KThread *thread) {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->exception_thread == thread) {
|
||||
/* TODO */
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void KProcess::RegisterThread(KThread *thread) {
|
||||
KScopedLightLock lk(this->list_lock);
|
||||
|
||||
|
|
|
@ -262,6 +262,16 @@ namespace ams::kern {
|
|||
cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress()));
|
||||
}
|
||||
|
||||
void KScheduler::ClearPreviousThread(KThread *thread) {
|
||||
MESOSPHERE_ASSERT(IsSchedulerLockedByCurrentThread());
|
||||
for (size_t i = 0; i < cpu::NumCores; ++i) {
|
||||
std::atomic<KThread *> *prev_thread_ptr = reinterpret_cast<std::atomic<KThread *> *>(std::addressof(Kernel::GetScheduler(static_cast<s32>(i)).prev_thread));
|
||||
static_assert(sizeof(*prev_thread_ptr) == sizeof(KThread *));
|
||||
|
||||
prev_thread_ptr->compare_exchange_weak(thread, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void KScheduler::OnThreadStateChanged(KThread *thread, KThread::ThreadState old_state) {
|
||||
MESOSPHERE_ASSERT(IsSchedulerLockedByCurrentThread());
|
||||
|
||||
|
|
|
@ -278,8 +278,60 @@ namespace ams::kern {
|
|||
this->Wakeup();
|
||||
}
|
||||
|
||||
void KThread::StartTermination() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Release user exception, if relevant. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->ReleaseUserException(this);
|
||||
if (this->parent->GetPreemptionStatePinnedThread(GetCurrentCoreId()) == this) {
|
||||
/* TODO: this->parent->UnpinCurrentThread(); */
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set state to terminated. */
|
||||
this->SetState(KThread::ThreadState_Terminated);
|
||||
|
||||
/* Clear the thread's status as running in parent. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->ClearRunningThread(this);
|
||||
}
|
||||
|
||||
/* Signal. */
|
||||
this->signaled = true;
|
||||
this->NotifyAvailable();
|
||||
|
||||
/* TODO: On Thread Termination handler */
|
||||
|
||||
/* Clear previous thread in KScheduler. */
|
||||
KScheduler::ClearPreviousThread(this);
|
||||
|
||||
/* Register terminated dpc flag. */
|
||||
this->RegisterDpc(DpcFlag_Terminated);
|
||||
}
|
||||
|
||||
void KThread::FinishTermination() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Ensure that the thread is not executing on any core. */
|
||||
if (this->parent != nullptr) {
|
||||
for (size_t i = 0; i < cpu::NumCores; ++i) {
|
||||
KThread *core_thread;
|
||||
do {
|
||||
core_thread = Kernel::GetCurrentContext(i).current_thread.load(std::memory_order_acquire);
|
||||
} while (core_thread == this);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the thread. */
|
||||
this->Close();
|
||||
}
|
||||
|
||||
void KThread::DoWorkerTask() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
/* Finish the termination that was begun by Exit(). */
|
||||
this->FinishTermination();
|
||||
}
|
||||
|
||||
void KThread::DisableCoreMigration() {
|
||||
|
@ -586,7 +638,28 @@ namespace ams::kern {
|
|||
void KThread::Exit() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
MESOSPHERE_ASSERT(this == GetCurrentThreadPointer());
|
||||
|
||||
/* TODO: KDebug::OnExitThread(this); */
|
||||
|
||||
/* Release the thread resource hint from parent. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->ReleaseResource(ams::svc::LimitableResource_ThreadCountMax, 0, 1);
|
||||
}
|
||||
|
||||
/* Perform termination. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Disallow all suspension. */
|
||||
this->suspend_allowed_flags = 0;
|
||||
|
||||
/* Start termination. */
|
||||
this->StartTermination();
|
||||
|
||||
/* Register the thread as a work task. */
|
||||
KWorkerTaskManager::AddTask(KWorkerTaskManager::WorkerType_Exit, this);
|
||||
}
|
||||
|
||||
MESOSPHERE_PANIC("KThread::Exit() would return");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue