3
0
Fork 0
forked from suyu/suyu

kernel: KLightConditionVariable: Update implementation to 12.x

Updates the implementation of KLightConditionVariable to FW 12.x
This commit is contained in:
Morph 2021-06-10 13:56:35 -04:00
parent 4547b2735a
commit aa79ca7a7a
2 changed files with 31 additions and 14 deletions

View file

@ -18,41 +18,58 @@ class KernelCore;
class KLightConditionVariable { class KLightConditionVariable {
public: public:
explicit KLightConditionVariable(KernelCore& kernel_) explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {}
: thread_queue(kernel_), kernel(kernel_) {}
void Wait(KLightLock* lock, s64 timeout = -1) { void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) {
WaitImpl(lock, timeout); WaitImpl(lock, timeout, allow_terminating_thread);
lock->Lock();
} }
void Broadcast() { void Broadcast() {
KScopedSchedulerLock lk{kernel}; KScopedSchedulerLock lk{kernel};
while (thread_queue.WakeupFrontThread() != nullptr) {
// We want to signal all threads, and so should continue waking up until there's nothing // Signal all threads.
// to wake. for (auto& thread : wait_list) {
thread.SetState(ThreadState::Runnable);
} }
} }
private: private:
void WaitImpl(KLightLock* lock, s64 timeout) { void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {
KThread* owner = GetCurrentThreadPointer(kernel); KThread* owner = GetCurrentThreadPointer(kernel);
// Sleep the thread. // Sleep the thread.
{ {
KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); KScopedSchedulerLockAndSleep lk{kernel, owner, timeout};
lock->Unlock();
if (!thread_queue.SleepThread(owner)) { if (!allow_terminating_thread && owner->IsTerminationRequested()) {
lk.CancelSleep(); lk.CancelSleep();
return; 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. // Cancel the task that the sleep setup.
kernel.TimeManager().UnscheduleTimeEvent(owner); kernel.TimeManager().UnscheduleTimeEvent(owner);
// Re-acquire the lock.
lock->Lock();
} }
KThreadQueue thread_queue;
KernelCore& kernel; KernelCore& kernel;
KThread::WaiterList wait_list{};
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -117,7 +117,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
if (current_hints[index] + value <= limit_values[index] && if (current_hints[index] + value <= limit_values[index] &&
(timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) { (timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) {
waiter_count++; waiter_count++;
cond_var.Wait(&lock, timeout); cond_var.Wait(&lock, timeout, false);
waiter_count--; waiter_count--;
} else { } else {
break; break;