Add mesosphere (VERY VERY WIP)
This commit is contained in:
62
mesosphere/source/threading/KMutex.cpp
Normal file
62
mesosphere/source/threading/KMutex.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <mesosphere/threading/KMutex.hpp>
|
||||
#include <mesosphere/threading/KThread.hpp>
|
||||
#include <mesosphere/threading/KScheduler.hpp>
|
||||
|
||||
namespace mesosphere
|
||||
{
|
||||
|
||||
void KMutex::lock_slow_path(KThread &owner, KThread &requester)
|
||||
{
|
||||
// Requester is currentThread most of (all ?) the time
|
||||
KCriticalSection &critsec = KScheduler::GetCriticalSection();
|
||||
std::lock_guard criticalSection{critsec};
|
||||
if (KCoreContext::GetCurrentInstance().GetScheduler()->IsActive()) {
|
||||
requester.SetWantedMutex((uiptr)this);
|
||||
owner.AddMutexWaiter(requester);
|
||||
|
||||
// If the requester is/was running, pause it (sets status even if force-paused).
|
||||
requester.RescheduleIfStatusEquals(KThread::SchedulingStatus::Running, KThread::SchedulingStatus::Paused);
|
||||
|
||||
// If the owner is force-paused, temporarily wake it.
|
||||
if (owner.IsForcePaused()) {
|
||||
owner.AdjustScheduling(owner.RevertForcePauseToField());
|
||||
}
|
||||
|
||||
// Commit scheduler changes NOW.
|
||||
critsec.unlock();
|
||||
critsec.lock();
|
||||
|
||||
/*
|
||||
At this point, mutex ownership has been transferred to requester or another thread (false wake).
|
||||
Make sure the requester, now resumed, isn't in any mutex wait list.
|
||||
*/
|
||||
owner.RemoveMutexWaiter(requester);
|
||||
}
|
||||
}
|
||||
|
||||
void KMutex::unlock_slow_path(KThread &owner)
|
||||
{
|
||||
std::lock_guard criticalSection{KScheduler::GetCriticalSection()};
|
||||
size_t count;
|
||||
KThread *newOwner = owner.RelinquishMutex(&count, (uiptr)this);
|
||||
native_handle_type newTag;
|
||||
|
||||
if (newOwner != nullptr) {
|
||||
// Wake up new owner
|
||||
newTag = (native_handle_type)newOwner | (count > 1 ? 1 : 0);
|
||||
// Sets status even if force-paused.
|
||||
newOwner->RescheduleIfStatusEquals(KThread::SchedulingStatus::Paused, KThread::SchedulingStatus::Running);
|
||||
} else {
|
||||
// Free the mutex.
|
||||
newTag = 0;
|
||||
}
|
||||
|
||||
// Allow previous owner to get back to forced-sleep, if no other thread wants the kmutexes it is holding.
|
||||
if (!owner.IsDying() && owner.GetNumberOfKMutexWaiters() == 0) {
|
||||
owner.AdjustScheduling(owner.CommitForcePauseToField());
|
||||
}
|
||||
|
||||
tag = newTag;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user