|
|
|
@ -12,11 +12,11 @@ namespace Kernel { |
|
|
|
constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
|
|
|
|
|
|
|
|
KResourceLimit::KResourceLimit(KernelCore& kernel) |
|
|
|
: KAutoObjectWithSlabHeapAndContainer{kernel}, lock{kernel}, cond_var{kernel} {} |
|
|
|
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {} |
|
|
|
KResourceLimit::~KResourceLimit() = default; |
|
|
|
|
|
|
|
void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) { |
|
|
|
core_timing = core_timing_; |
|
|
|
void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing) { |
|
|
|
m_core_timing = core_timing; |
|
|
|
} |
|
|
|
|
|
|
|
void KResourceLimit::Finalize() {} |
|
|
|
@ -25,11 +25,11 @@ s64 KResourceLimit::GetLimitValue(LimitableResource which) const { |
|
|
|
const auto index = static_cast<std::size_t>(which); |
|
|
|
s64 value{}; |
|
|
|
{ |
|
|
|
KScopedLightLock lk{lock}; |
|
|
|
value = limit_values[index]; |
|
|
|
KScopedLightLock lk{m_lock}; |
|
|
|
value = m_limit_values[index]; |
|
|
|
ASSERT(value >= 0); |
|
|
|
ASSERT(current_values[index] <= limit_values[index]); |
|
|
|
ASSERT(current_hints[index] <= current_values[index]); |
|
|
|
ASSERT(m_current_values[index] <= m_limit_values[index]); |
|
|
|
ASSERT(m_current_hints[index] <= m_current_values[index]); |
|
|
|
} |
|
|
|
return value; |
|
|
|
} |
|
|
|
@ -38,11 +38,11 @@ s64 KResourceLimit::GetCurrentValue(LimitableResource which) const { |
|
|
|
const auto index = static_cast<std::size_t>(which); |
|
|
|
s64 value{}; |
|
|
|
{ |
|
|
|
KScopedLightLock lk{lock}; |
|
|
|
value = current_values[index]; |
|
|
|
KScopedLightLock lk{m_lock}; |
|
|
|
value = m_current_values[index]; |
|
|
|
ASSERT(value >= 0); |
|
|
|
ASSERT(current_values[index] <= limit_values[index]); |
|
|
|
ASSERT(current_hints[index] <= current_values[index]); |
|
|
|
ASSERT(m_current_values[index] <= m_limit_values[index]); |
|
|
|
ASSERT(m_current_hints[index] <= m_current_values[index]); |
|
|
|
} |
|
|
|
return value; |
|
|
|
} |
|
|
|
@ -51,11 +51,11 @@ s64 KResourceLimit::GetPeakValue(LimitableResource which) const { |
|
|
|
const auto index = static_cast<std::size_t>(which); |
|
|
|
s64 value{}; |
|
|
|
{ |
|
|
|
KScopedLightLock lk{lock}; |
|
|
|
value = peak_values[index]; |
|
|
|
KScopedLightLock lk{m_lock}; |
|
|
|
value = m_peak_values[index]; |
|
|
|
ASSERT(value >= 0); |
|
|
|
ASSERT(current_values[index] <= limit_values[index]); |
|
|
|
ASSERT(current_hints[index] <= current_values[index]); |
|
|
|
ASSERT(m_current_values[index] <= m_limit_values[index]); |
|
|
|
ASSERT(m_current_hints[index] <= m_current_values[index]); |
|
|
|
} |
|
|
|
return value; |
|
|
|
} |
|
|
|
@ -64,11 +64,11 @@ s64 KResourceLimit::GetFreeValue(LimitableResource which) const { |
|
|
|
const auto index = static_cast<std::size_t>(which); |
|
|
|
s64 value{}; |
|
|
|
{ |
|
|
|
KScopedLightLock lk(lock); |
|
|
|
ASSERT(current_values[index] >= 0); |
|
|
|
ASSERT(current_values[index] <= limit_values[index]); |
|
|
|
ASSERT(current_hints[index] <= current_values[index]); |
|
|
|
value = limit_values[index] - current_values[index]; |
|
|
|
KScopedLightLock lk(m_lock); |
|
|
|
ASSERT(m_current_values[index] >= 0); |
|
|
|
ASSERT(m_current_values[index] <= m_limit_values[index]); |
|
|
|
ASSERT(m_current_hints[index] <= m_current_values[index]); |
|
|
|
value = m_limit_values[index] - m_current_values[index]; |
|
|
|
} |
|
|
|
|
|
|
|
return value; |
|
|
|
@ -76,51 +76,51 @@ s64 KResourceLimit::GetFreeValue(LimitableResource which) const { |
|
|
|
|
|
|
|
Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { |
|
|
|
const auto index = static_cast<std::size_t>(which); |
|
|
|
KScopedLightLock lk(lock); |
|
|
|
R_UNLESS(current_values[index] <= value, ResultInvalidState); |
|
|
|
KScopedLightLock lk(m_lock); |
|
|
|
R_UNLESS(m_current_values[index] <= value, ResultInvalidState); |
|
|
|
|
|
|
|
limit_values[index] = value; |
|
|
|
peak_values[index] = current_values[index]; |
|
|
|
m_limit_values[index] = value; |
|
|
|
m_peak_values[index] = m_current_values[index]; |
|
|
|
|
|
|
|
R_SUCCEED(); |
|
|
|
} |
|
|
|
|
|
|
|
bool KResourceLimit::Reserve(LimitableResource which, s64 value) { |
|
|
|
return Reserve(which, value, core_timing->GetGlobalTimeNs().count() + DefaultTimeout); |
|
|
|
return Reserve(which, value, m_core_timing->GetGlobalTimeNs().count() + DefaultTimeout); |
|
|
|
} |
|
|
|
|
|
|
|
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { |
|
|
|
ASSERT(value >= 0); |
|
|
|
const auto index = static_cast<std::size_t>(which); |
|
|
|
KScopedLightLock lk(lock); |
|
|
|
KScopedLightLock lk(m_lock); |
|
|
|
|
|
|
|
ASSERT(current_hints[index] <= current_values[index]); |
|
|
|
if (current_hints[index] >= limit_values[index]) { |
|
|
|
ASSERT(m_current_hints[index] <= m_current_values[index]); |
|
|
|
if (m_current_hints[index] >= m_limit_values[index]) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// Loop until we reserve or run out of time.
|
|
|
|
while (true) { |
|
|
|
ASSERT(current_values[index] <= limit_values[index]); |
|
|
|
ASSERT(current_hints[index] <= current_values[index]); |
|
|
|
ASSERT(m_current_values[index] <= m_limit_values[index]); |
|
|
|
ASSERT(m_current_hints[index] <= m_current_values[index]); |
|
|
|
|
|
|
|
// If we would overflow, don't allow to succeed.
|
|
|
|
if (Common::WrappingAdd(current_values[index], value) <= current_values[index]) { |
|
|
|
if (Common::WrappingAdd(m_current_values[index], value) <= m_current_values[index]) { |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if (current_values[index] + value <= limit_values[index]) { |
|
|
|
current_values[index] += value; |
|
|
|
current_hints[index] += value; |
|
|
|
peak_values[index] = std::max(peak_values[index], current_values[index]); |
|
|
|
if (m_current_values[index] + value <= m_limit_values[index]) { |
|
|
|
m_current_values[index] += value; |
|
|
|
m_current_hints[index] += value; |
|
|
|
m_peak_values[index] = std::max(m_peak_values[index], m_current_values[index]); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
if (current_hints[index] + value <= limit_values[index] && |
|
|
|
(timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) { |
|
|
|
waiter_count++; |
|
|
|
cond_var.Wait(&lock, timeout, false); |
|
|
|
waiter_count--; |
|
|
|
if (m_current_hints[index] + value <= m_limit_values[index] && |
|
|
|
(timeout < 0 || m_core_timing->GetGlobalTimeNs().count() < timeout)) { |
|
|
|
m_waiter_count++; |
|
|
|
m_cond_var.Wait(&m_lock, timeout, false); |
|
|
|
m_waiter_count--; |
|
|
|
} else { |
|
|
|
break; |
|
|
|
} |
|
|
|
@ -138,17 +138,17 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { |
|
|
|
ASSERT(hint >= 0); |
|
|
|
|
|
|
|
const auto index = static_cast<std::size_t>(which); |
|
|
|
KScopedLightLock lk(lock); |
|
|
|
ASSERT(current_values[index] <= limit_values[index]); |
|
|
|
ASSERT(current_hints[index] <= current_values[index]); |
|
|
|
ASSERT(value <= current_values[index]); |
|
|
|
ASSERT(hint <= current_hints[index]); |
|
|
|
KScopedLightLock lk(m_lock); |
|
|
|
ASSERT(m_current_values[index] <= m_limit_values[index]); |
|
|
|
ASSERT(m_current_hints[index] <= m_current_values[index]); |
|
|
|
ASSERT(value <= m_current_values[index]); |
|
|
|
ASSERT(hint <= m_current_hints[index]); |
|
|
|
|
|
|
|
current_values[index] -= value; |
|
|
|
current_hints[index] -= hint; |
|
|
|
m_current_values[index] -= value; |
|
|
|
m_current_hints[index] -= hint; |
|
|
|
|
|
|
|
if (waiter_count != 0) { |
|
|
|
cond_var.Broadcast(); |
|
|
|
if (m_waiter_count != 0) { |
|
|
|
m_cond_var.Broadcast(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|