summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar bunnei2021-11-10 22:28:30 -0800
committerGravatar bunnei2021-12-06 16:39:17 -0800
commitb0671c7cfaa8bdb9704827af83be9223a5890f97 (patch)
tree1cc9ae63853c390166832afe9218257eb0a4ee99 /src/core/hle/kernel
parenthle: kernel: KConditionVariable: Migrate to updated KThreadQueue. (diff)
downloadyuzu-b0671c7cfaa8bdb9704827af83be9223a5890f97.tar.gz
yuzu-b0671c7cfaa8bdb9704827af83be9223a5890f97.tar.xz
yuzu-b0671c7cfaa8bdb9704827af83be9223a5890f97.zip
hle: kernel: KThread: Migrate to updated KThreadQueue (part 1).
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/k_thread.cpp121
-rw-r--r--src/core/hle/kernel/k_thread.h4
-rw-r--r--src/core/hle/kernel/time_manager.cpp6
3 files changed, 71 insertions, 60 deletions
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 2c1f29bad..995f0ca50 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -59,6 +59,35 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
59 59
60namespace Kernel { 60namespace Kernel {
61 61
62namespace {
63
64class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait {
65public:
66 explicit ThreadQueueImplForKThreadSleep(KernelCore& kernel_)
67 : KThreadQueueWithoutEndWait(kernel_) {}
68};
69
70class ThreadQueueImplForKThreadSetProperty final : public KThreadQueue {
71private:
72 KThread::WaiterList* m_wait_list;
73
74public:
75 explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel_, KThread::WaiterList* wl)
76 : KThreadQueue(kernel_), m_wait_list(wl) { // ...
77 }
78
79 virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result,
80 bool cancel_timer_task) override {
81 // Remove the thread from the wait list.
82 m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread));
83
84 // Invoke the base cancel wait handler.
85 KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task);
86 }
87};
88
89} // namespace
90
62KThread::KThread(KernelCore& kernel_) 91KThread::KThread(KernelCore& kernel_)
63 : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {} 92 : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {}
64KThread::~KThread() = default; 93KThread::~KThread() = default;
@@ -274,11 +303,14 @@ void KThread::Finalize() {
274 303
275 auto it = waiter_list.begin(); 304 auto it = waiter_list.begin();
276 while (it != waiter_list.end()) { 305 while (it != waiter_list.end()) {
277 // The thread shouldn't be a kernel waiter. 306 // Clear the lock owner
278 it->SetLockOwner(nullptr); 307 it->SetLockOwner(nullptr);
279 it->SetWaitResult(ResultInvalidState); 308
280 it->Wakeup(); 309 // Erase the waiter from our list.
281 it = waiter_list.erase(it); 310 it = waiter_list.erase(it);
311
312 // Cancel the thread's wait.
313 it->CancelWait(ResultInvalidState, true);
282 } 314 }
283 } 315 }
284 316
@@ -295,15 +327,12 @@ bool KThread::IsSignaled() const {
295 return signaled; 327 return signaled;
296} 328}
297 329
298void KThread::Wakeup() { 330void KThread::OnTimer() {
299 KScopedSchedulerLock sl{kernel}; 331 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
300 332
333 // If we're waiting, cancel the wait.
301 if (GetState() == ThreadState::Waiting) { 334 if (GetState() == ThreadState::Waiting) {
302 if (sleeping_queue != nullptr) { 335 sleeping_queue->CancelWait(this, ResultTimedOut, false);
303 sleeping_queue->EndWait(this, ResultSuccess);
304 } else {
305 SetState(ThreadState::Runnable);
306 }
307 } 336 }
308} 337}
309 338
@@ -475,7 +504,6 @@ ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_m
475 504
476 return ResultSuccess; 505 return ResultSuccess;
477} 506}
478
479ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { 507ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) {
480 ASSERT(parent != nullptr); 508 ASSERT(parent != nullptr);
481 ASSERT(v_affinity_mask != 0); 509 ASSERT(v_affinity_mask != 0);
@@ -642,15 +670,9 @@ void KThread::WaitCancel() {
642 KScopedSchedulerLock sl{kernel}; 670 KScopedSchedulerLock sl{kernel};
643 671
644 // Check if we're waiting and cancellable. 672 // Check if we're waiting and cancellable.
645 if (GetState() == ThreadState::Waiting && cancellable) { 673 if (this->GetState() == ThreadState::Waiting && cancellable) {
646 if (sleeping_queue != nullptr) { 674 wait_cancelled = false;
647 sleeping_queue->WakeupThread(this); 675 sleeping_queue->CancelWait(this, ResultCancelled, true);
648 wait_cancelled = true;
649 } else {
650 SetWaitResult(ResultCancelled);
651 SetState(ThreadState::Runnable);
652 wait_cancelled = false;
653 }
654 } else { 676 } else {
655 // Otherwise, note that we cancelled a wait. 677 // Otherwise, note that we cancelled a wait.
656 wait_cancelled = true; 678 wait_cancelled = true;
@@ -701,60 +723,59 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
701 // Set the activity. 723 // Set the activity.
702 { 724 {
703 // Lock the scheduler. 725 // Lock the scheduler.
704 KScopedSchedulerLock sl{kernel}; 726 KScopedSchedulerLock sl(kernel);
705 727
706 // Verify our state. 728 // Verify our state.
707 const auto cur_state = GetState(); 729 const auto cur_state = this->GetState();
708 R_UNLESS((cur_state == ThreadState::Waiting || cur_state == ThreadState::Runnable), 730 R_UNLESS((cur_state == ThreadState::Waiting || cur_state == ThreadState::Runnable),
709 ResultInvalidState); 731 ResultInvalidState);
710 732
711 // Either pause or resume. 733 // Either pause or resume.
712 if (activity == Svc::ThreadActivity::Paused) { 734 if (activity == Svc::ThreadActivity::Paused) {
713 // Verify that we're not suspended. 735 // Verify that we're not suspended.
714 R_UNLESS(!IsSuspendRequested(SuspendType::Thread), ResultInvalidState); 736 R_UNLESS(!this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState);
715 737
716 // Suspend. 738 // Suspend.
717 RequestSuspend(SuspendType::Thread); 739 this->RequestSuspend(SuspendType::Thread);
718 } else { 740 } else {
719 ASSERT(activity == Svc::ThreadActivity::Runnable); 741 ASSERT(activity == Svc::ThreadActivity::Runnable);
720 742
721 // Verify that we're suspended. 743 // Verify that we're suspended.
722 R_UNLESS(IsSuspendRequested(SuspendType::Thread), ResultInvalidState); 744 R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState);
723 745
724 // Resume. 746 // Resume.
725 Resume(SuspendType::Thread); 747 this->Resume(SuspendType::Thread);
726 } 748 }
727 } 749 }
728 750
729 // If the thread is now paused, update the pinned waiter list. 751 // If the thread is now paused, update the pinned waiter list.
730 if (activity == Svc::ThreadActivity::Paused) { 752 if (activity == Svc::ThreadActivity::Paused) {
731 bool thread_is_pinned{}; 753 ThreadQueueImplForKThreadSetProperty wait_queue_(kernel,
732 bool thread_is_current{}; 754 std::addressof(pinned_waiter_list));
755
756 bool thread_is_current;
733 do { 757 do {
734 // Lock the scheduler. 758 // Lock the scheduler.
735 KScopedSchedulerLock sl{kernel}; 759 KScopedSchedulerLock sl(kernel);
736 760
737 // Don't do any further management if our termination has been requested. 761 // Don't do any further management if our termination has been requested.
738 R_SUCCEED_IF(IsTerminationRequested()); 762 R_SUCCEED_IF(this->IsTerminationRequested());
763
764 // By default, treat the thread as not current.
765 thread_is_current = false;
739 766
740 // Check whether the thread is pinned. 767 // Check whether the thread is pinned.
741 if (GetStackParameters().is_pinned) { 768 if (this->GetStackParameters().is_pinned) {
742 // Verify that the current thread isn't terminating. 769 // Verify that the current thread isn't terminating.
743 R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), 770 R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(),
744 ResultTerminationRequested); 771 ResultTerminationRequested);
745 772
746 // Note that the thread was pinned and not current.
747 thread_is_pinned = true;
748 thread_is_current = false;
749
750 // Wait until the thread isn't pinned any more. 773 // Wait until the thread isn't pinned any more.
751 pinned_waiter_list.push_back(GetCurrentThread(kernel)); 774 pinned_waiter_list.push_back(GetCurrentThread(kernel));
752 GetCurrentThread(kernel).SetState(ThreadState::Waiting); 775 GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue_));
753 } else { 776 } else {
754 // Check if the thread is currently running. 777 // Check if the thread is currently running.
755 // If it is, we'll need to retry. 778 // If it is, we'll need to retry.
756 thread_is_current = false;
757
758 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { 779 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
759 if (kernel.Scheduler(i).GetCurrentThread() == this) { 780 if (kernel.Scheduler(i).GetCurrentThread() == this) {
760 thread_is_current = true; 781 thread_is_current = true;
@@ -763,16 +784,6 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
763 } 784 }
764 } 785 }
765 } while (thread_is_current); 786 } while (thread_is_current);
766
767 // If the thread was pinned, it no longer is, and we should remove the current thread from
768 // our waiter list.
769 if (thread_is_pinned) {
770 // Lock the scheduler.
771 KScopedSchedulerLock sl{kernel};
772
773 // Remove from the list.
774 pinned_waiter_list.erase(pinned_waiter_list.iterator_to(GetCurrentThread(kernel)));
775 }
776 } 787 }
777 788
778 return ResultSuccess; 789 return ResultSuccess;
@@ -1000,26 +1011,22 @@ ResultCode KThread::Sleep(s64 timeout) {
1000 ASSERT(this == GetCurrentThreadPointer(kernel)); 1011 ASSERT(this == GetCurrentThreadPointer(kernel));
1001 ASSERT(timeout > 0); 1012 ASSERT(timeout > 0);
1002 1013
1014 ThreadQueueImplForKThreadSleep wait_queue(kernel);
1003 { 1015 {
1004 // Setup the scheduling lock and sleep. 1016 // Setup the scheduling lock and sleep.
1005 KScopedSchedulerLockAndSleep slp{kernel, this, timeout}; 1017 KScopedSchedulerLockAndSleep slp(kernel, this, timeout);
1006 1018
1007 // Check if the thread should terminate. 1019 // Check if the thread should terminate.
1008 if (IsTerminationRequested()) { 1020 if (this->IsTerminationRequested()) {
1009 slp.CancelSleep(); 1021 slp.CancelSleep();
1010 return ResultTerminationRequested; 1022 return ResultTerminationRequested;
1011 } 1023 }
1012 1024
1013 // Mark the thread as waiting. 1025 // Wait for the sleep to end.
1014 SetState(ThreadState::Waiting); 1026 this->BeginWait(std::addressof(wait_queue));
1015 SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); 1027 SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep);
1016 } 1028 }
1017 1029
1018 // The lock/sleep is done.
1019
1020 // Cancel the timer.
1021 kernel.TimeManager().UnscheduleTimeEvent(this);
1022
1023 return ResultSuccess; 1030 return ResultSuccess;
1024} 1031}
1025 1032
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index f9a324eb3..6d68c2399 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -161,8 +161,6 @@ public:
161 } 161 }
162 } 162 }
163 163
164 void Wakeup();
165
166 void SetBasePriority(s32 value); 164 void SetBasePriority(s32 value);
167 165
168 [[nodiscard]] ResultCode Run(); 166 [[nodiscard]] ResultCode Run();
@@ -380,6 +378,8 @@ public:
380 378
381 [[nodiscard]] bool IsSignaled() const override; 379 [[nodiscard]] bool IsSignaled() const override;
382 380
381 void OnTimer();
382
383 static void PostDestroy(uintptr_t arg); 383 static void PostDestroy(uintptr_t arg);
384 384
385 [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); 385 [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread);
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp
index 8cd7279a3..aa985d820 100644
--- a/src/core/hle/kernel/time_manager.cpp
+++ b/src/core/hle/kernel/time_manager.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/core.h" 6#include "core/core.h"
7#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/hle/kernel/k_scheduler.h"
8#include "core/hle/kernel/k_thread.h" 9#include "core/hle/kernel/k_thread.h"
9#include "core/hle/kernel/time_manager.h" 10#include "core/hle/kernel/time_manager.h"
10 11
@@ -15,7 +16,10 @@ TimeManager::TimeManager(Core::System& system_) : system{system_} {
15 Core::Timing::CreateEvent("Kernel::TimeManagerCallback", 16 Core::Timing::CreateEvent("Kernel::TimeManagerCallback",
16 [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) { 17 [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) {
17 KThread* thread = reinterpret_cast<KThread*>(thread_handle); 18 KThread* thread = reinterpret_cast<KThread*>(thread_handle);
18 thread->Wakeup(); 19 {
20 KScopedSchedulerLock sl(system.Kernel());
21 thread->OnTimer();
22 }
19 }); 23 });
20} 24}
21 25