summaryrefslogtreecommitdiff
path: root/Kernel/Thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Thread.cpp')
-rw-r--r--Kernel/Thread.cpp34
1 files changed, 30 insertions, 4 deletions
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index 6beac18097..3736b6fc74 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -114,6 +114,7 @@ Thread::~Thread()
void Thread::unblock()
{
+ ASSERT(m_lock.own_lock());
m_blocker = nullptr;
if (Thread::current() == this) {
if (m_should_die)
@@ -144,6 +145,7 @@ void Thread::set_should_die()
m_should_die = true;
if (is_blocked()) {
+ ScopedSpinLock lock(m_lock);
ASSERT(m_blocker != nullptr);
// We're blocked in the kernel.
m_blocker->set_interrupted_by_death();
@@ -264,6 +266,7 @@ void Thread::finalize()
set_state(Thread::State::Dead);
if (m_joiner) {
+ ScopedSpinLock lock(m_joiner->m_lock);
ASSERT(m_joiner->m_joinee == this);
static_cast<JoinBlocker*>(m_joiner->m_blocker)->set_joinee_exit_value(m_exit_value);
static_cast<JoinBlocker*>(m_joiner->m_blocker)->set_interrupted_by_death();
@@ -468,9 +471,11 @@ ShouldUnblockThread Thread::dispatch_signal(u8 signal)
set_state(m_stop_state);
m_stop_state = State::Invalid;
// make sure SemiPermanentBlocker is unblocked
- if (m_state != Thread::Runnable && m_state != Thread::Running
- && m_blocker && m_blocker->is_reason_signal())
- unblock();
+ if (m_state != Thread::Runnable && m_state != Thread::Running) {
+ ScopedSpinLock lock(m_lock);
+ if (m_blocker && m_blocker->is_reason_signal())
+ unblock();
+ }
}
else {
@@ -482,6 +487,7 @@ ShouldUnblockThread Thread::dispatch_signal(u8 signal)
if (!thread_tracer->has_pending_signal(signal)) {
m_stop_signal = signal;
// make sure SemiPermanentBlocker is unblocked
+ ScopedSpinLock lock(m_lock);
if (m_blocker && m_blocker->is_reason_signal())
unblock();
set_state(Stopped);
@@ -697,13 +703,15 @@ void Thread::set_state(State new_state)
m_stop_state = m_state;
}
+ auto previous_state = m_state;
m_state = new_state;
#ifdef THREAD_DEBUG
dbg() << "Set Thread " << *this << " state to " << state_string();
#endif
if (m_process->pid() != 0) {
- Scheduler::update_state_for_thread(*this);
+ update_state_for_thread(previous_state);
+ ASSERT(g_scheduler_data->has_thread(*this));
}
if (m_state == Dying && this != Thread::current() && is_finalizable()) {
@@ -713,6 +721,24 @@ void Thread::set_state(State new_state)
}
}
+void Thread::update_state_for_thread(Thread::State previous_state)
+{
+ ASSERT_INTERRUPTS_DISABLED();
+ ASSERT(g_scheduler_data);
+ ASSERT(g_scheduler_lock.own_lock());
+ auto& previous_list = g_scheduler_data->thread_list_for_state(previous_state);
+ auto& list = g_scheduler_data->thread_list_for_state(state());
+
+ if (&previous_list != &list) {
+ previous_list.remove(*this);
+ }
+
+ if (list.contains(*this))
+ return;
+
+ list.append(*this);
+}
+
String Thread::backtrace()
{
return backtrace_impl();