Kernel: Fix most of mutex + block race conditions

All block functions now take an optional mutex parameter that is
atomically unlocked instead of having the user unlock it before hand.
This prevents a ton of race conditions everywhere in the code!
This commit is contained in:
2025-06-06 03:59:22 +03:00
parent 96d5ed9cc7
commit eecdad50a6
36 changed files with 374 additions and 322 deletions

View File

@@ -29,30 +29,4 @@ namespace Kernel
Lock& m_lock;
};
template<typename Lock>
class LockFreeGuard
{
BAN_NON_COPYABLE(LockFreeGuard);
BAN_NON_MOVABLE(LockFreeGuard);
public:
LockFreeGuard(Lock& lock)
: m_lock(lock)
, m_depth(lock.lock_depth())
{
for (uint32_t i = 0; i < m_depth; i++)
m_lock.unlock();
}
~LockFreeGuard()
{
for (uint32_t i = 0; i < m_depth; i++)
m_lock.lock();
}
private:
Lock& m_lock;
const uint32_t m_depth;
};
}

View File

@@ -9,7 +9,19 @@
namespace Kernel
{
class Mutex
class BaseMutex
{
public:
virtual void lock() = 0;
virtual bool try_lock() = 0;
virtual void unlock() = 0;
virtual pid_t locker() const = 0;
virtual bool is_locked() const = 0;
virtual uint32_t lock_depth() const = 0;
};
class Mutex : public BaseMutex
{
BAN_NON_COPYABLE(Mutex);
BAN_NON_MOVABLE(Mutex);
@@ -17,9 +29,10 @@ namespace Kernel
public:
Mutex() = default;
void lock()
void lock() override
{
const auto tid = Thread::current_tid();
ASSERT(!tid || !Thread::current().has_spinlock());
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else
@@ -37,9 +50,10 @@ namespace Kernel
m_lock_depth++;
}
bool try_lock()
bool try_lock() override
{
const auto tid = Thread::current_tid();
ASSERT(!tid || !Thread::current().has_spinlock());
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else
@@ -55,7 +69,7 @@ namespace Kernel
return true;
}
void unlock()
void unlock() override
{
const auto tid = Thread::current_tid();
ASSERT(m_locker == tid);
@@ -68,16 +82,16 @@ namespace Kernel
}
}
pid_t locker() const { return m_locker; }
bool is_locked() const { return m_locker != -1; }
uint32_t lock_depth() const { return m_lock_depth; }
pid_t locker() const override { return m_locker; }
bool is_locked() const override { return m_locker != -1; }
uint32_t lock_depth() const override { return m_lock_depth; }
private:
BAN::Atomic<pid_t> m_locker { -1 };
uint32_t m_lock_depth { 0 };
};
class PriorityMutex
class PriorityMutex : public BaseMutex
{
BAN_NON_COPYABLE(PriorityMutex);
BAN_NON_MOVABLE(PriorityMutex);
@@ -85,7 +99,7 @@ namespace Kernel
public:
PriorityMutex() = default;
void lock()
void lock() override
{
const auto tid = Thread::current_tid();
ASSERT(!tid || !Thread::current().has_spinlock());
@@ -110,7 +124,7 @@ namespace Kernel
m_lock_depth++;
}
bool try_lock()
bool try_lock() override
{
const auto tid = Thread::current_tid();
ASSERT(!tid || !Thread::current().has_spinlock());
@@ -133,7 +147,7 @@ namespace Kernel
return true;
}
void unlock()
void unlock() override
{
const auto tid = Thread::current_tid();
ASSERT(m_locker == tid);
@@ -149,9 +163,9 @@ namespace Kernel
}
}
pid_t locker() const { return m_locker; }
bool is_locked() const { return m_locker != -1; }
uint32_t lock_depth() const { return m_lock_depth; }
pid_t locker() const override { return m_locker; }
bool is_locked() const override { return m_locker != -1; }
uint32_t lock_depth() const override { return m_lock_depth; }
private:
BAN::Atomic<pid_t> m_locker { -1 };

View File

@@ -24,6 +24,8 @@ namespace Kernel
void unlock(InterruptState state);
uint32_t lock_depth() const { return current_processor_has_lock(); }
bool current_processor_has_lock() const
{
return m_locker.load(BAN::MemoryOrder::memory_order_relaxed) == Processor::current_id().as_u32();
@@ -72,6 +74,8 @@ namespace Kernel
Processor::set_interrupt_state(state);
}
uint32_t lock_depth() const { return m_lock_depth; }
bool current_processor_has_lock() const
{
return m_locker.load(BAN::MemoryOrder::memory_order_relaxed) == Processor::current_id().as_u32();
@@ -82,6 +86,9 @@ namespace Kernel
uint32_t m_lock_depth { 0 };
};
template<typename Lock>
class SpinLockGuardAsMutex;
template<typename Lock>
class SpinLockGuard
{
@@ -103,6 +110,7 @@ namespace Kernel
private:
Lock& m_lock;
InterruptState m_state;
friend class SpinLockGuardAsMutex<Lock>;
};
}