diff --git a/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp b/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp index 06f8a9e95..716252b26 100644 --- a/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp +++ b/mesosphere/include/mesosphere/arch/arm64/KInterruptMaskGuard.hpp @@ -45,7 +45,7 @@ class KInterruptMaskGuard final { KInterruptMaskGuard &operator=(KInterruptMaskGuard &&) = delete; private: - FlagsType flags; + FlagsType flags = 0; }; } diff --git a/mesosphere/include/mesosphere/interrupts/KInterruptSpinLock.hpp b/mesosphere/include/mesosphere/interrupts/KInterruptSpinLock.hpp index 67df6c2d2..f22e7755d 100644 --- a/mesosphere/include/mesosphere/interrupts/KInterruptSpinLock.hpp +++ b/mesosphere/include/mesosphere/interrupts/KInterruptSpinLock.hpp @@ -12,7 +12,7 @@ inline void IncrementThreadInterruptBottomHalfLockCount(KThread &thread); inline void DecrementThreadInterruptBottomHalfLockCount(KThread &thread); template -class KInterruptSpinLock final : public KSpinLock { +class KInterruptSpinLock : public KSpinLock { public: bool try_lock() @@ -48,7 +48,7 @@ class KInterruptSpinLock final : public KSpinLock { }; template<> -class KInterruptSpinLock final : public KSpinLock { +class KInterruptSpinLock : public KSpinLock { public: bool try_lock() @@ -80,7 +80,7 @@ class KInterruptSpinLock final : public KSpinLock { KInterruptSpinLock &operator=(KInterruptSpinLock &&) = delete; private: - typename KInterruptMaskGuard::FlagsType flags; + typename KInterruptMaskGuard::FlagsType flags = 0; }; } diff --git a/mesosphere/include/mesosphere/threading/KCriticalSection.hpp b/mesosphere/include/mesosphere/threading/KCriticalSection.hpp new file mode 100644 index 000000000..ecbbcb640 --- /dev/null +++ b/mesosphere/include/mesosphere/threading/KCriticalSection.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace mesosphere +{ + +class KCriticalSection final : public KInterruptSpinLock { + public: + + bool try_lock(); + void lock(); + void unlock(); + + KCriticalSection() = default; + KCriticalSection(const KCriticalSection &) = delete; + KCriticalSection(KCriticalSection &&) = delete; + KCriticalSection &operator=(const KCriticalSection &) = delete; + KCriticalSection &operator=(KCriticalSection &&) = delete; + + private: + KThread *lockingThread = nullptr; + ulong lockCount = 0; +}; + +} diff --git a/mesosphere/include/mesosphere/threading/KScheduler.hpp b/mesosphere/include/mesosphere/threading/KScheduler.hpp index 7c4180f60..1844c8880 100644 --- a/mesosphere/include/mesosphere/threading/KScheduler.hpp +++ b/mesosphere/include/mesosphere/threading/KScheduler.hpp @@ -4,14 +4,12 @@ #include #include #include +#include #include namespace mesosphere { -//TODO -struct KCriticalSection { void lock() {} void unlock() {} bool try_lock() {return true;} }; - class KScheduler { public: class Global { @@ -40,6 +38,8 @@ class KScheduler { static constexpr uint minRegularPriority = 2; private: + friend class KScheduler; + static void TransferThreadToCore(KThread &thread, int coreId); static void AskForReselectionOrMarkRedundant(KThread *currentThread, KThread *winner); @@ -91,6 +91,11 @@ class KScheduler { static void YieldCurrentThreadAndBalanceLoad(); static void YieldCurrentThreadAndWaitForLoadBalancing(); + static void HandleCriticalSectionLeave(); + friend void SchedulerHandleCriticalSectionLeave() + { + HandleCriticalSectionLeave(); + } void ForceContextSwitch() {} void ForceContextSwitchAfterIrq() {} @@ -99,6 +104,7 @@ class KScheduler { constexpr ulong GetIdleSelectionCount() const { return idleSelectionCount; } constexpr bool IsActive() const { return /*isActive */ true; } // TODO + private: bool hasContextSwitchStartedAfterIrq; bool isActive; @@ -128,11 +134,4 @@ class KScheduler { } }; -// Convenience - -class KScopedCriticalSection { - private: - std::scoped_lock lk{KScheduler::GetCriticalSection()}; -}; - } diff --git a/mesosphere/include/mesosphere/threading/KScopedCriticalSection.hpp b/mesosphere/include/mesosphere/threading/KScopedCriticalSection.hpp new file mode 100644 index 000000000..4d9df0df6 --- /dev/null +++ b/mesosphere/include/mesosphere/threading/KScopedCriticalSection.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace mesosphere +{ + +class KScopedCriticalSection final { + private: + std::scoped_lock lk{KScheduler::GetCriticalSection()}; +}; + +} diff --git a/mesosphere/source/core/KSynchronizationObject.cpp b/mesosphere/source/core/KSynchronizationObject.cpp index c58cb992e..feea92987 100644 --- a/mesosphere/source/core/KSynchronizationObject.cpp +++ b/mesosphere/source/core/KSynchronizationObject.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/mesosphere/source/processes/KReadableEvent.cpp b/mesosphere/source/processes/KReadableEvent.cpp index 0c86ea3fb..bce2834e0 100644 --- a/mesosphere/source/processes/KReadableEvent.cpp +++ b/mesosphere/source/processes/KReadableEvent.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include namespace mesosphere { @@ -18,12 +18,12 @@ KReadableEvent::~KReadableEvent() Result KReadableEvent::Signal() { KScopedCriticalSection criticalSection{}; - + if (!this->isSignaled) { this->isSignaled = true; NotifyWaiters(); } - + return ResultSuccess(); } diff --git a/mesosphere/source/threading/KConditionVariable.cpp b/mesosphere/source/threading/KConditionVariable.cpp index bab058971..ea2787047 100644 --- a/mesosphere/source/threading/KConditionVariable.cpp +++ b/mesosphere/source/threading/KConditionVariable.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include namespace mesosphere diff --git a/mesosphere/source/threading/KCriticalSection.cpp b/mesosphere/source/threading/KCriticalSection.cpp new file mode 100644 index 000000000..fd0568767 --- /dev/null +++ b/mesosphere/source/threading/KCriticalSection.cpp @@ -0,0 +1,45 @@ +#include +#include +#include + +namespace mesosphere +{ + +bool KCriticalSection::try_lock() +{ + KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread(); + if (curThread == lockingThread) { + ++lockCount; + return true; + } else if (KInterruptSpinLock::try_lock()) { + lockingThread = curThread; + lockCount = 1; + return true; + } else { + return false; + } +} + +void KCriticalSection::lock() +{ + KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread(); + if (curThread == lockingThread) { + ++lockCount; + } else { + KInterruptSpinLock::lock(); + lockingThread = curThread; + lockCount = 1; + } +} + +void KCriticalSection::unlock() +{ + if (--lockCount == 0) { + lockingThread = nullptr; + KScheduler::HandleCriticalSectionLeave(); + } else { + KInterruptSpinLock::unlock(); + } +} + +} diff --git a/mesosphere/source/threading/KMutex.cpp b/mesosphere/source/threading/KMutex.cpp index e2c036e33..7b7aaa591 100644 --- a/mesosphere/source/threading/KMutex.cpp +++ b/mesosphere/source/threading/KMutex.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include namespace mesosphere { diff --git a/mesosphere/source/threading/KScheduler.cpp b/mesosphere/source/threading/KScheduler.cpp index 7a91806c8..db22c91b5 100644 --- a/mesosphere/source/threading/KScheduler.cpp +++ b/mesosphere/source/threading/KScheduler.cpp @@ -341,4 +341,15 @@ void KScheduler::YieldCurrentThreadAndWaitForLoadBalancing() cctx.GetScheduler()->DoYieldOperation(Global::YieldThreadAndWaitForLoadBalancing, *cctx.GetCurrentThread()); } +void KScheduler::HandleCriticalSectionLeave() +{ + if (KScheduler::Global::reselectionRequired) { + KScheduler::Global::SelectThreads(); + } + + std::atomic_thread_fence(std::memory_order_seq_cst); + + // TODO: check which cores needs ctx switches, sent interrupts and/or ctx switch ourselves +} + } diff --git a/mesosphere/source/threading/KThread.cpp b/mesosphere/source/threading/KThread.cpp index 856d90ae9..cd0a2da42 100644 --- a/mesosphere/source/threading/KThread.cpp +++ b/mesosphere/source/threading/KThread.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include namespace mesosphere {