From 7ccbdd4d8d3dea7294d2cac38779cceea9745d52 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 3 Apr 2021 22:22:36 -0700 Subject: [PATCH] hle: kernel: Migrate KProcess to KAutoObject. --- src/core/core.cpp | 9 ++++-- src/core/hle/kernel/handle_table.cpp | 10 +++--- src/core/hle/kernel/handle_table.h | 4 +-- src/core/hle/kernel/init/init_slab_setup.cpp | 9 ++++-- src/core/hle/kernel/init/init_slab_setup.h | 2 +- .../hle/kernel/k_synchronization_object.h | 5 ++- src/core/hle/kernel/kernel.cpp | 8 ++--- src/core/hle/kernel/kernel.h | 4 +-- src/core/hle/kernel/object.h | 4 +-- src/core/hle/kernel/process.cpp | 31 ++++++++++-------- src/core/hle/kernel/process.h | 32 +++++++++++++------ src/core/hle/kernel/svc.cpp | 6 ++-- src/core/hle/service/pm/pm.cpp | 12 +++---- src/yuzu/debugger/wait_tree.cpp | 2 +- 14 files changed, 80 insertions(+), 58 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index fdaa82c8f..f050a8d4b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -233,8 +233,11 @@ struct System::Impl { } telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); - auto main_process = - Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); + auto main_process = Kernel::Process::CreateWithKernel(system.Kernel()); + ASSERT(Kernel::Process::Initialize(main_process, system, "main", + Kernel::Process::ProcessType::Userland) + .IsSuccess()); + main_process->Open(); const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); if (load_result != Loader::ResultStatus::Success) { LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); @@ -244,7 +247,7 @@ struct System::Impl { static_cast(load_result)); } AddGlueRegistrationForProcess(*app_loader, *main_process); - kernel.MakeCurrentProcess(main_process.get()); + kernel.MakeCurrentProcess(main_process); kernel.InitializeCores(); // Initialize cheat engine diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 8eec8a3b5..f746c4888 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -100,7 +100,7 @@ ResultCode HandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) { } ResultVal HandleTable::Duplicate(Handle handle) { - std::shared_ptr object = GetGeneric(handle); + std::shared_ptr object = SharedFrom(GetGeneric(handle)); if (object == nullptr) { LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle); return ResultInvalidHandle; @@ -140,17 +140,17 @@ bool HandleTable::IsValid(Handle handle) const { return slot < table_size && is_object_valid && generations[slot] == generation; } -std::shared_ptr HandleTable::GetGeneric(Handle handle) const { +Object* HandleTable::GetGeneric(Handle handle) const { if (handle == CurrentThread) { - return SharedFrom(kernel.CurrentScheduler()->GetCurrentThread()); + return (kernel.CurrentScheduler()->GetCurrentThread()); } else if (handle == CurrentProcess) { - return SharedFrom(kernel.CurrentProcess()); + return (kernel.CurrentProcess()); } if (!IsValid(handle)) { return nullptr; } - return objects[GetSlot(handle)]; + return objects[GetSlot(handle)].get(); } void HandleTable::Clear() { diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index 555fb20e5..24a26b81d 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h @@ -98,7 +98,7 @@ public: * Looks up a handle. * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid. */ - std::shared_ptr GetGeneric(Handle handle) const; + Object* GetGeneric(Handle handle) const; /** * Looks up a handle while verifying its type. @@ -106,7 +106,7 @@ public: * type differs from the requested one. */ template - std::shared_ptr Get(Handle handle) const { + T* Get(Handle handle) const { return DynamicObjectCast(GetGeneric(handle)); } diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index a290249c7..a6fed524b 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -14,13 +14,16 @@ #include "core/hle/kernel/k_system_control.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/memory_types.h" +#include "core/hle/kernel/process.h" #include "core/memory.h" namespace Kernel::Init { #define SLAB_COUNT(CLASS) g_slab_resource_counts.num_##CLASS -#define FOREACH_SLAB_TYPE(HANDLER, ...) HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) +#define FOREACH_SLAB_TYPE(HANDLER, ...) \ + HANDLER(Process, (SLAB_COUNT(Process)), ##__VA_ARGS__) \ + HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) namespace { @@ -33,7 +36,7 @@ enum KSlabType : u32 { #undef DEFINE_SLAB_TYPE_ENUM_MEMBER // Constexpr counts. -constexpr size_t SlabCountKProcess = 80; +constexpr size_t SlabCountProcess = 80; constexpr size_t SlabCountKThread = 800; constexpr size_t SlabCountKEvent = 700; constexpr size_t SlabCountKInterruptEvent = 100; @@ -54,7 +57,7 @@ constexpr size_t SlabCountExtraKThread = 160; // Global to hold our resource counts. KSlabResourceCounts g_slab_resource_counts = { - .num_KProcess = SlabCountKProcess, + .num_Process = SlabCountProcess, .num_KThread = SlabCountKThread, .num_KEvent = SlabCountKEvent, .num_KInterruptEvent = SlabCountKInterruptEvent, diff --git a/src/core/hle/kernel/init/init_slab_setup.h b/src/core/hle/kernel/init/init_slab_setup.h index 6418b97ac..8876678b3 100644 --- a/src/core/hle/kernel/init/init_slab_setup.h +++ b/src/core/hle/kernel/init/init_slab_setup.h @@ -15,7 +15,7 @@ class KMemoryLayout; namespace Kernel::Init { struct KSlabResourceCounts { - size_t num_KProcess; + size_t num_Process; size_t num_KThread; size_t num_KEvent; size_t num_KInterruptEvent; diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index c8e840d89..5a99dbd46 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -53,10 +53,9 @@ private: // Specialization of DynamicObjectCast for KSynchronizationObjects template <> -inline std::shared_ptr DynamicObjectCast( - std::shared_ptr object) { +inline KSynchronizationObject* DynamicObjectCast(Object* object) { if (object != nullptr && object->IsWaitable()) { - return std::static_pointer_cast(object); + return reinterpret_cast(object); } return nullptr; } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d1359e434..1b5b11564 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -614,7 +614,7 @@ struct KernelCore::Impl { std::atomic next_thread_id{1}; // Lists all processes that exist in the current session. - std::vector> process_list; + std::vector process_list; Process* current_process = nullptr; std::unique_ptr global_scheduler_context; Kernel::TimeManager time_manager; @@ -699,8 +699,8 @@ KScopedAutoObject KernelCore::RetrieveThreadFromGlobalHandleTable(Handl return impl->global_handle_table.GetObject(handle); } -void KernelCore::AppendNewProcess(std::shared_ptr process) { - impl->process_list.push_back(std::move(process)); +void KernelCore::AppendNewProcess(Process* process) { + impl->process_list.push_back(process); } void KernelCore::MakeCurrentProcess(Process* process) { @@ -715,7 +715,7 @@ const Process* KernelCore::CurrentProcess() const { return impl->current_process; } -const std::vector>& KernelCore::GetProcessList() const { +const std::vector& KernelCore::GetProcessList() const { return impl->process_list; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3f5c2aec7..b78602f46 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -91,7 +91,7 @@ public: KScopedAutoObject RetrieveThreadFromGlobalHandleTable(Handle handle) const; /// Adds the given shared pointer to an internal list of active processes. - void AppendNewProcess(std::shared_ptr process); + void AppendNewProcess(Process* process); /// Makes the given process the new current process. void MakeCurrentProcess(Process* process); @@ -103,7 +103,7 @@ public: const Process* CurrentProcess() const; /// Retrieves the list of processes. - const std::vector>& GetProcessList() const; + const std::vector& GetProcessList() const; /// Gets the sole instance of the global scheduler Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 501e58b33..5c14aa46f 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h @@ -86,9 +86,9 @@ std::shared_ptr SharedFrom(T* raw) { * @return Derived pointer to the object, or `nullptr` if `object` isn't of type T. */ template -inline std::shared_ptr DynamicObjectCast(std::shared_ptr object) { +inline T* DynamicObjectCast(Object* object) { if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) { - return std::static_pointer_cast(object); + return reinterpret_cast(object); } return nullptr; } diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 796dca5ef..fe4558648 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -49,6 +49,8 @@ void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, // Register 1 must be a handle to the main thread Handle thread_handle{}; owner_process.GetHandleTable().Add(&thread_handle, thread); + + thread->SetName("main"); thread->GetContext32().cpu_registers[0] = 0; thread->GetContext64().cpu_registers[0] = 0; thread->GetContext32().cpu_registers[1] = thread_handle; @@ -115,10 +117,10 @@ private: std::bitset is_slot_used; }; -std::shared_ptr Process::Create(Core::System& system, std::string name, ProcessType type) { +ResultCode Process::Initialize(Process* process, Core::System& system, std::string name, + ProcessType type) { auto& kernel = system.Kernel(); - std::shared_ptr process = std::make_shared(system); process->name = std::move(name); process->resource_limit = kernel.GetSystemResourceLimit(); @@ -127,6 +129,7 @@ std::shared_ptr Process::Create(Core::System& system, std::string name, process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() : kernel.CreateNewUserProcessID(); process->capabilities.InitializeForMetadatalessProcess(); + process->is_initialized = true; std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))); std::uniform_int_distribution distribution; @@ -134,7 +137,8 @@ std::shared_ptr Process::Create(Core::System& system, std::string name, [&] { return distribution(rng); }); kernel.AppendNewProcess(process); - return process; + + return RESULT_SUCCESS; } std::shared_ptr Process::GetResourceLimit() const { @@ -332,7 +336,7 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) { ChangeStatus(ProcessStatus::Running); - SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); + SetupMainThread(kernel.System(), *this, main_thread_priority, main_thread_stack_top); } void Process::PrepareForTermination() { @@ -354,7 +358,7 @@ void Process::PrepareForTermination() { } }; - stop_threads(system.GlobalSchedulerContext().GetThreadList()); + stop_threads(kernel.System().GlobalSchedulerContext().GetThreadList()); FreeTLSRegion(tls_region_address); tls_region_address = 0; @@ -381,7 +385,7 @@ static auto FindTLSPageWithAvailableSlots(std::vector& tls_pages) { } VAddr Process::CreateTLSRegion() { - KScopedSchedulerLock lock(system.Kernel()); + KScopedSchedulerLock lock(kernel); if (auto tls_page_iter{FindTLSPageWithAvailableSlots(tls_pages)}; tls_page_iter != tls_pages.cend()) { return *tls_page_iter->ReserveSlot(); @@ -392,7 +396,7 @@ VAddr Process::CreateTLSRegion() { const VAddr start{page_table->GetKernelMapRegionStart()}; const VAddr size{page_table->GetKernelMapRegionEnd() - start}; - const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)}; + const PAddr tls_map_addr{kernel.System().DeviceMemory().GetPhysicalAddr(tls_page_ptr)}; const VAddr tls_page_addr{page_table ->AllocateAndMapMemory(1, PageSize, true, start, size / PageSize, KMemoryState::ThreadLocal, @@ -412,7 +416,7 @@ VAddr Process::CreateTLSRegion() { } void Process::FreeTLSRegion(VAddr tls_address) { - KScopedSchedulerLock lock(system.Kernel()); + KScopedSchedulerLock lock(kernel); const VAddr aligned_address = Common::AlignDown(tls_address, Core::Memory::PAGE_SIZE); auto iter = std::find_if(tls_pages.begin(), tls_pages.end(), [aligned_address](const auto& page) { @@ -433,7 +437,8 @@ void Process::LoadModule(CodeSet code_set, VAddr base_addr) { page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission); }; - system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size()); + kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(), + code_set.memory.size()); ReprotectSegment(code_set.CodeSegment(), KMemoryPermission::ReadAndExecute); ReprotectSegment(code_set.RODataSegment(), KMemoryPermission::Read); @@ -445,10 +450,10 @@ bool Process::IsSignaled() const { return is_signaled; } -Process::Process(Core::System& system) - : KSynchronizationObject{system.Kernel()}, page_table{std::make_unique(system)}, - handle_table{system.Kernel()}, address_arbiter{system}, condition_var{system}, - state_lock{system.Kernel()}, system{system} {} +Process::Process(KernelCore& kernel) + : KAutoObjectWithSlabHeapAndContainer{kernel}, + page_table{std::make_unique(kernel.System())}, handle_table{kernel}, + address_arbiter{kernel.System()}, condition_var{kernel.System()}, state_lock{kernel} {} Process::~Process() = default; diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 45eefb90e..df3c7997d 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -13,9 +13,11 @@ #include "common/common_types.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.h" +#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_condition_variable.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/process_capability.h" +#include "core/hle/kernel/slab_helpers.h" #include "core/hle/result.h" namespace Core { @@ -60,9 +62,11 @@ enum class ProcessStatus { DebugBreak, }; -class Process final : public KSynchronizationObject { +class Process final : public KAutoObjectWithSlabHeapAndContainer { + KERNEL_AUTOOBJECT_TRAITS(Process, KSynchronizationObject); + public: - explicit Process(Core::System& system); + explicit Process(KernelCore& kernel); ~Process() override; enum : u64 { @@ -85,8 +89,8 @@ public: static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; - static std::shared_ptr Create(Core::System& system, std::string name, - ProcessType type); + static ResultCode Initialize(Process* process, Core::System& system, std::string name, + ProcessType type); std::string GetTypeName() const override { return "Process"; @@ -338,9 +342,21 @@ public: void LoadModule(CodeSet code_set, VAddr base_addr); - bool IsSignaled() const override; + virtual bool IsInitialized() const override { + return is_initialized; + } - void Finalize() override {} + static void PostDestroy([[maybe_unused]] uintptr_t arg) {} + + virtual void Finalize() override { + UNIMPLEMENTED(); + } + + virtual u64 GetId() const override final { + return GetProcessID(); + } + + virtual bool IsSignaled() const override; void PinCurrentThread(); void UnpinCurrentThread(); @@ -462,6 +478,7 @@ private: bool is_signaled{}; bool is_suspended{}; + bool is_initialized{}; std::atomic num_created_threads{}; std::atomic num_threads{}; @@ -474,9 +491,6 @@ private: KThread* exception_thread{}; KLightLock state_lock; - - /// System context - Core::System& system; }; } // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index dca1bcc92..7d676e5f7 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -342,7 +342,7 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, static ResultCode SendSyncRequest(Core::System& system, Handle handle) { auto& kernel = system.Kernel(); const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); - std::shared_ptr session = handle_table.Get(handle); + auto session = handle_table.Get(handle); if (!session) { LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); return ResultInvalidHandle; @@ -437,7 +437,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha { auto object = handle_table.Get(handle); if (object) { - objects[i] = object.get(); + objects[i] = object; succeeded = true; } } @@ -1190,7 +1190,7 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add std::lock_guard lock{HLE::g_hle_lock}; LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - std::shared_ptr process = handle_table.Get(process_handle); + auto process = handle_table.Get(process_handle); if (!process) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index 68736c40c..3a00849e1 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -17,9 +17,8 @@ constexpr ResultCode ERROR_PROCESS_NOT_FOUND{ErrorModule::PM, 1}; constexpr u64 NO_PROCESS_FOUND_PID{0}; -std::optional> SearchProcessList( - const std::vector>& process_list, - std::function&)> predicate) { +std::optional SearchProcessList(const std::vector& process_list, + std::function predicate) { const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); if (iter == process_list.end()) { @@ -30,7 +29,7 @@ std::optional> SearchProcessList( } void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, - const std::vector>& process_list) { + const std::vector& process_list) { const auto process = SearchProcessList(process_list, [](const auto& process) { return process->GetProcessID() == Kernel::Process::ProcessIDMin; }); @@ -125,8 +124,7 @@ private: class Info final : public ServiceFramework { public: - explicit Info(Core::System& system_, - const std::vector>& process_list_) + explicit Info(Core::System& system_, const std::vector& process_list_) : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { static const FunctionInfo functions[] = { {0, &Info::GetTitleId, "GetTitleId"}, @@ -156,7 +154,7 @@ private: rb.Push((*process)->GetTitleID()); } - const std::vector>& process_list; + const std::vector& process_list; }; class Shell final : public ServiceFramework { diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index ef0ab0960..f4eeba2c5 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -118,7 +118,7 @@ WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTa : mutex_address(mutex_address) { mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address); owner_handle = static_cast(mutex_value & Kernel::Svc::HandleWaitMask); - owner = handle_table.Get(owner_handle); + owner = SharedFrom(handle_table.Get(owner_handle)); } WaitTreeMutexInfo::~WaitTreeMutexInfo() = default;