mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-15 23:54:24 -04:00
kern: implement lightlock slowpath (works on hw)
This commit is contained in:
parent
b3e6571586
commit
11f70759ce
7 changed files with 258 additions and 5 deletions
|
@ -17,12 +17,74 @@
|
|||
|
||||
namespace ams::kern {
|
||||
|
||||
void KLightLock::LockSlowPath(uintptr_t owner, uintptr_t cur_thread) {
|
||||
MESOSPHERE_TODO_IMPLEMENT();
|
||||
void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {
|
||||
KThread *cur_thread = reinterpret_cast<KThread *>(_cur_thread);
|
||||
|
||||
/* Pend the current thread waiting on the owner thread. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Ensure we actually have locking to do. */
|
||||
if (AMS_UNLIKELY(this->tag.load(std::memory_order_relaxed) != _owner)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add the current thread as a waiter on the owner. */
|
||||
KThread *owner_thread = reinterpret_cast<KThread *>(_owner & ~1ul);
|
||||
cur_thread->SetAddressKey(reinterpret_cast<uintptr_t>(std::addressof(this->tag)));
|
||||
owner_thread->AddWaiter(cur_thread);
|
||||
|
||||
/* Set thread states. */
|
||||
if (AMS_LIKELY(cur_thread->GetState() == KThread::ThreadState_Runnable)) {
|
||||
cur_thread->SetState(KThread::ThreadState_Waiting);
|
||||
}
|
||||
if (owner_thread->IsSuspended()) {
|
||||
owner_thread->ContinueIfHasKernelWaiters();
|
||||
}
|
||||
}
|
||||
|
||||
/* We're no longer waiting on the lock owner. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
KThread *owner_thread = cur_thread->GetLockOwner();
|
||||
if (AMS_UNLIKELY(owner_thread)) {
|
||||
owner_thread->RemoveWaiter(cur_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KLightLock::UnlockSlowPath(uintptr_t cur_thread) {
|
||||
MESOSPHERE_TODO_IMPLEMENT();
|
||||
void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) {
|
||||
KThread *owner_thread = reinterpret_cast<KThread *>(_cur_thread);
|
||||
|
||||
/* Unlock. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Get the next owner. */
|
||||
s32 num_waiters = 0;
|
||||
KThread *next_owner = owner_thread->RemoveWaiterByKey(std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(this->tag)));
|
||||
|
||||
/* Pass the lock to the next owner. */
|
||||
uintptr_t next_tag = 0;
|
||||
if (next_owner) {
|
||||
next_tag = reinterpret_cast<uintptr_t>(next_owner);
|
||||
if (num_waiters > 1) {
|
||||
next_tag |= 0x1;
|
||||
}
|
||||
|
||||
if (AMS_LIKELY(next_owner->GetState() == KThread::ThreadState_Waiting)) {
|
||||
next_owner->SetState(KThread::ThreadState_Runnable);
|
||||
}
|
||||
}
|
||||
|
||||
/* We may have unsuspended in the process of acquiring the lock, so we'll re-suspend now if so. */
|
||||
if (owner_thread->IsSuspended()) {
|
||||
owner_thread->TrySuspend();
|
||||
}
|
||||
|
||||
/* Write the new tag value. */
|
||||
this->tag.store(next_tag);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue