summaryrefslogtreecommitdiff
path: root/Kernel/Thread.cpp
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-08-01 20:04:56 -0600
committerAndreas Kling <kling@serenityos.org>2020-08-02 17:15:11 +0200
commit538b985487fd958a7e8663a32867ac39d6643d04 (patch)
tree50b4b97f8a469047cb97f5d64ffe98218c854ccb /Kernel/Thread.cpp
parent5bbf6ed46b7df3b649e4e940690a1479758ef8cf (diff)
downloadserenity-538b985487fd958a7e8663a32867ac39d6643d04.zip
Kernel: Remove ProcessInspectionHandle and make Process RefCounted
By making the Process class RefCounted we don't really need ProcessInspectionHandle anymore. This also fixes some race conditions where a Process may be deleted while still being used by ProcFS. Also make sure to acquire the Process' lock when accessing regions. Last but not least, there's no reason why a thread can't be scheduled while being inspected, though in practice it won't happen anyway because the scheduler lock is held at the same time.
Diffstat (limited to 'Kernel/Thread.cpp')
-rw-r--r--Kernel/Thread.cpp66
1 files changed, 17 insertions, 49 deletions
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index f9044109f4..00084c645c 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -46,27 +46,18 @@
namespace Kernel {
-HashTable<Thread*>& thread_table()
+Thread::Thread(NonnullRefPtr<Process> process)
+ : m_process(move(process))
+ , m_name(m_process->name())
{
- ASSERT_INTERRUPTS_DISABLED();
- static HashTable<Thread*>* table;
- if (!table)
- table = new HashTable<Thread*>;
- return *table;
-}
-
-Thread::Thread(Process& process)
- : m_process(process)
- , m_name(process.name())
-{
- if (m_process.m_thread_count.fetch_add(1, AK::MemoryOrder::memory_order_acq_rel) == 0) {
+ if (m_process->m_thread_count.fetch_add(1, AK::MemoryOrder::memory_order_acq_rel) == 0) {
// First thread gets TID == PID
- m_tid = process.pid();
+ m_tid = m_process->pid();
} else {
m_tid = Process::allocate_pid();
}
#ifdef THREAD_DEBUG
- dbg() << "Created new thread " << process.name() << "(" << process.pid() << ":" << m_tid << ")";
+ dbg() << "Created new thread " << m_process->name() << "(" << m_process->pid() << ":" << m_tid << ")";
#endif
set_default_signal_dispositions();
m_fpu_state = (FPUState*)kmalloc_aligned(sizeof(FPUState), 16);
@@ -77,7 +68,7 @@ Thread::Thread(Process& process)
// Only IF is set when a process boots.
m_tss.eflags = 0x0202;
- if (m_process.is_ring0()) {
+ if (m_process->is_ring0()) {
m_tss.cs = GDT_SELECTOR_CODE0;
m_tss.ds = GDT_SELECTOR_DATA0;
m_tss.es = GDT_SELECTOR_DATA0;
@@ -93,14 +84,14 @@ Thread::Thread(Process& process)
m_tss.gs = GDT_SELECTOR_TLS | 3;
}
- m_tss.cr3 = m_process.page_directory().cr3();
+ m_tss.cr3 = m_process->page_directory().cr3();
m_kernel_stack_region = MM.allocate_kernel_region(default_kernel_stack_size, String::format("Kernel Stack (Thread %d)", m_tid), Region::Access::Read | Region::Access::Write, false, true);
m_kernel_stack_region->set_stack(true);
m_kernel_stack_base = m_kernel_stack_region->vaddr().get();
m_kernel_stack_top = m_kernel_stack_region->vaddr().offset(default_kernel_stack_size).get() & 0xfffffff8u;
- if (m_process.is_ring0()) {
+ if (m_process->is_ring0()) {
m_tss.esp = m_tss.esp0 = m_kernel_stack_top;
} else {
// Ring 3 processes get a separate stack for ring 0.
@@ -109,22 +100,15 @@ Thread::Thread(Process& process)
m_tss.esp0 = m_kernel_stack_top;
}
- if (m_process.pid() != 0) {
- InterruptDisabler disabler;
- thread_table().set(this);
+ if (m_process->pid() != 0)
Scheduler::init_thread(*this);
- }
}
Thread::~Thread()
{
kfree_aligned(m_fpu_state);
- {
- InterruptDisabler disabler;
- thread_table().remove(this);
- }
- auto thread_cnt_before = m_process.m_thread_count.fetch_sub(1, AK::MemoryOrder::memory_order_acq_rel);
+ auto thread_cnt_before = m_process->m_thread_count.fetch_sub(1, AK::MemoryOrder::memory_order_acq_rel);
ASSERT(thread_cnt_before != 0);
}
@@ -318,9 +302,9 @@ bool Thread::tick()
{
++m_ticks;
if (tss().cs & 3)
- ++m_process.m_ticks_in_user;
+ ++m_process->m_ticks_in_user;
else
- ++m_process.m_ticks_in_kernel;
+ ++m_process->m_ticks_in_kernel;
return --m_ticks_left;
}
@@ -522,7 +506,7 @@ ShouldUnblockThread Thread::dispatch_signal(u8 signal)
});
[[fallthrough]];
case DefaultSignalAction::Terminate:
- m_process.terminate_due_to_signal(signal);
+ m_process->terminate_due_to_signal(signal);
return ShouldUnblockThread::No;
case DefaultSignalAction::Ignore:
ASSERT_NOT_REACHED();
@@ -642,7 +626,7 @@ RegisterState& Thread::get_register_dump_from_stack()
u32 Thread::make_userspace_stack_for_main_thread(Vector<String> arguments, Vector<String> environment, Vector<AuxiliaryValue> auxv)
{
- auto* region = m_process.allocate_region(VirtualAddress(), default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, false);
+ auto* region = m_process->allocate_region(VirtualAddress(), default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, false);
ASSERT(region);
region->set_stack(true);
@@ -714,22 +698,6 @@ Thread* Thread::clone(Process& process)
return clone;
}
-Vector<Thread*> Thread::all_threads()
-{
- Vector<Thread*> threads;
- InterruptDisabler disabler;
- threads.ensure_capacity(thread_table().size());
- for (auto* thread : thread_table())
- threads.unchecked_append(thread);
- return threads;
-}
-
-bool Thread::is_thread(void* ptr)
-{
- ASSERT_INTERRUPTS_DISABLED();
- return thread_table().contains((Thread*)ptr);
-}
-
void Thread::set_state(State new_state)
{
ScopedSpinLock lock(g_scheduler_lock);
@@ -750,7 +718,7 @@ void Thread::set_state(State new_state)
dbg() << "Set Thread " << *this << " state to " << state_string();
#endif
- if (m_process.pid() != 0) {
+ if (m_process->pid() != 0) {
Scheduler::update_state_for_thread(*this);
}
@@ -761,7 +729,7 @@ void Thread::set_state(State new_state)
}
}
-String Thread::backtrace(ProcessInspectionHandle&)
+String Thread::backtrace()
{
return backtrace_impl();
}