diff options
author | Tom <tomut@yahoo.com> | 2020-12-31 22:45:16 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-01 23:43:44 +0100 |
commit | a0c91719d85ca37f613acee5b7f3d16dca6b3ebd (patch) | |
tree | 5e63adbab1a1ea8ac8cc354afeca93867dce5c3a | |
parent | bf9be3ec01a90fd9164162a9fdd4647c319c589a (diff) | |
download | serenity-a0c91719d85ca37f613acee5b7f3d16dca6b3ebd.zip |
Kernel: Restore thread count if thread cannot be fully created
-rw-r--r-- | Kernel/Thread.cpp | 14 | ||||
-rw-r--r-- | Kernel/Thread.h | 1 |
2 files changed, 13 insertions, 2 deletions
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 2b7e1b7ea6..af14611dd3 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -25,6 +25,7 @@ */ #include <AK/Demangle.h> +#include <AK/ScopeGuard.h> #include <AK/StringBuilder.h> #include <AK/Time.h> #include <Kernel/Arch/i386/CPU.h> @@ -50,7 +51,11 @@ Thread::Thread(NonnullRefPtr<Process> process) : m_process(move(process)) , m_name(m_process->name()) { - if (m_process->m_thread_count.fetch_add(1, AK::MemoryOrder::memory_order_relaxed) == 0) { + bool is_first_thread = m_process->m_thread_count.fetch_add(1, AK::MemoryOrder::memory_order_relaxed) == 0; + ArmedScopeGuard guard([&]() { + drop_thread_count(is_first_thread); + }); + if (is_first_thread) { // First thread gets TID == PID m_tid = m_process->pid().value(); } else { @@ -112,6 +117,7 @@ Thread::Thread(NonnullRefPtr<Process> process) // The finalizer is responsible for dropping this reference once this // thread is ready to be cleaned up. ref(); + guard.disarm(); if (m_process->pid() != 0) Scheduler::init_thread(*this); @@ -374,11 +380,15 @@ void Thread::finalize() dbg() << backtrace_impl(); kfree_aligned(m_fpu_state); + drop_thread_count(false); +} +void Thread::drop_thread_count(bool initializing_first_thread) +{ auto thread_cnt_before = m_process->m_thread_count.fetch_sub(1, AK::MemoryOrder::memory_order_acq_rel); ASSERT(thread_cnt_before != 0); - if (thread_cnt_before == 1) + if (!initializing_first_thread && thread_cnt_before == 1) process().finalize(); } diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 7fd4ec0a22..8de108bd98 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -1216,6 +1216,7 @@ private: void donate_without_holding_big_lock(RefPtr<Thread>&, const char*); void yield_while_not_holding_big_lock(); void update_state_for_thread(Thread::State previous_state); + void drop_thread_count(bool); }; template<typename Callback> |