mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-17 17:36:44 +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 {
|
class KLightConditionVariable {
|
||||||
private:
|
private:
|
||||||
KThreadQueue m_thread_queue;
|
KThread::WaiterList m_wait_list;
|
||||||
public:
|
public:
|
||||||
constexpr ALWAYS_INLINE KLightConditionVariable() : m_thread_queue() { /* ... */ }
|
constexpr ALWAYS_INLINE KLightConditionVariable() : m_wait_list() { /* ... */ }
|
||||||
private:
|
private:
|
||||||
void WaitImpl(KLightLock *lock, s64 timeout) {
|
void WaitImpl(KLightLock *lock, s64 timeout, bool allow_terminating_thread) {
|
||||||
KThread *owner = GetCurrentThreadPointer();
|
KThread *owner = GetCurrentThreadPointer();
|
||||||
KHardwareTimer *timer;
|
KHardwareTimer *timer;
|
||||||
|
|
||||||
/* Sleep the thread. */
|
/* Sleep the thread. */
|
||||||
{
|
{
|
||||||
KScopedSchedulerLockAndSleep lk(&timer, owner, timeout);
|
KScopedSchedulerLockAndSleep lk(&timer, owner, timeout);
|
||||||
lock->Unlock();
|
|
||||||
|
|
||||||
if (!m_thread_queue.SleepThread(owner)) {
|
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
||||||
lk.CancelSleep();
|
lk.CancelSleep();
|
||||||
return;
|
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. */
|
/* Cancel the task that the sleep setup. */
|
||||||
if (timer != nullptr) {
|
if (timer != nullptr) {
|
||||||
timer->CancelTask(owner);
|
timer->CancelTask(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Re-acquire the lock. */
|
||||||
|
lock->Lock();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
void Wait(KLightLock *lock, s64 timeout = -1ll) {
|
void Wait(KLightLock *lock, s64 timeout = -1ll, bool allow_terminating_thread = true) {
|
||||||
this->WaitImpl(lock, timeout);
|
this->WaitImpl(lock, timeout, allow_terminating_thread);
|
||||||
lock->Lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Broadcast() {
|
void Broadcast() {
|
||||||
KScopedSchedulerLock lk;
|
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. */
|
/* Wait for a request. */
|
||||||
{
|
{
|
||||||
KScopedLightLock lk(g_cv_lock);
|
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));
|
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)) {
|
if (m_current_hints[which] + value <= m_limit_values[which] && (timeout < 0 || KHardwareTimer::GetTick() < timeout)) {
|
||||||
m_waiter_count++;
|
m_waiter_count++;
|
||||||
m_cond_var.Wait(&m_lock, timeout);
|
m_cond_var.Wait(&m_lock, timeout, false);
|
||||||
m_waiter_count--;
|
m_waiter_count--;
|
||||||
|
|
||||||
|
if (GetCurrentThread().IsTerminationRequested()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue