Kernel: Fix thread signal handling

Threads will now only handle signals once they are not holding any
mutexes. This removes some dead locks.
This commit is contained in:
Bananymous 2024-05-26 20:08:35 +03:00
parent a4c634e4bf
commit 2d3810874d
3 changed files with 27 additions and 11 deletions

View File

@ -27,6 +27,8 @@ namespace Kernel
while (!m_locker.compare_exchange(-1, tid)) while (!m_locker.compare_exchange(-1, tid))
Scheduler::get().yield(); Scheduler::get().yield();
ASSERT(m_lock_depth == 0); ASSERT(m_lock_depth == 0);
if (Scheduler::current_tid())
Thread::current().add_mutex();
} }
m_lock_depth++; m_lock_depth++;
} }
@ -41,6 +43,8 @@ namespace Kernel
if (!m_locker.compare_exchange(-1, tid)) if (!m_locker.compare_exchange(-1, tid))
return false; return false;
ASSERT(m_lock_depth == 0); ASSERT(m_lock_depth == 0);
if (Scheduler::current_tid())
Thread::current().add_mutex();
} }
m_lock_depth++; m_lock_depth++;
return true; return true;
@ -51,7 +55,11 @@ namespace Kernel
ASSERT(m_locker == Scheduler::current_tid()); ASSERT(m_locker == Scheduler::current_tid());
ASSERT(m_lock_depth > 0); ASSERT(m_lock_depth > 0);
if (--m_lock_depth == 0) if (--m_lock_depth == 0)
{
m_locker = -1; m_locker = -1;
if (Scheduler::current_tid())
Thread::current().remove_mutex();
}
} }
pid_t locker() const { return m_locker; } pid_t locker() const { return m_locker; }
@ -84,6 +92,8 @@ namespace Kernel
while (!(has_priority || m_queue_length == 0) || !m_locker.compare_exchange(-1, tid)) while (!(has_priority || m_queue_length == 0) || !m_locker.compare_exchange(-1, tid))
Scheduler::get().yield(); Scheduler::get().yield();
ASSERT(m_lock_depth == 0); ASSERT(m_lock_depth == 0);
if (Scheduler::current_tid())
Thread::current().add_mutex();
} }
m_lock_depth++; m_lock_depth++;
} }
@ -101,6 +111,8 @@ namespace Kernel
if (has_priority) if (has_priority)
m_queue_length++; m_queue_length++;
ASSERT(m_lock_depth == 0); ASSERT(m_lock_depth == 0);
if (Scheduler::current_tid())
Thread::current().add_mutex();
} }
m_lock_depth++; m_lock_depth++;
return true; return true;
@ -117,6 +129,8 @@ namespace Kernel
if (has_priority) if (has_priority)
m_queue_length--; m_queue_length--;
m_locker = -1; m_locker = -1;
if (Scheduler::current_tid())
Thread::current().remove_mutex();
} }
} }

View File

@ -38,9 +38,8 @@ namespace Kernel
void setup_exec(); void setup_exec();
void setup_process_cleanup(); void setup_process_cleanup();
// Adds pending signals to thread if possible and // Returns true, if thread is going to trigger signal
// returns true, if thread is going to trigger signal bool is_interrupted_by_signal() const;
bool is_interrupted_by_signal();
// Returns true if pending signal can be added to thread // Returns true if pending signal can be added to thread
bool can_add_signal_to_execute() const; bool can_add_signal_to_execute() const;
@ -86,6 +85,9 @@ namespace Kernel
static Thread* sse_thread(); static Thread* sse_thread();
#endif #endif
void add_mutex() { m_mutex_count++; }
void remove_mutex() { m_mutex_count--; }
private: private:
Thread(pid_t tid, Process*); Thread(pid_t tid, Process*);
@ -111,6 +113,8 @@ namespace Kernel
SpinLock m_signal_lock; SpinLock m_signal_lock;
static_assert(_SIGMAX < 64); static_assert(_SIGMAX < 64);
BAN::Atomic<uint32_t> m_mutex_count { 0 };
#if __enable_sse #if __enable_sse
alignas(16) uint8_t m_sse_storage[512] {}; alignas(16) uint8_t m_sse_storage[512] {};
#endif #endif

View File

@ -272,14 +272,7 @@ namespace Kernel
memset(&m_interrupt_registers, 0, sizeof(InterruptRegisters)); memset(&m_interrupt_registers, 0, sizeof(InterruptRegisters));
} }
bool Thread::is_interrupted_by_signal() bool Thread::is_interrupted_by_signal() const
{
while (can_add_signal_to_execute())
handle_signal();
return will_execute_signal();
}
bool Thread::can_add_signal_to_execute() const
{ {
if (!is_userspace() || m_state != State::Executing) if (!is_userspace() || m_state != State::Executing)
return false; return false;
@ -290,6 +283,11 @@ namespace Kernel
return full_pending_mask & ~m_signal_block_mask; return full_pending_mask & ~m_signal_block_mask;
} }
bool Thread::can_add_signal_to_execute() const
{
return is_interrupted_by_signal() && m_mutex_count == 0;
}
bool Thread::will_execute_signal() const bool Thread::will_execute_signal() const
{ {
if (!is_userspace() || m_state != State::Executing) if (!is_userspace() || m_state != State::Executing)