Kernel: Fix all broken locks from new mutexes
This commit is contained in:
58
kernel/include/kernel/Lock/LockGuard.h
Normal file
58
kernel/include/kernel/Lock/LockGuard.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/NoCopyMove.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
template<typename Lock>
|
||||
class LockGuard
|
||||
{
|
||||
BAN_NON_COPYABLE(LockGuard);
|
||||
BAN_NON_MOVABLE(LockGuard);
|
||||
|
||||
public:
|
||||
LockGuard(Lock& lock)
|
||||
: m_lock(lock)
|
||||
{
|
||||
m_lock.lock();
|
||||
}
|
||||
|
||||
~LockGuard()
|
||||
{
|
||||
m_lock.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
131
kernel/include/kernel/Lock/Mutex.h
Normal file
131
kernel/include/kernel/Lock/Mutex.h
Normal file
@@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Atomic.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Mutex
|
||||
{
|
||||
BAN_NON_COPYABLE(Mutex);
|
||||
BAN_NON_MOVABLE(Mutex);
|
||||
|
||||
public:
|
||||
Mutex() = default;
|
||||
|
||||
void lock()
|
||||
{
|
||||
auto tid = Scheduler::current_tid();
|
||||
if (tid == m_locker)
|
||||
ASSERT_GT(m_lock_depth, 0);
|
||||
else
|
||||
{
|
||||
while (!m_locker.compare_exchange(-1, tid))
|
||||
Scheduler::get().reschedule();
|
||||
ASSERT_EQ(m_lock_depth, 0);
|
||||
}
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
auto tid = Scheduler::current_tid();
|
||||
if (tid == m_locker)
|
||||
ASSERT_GT(m_lock_depth, 0);
|
||||
else
|
||||
{
|
||||
if (!m_locker.compare_exchange(-1, tid))
|
||||
return false;
|
||||
ASSERT_EQ(m_lock_depth, 0);
|
||||
}
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
ASSERT_EQ(m_locker.load(), Scheduler::current_tid());
|
||||
ASSERT_GT(m_lock_depth, 0);
|
||||
if (--m_lock_depth == 0)
|
||||
m_locker = -1;
|
||||
}
|
||||
|
||||
pid_t locker() const { return m_locker; }
|
||||
bool is_locked() const { return m_locker != -1; }
|
||||
uint32_t lock_depth() const { return m_lock_depth; }
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
uint32_t m_lock_depth { 0 };
|
||||
};
|
||||
|
||||
class PriorityMutex
|
||||
{
|
||||
BAN_NON_COPYABLE(PriorityMutex);
|
||||
BAN_NON_MOVABLE(PriorityMutex);
|
||||
|
||||
public:
|
||||
PriorityMutex() = default;
|
||||
|
||||
void lock()
|
||||
{
|
||||
auto tid = Scheduler::current_tid();
|
||||
if (tid == m_locker)
|
||||
ASSERT_GT(m_lock_depth, 0);
|
||||
else
|
||||
{
|
||||
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
||||
if (has_priority)
|
||||
m_queue_length++;
|
||||
while (!(has_priority || m_queue_length == 0) || !m_locker.compare_exchange(-1, tid))
|
||||
Scheduler::get().reschedule();
|
||||
ASSERT_EQ(m_lock_depth, 0);
|
||||
}
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
auto tid = Scheduler::current_tid();
|
||||
if (tid == m_locker)
|
||||
ASSERT_GT(m_lock_depth, 0);
|
||||
else
|
||||
{
|
||||
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
||||
if (!(has_priority || m_queue_length == 0) || !m_locker.compare_exchange(-1, tid))
|
||||
return false;
|
||||
if (has_priority)
|
||||
m_queue_length++;
|
||||
ASSERT_EQ(m_lock_depth, 0);
|
||||
}
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
auto tid = Scheduler::current_tid();
|
||||
ASSERT_EQ(m_locker.load(), tid);
|
||||
ASSERT_GT(m_lock_depth, 0);
|
||||
if (--m_lock_depth == 0)
|
||||
{
|
||||
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
||||
if (has_priority)
|
||||
m_queue_length--;
|
||||
m_locker = -1;
|
||||
}
|
||||
}
|
||||
|
||||
pid_t locker() const { return m_locker; }
|
||||
bool is_locked() const { return m_locker != -1; }
|
||||
uint32_t lock_depth() const { return m_lock_depth; }
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
uint32_t m_lock_depth { 0 };
|
||||
BAN::Atomic<uint32_t> m_queue_length { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
67
kernel/include/kernel/Lock/SpinLock.h
Normal file
67
kernel/include/kernel/Lock/SpinLock.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Atomic.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
using InterruptState = bool;
|
||||
|
||||
class SpinLock
|
||||
{
|
||||
BAN_NON_COPYABLE(SpinLock);
|
||||
BAN_NON_MOVABLE(SpinLock);
|
||||
|
||||
public:
|
||||
SpinLock() = default;
|
||||
|
||||
InterruptState lock();
|
||||
void unlock(InterruptState state);
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
};
|
||||
|
||||
class RecursiveSpinLock
|
||||
{
|
||||
BAN_NON_COPYABLE(RecursiveSpinLock);
|
||||
BAN_NON_MOVABLE(RecursiveSpinLock);
|
||||
|
||||
public:
|
||||
RecursiveSpinLock() = default;
|
||||
|
||||
InterruptState lock();
|
||||
void unlock(InterruptState state);
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
uint32_t m_lock_depth { 0 };
|
||||
};
|
||||
|
||||
template<typename Lock>
|
||||
class SpinLockGuard
|
||||
{
|
||||
BAN_NON_COPYABLE(SpinLockGuard);
|
||||
BAN_NON_MOVABLE(SpinLockGuard);
|
||||
|
||||
public:
|
||||
SpinLockGuard(Lock& lock)
|
||||
: m_lock(lock)
|
||||
{
|
||||
m_state = m_lock.lock();
|
||||
}
|
||||
|
||||
~SpinLockGuard()
|
||||
{
|
||||
m_lock.unlock(m_state);
|
||||
}
|
||||
|
||||
private:
|
||||
Lock& m_lock;
|
||||
InterruptState m_state;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user