From 59add00d4a37a8f7b1bc8b4c39e46fae35150540 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sat, 22 Jan 2022 21:09:45 -0800
Subject: [PATCH] hle: kernel: KThread: Improve Increment/Decrement
 RunningThreadCount.

- Previously implementation was incorrect, and would occasionally underflow.
---
 src/core/hle/kernel/k_process.cpp | 26 +++++++++++++++-----------
 src/core/hle/kernel/k_process.h   |  8 +++-----
 src/core/hle/kernel/k_thread.cpp  | 11 +++--------
 3 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 265ac6fa1e..85c5069793 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -146,6 +146,13 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st
     // Open a reference to the resource limit.
     process->resource_limit->Open();
 
+    // Clear remaining fields.
+    process->num_running_threads = 0;
+    process->is_signaled = false;
+    process->exception_thread = nullptr;
+    process->is_suspended = false;
+    process->schedule_count = 0;
+
     return ResultSuccess;
 }
 
@@ -157,20 +164,17 @@ KResourceLimit* KProcess::GetResourceLimit() const {
     return resource_limit;
 }
 
-void KProcess::IncrementThreadCount() {
-    ASSERT(num_threads >= 0);
-    num_created_threads++;
-
-    if (const auto count = ++num_threads; count > peak_num_threads) {
-        peak_num_threads = count;
-    }
+void KProcess::IncrementRunningThreadCount() {
+    ASSERT(num_running_threads.load() >= 0);
+    ++num_running_threads;
 }
 
-void KProcess::DecrementThreadCount() {
-    ASSERT(num_threads > 0);
+void KProcess::DecrementRunningThreadCount() {
+    ASSERT(num_running_threads.load() > 0);
 
-    if (const auto count = --num_threads; count == 0) {
-        LOG_WARNING(Kernel, "Process termination is not fully implemented.");
+    if (const auto prev = num_running_threads--; prev == 1) {
+        // TODO(bunnei): Process termination to be implemented when multiprocess is supported.
+        UNIMPLEMENTED_MSG("KProcess termination is not implemennted!");
     }
 }
 
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index c2a6720211..38b4463508 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -235,8 +235,8 @@ public:
         ++schedule_count;
     }
 
-    void IncrementThreadCount();
-    void DecrementThreadCount();
+    void IncrementRunningThreadCount();
+    void DecrementRunningThreadCount();
 
     void SetRunningThread(s32 core, KThread* thread, u64 idle_count) {
         running_threads[core] = thread;
@@ -473,9 +473,7 @@ private:
     bool is_suspended{};
     bool is_initialized{};
 
-    std::atomic<s32> num_created_threads{};
-    std::atomic<u16> num_threads{};
-    u16 peak_num_threads{};
+    std::atomic<u16> num_running_threads{};
 
     std::array<KThread*, Core::Hardware::NUM_CPU_CORES> running_threads{};
     std::array<u64, Core::Hardware::NUM_CPU_CORES> running_thread_idle_counts{};
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index f42abb8a11..de3ffe0c75 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -215,7 +215,6 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
 
         parent = owner;
         parent->Open();
-        parent->IncrementThreadCount();
     }
 
     // Initialize thread context.
@@ -327,11 +326,6 @@ void KThread::Finalize() {
         }
     }
 
-    // Decrement the parent process's thread count.
-    if (parent != nullptr) {
-        parent->DecrementThreadCount();
-    }
-
     // Perform inherited finalization.
     KSynchronizationObject::Finalize();
 }
@@ -1011,7 +1005,7 @@ ResultCode KThread::Run() {
             if (IsUserThread() && IsSuspended()) {
                 this->UpdateState();
             }
-            owner->IncrementThreadCount();
+            owner->IncrementRunningThreadCount();
         }
 
         // Set our state and finish.
@@ -1026,10 +1020,11 @@ ResultCode KThread::Run() {
 void KThread::Exit() {
     ASSERT(this == GetCurrentThreadPointer(kernel));
 
-    // Release the thread resource hint from parent.
+    // Release the thread resource hint, running thread count from parent.
     if (parent != nullptr) {
         parent->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 0, 1);
         resource_limit_release_hint = true;
+        parent->DecrementRunningThreadCount();
     }
 
     // Perform termination.