Kernel: Add Spinlock and LockedValue<T>
This commit is contained in:
parent
6e5d2b5335
commit
f97515bd7e
@ -12,6 +12,7 @@ set(SOURCES
|
||||
src/boot/Init.cpp
|
||||
src/arch/Serial.cpp
|
||||
src/arch/Timer.cpp
|
||||
src/thread/Spinlock.cpp
|
||||
src/thread/Thread.cpp
|
||||
src/thread/Scheduler.cpp
|
||||
)
|
||||
|
22
kernel/src/thread/Spinlock.cpp
Normal file
22
kernel/src/thread/Spinlock.cpp
Normal 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);
|
||||
}
|
||||
}
|
86
kernel/src/thread/Spinlock.h
Normal file
86
kernel/src/thread/Spinlock.h
Normal 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;
|
||||
};
|
Loading…
Reference in New Issue
Block a user