mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	kernel: convert KResourceLimit
This commit is contained in:
		@@ -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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,10 +28,10 @@ class KResourceLimit final
 | 
			
		||||
    KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit KResourceLimit(KernelCore& kernel_);
 | 
			
		||||
    explicit KResourceLimit(KernelCore& kernel);
 | 
			
		||||
    ~KResourceLimit() override;
 | 
			
		||||
 | 
			
		||||
    void Initialize(const Core::Timing::CoreTiming* core_timing_);
 | 
			
		||||
    void Initialize(const Core::Timing::CoreTiming* core_timing);
 | 
			
		||||
    void Finalize() override;
 | 
			
		||||
 | 
			
		||||
    s64 GetLimitValue(LimitableResource which) const;
 | 
			
		||||
@@ -50,14 +50,14 @@ public:
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>;
 | 
			
		||||
    ResourceArray limit_values{};
 | 
			
		||||
    ResourceArray current_values{};
 | 
			
		||||
    ResourceArray current_hints{};
 | 
			
		||||
    ResourceArray peak_values{};
 | 
			
		||||
    mutable KLightLock lock;
 | 
			
		||||
    s32 waiter_count{};
 | 
			
		||||
    KLightConditionVariable cond_var;
 | 
			
		||||
    const Core::Timing::CoreTiming* core_timing{};
 | 
			
		||||
    ResourceArray m_limit_values{};
 | 
			
		||||
    ResourceArray m_current_values{};
 | 
			
		||||
    ResourceArray m_current_hints{};
 | 
			
		||||
    ResourceArray m_peak_values{};
 | 
			
		||||
    mutable KLightLock m_lock;
 | 
			
		||||
    s32 m_waiter_count{};
 | 
			
		||||
    KLightConditionVariable m_cond_var;
 | 
			
		||||
    const Core::Timing::CoreTiming* m_core_timing{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user