diff options
| author | bunnei <bunneidev@gmail.com> | 2021-11-09 20:51:47 -0800 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2021-12-06 16:39:17 -0800 | 
| commit | 423acf53b740ce96ca37988aad79ddf5013645ef (patch) | |
| tree | 8e0674b69def392ef7e634e24d0027b9e0f213ad /src/core/hle | |
| parent | 15c721b90977865d964e26537f8a8f8740134164 (diff) | |
hle: kernel: KLightLock: Migrate to updated KThreadQueue.
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/k_light_lock.cpp | 69 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_light_lock.h | 2 | 
2 files changed, 36 insertions, 35 deletions
| diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index 0896e705f..5e8f1a510 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -5,44 +5,54 @@  #include "core/hle/kernel/k_light_lock.h"  #include "core/hle/kernel/k_scheduler.h"  #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_thread_queue.h"  #include "core/hle/kernel/kernel.h"  namespace Kernel { +namespace { + +class ThreadQueueImplForKLightLock final : public KThreadQueue { +public: +    explicit ThreadQueueImplForKLightLock(KernelCore& kernel_) : KThreadQueue(kernel_) {} + +    virtual void CancelWait([[maybe_unused]] KThread* waiting_thread, +                            [[maybe_unused]] ResultCode wait_result, +                            [[maybe_unused]] bool cancel_timer_task) override { +        // Do nothing, waiting to acquire a light lock cannot be canceled. +    } +}; + +} // namespace +  void KLightLock::Lock() {      const uintptr_t cur_thread = reinterpret_cast<uintptr_t>(GetCurrentThreadPointer(kernel)); -    const uintptr_t cur_thread_tag = (cur_thread | 1);      while (true) {          uintptr_t old_tag = tag.load(std::memory_order_relaxed); -        while (!tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : old_tag | 1, +        while (!tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1),                                            std::memory_order_acquire)) { -            if ((old_tag | 1) == cur_thread_tag) { -                return; -            }          } -        if ((old_tag == 0) || ((old_tag | 1) == cur_thread_tag)) { +        if (old_tag == 0 || this->LockSlowPath(old_tag | 1, cur_thread)) {              break;          } - -        LockSlowPath(old_tag | 1, cur_thread);      }  }  void KLightLock::Unlock() {      const uintptr_t cur_thread = reinterpret_cast<uintptr_t>(GetCurrentThreadPointer(kernel)); +      uintptr_t expected = cur_thread; -    do { -        if (expected != cur_thread) { -            return UnlockSlowPath(cur_thread); -        } -    } while (!tag.compare_exchange_weak(expected, 0, std::memory_order_release)); +    if (!tag.compare_exchange_strong(expected, 0, std::memory_order_release)) { +        this->UnlockSlowPath(cur_thread); +    }  } -void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { +bool KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {      KThread* cur_thread = reinterpret_cast<KThread*>(_cur_thread); +    ThreadQueueImplForKLightLock wait_queue(kernel);      // Pend the current thread waiting on the owner thread.      { @@ -50,30 +60,23 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {          // Ensure we actually have locking to do.          if (tag.load(std::memory_order_relaxed) != _owner) { -            return; +            return false;          }          // Add the current thread as a waiter on the owner. -        KThread* owner_thread = reinterpret_cast<KThread*>(_owner & ~1ULL); +        KThread* owner_thread = reinterpret_cast<KThread*>(_owner & ~1ul);          cur_thread->SetAddressKey(reinterpret_cast<uintptr_t>(std::addressof(tag)));          owner_thread->AddWaiter(cur_thread); -        // Set thread states. -        cur_thread->SetState(ThreadState::Waiting); +        // Begin waiting to hold the lock. +        cur_thread->BeginWait(std::addressof(wait_queue));          if (owner_thread->IsSuspended()) {              owner_thread->ContinueIfHasKernelWaiters();          }      } -    // We're no longer waiting on the lock owner. -    { -        KScopedSchedulerLock sl{kernel}; - -        if (KThread* owner_thread = cur_thread->GetLockOwner(); owner_thread != nullptr) { -            owner_thread->RemoveWaiter(cur_thread); -        } -    } +    return true;  }  void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { @@ -81,22 +84,20 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) {      // Unlock.      { -        KScopedSchedulerLock sl{kernel}; +        KScopedSchedulerLock sl(kernel);          // Get the next owner. -        s32 num_waiters = 0; +        s32 num_waiters;          KThread* next_owner = owner_thread->RemoveWaiterByKey(              std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(tag)));          // Pass the lock to the next owner.          uintptr_t next_tag = 0;          if (next_owner != nullptr) { -            next_tag = reinterpret_cast<uintptr_t>(next_owner); -            if (num_waiters > 1) { -                next_tag |= 0x1; -            } +            next_tag = +                reinterpret_cast<uintptr_t>(next_owner) | static_cast<uintptr_t>(num_waiters > 1); -            next_owner->SetState(ThreadState::Runnable); +            next_owner->EndWait(ResultSuccess);              if (next_owner->IsSuspended()) {                  next_owner->ContinueIfHasKernelWaiters(); @@ -110,7 +111,7 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) {          }          // Write the new tag value. -        tag.store(next_tag); +        tag.store(next_tag, std::memory_order_release);      }  } diff --git a/src/core/hle/kernel/k_light_lock.h b/src/core/hle/kernel/k_light_lock.h index ad853661d..4163b8a85 100644 --- a/src/core/hle/kernel/k_light_lock.h +++ b/src/core/hle/kernel/k_light_lock.h @@ -20,7 +20,7 @@ public:      void Unlock(); -    void LockSlowPath(uintptr_t owner, uintptr_t cur_thread); +    bool LockSlowPath(uintptr_t owner, uintptr_t cur_thread);      void UnlockSlowPath(uintptr_t cur_thread); | 
