kern: mostly implement thread exit

This commit is contained in:
Michael Scire 2020-07-10 18:39:53 -07:00
parent c8f71007ec
commit 4a767c9082
8 changed files with 126 additions and 3 deletions

View file

@ -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();

View file

@ -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);

View file

@ -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());

View file

@ -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");
}