diff options
| author | bunnei <bunneidev@gmail.com> | 2021-06-11 11:03:55 -0700 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-11 11:03:55 -0700 | 
| commit | 0c0c1a039ec73937db4bc24e0bcbc478e3e6704b (patch) | |
| tree | 54b9110b9b80047ed0bebd3982fdfccc51dda76d /src/core/hle/kernel | |
| parent | fbb170857fab65e67a423c7e60cd1d7dc72e0663 (diff) | |
| parent | ebd38d66dbdb7fc934f52b9fb0fbb2b862afe7e5 (diff) | |
Merge pull request #6443 from Morph1984/k-light-condition-variable
kernel: KLightConditionVariable: Update implementation to 12.x
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_light_condition_variable.h | 43 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_light_lock.cpp | 19 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_resource_limit.cpp | 2 | 
4 files changed, 43 insertions, 37 deletions
| diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index ca2e539a7..a95fa41f3 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -18,41 +18,58 @@ class KernelCore;  class KLightConditionVariable {  public: -    explicit KLightConditionVariable(KernelCore& kernel_) -        : thread_queue(kernel_), kernel(kernel_) {} +    explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {} -    void Wait(KLightLock* lock, s64 timeout = -1) { -        WaitImpl(lock, timeout); -        lock->Lock(); +    void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) { +        WaitImpl(lock, timeout, allow_terminating_thread);      }      void Broadcast() {          KScopedSchedulerLock lk{kernel}; -        while (thread_queue.WakeupFrontThread() != nullptr) { -            // We want to signal all threads, and so should continue waking up until there's nothing -            // to wake. + +        // Signal all threads. +        for (auto& thread : wait_list) { +            thread.SetState(ThreadState::Runnable);          }      }  private: -    void WaitImpl(KLightLock* lock, s64 timeout) { +    void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {          KThread* owner = GetCurrentThreadPointer(kernel);          // Sleep the thread.          { -            KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); -            lock->Unlock(); +            KScopedSchedulerLockAndSleep lk{kernel, owner, timeout}; -            if (!thread_queue.SleepThread(owner)) { +            if (!allow_terminating_thread && owner->IsTerminationRequested()) {                  lk.CancelSleep();                  return;              } + +            lock->Unlock(); + +            // Set the thread as waiting. +            GetCurrentThread(kernel).SetState(ThreadState::Waiting); + +            // Add the thread to the queue. +            wait_list.push_back(GetCurrentThread(kernel)); +        } + +        // Remove the thread from the wait list. +        { +            KScopedSchedulerLock sl{kernel}; + +            wait_list.erase(wait_list.iterator_to(GetCurrentThread(kernel)));          }          // Cancel the task that the sleep setup.          kernel.TimeManager().UnscheduleTimeEvent(owner); + +        // Re-acquire the lock. +        lock->Lock();      } -    KThreadQueue thread_queue; +      KernelCore& kernel; +    KThread::WaiterList wait_list{};  };  } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index f974022e8..0896e705f 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -59,11 +59,7 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {          owner_thread->AddWaiter(cur_thread);          // Set thread states. -        if (cur_thread->GetState() == ThreadState::Runnable) { -            cur_thread->SetState(ThreadState::Waiting); -        } else { -            KScheduler::SetSchedulerUpdateNeeded(kernel); -        } +        cur_thread->SetState(ThreadState::Waiting);          if (owner_thread->IsSuspended()) {              owner_thread->ContinueIfHasKernelWaiters(); @@ -73,10 +69,9 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {      // We're no longer waiting on the lock owner.      {          KScopedSchedulerLock sl{kernel}; -        KThread* owner_thread = cur_thread->GetLockOwner(); -        if (owner_thread) { + +        if (KThread* owner_thread = cur_thread->GetLockOwner(); owner_thread != nullptr) {              owner_thread->RemoveWaiter(cur_thread); -            KScheduler::SetSchedulerUpdateNeeded(kernel);          }      }  } @@ -95,17 +90,13 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) {          // Pass the lock to the next owner.          uintptr_t next_tag = 0; -        if (next_owner) { +        if (next_owner != nullptr) {              next_tag = reinterpret_cast<uintptr_t>(next_owner);              if (num_waiters > 1) {                  next_tag |= 0x1;              } -            if (next_owner->GetState() == ThreadState::Waiting) { -                next_owner->SetState(ThreadState::Runnable); -            } else { -                KScheduler::SetSchedulerUpdateNeeded(kernel); -            } +            next_owner->SetState(ThreadState::Runnable);              if (next_owner->IsSuspended()) {                  next_owner->ContinueIfHasKernelWaiters(); diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 06b8ce151..d1bd98051 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -201,17 +201,15 @@ bool KProcess::ReleaseUserException(KThread* thread) {          // Remove waiter thread.          s32 num_waiters{}; -        KThread* next = thread->RemoveWaiterByKey( -            std::addressof(num_waiters), -            reinterpret_cast<uintptr_t>(std::addressof(exception_thread))); -        if (next != nullptr) { -            if (next->GetState() == ThreadState::Waiting) { -                next->SetState(ThreadState::Runnable); -            } else { -                KScheduler::SetSchedulerUpdateNeeded(kernel); -            } +        if (KThread* next = thread->RemoveWaiterByKey( +                std::addressof(num_waiters), +                reinterpret_cast<uintptr_t>(std::addressof(exception_thread))); +            next != nullptr) { +            next->SetState(ThreadState::Runnable);          } +        KScheduler::SetSchedulerUpdateNeeded(kernel); +          return true;      } else {          return false; diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index f91cb65dc..da88f35bc 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -117,7 +117,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {          if (current_hints[index] + value <= limit_values[index] &&              (timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) {              waiter_count++; -            cond_var.Wait(&lock, timeout); +            cond_var.Wait(&lock, timeout, false);              waiter_count--;          } else {              break; | 
