early-access version 1397
This commit is contained in:
parent
403e95dd8c
commit
88a41fdf63
14 changed files with 368 additions and 54 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1396.
|
This is the source code for early-access 1397.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -159,9 +159,12 @@ add_library(core STATIC
|
||||||
hle/kernel/k_affinity_mask.h
|
hle/kernel/k_affinity_mask.h
|
||||||
hle/kernel/k_condition_variable.cpp
|
hle/kernel/k_condition_variable.cpp
|
||||||
hle/kernel/k_condition_variable.h
|
hle/kernel/k_condition_variable.h
|
||||||
|
hle/kernel/k_light_condition_variable.h
|
||||||
hle/kernel/k_light_lock.cpp
|
hle/kernel/k_light_lock.cpp
|
||||||
hle/kernel/k_light_lock.h
|
hle/kernel/k_light_lock.h
|
||||||
hle/kernel/k_priority_queue.h
|
hle/kernel/k_priority_queue.h
|
||||||
|
hle/kernel/k_resource_limit.cpp
|
||||||
|
hle/kernel/k_resource_limit.h
|
||||||
hle/kernel/k_scheduler.cpp
|
hle/kernel/k_scheduler.cpp
|
||||||
hle/kernel/k_scheduler.h
|
hle/kernel/k_scheduler.h
|
||||||
hle/kernel/k_scheduler_lock.h
|
hle/kernel/k_scheduler_lock.h
|
||||||
|
@ -202,8 +205,6 @@ add_library(core STATIC
|
||||||
hle/kernel/process_capability.h
|
hle/kernel/process_capability.h
|
||||||
hle/kernel/readable_event.cpp
|
hle/kernel/readable_event.cpp
|
||||||
hle/kernel/readable_event.h
|
hle/kernel/readable_event.h
|
||||||
hle/kernel/resource_limit.cpp
|
|
||||||
hle/kernel/resource_limit.h
|
|
||||||
hle/kernel/server_port.cpp
|
hle/kernel/server_port.cpp
|
||||||
hle/kernel/server_port.h
|
hle/kernel/server_port.h
|
||||||
hle/kernel/server_session.cpp
|
hle/kernel/server_session.cpp
|
||||||
|
|
60
src/core/hle/kernel/k_light_condition_variable.h
Executable file
60
src/core/hle/kernel/k_light_condition_variable.h
Executable file
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright 2020 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
// This file references various implementation details from Atmosphere, an open-source firmware for
|
||||||
|
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
|
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||||
|
#include "core/hle/kernel/k_thread_queue.h"
|
||||||
|
#include "core/hle/kernel/time_manager.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KernelCore;
|
||||||
|
|
||||||
|
class KLightConditionVariable {
|
||||||
|
private:
|
||||||
|
KThreadQueue m_thread_queue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
KLightConditionVariable(KernelCore& kernel) : m_thread_queue(kernel), kernel(kernel) {}
|
||||||
|
|
||||||
|
void Wait(KLightLock* lock, s64 timeout = -1ll) {
|
||||||
|
WaitImpl(lock, timeout);
|
||||||
|
lock->Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Broadcast() {
|
||||||
|
KScopedSchedulerLock lk{kernel};
|
||||||
|
while (m_thread_queue.WakeupFrontThread() != nullptr) {
|
||||||
|
/* We want to signal all threads, and so should continue waking up until there's nothing
|
||||||
|
* to wake. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void WaitImpl(KLightLock* lock, s64 timeout) {
|
||||||
|
KThread* owner = GetCurrentThreadPointer(kernel);
|
||||||
|
// KHardwareTimer* timer;
|
||||||
|
|
||||||
|
/* Sleep the thread. */
|
||||||
|
{
|
||||||
|
KScopedSchedulerLockAndSleep lk(kernel, owner, timeout);
|
||||||
|
lock->Unlock();
|
||||||
|
|
||||||
|
if (!m_thread_queue.SleepThread(owner)) {
|
||||||
|
lk.CancelSleep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cancel the task that the sleep setup. */
|
||||||
|
kernel.TimeManager().UnscheduleTimeEvent(owner);
|
||||||
|
}
|
||||||
|
KernelCore& kernel;
|
||||||
|
};
|
||||||
|
} // namespace Kernel
|
154
src/core/hle/kernel/k_resource_limit.cpp
Executable file
154
src/core/hle/kernel/k_resource_limit.cpp
Executable file
|
@ -0,0 +1,154 @@
|
||||||
|
// Copyright 2020 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
// This file references various implementation details from Atmosphere, an open-source firmware for
|
||||||
|
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/core_timing.h"
|
||||||
|
#include "core/core_timing_util.h"
|
||||||
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
namespace {
|
||||||
|
constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system)
|
||||||
|
: Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {}
|
||||||
|
KResourceLimit::~KResourceLimit() = default;
|
||||||
|
|
||||||
|
s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
|
||||||
|
const auto index = static_cast<std::size_t>(which);
|
||||||
|
s64 value{};
|
||||||
|
{
|
||||||
|
KScopedLightLock lk{lock};
|
||||||
|
value = limit_values[index];
|
||||||
|
ASSERT(value >= 0);
|
||||||
|
ASSERT(current_values[index] <= limit_values[index]);
|
||||||
|
ASSERT(current_hints[index] <= current_values[index]);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 KResourceLimit::GetCurrentValue(LimitableResource which) const {
|
||||||
|
const auto index = static_cast<std::size_t>(which);
|
||||||
|
s64 value{};
|
||||||
|
{
|
||||||
|
KScopedLightLock lk{lock};
|
||||||
|
value = current_values[index];
|
||||||
|
ASSERT(value >= 0);
|
||||||
|
ASSERT(current_values[index] <= limit_values[index]);
|
||||||
|
ASSERT(current_hints[index] <= current_values[index]);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 KResourceLimit::GetPeakValue(LimitableResource which) const {
|
||||||
|
const auto index = static_cast<std::size_t>(which);
|
||||||
|
s64 value{};
|
||||||
|
{
|
||||||
|
KScopedLightLock lk{lock};
|
||||||
|
value = peak_values[index];
|
||||||
|
ASSERT(value >= 0);
|
||||||
|
ASSERT(current_values[index] <= limit_values[index]);
|
||||||
|
ASSERT(current_hints[index] <= current_values[index]);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
|
||||||
|
const auto index = static_cast<std::size_t>(which);
|
||||||
|
KScopedLightLock lk(lock);
|
||||||
|
R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState);
|
||||||
|
|
||||||
|
limit_values[index] = value;
|
||||||
|
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
|
||||||
|
return Reserve(which, value, system.CoreTiming().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);
|
||||||
|
|
||||||
|
ASSERT(current_hints[index] <= current_values[index]);
|
||||||
|
if (current_hints[index] >= 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]);
|
||||||
|
|
||||||
|
// If we would overflow, don't allow to succeed.
|
||||||
|
if (current_values[index] + value <= 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]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_hints[index] + value <= limit_values[index] &&
|
||||||
|
(timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) {
|
||||||
|
waiter_count++;
|
||||||
|
cond_var.Wait(&lock, timeout);
|
||||||
|
waiter_count--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KResourceLimit::Release(LimitableResource which, s64 value) {
|
||||||
|
Release(which, value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
|
||||||
|
ASSERT(value >= 0);
|
||||||
|
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]);
|
||||||
|
|
||||||
|
current_values[index] -= value;
|
||||||
|
current_hints[index] -= hint;
|
||||||
|
|
||||||
|
if (waiter_count != 0) {
|
||||||
|
cond_var.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Kernel
|
80
src/core/hle/kernel/k_resource_limit.h
Executable file
80
src/core/hle/kernel/k_resource_limit.h
Executable file
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright 2020 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
// This file references various implementation details from Atmosphere, an open-source firmware for
|
||||||
|
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/kernel/k_light_condition_variable.h"
|
||||||
|
#include "core/hle/kernel/k_light_lock.h"
|
||||||
|
#include "core/hle/kernel/object.h"
|
||||||
|
|
||||||
|
union ResultCode;
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KernelCore;
|
||||||
|
enum class LimitableResource : u32 {
|
||||||
|
PhysicalMemoryMax = 0,
|
||||||
|
ThreadCountMax = 1,
|
||||||
|
EventCountMax = 2,
|
||||||
|
TransferMemoryCountMax = 3,
|
||||||
|
SessionCountMax = 4,
|
||||||
|
|
||||||
|
Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr bool IsValidResourceType(LimitableResource type) {
|
||||||
|
return type < LimitableResource::Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
class KResourceLimit final : public Object {
|
||||||
|
public:
|
||||||
|
KResourceLimit(KernelCore& kernel, Core::System& system);
|
||||||
|
~KResourceLimit();
|
||||||
|
|
||||||
|
s64 GetLimitValue(LimitableResource which) const;
|
||||||
|
s64 GetCurrentValue(LimitableResource which) const;
|
||||||
|
s64 GetPeakValue(LimitableResource which) const;
|
||||||
|
s64 GetFreeValue(LimitableResource which) const;
|
||||||
|
|
||||||
|
ResultCode SetLimitValue(LimitableResource which, s64 value);
|
||||||
|
|
||||||
|
bool Reserve(LimitableResource which, s64 value);
|
||||||
|
bool Reserve(LimitableResource which, s64 value, s64 timeout);
|
||||||
|
void Release(LimitableResource which, s64 value);
|
||||||
|
void Release(LimitableResource which, s64 value, s64 hint);
|
||||||
|
|
||||||
|
std::string GetTypeName() const override {
|
||||||
|
return "KResourceLimit";
|
||||||
|
}
|
||||||
|
std::string GetName() const override {
|
||||||
|
return GetTypeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
|
||||||
|
HandleType GetHandleType() const override {
|
||||||
|
return HANDLE_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Finalize() override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<s64, static_cast<std::size_t>(LimitableResource::Count)> limit_values{};
|
||||||
|
std::array<s64, static_cast<std::size_t>(LimitableResource::Count)> current_values{};
|
||||||
|
std::array<s64, static_cast<std::size_t>(LimitableResource::Count)> current_hints{};
|
||||||
|
std::array<s64, static_cast<std::size_t>(LimitableResource::Count)> peak_values{};
|
||||||
|
mutable KLightLock lock;
|
||||||
|
s32 waiter_count{};
|
||||||
|
KLightConditionVariable cond_var;
|
||||||
|
KernelCore& kernel;
|
||||||
|
Core::System& system;
|
||||||
|
};
|
||||||
|
} // namespace Kernel
|
|
@ -21,6 +21,7 @@
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/k_condition_variable.h"
|
#include "core/hle/kernel/k_condition_variable.h"
|
||||||
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
|
@ -29,7 +30,6 @@
|
||||||
#include "core/hle/kernel/memory/memory_layout.h"
|
#include "core/hle/kernel/memory/memory_layout.h"
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/resource_limit.h"
|
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/kernel/time_manager.h"
|
#include "core/hle/kernel/time_manager.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
@ -247,7 +247,7 @@ void KThread::Finalize() {
|
||||||
// Decrement the parent process's thread count.
|
// Decrement the parent process's thread count.
|
||||||
if (parent != nullptr) {
|
if (parent != nullptr) {
|
||||||
parent->DecrementThreadCount();
|
parent->DecrementThreadCount();
|
||||||
parent->GetResourceLimit()->Release(ResourceType::Threads, 1);
|
parent->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "core/hle/kernel/client_port.h"
|
#include "core/hle/kernel/client_port.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
@ -36,7 +37,6 @@
|
||||||
#include "core/hle/kernel/memory/slab_heap.h"
|
#include "core/hle/kernel/memory/slab_heap.h"
|
||||||
#include "core/hle/kernel/physical_core.h"
|
#include "core/hle/kernel/physical_core.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/resource_limit.h"
|
|
||||||
#include "core/hle/kernel/service_thread.h"
|
#include "core/hle/kernel/service_thread.h"
|
||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
#include "core/hle/kernel/time_manager.h"
|
#include "core/hle/kernel/time_manager.h"
|
||||||
|
@ -66,7 +66,7 @@ struct KernelCore::Impl {
|
||||||
is_phantom_mode_for_singlecore = false;
|
is_phantom_mode_for_singlecore = false;
|
||||||
|
|
||||||
InitializePhysicalCores();
|
InitializePhysicalCores();
|
||||||
InitializeSystemResourceLimit(kernel);
|
InitializeSystemResourceLimit(kernel, system);
|
||||||
InitializeMemoryLayout();
|
InitializeMemoryLayout();
|
||||||
InitializePreemption(kernel);
|
InitializePreemption(kernel);
|
||||||
InitializeSchedulers();
|
InitializeSchedulers();
|
||||||
|
@ -131,19 +131,23 @@ struct KernelCore::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the default system resource limit
|
// Creates the default system resource limit
|
||||||
void InitializeSystemResourceLimit(KernelCore& kernel) {
|
void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
|
||||||
system_resource_limit = ResourceLimit::Create(kernel);
|
system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
|
||||||
|
|
||||||
// If setting the default system values fails, then something seriously wrong has occurred.
|
// If setting the default system values fails, then something seriously wrong has occurred.
|
||||||
ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000)
|
ASSERT(
|
||||||
|
system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, 0x100000000)
|
||||||
|
.IsSuccess());
|
||||||
|
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800)
|
||||||
|
.IsSuccess());
|
||||||
|
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 700)
|
||||||
|
.IsSuccess());
|
||||||
|
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200)
|
||||||
|
.IsSuccess());
|
||||||
|
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 900)
|
||||||
.IsSuccess());
|
.IsSuccess());
|
||||||
ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
|
|
||||||
ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
|
|
||||||
ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
|
|
||||||
ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
|
|
||||||
|
|
||||||
if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) ||
|
if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, 0x60000)) {
|
||||||
!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +324,7 @@ struct KernelCore::Impl {
|
||||||
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
|
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
|
||||||
Kernel::TimeManager time_manager;
|
Kernel::TimeManager time_manager;
|
||||||
|
|
||||||
std::shared_ptr<ResourceLimit> system_resource_limit;
|
std::shared_ptr<KResourceLimit> system_resource_limit;
|
||||||
|
|
||||||
std::shared_ptr<Core::Timing::EventType> preemption_event;
|
std::shared_ptr<Core::Timing::EventType> preemption_event;
|
||||||
|
|
||||||
|
@ -390,7 +394,7 @@ void KernelCore::Shutdown() {
|
||||||
impl->Shutdown();
|
impl->Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
|
std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const {
|
||||||
return impl->system_resource_limit;
|
return impl->system_resource_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class GlobalSchedulerContext;
|
||||||
class HandleTable;
|
class HandleTable;
|
||||||
class PhysicalCore;
|
class PhysicalCore;
|
||||||
class Process;
|
class Process;
|
||||||
class ResourceLimit;
|
class KResourceLimit;
|
||||||
class KScheduler;
|
class KScheduler;
|
||||||
class SharedMemory;
|
class SharedMemory;
|
||||||
class ServiceThread;
|
class ServiceThread;
|
||||||
|
@ -85,7 +85,7 @@ public:
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
/// Retrieves a shared pointer to the system resource limit instance.
|
/// Retrieves a shared pointer to the system resource limit instance.
|
||||||
std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const;
|
std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const;
|
||||||
|
|
||||||
/// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
|
/// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
|
||||||
std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
|
std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/memory/address_space_info.h"
|
#include "core/hle/kernel/memory/address_space_info.h"
|
||||||
#include "core/hle/kernel/memory/memory_block.h"
|
#include "core/hle/kernel/memory/memory_block.h"
|
||||||
|
@ -15,7 +16,6 @@
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/memory/system_control.h"
|
#include "core/hle/kernel/memory/system_control.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/resource_limit.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel::Memory {
|
||||||
|
@ -413,8 +413,8 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
const std::size_t remaining_size{size - mapped_size};
|
const std::size_t remaining_size{size - mapped_size};
|
||||||
const std::size_t remaining_pages{remaining_size / PageSize};
|
const std::size_t remaining_pages{remaining_size / PageSize};
|
||||||
|
|
||||||
if (process->GetResourceLimit() &&
|
if (process->GetResourceLimit() && !process->GetResourceLimit()->Reserve(
|
||||||
!process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, remaining_size)) {
|
LimitableResource::PhysicalMemoryMax, remaining_size)) {
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +422,8 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
{
|
{
|
||||||
auto block_guard = detail::ScopeExit([&] {
|
auto block_guard = detail::ScopeExit([&] {
|
||||||
system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool);
|
system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool);
|
||||||
process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, remaining_size);
|
process->GetResourceLimit()->Release(LimitableResource::PhysicalMemoryMax,
|
||||||
|
remaining_size);
|
||||||
});
|
});
|
||||||
|
|
||||||
CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
|
CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
|
||||||
|
@ -474,7 +475,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
CASCADE_CODE(UnmapMemory(addr, size));
|
CASCADE_CODE(UnmapMemory(addr, size));
|
||||||
|
|
||||||
auto process{system.Kernel().CurrentProcess()};
|
auto process{system.Kernel().CurrentProcess()};
|
||||||
process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, mapped_size);
|
process->GetResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, mapped_size);
|
||||||
physical_memory_usage -= mapped_size;
|
physical_memory_usage -= mapped_size;
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
@ -783,7 +784,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
||||||
|
|
||||||
auto process{system.Kernel().CurrentProcess()};
|
auto process{system.Kernel().CurrentProcess()};
|
||||||
if (process->GetResourceLimit() && delta != 0 &&
|
if (process->GetResourceLimit() && delta != 0 &&
|
||||||
!process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, delta)) {
|
!process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, delta)) {
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "core/file_sys/program_metadata.h"
|
#include "core/file_sys/program_metadata.h"
|
||||||
#include "core/hle/kernel/code_set.h"
|
#include "core/hle/kernel/code_set.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
#include "core/hle/kernel/errors.h"
|
||||||
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
@ -22,7 +23,6 @@
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/memory/slab_heap.h"
|
#include "core/hle/kernel/memory/slab_heap.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/resource_limit.h"
|
|
||||||
#include "core/hle/lock.h"
|
#include "core/hle/lock.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
@ -116,7 +116,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
|
||||||
|
|
||||||
std::shared_ptr<Process> process = std::make_shared<Process>(system);
|
std::shared_ptr<Process> process = std::make_shared<Process>(system);
|
||||||
process->name = std::move(name);
|
process->name = std::move(name);
|
||||||
process->resource_limit = ResourceLimit::Create(kernel);
|
process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
|
||||||
process->status = ProcessStatus::Created;
|
process->status = ProcessStatus::Created;
|
||||||
process->program_id = 0;
|
process->program_id = 0;
|
||||||
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
|
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
|
||||||
|
@ -132,7 +132,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ResourceLimit> Process::GetResourceLimit() const {
|
std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const {
|
||||||
return resource_limit;
|
return resource_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ void Process::DecrementThreadCount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Process::GetTotalPhysicalMemoryAvailable() const {
|
u64 Process::GetTotalPhysicalMemoryAvailable() const {
|
||||||
const u64 capacity{resource_limit->GetCurrentResourceValue(ResourceType::PhysicalMemory) +
|
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemoryMax) +
|
||||||
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
|
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
|
||||||
main_thread_stack_size};
|
main_thread_stack_size};
|
||||||
|
|
||||||
|
@ -308,13 +308,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
|
||||||
|
|
||||||
// Set initial resource limits
|
// Set initial resource limits
|
||||||
resource_limit->SetLimitValue(
|
resource_limit->SetLimitValue(
|
||||||
ResourceType::PhysicalMemory,
|
LimitableResource::PhysicalMemoryMax,
|
||||||
kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application));
|
kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application));
|
||||||
resource_limit->SetLimitValue(ResourceType::Threads, 608);
|
resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 608);
|
||||||
resource_limit->SetLimitValue(ResourceType::Events, 700);
|
resource_limit->SetLimitValue(LimitableResource::EventCountMax, 700);
|
||||||
resource_limit->SetLimitValue(ResourceType::TransferMemory, 128);
|
resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 128);
|
||||||
resource_limit->SetLimitValue(ResourceType::Sessions, 894);
|
resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 894);
|
||||||
ASSERT(resource_limit->Reserve(ResourceType::PhysicalMemory, code_size));
|
ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, code_size));
|
||||||
|
|
||||||
// Create TLS region
|
// Create TLS region
|
||||||
tls_region_address = CreateTLSRegion();
|
tls_region_address = CreateTLSRegion();
|
||||||
|
@ -331,8 +331,8 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) {
|
||||||
ChangeStatus(ProcessStatus::Running);
|
ChangeStatus(ProcessStatus::Running);
|
||||||
|
|
||||||
SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top);
|
SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top);
|
||||||
resource_limit->Reserve(ResourceType::Threads, 1);
|
resource_limit->Reserve(LimitableResource::ThreadCountMax, 1);
|
||||||
resource_limit->Reserve(ResourceType::PhysicalMemory, main_thread_stack_size);
|
resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, main_thread_stack_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::PrepareForTermination() {
|
void Process::PrepareForTermination() {
|
||||||
|
|
|
@ -29,7 +29,7 @@ class ProgramMetadata;
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class KernelCore;
|
class KernelCore;
|
||||||
class ResourceLimit;
|
class KResourceLimit;
|
||||||
class KThread;
|
class KThread;
|
||||||
class TLSPage;
|
class TLSPage;
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the resource limit descriptor for this process
|
/// Gets the resource limit descriptor for this process
|
||||||
std::shared_ptr<ResourceLimit> GetResourceLimit() const;
|
std::shared_ptr<KResourceLimit> GetResourceLimit() const;
|
||||||
|
|
||||||
/// Gets the ideal CPU core ID for this process
|
/// Gets the ideal CPU core ID for this process
|
||||||
u8 GetIdealCoreId() const {
|
u8 GetIdealCoreId() const {
|
||||||
|
@ -402,7 +402,7 @@ private:
|
||||||
u32 system_resource_size = 0;
|
u32 system_resource_size = 0;
|
||||||
|
|
||||||
/// Resource limit descriptor for this process
|
/// Resource limit descriptor for this process
|
||||||
std::shared_ptr<ResourceLimit> resource_limit;
|
std::shared_ptr<KResourceLimit> resource_limit;
|
||||||
|
|
||||||
/// The ideal CPU core for this process, threads are scheduled on this core by default.
|
/// The ideal CPU core for this process, threads are scheduled on this core by default.
|
||||||
u8 ideal_core = 0;
|
u8 ideal_core = 0;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/k_address_arbiter.h"
|
#include "core/hle/kernel/k_address_arbiter.h"
|
||||||
#include "core/hle/kernel/k_condition_variable.h"
|
#include "core/hle/kernel/k_condition_variable.h"
|
||||||
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||||
#include "core/hle/kernel/k_synchronization_object.h"
|
#include "core/hle/kernel/k_synchronization_object.h"
|
||||||
|
@ -37,7 +38,6 @@
|
||||||
#include "core/hle/kernel/physical_core.h"
|
#include "core/hle/kernel/physical_core.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/readable_event.h"
|
#include "core/hle/kernel/readable_event.h"
|
||||||
#include "core/hle/kernel/resource_limit.h"
|
|
||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
@ -141,7 +141,7 @@ enum class ResourceLimitValueType {
|
||||||
ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit,
|
ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit,
|
||||||
u32 resource_type, ResourceLimitValueType value_type) {
|
u32 resource_type, ResourceLimitValueType value_type) {
|
||||||
std::lock_guard lock{HLE::g_hle_lock};
|
std::lock_guard lock{HLE::g_hle_lock};
|
||||||
const auto type = static_cast<ResourceType>(resource_type);
|
const auto type = static_cast<LimitableResource>(resource_type);
|
||||||
if (!IsValidResourceType(type)) {
|
if (!IsValidResourceType(type)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ERR_INVALID_ENUM_VALUE;
|
||||||
|
@ -151,7 +151,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
|
||||||
ASSERT(current_process != nullptr);
|
ASSERT(current_process != nullptr);
|
||||||
|
|
||||||
const auto resource_limit_object =
|
const auto resource_limit_object =
|
||||||
current_process->GetHandleTable().Get<ResourceLimit>(resource_limit);
|
current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
|
||||||
if (!resource_limit_object) {
|
if (!resource_limit_object) {
|
||||||
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
||||||
resource_limit);
|
resource_limit);
|
||||||
|
@ -159,10 +159,10 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value_type == ResourceLimitValueType::CurrentValue) {
|
if (value_type == ResourceLimitValueType::CurrentValue) {
|
||||||
return MakeResult(resource_limit_object->GetCurrentResourceValue(type));
|
return MakeResult(resource_limit_object->GetCurrentValue(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeResult(resource_limit_object->GetMaxResourceValue(type));
|
return MakeResult(resource_limit_object->GetLimitValue(type));
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
@ -312,7 +312,8 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
|
||||||
return ERR_NOT_FOUND;
|
return ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1));
|
ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::SessionCountMax,
|
||||||
|
1));
|
||||||
|
|
||||||
auto client_port = it->second;
|
auto client_port = it->second;
|
||||||
|
|
||||||
|
@ -1450,7 +1451,9 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
|
||||||
Svc::ResultInvalidPriority);
|
Svc::ResultInvalidPriority);
|
||||||
R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
|
R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
|
||||||
|
|
||||||
ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1));
|
ASSERT(process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1,
|
||||||
|
system.CoreTiming().GetGlobalTimeNs().count() +
|
||||||
|
100000000));
|
||||||
|
|
||||||
std::shared_ptr<KThread> thread;
|
std::shared_ptr<KThread> thread;
|
||||||
{
|
{
|
||||||
|
@ -1972,7 +1975,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
|
||||||
LOG_DEBUG(Kernel_SVC, "called");
|
LOG_DEBUG(Kernel_SVC, "called");
|
||||||
|
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
auto resource_limit = ResourceLimit::Create(kernel);
|
auto resource_limit = std::make_shared<KResourceLimit>(kernel, system);
|
||||||
|
|
||||||
auto* const current_process = kernel.CurrentProcess();
|
auto* const current_process = kernel.CurrentProcess();
|
||||||
ASSERT(current_process != nullptr);
|
ASSERT(current_process != nullptr);
|
||||||
|
@ -2019,7 +2022,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
|
||||||
LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit,
|
LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit,
|
||||||
resource_type, value);
|
resource_type, value);
|
||||||
|
|
||||||
const auto type = static_cast<ResourceType>(resource_type);
|
const auto type = static_cast<LimitableResource>(resource_type);
|
||||||
if (!IsValidResourceType(type)) {
|
if (!IsValidResourceType(type)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ERR_INVALID_ENUM_VALUE;
|
||||||
|
@ -2029,7 +2032,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
|
||||||
ASSERT(current_process != nullptr);
|
ASSERT(current_process != nullptr);
|
||||||
|
|
||||||
auto resource_limit_object =
|
auto resource_limit_object =
|
||||||
current_process->GetHandleTable().Get<ResourceLimit>(resource_limit);
|
current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
|
||||||
if (!resource_limit_object) {
|
if (!resource_limit_object) {
|
||||||
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
||||||
resource_limit);
|
resource_limit);
|
||||||
|
@ -2041,8 +2044,8 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
Kernel_SVC,
|
Kernel_SVC,
|
||||||
"Attempted to lower resource limit ({}) for category '{}' below its current value ({})",
|
"Attempted to lower resource limit ({}) for category '{}' below its current value ({})",
|
||||||
resource_limit_object->GetMaxResourceValue(type), resource_type,
|
resource_limit_object->GetLimitValue(type), resource_type,
|
||||||
resource_limit_object->GetCurrentResourceValue(type));
|
resource_limit_object->GetCurrentValue(type));
|
||||||
return set_result;
|
return set_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -416,6 +416,16 @@ void BSD::Close(Kernel::HLERequestContext& ctx) {
|
||||||
BuildErrnoResponse(ctx, CloseImpl(fd));
|
BuildErrnoResponse(ctx, CloseImpl(fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BSD::EventFd(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service, "(STUBBED) called");
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const s32 fd = rp.Pop<s32>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service, "called. fd={}", fd);
|
||||||
|
|
||||||
|
BuildErrnoResponse(ctx, Errno::SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Work>
|
template <typename Work>
|
||||||
void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, Work work) {
|
void BSD::ExecuteWork(Kernel::HLERequestContext& ctx, Work work) {
|
||||||
work.Execute(this);
|
work.Execute(this);
|
||||||
|
@ -841,7 +851,7 @@ BSD::BSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
|
||||||
{28, nullptr, "GetResourceStatistics"},
|
{28, nullptr, "GetResourceStatistics"},
|
||||||
{29, nullptr, "RecvMMsg"},
|
{29, nullptr, "RecvMMsg"},
|
||||||
{30, nullptr, "SendMMsg"},
|
{30, nullptr, "SendMMsg"},
|
||||||
{31, nullptr, "EventFd"},
|
{31, &BSD::EventFd, "EventFd"},
|
||||||
{32, nullptr, "RegisterResourceStatisticsName"},
|
{32, nullptr, "RegisterResourceStatisticsName"},
|
||||||
{33, nullptr, "Initialize2"},
|
{33, nullptr, "Initialize2"},
|
||||||
};
|
};
|
||||||
|
|
|
@ -136,6 +136,7 @@ private:
|
||||||
void SendTo(Kernel::HLERequestContext& ctx);
|
void SendTo(Kernel::HLERequestContext& ctx);
|
||||||
void Write(Kernel::HLERequestContext& ctx);
|
void Write(Kernel::HLERequestContext& ctx);
|
||||||
void Close(Kernel::HLERequestContext& ctx);
|
void Close(Kernel::HLERequestContext& ctx);
|
||||||
|
void EventFd(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
template <typename Work>
|
template <typename Work>
|
||||||
void ExecuteWork(Kernel::HLERequestContext& ctx, Work work);
|
void ExecuteWork(Kernel::HLERequestContext& ctx, Work work);
|
||||||
|
|
Loading…
Reference in a new issue