Luna/kernel/src/thread/Spinlock.h
apio 4287ec6cb0
All checks were successful
continuous-integration/drone/push Build is passing
Bitmap: Introduce a new method 'find' and use it in MM and KernelVM
This method looks for the first bit with a value, optionally from a starting index, and returns its index.
This should be (haven't benchmarked) way faster than the manual way,
AKA what MM and KernelVM were doing.

This is due to this method using bit and byte manipulation tricks instead of just calling get() until getting the desired result :)
2023-01-09 17:59:52 +01:00

108 lines
1.9 KiB
C++

#pragma once
#include "Log.h"
#include "arch/CPU.h"
#include <luna/Atomic.h>
#include <luna/Option.h>
class Spinlock
{
public:
void lock();
void unlock();
bool try_lock();
bool is_locked() const
{
return m_lock.load() != 0;
}
private:
Atomic<int> m_lock { 0 };
};
template <typename T> class LockedValue
{
struct LockedValueGuard
{
LockedValueGuard(LockedValue& value_ref) : m_value_ref(&value_ref)
{
}
LockedValueGuard(const LockedValueGuard& other) = delete;
LockedValueGuard(LockedValueGuard&& other)
{
m_value_ref = other.m_value_ref;
other.m_value_ref = nullptr;
}
~LockedValueGuard()
{
if (m_value_ref) m_value_ref->m_lock.unlock();
}
T& ref()
{
expect(m_value_ref, "LockedValueGuard::ref() called on a moved LockedValueGuard");
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)
{
}
#ifndef LOCKED_VALUE_DEBUG
LockedValueGuard lock()
{
m_lock.lock();
return { *this };
}
#else
LockedValueGuard lock()
{
if (m_lock.try_lock()) { return { *this }; }
kwarnln("Spinning on a locked LockedValue. This might lead to a deadlock...");
CPU::print_stack_trace();
m_lock.lock();
return { *this };
}
#endif
Option<LockedValueGuard> try_lock()
{
if (m_lock.try_lock()) { return { *this }; }
return {};
}
private:
T m_value;
Spinlock m_lock;
};