Kernel: Implement RecursivePrioritySpinLock

This locks won't allow locking from userspace thread if there is
kernel thread waiting to lock this.
This commit is contained in:
Bananymous 2023-12-07 13:18:21 +02:00
parent 669d55707e
commit 7c25e4ce5a
2 changed files with 78 additions and 1 deletions

View File

@ -39,4 +39,24 @@ namespace Kernel
SpinLock m_lock;
};
}
class RecursivePrioritySpinLock
{
BAN_NON_COPYABLE(RecursivePrioritySpinLock);
BAN_NON_MOVABLE(RecursivePrioritySpinLock);
public:
RecursivePrioritySpinLock() = default;
void lock();
void unlock();
bool is_locked() const;
uint32_t lock_depth() const { return m_lock_depth; }
private:
pid_t m_locker = -1;
uint32_t m_queue_length = 0;
uint32_t m_lock_depth = 0;
SpinLock m_lock;
};
}

View File

@ -80,4 +80,61 @@ namespace Kernel
return m_locker != -1;
}
void RecursivePrioritySpinLock::lock()
{
pid_t tid = Scheduler::current_tid();
bool has_priority = !Thread::current().is_userspace();
if (has_priority)
{
m_lock.lock();
m_queue_length++;
m_lock.unlock();
}
while (true)
{
m_lock.lock();
if (m_locker == tid)
{
m_lock_depth++;
break;
}
if (m_locker == -1 && (has_priority || m_queue_length == 0))
{
m_locker = tid;
m_lock_depth = 1;
break;
}
m_lock.unlock();
}
m_lock.unlock();
}
void RecursivePrioritySpinLock::unlock()
{
m_lock.lock();
ASSERT(m_lock_depth > 0);
ASSERT(m_locker == Scheduler::current_tid());
bool has_priority = !Thread::current().is_userspace();
if (has_priority)
m_queue_length--;
m_lock_depth--;
if (m_lock_depth == 0)
m_locker = -1;
m_lock.unlock();
}
bool RecursivePrioritySpinLock::is_locked() const
{
return m_locker != -1;
}
}