summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-12-31 22:45:16 -0700
committerAndreas Kling <kling@serenityos.org>2021-01-01 23:43:44 +0100
commita0c91719d85ca37f613acee5b7f3d16dca6b3ebd (patch)
tree5e63adbab1a1ea8ac8cc354afeca93867dce5c3a
parentbf9be3ec01a90fd9164162a9fdd4647c319c589a (diff)
downloadserenity-a0c91719d85ca37f613acee5b7f3d16dca6b3ebd.zip
Kernel: Restore thread count if thread cannot be fully created
-rw-r--r--Kernel/Thread.cpp14
-rw-r--r--Kernel/Thread.h1
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>