Implement KCriticalSection (mostly)

This commit is contained in:
TuxSH 2018-11-08 01:04:06 +01:00 committed by Michael Scire
parent 4238d2e97f
commit 0fb40d1ef5
12 changed files with 115 additions and 21 deletions

View file

@ -45,7 +45,7 @@ class KInterruptMaskGuard final {
KInterruptMaskGuard &operator=(KInterruptMaskGuard &&) = delete;
private:
FlagsType flags;
FlagsType flags = 0;
};
}

View file

@ -12,7 +12,7 @@ inline void IncrementThreadInterruptBottomHalfLockCount(KThread &thread);
inline void DecrementThreadInterruptBottomHalfLockCount(KThread &thread);
template<bool disableInterrupts = false>
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<true> final : public KSpinLock {
class KInterruptSpinLock<true> : public KSpinLock {
public:
bool try_lock()
@ -80,7 +80,7 @@ class KInterruptSpinLock<true> final : public KSpinLock {
KInterruptSpinLock &operator=(KInterruptSpinLock &&) = delete;
private:
typename KInterruptMaskGuard::FlagsType flags;
typename KInterruptMaskGuard::FlagsType flags = 0;
};
}

View file

@ -0,0 +1,26 @@
#pragma once
#include <mesosphere/interrupts/KInterruptSpinLock.hpp>
namespace mesosphere
{
class KCriticalSection final : public KInterruptSpinLock<false> {
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;
};
}

View file

@ -4,14 +4,12 @@
#include <mutex>
#include <mesosphere/core/util.hpp>
#include <mesosphere/threading/KMultiLevelQueue.hpp>
#include <mesosphere/threading/KCriticalSection.hpp>
#include <mesosphere/threading/KThread.hpp>
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<KCriticalSection> lk{KScheduler::GetCriticalSection()};
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <mesosphere/threading/KScheduler.hpp>
namespace mesosphere
{
class KScopedCriticalSection final {
private:
std::scoped_lock<KCriticalSection> lk{KScheduler::GetCriticalSection()};
};
}

View file

@ -1,6 +1,6 @@
#include <mesosphere/core/KSynchronizationObject.hpp>
#include <mesosphere/core/Result.hpp>
#include <mesosphere/threading/KScheduler.hpp>
#include <mesosphere/threading/KScopedCriticalSection.hpp>
#include <mesosphere/threading/KThread.hpp>
#include <mutex>

View file

@ -1,7 +1,7 @@
#include <mesosphere/processes/KWritableEvent.hpp>
#include <mesosphere/processes/KReadableEvent.hpp>
#include <mesosphere/processes/KEvent.hpp>
#include <mesosphere/threading/KScheduler.hpp>
#include <mesosphere/threading/KScopedCriticalSection.hpp>
namespace mesosphere
{

View file

@ -1,5 +1,5 @@
#include <mesosphere/threading/KConditionVariable.hpp>
#include <mesosphere/threading/KScheduler.hpp>
#include <mesosphere/threading/KScopedCriticalSection.hpp>
#include <mesosphere/core/KCoreContext.hpp>
namespace mesosphere

View file

@ -0,0 +1,45 @@
#include <mesosphere/threading/KCriticalSection.hpp>
#include <mesosphere/threading/KScheduler.hpp>
#include <mesosphere/core/KCoreContext.hpp>
namespace mesosphere
{
bool KCriticalSection::try_lock()
{
KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread();
if (curThread == lockingThread) {
++lockCount;
return true;
} else if (KInterruptSpinLock<false>::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<false>::lock();
lockingThread = curThread;
lockCount = 1;
}
}
void KCriticalSection::unlock()
{
if (--lockCount == 0) {
lockingThread = nullptr;
KScheduler::HandleCriticalSectionLeave();
} else {
KInterruptSpinLock<false>::unlock();
}
}
}

View file

@ -1,6 +1,6 @@
#include <mesosphere/threading/KMutex.hpp>
#include <mesosphere/threading/KThread.hpp>
#include <mesosphere/threading/KScheduler.hpp>
#include <mesosphere/threading/KScopedCriticalSection.hpp>
namespace mesosphere
{

View file

@ -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
}
}

View file

@ -3,7 +3,7 @@
#include <algorithm>
#include <mesosphere/threading/KThread.hpp>
#include <mesosphere/threading/KScheduler.hpp>
#include <mesosphere/threading/KScopedCriticalSection.hpp>
namespace mesosphere
{