diff options
Diffstat (limited to '')
21 files changed, 378 insertions, 241 deletions
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp index a4a9a757d..5b1065520 100644 --- a/src/audio_core/command_generator.cpp +++ b/src/audio_core/command_generator.cpp @@ -383,11 +383,14 @@ void CommandGenerator::GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, E const auto channel_count = params.channel_count; for (s32 i = 0; i < channel_count; i++) { // TODO(ogniK): Actually implement reverb + /* if (params.input[i] != params.output[i]) { const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]); auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]); ApplyMix<1>(output, input, 32768, worker_params.sample_count); - } + }*/ + auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]); + std::memset(output, 0, worker_params.sample_count * sizeof(s32)); } } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 397cc028f..0ee02c81d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -160,9 +160,12 @@ add_library(core STATIC hle/kernel/k_affinity_mask.h hle/kernel/k_condition_variable.cpp hle/kernel/k_condition_variable.h + hle/kernel/k_light_condition_variable.h hle/kernel/k_light_lock.cpp hle/kernel/k_light_lock.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.h hle/kernel/k_scheduler_lock.h @@ -203,8 +206,6 @@ add_library(core STATIC hle/kernel/process_capability.h hle/kernel/readable_event.cpp hle/kernel/readable_event.h - hle/kernel/resource_limit.cpp - hle/kernel/resource_limit.h hle/kernel/server_port.cpp hle/kernel/server_port.h hle/kernel/server_session.cpp diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index cebe2ce37..ad116dcc0 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -568,6 +568,11 @@ KeyManager::KeyManager() { // Initialize keys const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath(); const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); + + if (!Common::FS::Exists(yuzu_keys_dir)) { + Common::FS::CreateDir(yuzu_keys_dir); + } + if (Settings::values.use_dev_keys) { dev_mode = true; AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false); diff --git a/src/core/hle/kernel/k_affinity_mask.h b/src/core/hle/kernel/k_affinity_mask.h index dd73781cd..b906895fc 100644 --- a/src/core/hle/kernel/k_affinity_mask.h +++ b/src/core/hle/kernel/k_affinity_mask.h @@ -27,7 +27,7 @@ public: } [[nodiscard]] constexpr bool GetAffinity(s32 core) const { - return this->mask & GetCoreBit(core); + return (this->mask & GetCoreBit(core)) != 0; } constexpr void SetAffinity(s32 core, bool set) { diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h new file mode 100644 index 000000000..362d0db28 --- /dev/null +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -0,0 +1,57 @@ +// 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 { +public: + explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {} + + void Wait(KLightLock* lock, s64 timeout = -1) { + WaitImpl(lock, timeout); + lock->Lock(); + } + + void Broadcast() { + KScopedSchedulerLock lk{kernel}; + while (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); + + // Sleep the thread. + { + KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); + lock->Unlock(); + + if (!thread_queue.SleepThread(owner)) { + lk.CancelSleep(); + return; + } + } + + // Cancel the task that the sleep setup. + kernel.TimeManager().UnscheduleTimeEvent(owner); + } + KThreadQueue thread_queue; + KernelCore& kernel; +}; +} // namespace Kernel diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp new file mode 100644 index 000000000..ab2ab683f --- /dev/null +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -0,0 +1,152 @@ +// 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 { +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 diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h new file mode 100644 index 000000000..58ae456f1 --- /dev/null +++ b/src/core/hle/kernel/k_resource_limit.h @@ -0,0 +1,81 @@ +// 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 { + PhysicalMemory = 0, + Threads = 1, + Events = 2, + TransferMemory = 3, + Sessions = 4, + + Count, +}; + +constexpr bool IsValidResourceType(LimitableResource type) { + return type < LimitableResource::Count; +} + +class KResourceLimit final : public Object { +public: + explicit 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: + 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; + KernelCore& kernel; + Core::System& system; +}; +} // namespace Kernel diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index aa100e139..b59259c4f 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -21,6 +21,7 @@ #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.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_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_thread.h" @@ -29,7 +30,6 @@ #include "core/hle/kernel/memory/memory_layout.h" #include "core/hle/kernel/object.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/time_manager.h" #include "core/hle/result.h" @@ -247,7 +247,7 @@ void KThread::Finalize() { // Decrement the parent process's thread count. if (parent != nullptr) { parent->DecrementThreadCount(); - parent->GetResourceLimit()->Release(ResourceType::Threads, 1); + parent->GetResourceLimit()->Release(LimitableResource::Threads, 1); } } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index df309d523..b20c2d13a 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -28,6 +28,7 @@ #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/errors.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_thread.h" #include "core/hle/kernel/kernel.h" @@ -36,7 +37,6 @@ #include "core/hle/kernel/memory/slab_heap.h" #include "core/hle/kernel/physical_core.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/shared_memory.h" #include "core/hle/kernel/time_manager.h" @@ -66,7 +66,7 @@ struct KernelCore::Impl { is_phantom_mode_for_singlecore = false; InitializePhysicalCores(); - InitializeSystemResourceLimit(kernel); + InitializeSystemResourceLimit(kernel, system); InitializeMemoryLayout(); InitializePreemption(kernel); InitializeSchedulers(); @@ -131,19 +131,19 @@ struct KernelCore::Impl { } // Creates the default system resource limit - void InitializeSystemResourceLimit(KernelCore& kernel) { - system_resource_limit = ResourceLimit::Create(kernel); + void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) { + system_resource_limit = std::make_shared<KResourceLimit>(kernel, system); // 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::PhysicalMemory, 0x100000000) .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()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) + .IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 900).IsSuccess()); - if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) || - !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) { + if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 0x60000)) { UNREACHABLE(); } } @@ -320,7 +320,7 @@ struct KernelCore::Impl { std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 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; @@ -390,7 +390,7 @@ void KernelCore::Shutdown() { impl->Shutdown(); } -std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const { +std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const { return impl->system_resource_limit; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index e7c77727b..806a0d986 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -38,7 +38,7 @@ class GlobalSchedulerContext; class HandleTable; class PhysicalCore; class Process; -class ResourceLimit; +class KResourceLimit; class KScheduler; class SharedMemory; class ServiceThread; @@ -85,7 +85,7 @@ public: void Shutdown(); /// 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. std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index 080886554..7de91c768 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp @@ -7,6 +7,7 @@ #include "common/scope_exit.h" #include "core/core.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/memory/address_space_info.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/system_control.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/resource_limit.h" #include "core/memory.h" namespace Kernel::Memory { @@ -414,7 +414,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { const std::size_t remaining_pages{remaining_size / PageSize}; if (process->GetResourceLimit() && - !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, remaining_size)) { + !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, remaining_size)) { return ERR_RESOURCE_LIMIT_EXCEEDED; } @@ -422,7 +422,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { { auto block_guard = detail::ScopeExit([&] { system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool); - process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, remaining_size); + process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, remaining_size); }); CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, @@ -474,7 +474,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { CASCADE_CODE(UnmapMemory(addr, size)); auto process{system.Kernel().CurrentProcess()}; - process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, mapped_size); + process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size); physical_memory_usage -= mapped_size; return RESULT_SUCCESS; @@ -783,7 +783,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) { auto process{system.Kernel().CurrentProcess()}; if (process->GetResourceLimit() && delta != 0 && - !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, delta)) { + !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, delta)) { return ERR_RESOURCE_LIMIT_EXCEEDED; } diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 0edbfc4cc..afdb27c54 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -15,6 +15,7 @@ #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/code_set.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_thread.h" #include "core/hle/kernel/kernel.h" @@ -22,7 +23,6 @@ #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/memory/slab_heap.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/resource_limit.h" #include "core/hle/lock.h" #include "core/memory.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); 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->program_id = 0; 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; } -std::shared_ptr<ResourceLimit> Process::GetResourceLimit() const { +std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const { return resource_limit; } @@ -154,7 +154,7 @@ void Process::DecrementThreadCount() { } u64 Process::GetTotalPhysicalMemoryAvailable() const { - const u64 capacity{resource_limit->GetCurrentResourceValue(ResourceType::PhysicalMemory) + + const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + main_thread_stack_size}; @@ -308,13 +308,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, // Set initial resource limits resource_limit->SetLimitValue( - ResourceType::PhysicalMemory, + LimitableResource::PhysicalMemory, kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); - resource_limit->SetLimitValue(ResourceType::Threads, 608); - resource_limit->SetLimitValue(ResourceType::Events, 700); - resource_limit->SetLimitValue(ResourceType::TransferMemory, 128); - resource_limit->SetLimitValue(ResourceType::Sessions, 894); - ASSERT(resource_limit->Reserve(ResourceType::PhysicalMemory, code_size)); + resource_limit->SetLimitValue(LimitableResource::Threads, 608); + resource_limit->SetLimitValue(LimitableResource::Events, 700); + resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); + resource_limit->SetLimitValue(LimitableResource::Sessions, 894); + ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemory, code_size)); // Create TLS region tls_region_address = CreateTLSRegion(); @@ -331,8 +331,8 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) { ChangeStatus(ProcessStatus::Running); SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); - resource_limit->Reserve(ResourceType::Threads, 1); - resource_limit->Reserve(ResourceType::PhysicalMemory, main_thread_stack_size); + resource_limit->Reserve(LimitableResource::Threads, 1); + resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); } void Process::PrepareForTermination() { diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 26e647743..c8af76ce8 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -29,7 +29,7 @@ class ProgramMetadata; namespace Kernel { class KernelCore; -class ResourceLimit; +class KResourceLimit; class KThread; class TLSPage; @@ -170,7 +170,7 @@ public: } /// 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 u8 GetIdealCoreId() const { @@ -402,7 +402,7 @@ private: u32 system_resource_size = 0; /// 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. u8 ideal_core = 0; diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp deleted file mode 100644 index 7bf50339d..000000000 --- a/src/core/hle/kernel/resource_limit.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/kernel/errors.h" -#include "core/hle/kernel/resource_limit.h" -#include "core/hle/result.h" - -namespace Kernel { -namespace { -constexpr std::size_t ResourceTypeToIndex(ResourceType type) { - return static_cast<std::size_t>(type); -} -} // Anonymous namespace - -ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {} -ResourceLimit::~ResourceLimit() = default; - -bool ResourceLimit::Reserve(ResourceType resource, s64 amount) { - return Reserve(resource, amount, 10000000000); -} - -bool ResourceLimit::Reserve(ResourceType resource, s64 amount, u64 timeout) { - const std::size_t index{ResourceTypeToIndex(resource)}; - - s64 new_value = current[index] + amount; - if (new_value > limit[index] && available[index] + amount <= limit[index]) { - // TODO(bunnei): This is wrong for multicore, we should wait the calling thread for timeout - new_value = current[index] + amount; - } - - if (new_value <= limit[index]) { - current[index] = new_value; - return true; - } - return false; -} - -void ResourceLimit::Release(ResourceType resource, u64 amount) { - Release(resource, amount, amount); -} - -void ResourceLimit::Release(ResourceType resource, u64 used_amount, u64 available_amount) { - const std::size_t index{ResourceTypeToIndex(resource)}; - - current[index] -= used_amount; - available[index] -= available_amount; -} - -std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel) { - return std::make_shared<ResourceLimit>(kernel); -} - -s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const { - return limit.at(ResourceTypeToIndex(resource)) - current.at(ResourceTypeToIndex(resource)); -} - -s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const { - return limit.at(ResourceTypeToIndex(resource)); -} - -ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) { - const std::size_t index{ResourceTypeToIndex(resource)}; - if (current[index] <= value) { - limit[index] = value; - return RESULT_SUCCESS; - } else { - LOG_ERROR(Kernel, "Limit value is too large! resource={}, value={}, index={}", resource, - value, index); - return ERR_INVALID_STATE; - } -} -} // namespace Kernel diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h deleted file mode 100644 index 464d4f2a6..000000000 --- a/src/core/hle/kernel/resource_limit.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <memory> - -#include "common/common_types.h" -#include "core/hle/kernel/object.h" - -union ResultCode; - -namespace Kernel { - -class KernelCore; - -enum class ResourceType : u32 { - PhysicalMemory, - Threads, - Events, - TransferMemory, - Sessions, - - // Used as a count, not an actual type. - ResourceTypeCount -}; - -constexpr bool IsValidResourceType(ResourceType type) { - return type < ResourceType::ResourceTypeCount; -} - -class ResourceLimit final : public Object { -public: - explicit ResourceLimit(KernelCore& kernel); - ~ResourceLimit() override; - - /// Creates a resource limit object. - static std::shared_ptr<ResourceLimit> Create(KernelCore& kernel); - - std::string GetTypeName() const override { - return "ResourceLimit"; - } - std::string GetName() const override { - return GetTypeName(); - } - - static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - bool Reserve(ResourceType resource, s64 amount); - bool Reserve(ResourceType resource, s64 amount, u64 timeout); - void Release(ResourceType resource, u64 amount); - void Release(ResourceType resource, u64 used_amount, u64 available_amount); - - /** - * Gets the current value for the specified resource. - * @param resource Requested resource type - * @returns The current value of the resource type - */ - s64 GetCurrentResourceValue(ResourceType resource) const; - - /** - * Gets the max value for the specified resource. - * @param resource Requested resource type - * @returns The max value of the resource type - */ - s64 GetMaxResourceValue(ResourceType resource) const; - - /** - * Sets the limit value for a given resource type. - * - * @param resource The resource type to apply the limit to. - * @param value The limit to apply to the given resource type. - * - * @return A result code indicating if setting the limit value - * was successful or not. - * - * @note The supplied limit value *must* be greater than or equal to - * the current resource value for the given resource type, - * otherwise ERR_INVALID_STATE will be returned. - */ - ResultCode SetLimitValue(ResourceType resource, s64 value); - - void Finalize() override {} - -private: - // TODO(Subv): Increment resource limit current values in their respective Kernel::T::Create - // functions - // - // Currently we have no way of distinguishing if a Create was called by the running application, - // or by a service module. Approach this once we have separated the service modules into their - // own processes - - using ResourceArray = - std::array<s64, static_cast<std::size_t>(ResourceType::ResourceTypeCount)>; - - ResourceArray limit{}; - ResourceArray current{}; - ResourceArray available{}; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 7fd514e9d..74eb90100 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -26,6 +26,7 @@ #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.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_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_synchronization_object.h" @@ -37,7 +38,6 @@ #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/process.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/svc.h" #include "core/hle/kernel/svc_results.h" @@ -141,7 +141,7 @@ enum class ResourceLimitValueType { ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, u32 resource_type, ResourceLimitValueType value_type) { 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)) { LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); return ERR_INVALID_ENUM_VALUE; @@ -151,7 +151,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_ ASSERT(current_process != nullptr); const auto resource_limit_object = - current_process->GetHandleTable().Get<ResourceLimit>(resource_limit); + current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); if (!resource_limit_object) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); @@ -159,10 +159,10 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_ } 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 @@ -312,7 +312,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, return ERR_NOT_FOUND; } - ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1)); + ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::Sessions, 1)); auto client_port = it->second; @@ -1450,7 +1450,8 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e Svc::ResultInvalidPriority); R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); - ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1)); + ASSERT(process.GetResourceLimit()->Reserve( + LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); std::shared_ptr<KThread> thread; { @@ -1972,7 +1973,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) LOG_DEBUG(Kernel_SVC, "called"); 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(); ASSERT(current_process != nullptr); @@ -2019,7 +2020,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, resource_type, value); - const auto type = static_cast<ResourceType>(resource_type); + const auto type = static_cast<LimitableResource>(resource_type); if (!IsValidResourceType(type)) { LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); return ERR_INVALID_ENUM_VALUE; @@ -2029,7 +2030,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour ASSERT(current_process != nullptr); auto resource_limit_object = - current_process->GetHandleTable().Get<ResourceLimit>(resource_limit); + current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); if (!resource_limit_object) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); @@ -2041,8 +2042,8 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour LOG_ERROR( Kernel_SVC, "Attempted to lower resource limit ({}) for category '{}' below its current value ({})", - resource_limit_object->GetMaxResourceValue(type), resource_type, - resource_limit_object->GetCurrentResourceValue(type)); + resource_limit_object->GetLimitValue(type), resource_type, + resource_limit_object->GetCurrentValue(type)); return set_result; } diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index d9865d56f..50b2c58e2 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -41,12 +41,18 @@ constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "/system/save/8000000000000010/su/ ProfileManager::ProfileManager() { ParseUserSaveFile(); - if (user_count == 0) + // Create an user if none are present + if (user_count == 0) { CreateNewUser(UUID::Generate(), "yuzu"); + } auto current = std::clamp<int>(Settings::values.current_user, 0, MAX_USERS - 1); - if (UserExistsIndex(current)) + + // If user index don't exist. Load the first user and change the active user + if (!UserExistsIndex(current)) { current = 0; + Settings::values.current_user = 0; + } OpenUser(*GetUser(current)); } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 5efc1237e..4cee4838c 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -126,14 +126,23 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); } + // If ns_late is higher than the update rate ignore the delay + if (ns_late > motion_update_ns) { + ns_late = {}; + } + core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); } void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); - for (const auto& controller : controllers) { - controller->OnMotionUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); + controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate( + core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); + + // If ns_late is higher than the update rate ignore the delay + if (ns_late > motion_update_ns) { + ns_late = {}; } core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 39306509a..2ae5196e0 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -70,6 +70,9 @@ void LogSettings() { log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); log_setting("Audio_OutputDevice", values.audio_device_id); log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); + log_setting("DataStorage_CacheDir", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)); + log_setting("DataStorage_ConfigDir", Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); + log_setting("DataStorage_LoadDir", Common::FS::GetUserPath(Common::FS::UserPath::LoadDir)); log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir)); log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir)); log_setting("Debugging_ProgramArgs", values.program_args); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index fbe36046b..1ab5bcbb9 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -580,9 +580,7 @@ void ConfigureInputPlayer::ApplyConfiguration() { if (player_index == 0) { auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; const auto handheld_connected = handheld.connected; - if (player.controller_type == Settings::ControllerType::Handheld) { - handheld = player; - } + handheld = player; handheld.connected = handheld_connected; } } @@ -596,7 +594,7 @@ void ConfigureInputPlayer::TryConnectSelectedController() { controller_type != Settings::ControllerType::Handheld; // Connect Handheld depending on Player 1's controller configuration. - if (player_index == 0 && controller_type == Settings::ControllerType::Handheld) { + if (player_index == 0) { auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; const auto handheld_connected = ui->groupConnectedController->isChecked() && controller_type == Settings::ControllerType::Handheld; diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index d102a43af..51647a028 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -116,8 +116,8 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent) scene = new QGraphicsScene; ui->current_user_icon->setScene(scene); - SetConfiguration(); RetranslateUI(); + SetConfiguration(); } ConfigureProfileManager::~ConfigureProfileManager() = default; |