kernel, luna: Move Spinlock.h to luna
This commit is contained in:
parent
c422d11682
commit
9274ad0404
@ -1,53 +0,0 @@
|
|||||||
#include "thread/Spinlock.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include "arch/CPU.h"
|
|
||||||
|
|
||||||
void Spinlock::lock()
|
|
||||||
{
|
|
||||||
int expected = 0;
|
|
||||||
while (!m_lock.compare_exchange_strong(expected, 1))
|
|
||||||
{
|
|
||||||
expected = 0;
|
|
||||||
CPU::pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Spinlock::try_lock()
|
|
||||||
{
|
|
||||||
int expected = 0;
|
|
||||||
return m_lock.compare_exchange_strong(expected, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Spinlock::unlock()
|
|
||||||
{
|
|
||||||
int expected = 1;
|
|
||||||
if (!m_lock.compare_exchange_strong(expected, 0))
|
|
||||||
{
|
|
||||||
kwarnln("Spinlock::unlock() called on an unlocked lock with value %d", expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopeLock::ScopeLock(Spinlock& lock) : m_lock(lock)
|
|
||||||
{
|
|
||||||
m_lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopeLock::~ScopeLock()
|
|
||||||
{
|
|
||||||
m_lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 RETRIES = 5000000;
|
|
||||||
|
|
||||||
SafeScopeLock::SafeScopeLock(Spinlock& lock) : m_lock(lock)
|
|
||||||
{
|
|
||||||
u32 tries_left = RETRIES;
|
|
||||||
while (!lock.try_lock() && --tries_left) { CPU::pause(); }
|
|
||||||
|
|
||||||
if (tries_left) m_success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeScopeLock::~SafeScopeLock()
|
|
||||||
{
|
|
||||||
if (m_success) m_lock.unlock();
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
#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 };
|
|
||||||
};
|
|
||||||
|
|
||||||
class ScopeLock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ScopeLock(Spinlock& lock);
|
|
||||||
~ScopeLock();
|
|
||||||
|
|
||||||
ScopeLock(const ScopeLock&) = delete;
|
|
||||||
ScopeLock(ScopeLock&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Spinlock& m_lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SafeScopeLock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SafeScopeLock(Spinlock& lock);
|
|
||||||
~SafeScopeLock();
|
|
||||||
|
|
||||||
SafeScopeLock(const SafeScopeLock&) = delete;
|
|
||||||
SafeScopeLock(SafeScopeLock&&) = delete;
|
|
||||||
|
|
||||||
bool did_succeed() const
|
|
||||||
{
|
|
||||||
return m_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Spinlock& m_lock;
|
|
||||||
bool m_success { false };
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user