mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
kern: update KLightConditionVariable
This commit is contained in:
parent
b4498734e4
commit
c62a7381f8
3 changed files with 35 additions and 12 deletions
|
@ -24,40 +24,59 @@ namespace ams::kern {
|
|||
|
||||
class KLightConditionVariable {
|
||||
private:
|
||||
KThreadQueue m_thread_queue;
|
||||
KThread::WaiterList m_wait_list;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KLightConditionVariable() : m_thread_queue() { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KLightConditionVariable() : m_wait_list() { /* ... */ }
|
||||
private:
|
||||
void WaitImpl(KLightLock *lock, s64 timeout) {
|
||||
void WaitImpl(KLightLock *lock, s64 timeout, bool allow_terminating_thread) {
|
||||
KThread *owner = GetCurrentThreadPointer();
|
||||
KHardwareTimer *timer;
|
||||
|
||||
/* Sleep the thread. */
|
||||
{
|
||||
KScopedSchedulerLockAndSleep lk(&timer, owner, timeout);
|
||||
lock->Unlock();
|
||||
|
||||
if (!m_thread_queue.SleepThread(owner)) {
|
||||
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
||||
lk.CancelSleep();
|
||||
return;
|
||||
}
|
||||
|
||||
lock->Unlock();
|
||||
|
||||
|
||||
/* Set the thread as waiting. */
|
||||
GetCurrentThread().SetState(KThread::ThreadState_Waiting);
|
||||
|
||||
/* Add the thread to the queue. */
|
||||
m_wait_list.push_back(GetCurrentThread());
|
||||
}
|
||||
|
||||
/* Remove the thread from the wait list. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
m_wait_list.erase(m_wait_list.iterator_to(GetCurrentThread()));
|
||||
}
|
||||
|
||||
/* Cancel the task that the sleep setup. */
|
||||
if (timer != nullptr) {
|
||||
timer->CancelTask(owner);
|
||||
}
|
||||
|
||||
/* Re-acquire the lock. */
|
||||
lock->Lock();
|
||||
}
|
||||
public:
|
||||
void Wait(KLightLock *lock, s64 timeout = -1ll) {
|
||||
this->WaitImpl(lock, timeout);
|
||||
lock->Lock();
|
||||
void Wait(KLightLock *lock, s64 timeout = -1ll, bool allow_terminating_thread = true) {
|
||||
this->WaitImpl(lock, timeout, allow_terminating_thread);
|
||||
}
|
||||
|
||||
void Broadcast() {
|
||||
KScopedSchedulerLock lk;
|
||||
while (m_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 : m_wait_list) {
|
||||
thread.SetState(KThread::ThreadState_Runnable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -492,7 +492,7 @@ namespace ams::kern::board::nintendo::nx {
|
|||
/* Wait for a request. */
|
||||
{
|
||||
KScopedLightLock lk(g_cv_lock);
|
||||
while (!(g_sleep_target_cores & target_core_mask)) {
|
||||
while ((g_sleep_target_cores & target_core_mask) == 0) {
|
||||
g_cv.Wait(std::addressof(g_cv_lock));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,8 +146,12 @@ namespace ams::kern {
|
|||
|
||||
if (m_current_hints[which] + value <= m_limit_values[which] && (timeout < 0 || KHardwareTimer::GetTick() < timeout)) {
|
||||
m_waiter_count++;
|
||||
m_cond_var.Wait(&m_lock, timeout);
|
||||
m_cond_var.Wait(&m_lock, timeout, false);
|
||||
m_waiter_count--;
|
||||
|
||||
if (GetCurrentThread().IsTerminationRequested()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue