mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 18:54:14 +01:00 
			
		
		
		
	hle: kernel: Migrate KResourceLimit to KAutoObject.
This commit is contained in:
		
							parent
							
								
									674122038a
								
							
						
					
					
						commit
						b57c5a9b54
					
				| @ -12,11 +12,12 @@ | ||||
| #include "core/hle/kernel/k_event.h" | ||||
| #include "core/hle/kernel/k_memory_layout.h" | ||||
| #include "core/hle/kernel/k_memory_manager.h" | ||||
| #include "core/hle/kernel/k_resource_limit.h" | ||||
| #include "core/hle/kernel/k_session.h" | ||||
| #include "core/hle/kernel/k_shared_memory.h" | ||||
| #include "core/hle/kernel/k_transfer_memory.h" | ||||
| #include "core/hle/kernel/k_system_control.h" | ||||
| #include "core/hle/kernel/k_thread.h" | ||||
| #include "core/hle/kernel/k_transfer_memory.h" | ||||
| #include "core/hle/kernel/memory_types.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/memory.h" | ||||
| @ -31,7 +32,8 @@ namespace Kernel::Init { | ||||
|     HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__)                                           \ | ||||
|     HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__)                         \ | ||||
|     HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__)                             \ | ||||
|     HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) | ||||
|     HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__)                                       \ | ||||
|     HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
|  | ||||
| @ -10,10 +10,16 @@ | ||||
| namespace Kernel { | ||||
| constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
 | ||||
| 
 | ||||
| KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_) | ||||
|     : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {} | ||||
| KResourceLimit::KResourceLimit(KernelCore& kernel) | ||||
|     : KAutoObjectWithSlabHeapAndContainer{kernel}, lock{kernel}, cond_var{kernel} {} | ||||
| KResourceLimit::~KResourceLimit() = default; | ||||
| 
 | ||||
| void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) { | ||||
|     core_timing = core_timing_; | ||||
| } | ||||
| 
 | ||||
| void KResourceLimit::Finalize() {} | ||||
| 
 | ||||
| s64 KResourceLimit::GetLimitValue(LimitableResource which) const { | ||||
|     const auto index = static_cast<std::size_t>(which); | ||||
|     s64 value{}; | ||||
| @ -78,7 +84,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { | ||||
| } | ||||
| 
 | ||||
| bool KResourceLimit::Reserve(LimitableResource which, s64 value) { | ||||
|     return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout); | ||||
|     return Reserve(which, value, core_timing->GetGlobalTimeNs().count() + DefaultTimeout); | ||||
| } | ||||
| 
 | ||||
| bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { | ||||
| @ -109,7 +115,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { | ||||
|         } | ||||
| 
 | ||||
|         if (current_hints[index] + value <= limit_values[index] && | ||||
|             (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) { | ||||
|             (timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) { | ||||
|             waiter_count++; | ||||
|             cond_var.Wait(&lock, timeout); | ||||
|             waiter_count--; | ||||
|  | ||||
| @ -32,10 +32,16 @@ constexpr bool IsValidResourceType(LimitableResource type) { | ||||
|     return type < LimitableResource::Count; | ||||
| } | ||||
| 
 | ||||
| class KResourceLimit final : public Object { | ||||
| class KResourceLimit final | ||||
|     : public KAutoObjectWithSlabHeapAndContainer<KResourceLimit, KAutoObjectWithList> { | ||||
|     KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject); | ||||
| 
 | ||||
| public: | ||||
|     explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_); | ||||
|     ~KResourceLimit(); | ||||
|     explicit KResourceLimit(KernelCore& kernel); | ||||
|     virtual ~KResourceLimit(); | ||||
| 
 | ||||
|     void Initialize(const Core::Timing::CoreTiming* core_timing_); | ||||
|     virtual void Finalize() override; | ||||
| 
 | ||||
|     s64 GetLimitValue(LimitableResource which) const; | ||||
|     s64 GetCurrentValue(LimitableResource which) const; | ||||
| @ -49,6 +55,10 @@ public: | ||||
|     void Release(LimitableResource which, s64 value); | ||||
|     void Release(LimitableResource which, s64 value, s64 hint); | ||||
| 
 | ||||
|     static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | ||||
| 
 | ||||
|     // DEPRECATED
 | ||||
| 
 | ||||
|     std::string GetTypeName() const override { | ||||
|         return "KResourceLimit"; | ||||
|     } | ||||
| @ -61,8 +71,6 @@ public: | ||||
|         return HANDLE_TYPE; | ||||
|     } | ||||
| 
 | ||||
|     virtual void Finalize() override {} | ||||
| 
 | ||||
| private: | ||||
|     using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>; | ||||
|     ResourceArray limit_values{}; | ||||
| @ -72,6 +80,6 @@ private: | ||||
|     mutable KLightLock lock; | ||||
|     s32 waiter_count{}; | ||||
|     KLightConditionVariable cond_var; | ||||
|     const Core::Timing::CoreTiming& core_timing; | ||||
|     const Core::Timing::CoreTiming* core_timing{}; | ||||
| }; | ||||
| } // namespace Kernel
 | ||||
|  | ||||
| @ -15,8 +15,7 @@ namespace Kernel { | ||||
| 
 | ||||
| class KScopedResourceReservation { | ||||
| public: | ||||
|     explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, | ||||
|                                         s64 v, s64 timeout) | ||||
|     explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) | ||||
|         : resource_limit(std::move(l)), value(v), resource(r) { | ||||
|         if (resource_limit && value) { | ||||
|             success = resource_limit->Reserve(resource, value, timeout); | ||||
| @ -25,8 +24,7 @@ public: | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, | ||||
|                                         s64 v = 1) | ||||
|     explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v = 1) | ||||
|         : resource_limit(std::move(l)), value(v), resource(r) { | ||||
|         if (resource_limit && value) { | ||||
|             success = resource_limit->Reserve(resource, value); | ||||
| @ -58,7 +56,7 @@ public: | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     std::shared_ptr<KResourceLimit> resource_limit; | ||||
|     KResourceLimit* resource_limit{}; | ||||
|     s64 value; | ||||
|     LimitableResource resource; | ||||
|     bool success; | ||||
|  | ||||
| @ -8,6 +8,7 @@ | ||||
| #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||||
| #include "core/hle/kernel/k_shared_memory.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/svc_results.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| @ -22,12 +23,7 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de | ||||
|                                      KMemoryPermission owner_permission_, | ||||
|                                      KMemoryPermission user_permission_, PAddr physical_address_, | ||||
|                                      std::size_t size_, std::string name_) { | ||||
| 
 | ||||
|     resource_limit = kernel_.GetSystemResourceLimit(); | ||||
|     KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | ||||
|                                                   size_); | ||||
|     ASSERT(memory_reservation.Succeeded()); | ||||
| 
 | ||||
|     // Set members.
 | ||||
|     owner_process = owner_process_; | ||||
|     device_memory = &device_memory_; | ||||
|     page_list = std::move(page_list_); | ||||
| @ -36,9 +32,27 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de | ||||
|     physical_address = physical_address_; | ||||
|     size = size_; | ||||
|     name = name_; | ||||
| 
 | ||||
|     // Get the resource limit.
 | ||||
|     KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); | ||||
| 
 | ||||
|     // Reserve memory for ourselves.
 | ||||
|     KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemory, | ||||
|                                                   size_); | ||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
|     // Commit our reservation.
 | ||||
|     memory_reservation.Commit(); | ||||
| 
 | ||||
|     // Set our resource limit.
 | ||||
|     resource_limit = reslimit; | ||||
|     resource_limit->Open(); | ||||
| 
 | ||||
|     // Mark initialized.
 | ||||
|     is_initialized = true; | ||||
| 
 | ||||
|     memory_reservation.Commit(); | ||||
|     // Clear all pages in the memory.
 | ||||
|     std::memset(device_memory_.GetPointer(physical_address_), 0, size_); | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | ||||
| @ -88,7 +88,7 @@ private: | ||||
|     KMemoryPermission user_permission{}; | ||||
|     PAddr physical_address{}; | ||||
|     std::size_t size{}; | ||||
|     std::shared_ptr<KResourceLimit> resource_limit; | ||||
|     KResourceLimit* resource_limit{}; | ||||
|     bool is_initialized{}; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -27,9 +27,7 @@ class KTransferMemory final | ||||
| 
 | ||||
| public: | ||||
|     explicit KTransferMemory(KernelCore& kernel); | ||||
|     ~KTransferMemory() override; | ||||
| 
 | ||||
|     static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; | ||||
|     virtual ~KTransferMemory() override; | ||||
| 
 | ||||
|     ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); | ||||
| 
 | ||||
| @ -67,6 +65,7 @@ public: | ||||
|         return GetTypeName(); | ||||
|     } | ||||
| 
 | ||||
|     static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; | ||||
|     HandleType GetHandleType() const override { | ||||
|         return HANDLE_TYPE; | ||||
|     } | ||||
|  | ||||
| @ -74,8 +74,8 @@ struct KernelCore::Impl { | ||||
|         Init::InitializeSlabHeaps(system, memory_layout); | ||||
| 
 | ||||
|         // Initialize kernel memory and resources.
 | ||||
|         InitializeMemoryLayout(memory_layout); | ||||
|         InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout); | ||||
|         InitializeMemoryLayout(memory_layout); | ||||
|         InitializePageSlab(); | ||||
|         InitializeSchedulers(); | ||||
|         InitializeSuspendThreads(); | ||||
| @ -126,11 +126,19 @@ struct KernelCore::Impl { | ||||
| 
 | ||||
|         exclusive_monitor.reset(); | ||||
| 
 | ||||
|         hid_shared_mem->Close(); | ||||
|         hid_shared_mem = nullptr; | ||||
| 
 | ||||
|         font_shared_mem->Close(); | ||||
|         font_shared_mem = nullptr; | ||||
| 
 | ||||
|         irs_shared_mem->Close(); | ||||
|         irs_shared_mem = nullptr; | ||||
| 
 | ||||
|         time_shared_mem->Close(); | ||||
|         time_shared_mem = nullptr; | ||||
| 
 | ||||
|         system_resource_limit->Close(); | ||||
|         system_resource_limit = nullptr; | ||||
| 
 | ||||
|         // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
 | ||||
| @ -156,7 +164,9 @@ struct KernelCore::Impl { | ||||
|     void InitializeSystemResourceLimit(KernelCore& kernel, | ||||
|                                        const Core::Timing::CoreTiming& core_timing, | ||||
|                                        const KMemoryLayout& memory_layout) { | ||||
|         system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing); | ||||
|         system_resource_limit = KResourceLimit::Create(system.Kernel()); | ||||
|         system_resource_limit->Initialize(&core_timing); | ||||
| 
 | ||||
|         const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); | ||||
| 
 | ||||
|         // If setting the default system values fails, then something seriously wrong has occurred.
 | ||||
| @ -627,11 +637,11 @@ struct KernelCore::Impl { | ||||
| 
 | ||||
|     // Lists all processes that exist in the current session.
 | ||||
|     std::vector<Process*> process_list; | ||||
|     Process* current_process = nullptr; | ||||
|     Process* current_process{}; | ||||
|     std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; | ||||
|     Kernel::TimeManager time_manager; | ||||
| 
 | ||||
|     std::shared_ptr<KResourceLimit> system_resource_limit; | ||||
|     KResourceLimit* system_resource_limit{}; | ||||
| 
 | ||||
|     std::shared_ptr<Core::Timing::EventType> preemption_event; | ||||
| 
 | ||||
| @ -704,7 +714,11 @@ void KernelCore::Shutdown() { | ||||
|     impl->Shutdown(); | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const { | ||||
| const KResourceLimit* KernelCore::GetSystemResourceLimit() const { | ||||
|     return impl->system_resource_limit; | ||||
| } | ||||
| 
 | ||||
| KResourceLimit* KernelCore::GetSystemResourceLimit() { | ||||
|     return impl->system_resource_limit; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -92,7 +92,10 @@ public: | ||||
|     void Shutdown(); | ||||
| 
 | ||||
|     /// Retrieves a shared pointer to the system resource limit instance.
 | ||||
|     std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const; | ||||
|     const KResourceLimit* GetSystemResourceLimit() const; | ||||
| 
 | ||||
|     /// Retrieves a shared pointer to the system resource limit instance.
 | ||||
|     KResourceLimit* GetSystemResourceLimit(); | ||||
| 
 | ||||
|     /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
 | ||||
|     KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; | ||||
| @ -263,24 +266,26 @@ public: | ||||
|     /// Gets the slab heap for the specified kernel object type.
 | ||||
|     template <typename T> | ||||
|     KSlabHeap<T>& SlabHeap() { | ||||
|         if constexpr (std::is_same_v<T, Process>) { | ||||
|             return slab_heap_container->process; | ||||
|         } else if constexpr (std::is_same_v<T, KThread>) { | ||||
|             return slab_heap_container->thread; | ||||
|         if constexpr (std::is_same_v<T, KClientSession>) { | ||||
|             return slab_heap_container->client_session; | ||||
|         } else if constexpr (std::is_same_v<T, KEvent>) { | ||||
|             return slab_heap_container->event; | ||||
|         } else if constexpr (std::is_same_v<T, KSharedMemory>) { | ||||
|             return slab_heap_container->shared_memory; | ||||
|         } else if constexpr (std::is_same_v<T, KLinkedListNode>) { | ||||
|             return slab_heap_container->linked_list_node; | ||||
|         } else if constexpr (std::is_same_v<T, KWritableEvent>) { | ||||
|             return slab_heap_container->writeable_event; | ||||
|         } else if constexpr (std::is_same_v<T, KClientSession>) { | ||||
|             return slab_heap_container->client_session; | ||||
|         } else if constexpr (std::is_same_v<T, Process>) { | ||||
|             return slab_heap_container->process; | ||||
|         } else if constexpr (std::is_same_v<T, KResourceLimit>) { | ||||
|             return slab_heap_container->resource_limit; | ||||
|         } else if constexpr (std::is_same_v<T, KSession>) { | ||||
|             return slab_heap_container->session; | ||||
|         } else if constexpr (std::is_same_v<T, KSharedMemory>) { | ||||
|             return slab_heap_container->shared_memory; | ||||
|         } else if constexpr (std::is_same_v<T, KThread>) { | ||||
|             return slab_heap_container->thread; | ||||
|         } else if constexpr (std::is_same_v<T, KTransferMemory>) { | ||||
|             return slab_heap_container->transfer_memory; | ||||
|         } else if constexpr (std::is_same_v<T, KWritableEvent>) { | ||||
|             return slab_heap_container->writeable_event; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -315,15 +320,16 @@ private: | ||||
| private: | ||||
|     /// Helper to encapsulate all slab heaps in a single heap allocated container
 | ||||
|     struct SlabHeapContainer { | ||||
|         KSlabHeap<Process> process; | ||||
|         KSlabHeap<KThread> thread; | ||||
|         KSlabHeap<KEvent> event; | ||||
|         KSlabHeap<KSharedMemory> shared_memory; | ||||
|         KSlabHeap<KLinkedListNode> linked_list_node; | ||||
|         KSlabHeap<KWritableEvent> writeable_event; | ||||
|         KSlabHeap<KClientSession> client_session; | ||||
|         KSlabHeap<KEvent> event; | ||||
|         KSlabHeap<KLinkedListNode> linked_list_node; | ||||
|         KSlabHeap<Process> process; | ||||
|         KSlabHeap<KResourceLimit> resource_limit; | ||||
|         KSlabHeap<KSession> session; | ||||
|         KSlabHeap<KSharedMemory> shared_memory; | ||||
|         KSlabHeap<KThread> thread; | ||||
|         KSlabHeap<KTransferMemory> transfer_memory; | ||||
|         KSlabHeap<KWritableEvent> writeable_event; | ||||
|     }; | ||||
| 
 | ||||
|     std::unique_ptr<SlabHeapContainer> slab_heap_container; | ||||
|  | ||||
| @ -138,10 +138,13 @@ ResultCode Process::Initialize(Process* process, Core::System& system, std::stri | ||||
| 
 | ||||
|     kernel.AppendNewProcess(process); | ||||
| 
 | ||||
|     // Open a reference to the resource limit.
 | ||||
|     process->resource_limit->Open(); | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const { | ||||
| KResourceLimit* Process::GetResourceLimit() const { | ||||
|     return resource_limit; | ||||
| } | ||||
| 
 | ||||
| @ -166,7 +169,10 @@ u64 Process::GetTotalPhysicalMemoryAvailable() const { | ||||
|     const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | ||||
|                        page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + | ||||
|                        main_thread_stack_size}; | ||||
|     ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||||
|     if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); | ||||
|         capacity != pool_size) { | ||||
|         LOG_WARNING(Kernel, "capacity {} != application pool size {}", capacity, pool_size); | ||||
|     } | ||||
|     if (capacity < memory_usage_capacity) { | ||||
|         return capacity; | ||||
|     } | ||||
| @ -371,6 +377,16 @@ void Process::PrepareForTermination() { | ||||
|     ChangeStatus(ProcessStatus::Exited); | ||||
| } | ||||
| 
 | ||||
| void Process::Finalize() { | ||||
|     // Release memory to the resource limit.
 | ||||
|     if (resource_limit != nullptr) { | ||||
|         resource_limit->Close(); | ||||
|     } | ||||
| 
 | ||||
|     // Perform inherited finalization.
 | ||||
|     KAutoObjectWithSlabHeapAndContainer<Process, KSynchronizationObject>::Finalize(); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Attempts to find a TLS page that contains a free slot for | ||||
|  * use by a thread. | ||||
|  | ||||
| @ -171,7 +171,7 @@ public: | ||||
|     } | ||||
| 
 | ||||
|     /// Gets the resource limit descriptor for this process
 | ||||
|     std::shared_ptr<KResourceLimit> GetResourceLimit() const; | ||||
|     KResourceLimit* GetResourceLimit() const; | ||||
| 
 | ||||
|     /// Gets the ideal CPU core ID for this process
 | ||||
|     u8 GetIdealCoreId() const { | ||||
| @ -348,9 +348,7 @@ public: | ||||
| 
 | ||||
|     static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | ||||
| 
 | ||||
|     virtual void Finalize() override { | ||||
|         UNIMPLEMENTED(); | ||||
|     } | ||||
|     virtual void Finalize(); | ||||
| 
 | ||||
|     virtual u64 GetId() const override final { | ||||
|         return GetProcessID(); | ||||
| @ -415,7 +413,7 @@ private: | ||||
|     u32 system_resource_size = 0; | ||||
| 
 | ||||
|     /// Resource limit descriptor for this process
 | ||||
|     std::shared_ptr<KResourceLimit> resource_limit; | ||||
|     KResourceLimit* resource_limit{}; | ||||
| 
 | ||||
|     /// The ideal CPU core for this process, threads are scheduled on this core by default.
 | ||||
|     u8 ideal_core = 0; | ||||
|  | ||||
| @ -153,9 +153,9 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_ | ||||
|     const auto* const current_process = system.Kernel().CurrentProcess(); | ||||
|     ASSERT(current_process != nullptr); | ||||
| 
 | ||||
|     const auto resource_limit_object = | ||||
|         current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); | ||||
|     if (!resource_limit_object) { | ||||
|     auto resource_limit_object = | ||||
|         current_process->GetHandleTable().GetObject<KResourceLimit>(resource_limit); | ||||
|     if (resource_limit_object.IsNull()) { | ||||
|         LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", | ||||
|                   resource_limit); | ||||
|         return ResultInvalidHandle; | ||||
| @ -843,12 +843,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle | ||||
|             return RESULT_SUCCESS; | ||||
|         } | ||||
| 
 | ||||
|         const auto table_result = handle_table.Create(resource_limit.get()); | ||||
|         if (table_result.Failed()) { | ||||
|             return table_result.Code(); | ||||
|         } | ||||
|         Handle handle{}; | ||||
|         R_TRY(handle_table.Add(&handle, resource_limit)); | ||||
| 
 | ||||
|         *result = *table_result; | ||||
|         *result = handle; | ||||
|         return RESULT_SUCCESS; | ||||
|     } | ||||
| 
 | ||||
| @ -2093,83 +2091,86 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ | ||||
| } | ||||
| 
 | ||||
| static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { | ||||
|     std::lock_guard lock{HLE::g_hle_lock}; | ||||
|     LOG_DEBUG(Kernel_SVC, "called"); | ||||
| 
 | ||||
|     // Create a new resource limit.
 | ||||
|     auto& kernel = system.Kernel(); | ||||
|     auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming()); | ||||
|     KResourceLimit* resource_limit = KResourceLimit::Create(kernel); | ||||
|     R_UNLESS(resource_limit != nullptr, ResultOutOfResource); | ||||
| 
 | ||||
|     auto* const current_process = kernel.CurrentProcess(); | ||||
|     ASSERT(current_process != nullptr); | ||||
|     // Ensure we don't leak a reference to the limit.
 | ||||
|     SCOPE_EXIT({ resource_limit->Close(); }); | ||||
| 
 | ||||
|     const auto handle = current_process->GetHandleTable().Create(resource_limit.get()); | ||||
|     if (handle.Failed()) { | ||||
|         return handle.Code(); | ||||
|     } | ||||
|     // Initialize the resource limit.
 | ||||
|     resource_limit->Initialize(&system.CoreTiming()); | ||||
| 
 | ||||
|     // Register the limit.
 | ||||
|     KResourceLimit::Register(kernel, resource_limit); | ||||
| 
 | ||||
|     // Add the limit to the handle table.
 | ||||
|     R_TRY(kernel.CurrentProcess()->GetHandleTable().Add(out_handle, resource_limit)); | ||||
| 
 | ||||
|     *out_handle = *handle; | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_value, | ||||
|                                              Handle resource_limit, u32 resource_type) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); | ||||
| static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value, | ||||
|                                              Handle resource_limit_handle, | ||||
|                                              LimitableResource which) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, | ||||
|               which); | ||||
| 
 | ||||
|     const auto limit_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, | ||||
|                                                         ResourceLimitValueType::LimitValue); | ||||
|     if (limit_value.Failed()) { | ||||
|         return limit_value.Code(); | ||||
|     } | ||||
|     // Validate the resource.
 | ||||
|     R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); | ||||
| 
 | ||||
|     // Get the resource limit.
 | ||||
|     auto& kernel = system.Kernel(); | ||||
|     KScopedAutoObject resource_limit = | ||||
|         kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); | ||||
|     R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); | ||||
| 
 | ||||
|     // Get the limit value.
 | ||||
|     *out_limit_value = resource_limit->GetLimitValue(which); | ||||
| 
 | ||||
|     *out_value = static_cast<u64>(*limit_value); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_value, | ||||
|                                                Handle resource_limit, u32 resource_type) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); | ||||
| static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value, | ||||
|                                                Handle resource_limit_handle, | ||||
|                                                LimitableResource which) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, | ||||
|               which); | ||||
| 
 | ||||
|     const auto current_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, | ||||
|                                                           ResourceLimitValueType::CurrentValue); | ||||
|     if (current_value.Failed()) { | ||||
|         return current_value.Code(); | ||||
|     } | ||||
|     // Validate the resource.
 | ||||
|     R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); | ||||
| 
 | ||||
|     // Get the resource limit.
 | ||||
|     auto& kernel = system.Kernel(); | ||||
|     KScopedAutoObject resource_limit = | ||||
|         kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); | ||||
|     R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); | ||||
| 
 | ||||
|     // Get the current value.
 | ||||
|     *out_current_value = resource_limit->GetCurrentValue(which); | ||||
| 
 | ||||
|     *out_value = static_cast<u64>(*current_value); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit, | ||||
|                                              u32 resource_type, u64 value) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, | ||||
|               resource_type, value); | ||||
| static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle, | ||||
|                                              LimitableResource which, u64 limit_value) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}", | ||||
|               resource_limit_handle, which, limit_value); | ||||
| 
 | ||||
|     const auto type = static_cast<LimitableResource>(resource_type); | ||||
|     if (!IsValidResourceType(type)) { | ||||
|         LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); | ||||
|         return ResultInvalidEnumValue; | ||||
|     } | ||||
|     // Validate the resource.
 | ||||
|     R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); | ||||
| 
 | ||||
|     auto* const current_process = system.Kernel().CurrentProcess(); | ||||
|     ASSERT(current_process != nullptr); | ||||
|     // Get the resource limit.
 | ||||
|     auto& kernel = system.Kernel(); | ||||
|     KScopedAutoObject resource_limit = | ||||
|         kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); | ||||
|     R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); | ||||
| 
 | ||||
|     auto resource_limit_object = | ||||
|         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); | ||||
|         return ResultInvalidHandle; | ||||
|     } | ||||
| 
 | ||||
|     const auto set_result = resource_limit_object->SetLimitValue(type, static_cast<s64>(value)); | ||||
|     if (set_result.IsError()) { | ||||
|         LOG_ERROR(Kernel_SVC, | ||||
|                   "Attempted to lower resource limit ({}) for category '{}' below its current " | ||||
|                   "value ({})", | ||||
|                   resource_limit_object->GetLimitValue(type), resource_type, | ||||
|                   resource_limit_object->GetCurrentValue(type)); | ||||
|         return set_result; | ||||
|     } | ||||
|     // Set the limit value.
 | ||||
|     R_TRY(resource_limit->SetLimitValue(which, limit_value)); | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | ||||
| @ -154,15 +154,28 @@ void SvcWrap64(Core::System& system) { | ||||
|     FuncReturn(system, retval); | ||||
| } | ||||
| 
 | ||||
| // Used by GetResourceLimitLimitValue.
 | ||||
| template <ResultCode func(Core::System&, u64*, Handle, LimitableResource)> | ||||
| void SvcWrap64(Core::System& system) { | ||||
|     u64 param_1 = 0; | ||||
|     const u32 retval = func(system, ¶m_1, static_cast<Handle>(Param(system, 1)), | ||||
|                             static_cast<LimitableResource>(Param(system, 2))) | ||||
|                            .raw; | ||||
| 
 | ||||
|     system.CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(system, retval); | ||||
| } | ||||
| 
 | ||||
| template <ResultCode func(Core::System&, u32, u64)> | ||||
| void SvcWrap64(Core::System& system) { | ||||
|     FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw); | ||||
| } | ||||
| 
 | ||||
| template <ResultCode func(Core::System&, u32, u32, u64)> | ||||
| // Used by SetResourceLimitLimitValue
 | ||||
| template <ResultCode func(Core::System&, Handle, LimitableResource, u64)> | ||||
| void SvcWrap64(Core::System& system) { | ||||
|     FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), | ||||
|                             static_cast<u32>(Param(system, 1)), Param(system, 2)) | ||||
|     FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), | ||||
|                             static_cast<LimitableResource>(Param(system, 1)), Param(system, 2)) | ||||
|                            .raw); | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user