Kernel: Add Spinlock and LockedValue<T>

This commit is contained in:
apio 2022-12-17 10:52:40 +01:00
parent 6e5d2b5335
commit f97515bd7e
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 109 additions and 0 deletions

View File

@ -12,6 +12,7 @@ set(SOURCES
src/boot/Init.cpp src/boot/Init.cpp
src/arch/Serial.cpp src/arch/Serial.cpp
src/arch/Timer.cpp src/arch/Timer.cpp
src/thread/Spinlock.cpp
src/thread/Thread.cpp src/thread/Thread.cpp
src/thread/Scheduler.cpp src/thread/Scheduler.cpp
) )

View File

@ -0,0 +1,22 @@
#include "thread/Spinlock.h"
#include "Log.h"
#include "arch/CPU.h"
void Spinlock::lock()
{
int expected = -1;
while (!m_lock.compare_exchange_strong(expected, 0))
{
expected = -1;
CPU::pause();
}
}
void Spinlock::unlock()
{
int expected = 0;
if (!m_lock.compare_exchange_strong(expected, -1))
{
kwarnln("Spinlock::unlock() called on an unlocked lock with value %d", expected);
}
}

View File

@ -0,0 +1,86 @@
#pragma once
#include <luna/Atomic.h>
class Spinlock
{
public:
void lock();
void unlock();
bool is_locked() const
{
return m_lock.load() != -1;
}
// Call this before use if the Spinlock is a global variable.
void init()
{
m_lock = -1;
}
private:
Atomic<int> m_lock{-1};
};
template <typename T> class LockedValue
{
struct LockedValueGuard
{
LockedValueGuard(LockedValue& value_ref) : m_value_ref(value_ref)
{
}
~LockedValueGuard()
{
m_value_ref.m_lock.unlock();
}
T& ref()
{
return m_value_ref.m_value;
}
void set(const T& other)
{
ref() = other;
}
T* operator->()
{
return &ref();
}
T& operator*()
{
return ref();
}
private:
LockedValue& m_value_ref;
};
public:
LockedValue() : m_value()
{
}
LockedValue(T value) : m_value(value)
{
}
// Call this before use if the LockedValue is a global variable.
void init()
{
m_lock.init();
}
LockedValueGuard lock()
{
m_lock.lock();
return {*this};
}
private:
T m_value;
Spinlock m_lock;
};