diff --git a/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp b/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp index 5cdb74ed6..06f8a9e95 100644 --- a/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp +++ b/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp @@ -15,13 +15,26 @@ inline namespace arm64 class KInterruptMaskGuard final { public: + using FlagsType = u64; + KInterruptMaskGuard() { - flags = MESOSPHERE_READ_SYSREG(daif); - MESOSPHERE_WRITE_SYSREG(flags | PSR_I_BIT, daif); + flags = MaskInterrupts(); } ~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); } @@ -32,7 +45,7 @@ class KInterruptMaskGuard final { KInterruptMaskGuard &operator=(KInterruptMaskGuard &&) = delete; private: - u64 flags; + FlagsType flags; }; } diff --git a/mesosphere/include/mesosphere/arch/arm64/KSpinLock.hpp b/mesosphere/include/mesosphere/arch/arm64/KSpinLock.hpp index 04cf16c51..63a8f5739 100644 --- a/mesosphere/include/mesosphere/arch/arm64/KSpinLock.hpp +++ b/mesosphere/include/mesosphere/arch/arm64/KSpinLock.hpp @@ -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). -class KSpinLock final { +class KSpinLock { private: diff --git a/mesosphere/include/mesosphere/interrupts/KAlarm.hpp b/mesosphere/include/mesosphere/interrupts/KAlarm.hpp index 113716dbb..6e071d876 100644 --- a/mesosphere/include/mesosphere/interrupts/KAlarm.hpp +++ b/mesosphere/include/mesosphere/interrupts/KAlarm.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include namespace mesosphere @@ -27,7 +27,7 @@ class KAlarm final : public IInterruptibleWork { KAlarm &operator=(KAlarm &&) = delete; private: - KSpinLock spinlock{}; + mutable KInterruptSpinLock spinlock{}; AlarmableSetType alarmables{}; }; diff --git a/mesosphere/include/mesosphere/interrupts/KInterruptSpinLock.hpp b/mesosphere/include/mesosphere/interrupts/KInterruptSpinLock.hpp new file mode 100644 index 000000000..67df6c2d2 --- /dev/null +++ b/mesosphere/include/mesosphere/interrupts/KInterruptSpinLock.hpp @@ -0,0 +1,86 @@ +#pragma once + +#include +#include +#include + +namespace mesosphere +{ + +class KThread; +inline void IncrementThreadInterruptBottomHalfLockCount(KThread &thread); +inline void DecrementThreadInterruptBottomHalfLockCount(KThread &thread); + +template +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 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; +}; + +} diff --git a/mesosphere/include/mesosphere/kresources/KObjectAllocator.hpp b/mesosphere/include/mesosphere/kresources/KObjectAllocator.hpp index 6b2377e89..906d0e4c5 100644 --- a/mesosphere/include/mesosphere/kresources/KObjectAllocator.hpp +++ b/mesosphere/include/mesosphere/kresources/KObjectAllocator.hpp @@ -64,7 +64,7 @@ class KObjectAllocator { private: AllocatedSetType allocatedSet{}; KSlabHeap slabHeap{}; - KMutex mutex{}; + mutable KMutex mutex{}; }; } diff --git a/mesosphere/include/mesosphere/processes/KHandleTable.hpp b/mesosphere/include/mesosphere/processes/KHandleTable.hpp index d096f2ac1..44c9c2a00 100644 --- a/mesosphere/include/mesosphere/processes/KHandleTable.hpp +++ b/mesosphere/include/mesosphere/processes/KHandleTable.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -72,7 +72,7 @@ class KHandleTable final { u16 numActive = 0, size = 0, capacity = 0; - mutable KSpinLock spinlock; + mutable KInterruptSpinLock spinlock; }; }