Add KInterruptSpinLock, which is what is really used in the official kernel

This commit is contained in:
TuxSH 2018-11-08 00:11:30 +01:00 committed by Michael Scire
parent 7b726c3184
commit 4238d2e97f
6 changed files with 108 additions and 9 deletions

View file

@ -15,13 +15,26 @@ inline namespace arm64
class KInterruptMaskGuard final { class KInterruptMaskGuard final {
public: public:
using FlagsType = u64;
KInterruptMaskGuard() KInterruptMaskGuard()
{ {
flags = MESOSPHERE_READ_SYSREG(daif); flags = MaskInterrupts();
MESOSPHERE_WRITE_SYSREG(flags | PSR_I_BIT, daif);
} }
~KInterruptMaskGuard() ~KInterruptMaskGuard()
{
RestoreInterrupts(flags);
}
static FlagsType MaskInterrupts()
{
FlagsType flags = MESOSPHERE_READ_SYSREG(daif);
MESOSPHERE_WRITE_SYSREG(flags | PSR_I_BIT, daif);
return flags;
}
static void RestoreInterrupts(FlagsType flags)
{ {
MESOSPHERE_WRITE_SYSREG(MESOSPHERE_READ_SYSREG(daif) | (flags & PSR_I_BIT), daif); MESOSPHERE_WRITE_SYSREG(MESOSPHERE_READ_SYSREG(daif) | (flags & PSR_I_BIT), daif);
} }
@ -32,7 +45,7 @@ class KInterruptMaskGuard final {
KInterruptMaskGuard &operator=(KInterruptMaskGuard &&) = delete; KInterruptMaskGuard &operator=(KInterruptMaskGuard &&) = delete;
private: private:
u64 flags; FlagsType flags;
}; };
} }

View file

@ -10,7 +10,7 @@ inline namespace arm64
{ {
// This largely uses the Linux kernel spinlock code, which is more efficient than Nintendo's (serializing two u16s into an u32). // This largely uses the Linux kernel spinlock code, which is more efficient than Nintendo's (serializing two u16s into an u32).
class KSpinLock final { class KSpinLock {
private: private:

View file

@ -2,7 +2,7 @@
#include <mesosphere/interfaces/IInterruptibleWork.hpp> #include <mesosphere/interfaces/IInterruptibleWork.hpp>
#include <mesosphere/interfaces/IAlarmable.hpp> #include <mesosphere/interfaces/IAlarmable.hpp>
#include <mesosphere/arch/KSpinLock.hpp> #include <mesosphere/interrupts/KInterruptSpinLock.hpp>
#include <mesosphere/board/KSystemClock.hpp> #include <mesosphere/board/KSystemClock.hpp>
namespace mesosphere namespace mesosphere
@ -27,7 +27,7 @@ class KAlarm final : public IInterruptibleWork {
KAlarm &operator=(KAlarm &&) = delete; KAlarm &operator=(KAlarm &&) = delete;
private: private:
KSpinLock spinlock{}; mutable KInterruptSpinLock<false> spinlock{};
AlarmableSetType alarmables{}; AlarmableSetType alarmables{};
}; };

View file

@ -0,0 +1,86 @@
#pragma once
#include <mesosphere/core/KCoreContext.hpp>
#include <mesosphere/arch/KInterruptMaskGuard.hpp>
#include <mesosphere/arch/KSpinLock.hpp>
namespace mesosphere
{
class KThread;
inline void IncrementThreadInterruptBottomHalfLockCount(KThread &thread);
inline void DecrementThreadInterruptBottomHalfLockCount(KThread &thread);
template<bool disableInterrupts = false>
class KInterruptSpinLock final : public KSpinLock {
public:
bool try_lock()
{
KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread();
IncrementThreadInterruptBottomHalfLockCount(*curThread);
if (!KSpinLock::try_lock()) {
DecrementThreadInterruptBottomHalfLockCount(*curThread);
return false;
}
return true;
}
void lock()
{
KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread();
IncrementThreadInterruptBottomHalfLockCount(*curThread);
KSpinLock::lock();
}
void unlock()
{
KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread();
KSpinLock::unlock();
DecrementThreadInterruptBottomHalfLockCount(*curThread);
}
KInterruptSpinLock() = default;
KInterruptSpinLock(const KInterruptSpinLock &) = delete;
KInterruptSpinLock(KInterruptSpinLock &&) = delete;
KInterruptSpinLock &operator=(const KInterruptSpinLock &) = delete;
KInterruptSpinLock &operator=(KInterruptSpinLock &&) = delete;
};
template<>
class KInterruptSpinLock<true> final : public KSpinLock {
public:
bool try_lock()
{
flags = KInterruptMaskGuard::MaskInterrupts();
if (!KSpinLock::try_lock()) {
KInterruptMaskGuard::RestoreInterrupts(flags);
return false;
}
return true;
}
void lock()
{
flags = KInterruptMaskGuard::MaskInterrupts();
KSpinLock::lock();
}
void unlock()
{
KSpinLock::unlock();
KInterruptMaskGuard::RestoreInterrupts(flags);
}
KInterruptSpinLock() = default;
KInterruptSpinLock(const KInterruptSpinLock &) = delete;
KInterruptSpinLock(KInterruptSpinLock &&) = delete;
KInterruptSpinLock &operator=(const KInterruptSpinLock &) = delete;
KInterruptSpinLock &operator=(KInterruptSpinLock &&) = delete;
private:
typename KInterruptMaskGuard::FlagsType flags;
};
}

View file

@ -64,7 +64,7 @@ class KObjectAllocator {
private: private:
AllocatedSetType allocatedSet{}; AllocatedSetType allocatedSet{};
KSlabHeap<T> slabHeap{}; KSlabHeap<T> slabHeap{};
KMutex mutex{}; mutable KMutex mutex{};
}; };
} }

View file

@ -4,7 +4,7 @@
#include <mesosphere/core/Handle.hpp> #include <mesosphere/core/Handle.hpp>
#include <mesosphere/core/Result.hpp> #include <mesosphere/core/Result.hpp>
#include <mesosphere/core/KAutoObject.hpp> #include <mesosphere/core/KAutoObject.hpp>
#include <mesosphere/arch/KSpinLock.hpp> #include <mesosphere/interrupts/KInterruptSpinLock.hpp>
#include <array> #include <array>
#include <tuple> #include <tuple>
@ -72,7 +72,7 @@ class KHandleTable final {
u16 numActive = 0, size = 0, capacity = 0; u16 numActive = 0, size = 0, capacity = 0;
mutable KSpinLock spinlock; mutable KInterruptSpinLock<false> spinlock;
}; };
} }