mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #4358 from wwylele/kernel-global-2
kernel: Eliminate global state in process and handle_table
This commit is contained in:
		
						commit
						f3ee5feb02
					
				
					 29 changed files with 312 additions and 230 deletions
				
			
		|  | @ -126,7 +126,9 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file | |||
|         return init_result; | ||||
|     } | ||||
| 
 | ||||
|     const Loader::ResultStatus load_result{app_loader->Load(Kernel::g_current_process)}; | ||||
|     Kernel::SharedPtr<Kernel::Process> process; | ||||
|     const Loader::ResultStatus load_result{app_loader->Load(process)}; | ||||
|     kernel->SetCurrentProcess(process); | ||||
|     if (Loader::ResultStatus::Success != load_result) { | ||||
|         LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<u32>(load_result)); | ||||
|         System::Shutdown(); | ||||
|  | @ -140,7 +142,7 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file | |||
|             return ResultStatus::ErrorLoader; | ||||
|         } | ||||
|     } | ||||
|     Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); | ||||
|     Memory::SetCurrentPageTable(&kernel->GetCurrentProcess()->vm_manager.page_table); | ||||
|     status = ResultStatus::Success; | ||||
|     m_emu_window = &emu_window; | ||||
|     m_filepath = filepath; | ||||
|  |  | |||
|  | @ -251,8 +251,11 @@ private: | |||
| 
 | ||||
|     std::unique_ptr<Service::FS::ArchiveManager> archive_manager; | ||||
| 
 | ||||
| public: // HACK: this is temporary exposed for tests,
 | ||||
|         // due to WIP kernel refactor causing desync state in memory
 | ||||
|     std::unique_ptr<Kernel::KernelSystem> kernel; | ||||
| 
 | ||||
| private: | ||||
|     static System s_instance; | ||||
| 
 | ||||
|     ResultStatus status = ResultStatus::Success; | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <utility> | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/archive_savedata.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| 
 | ||||
|  | @ -16,16 +17,19 @@ ArchiveFactory_SaveData::ArchiveFactory_SaveData( | |||
|     : sd_savedata_source(std::move(sd_savedata)) {} | ||||
| 
 | ||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { | ||||
|     return sd_savedata_source->Open(Kernel::g_current_process->codeset->program_id); | ||||
|     return sd_savedata_source->Open( | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id); | ||||
| } | ||||
| 
 | ||||
| ResultCode ArchiveFactory_SaveData::Format(const Path& path, | ||||
|                                            const FileSys::ArchiveFormatInfo& format_info) { | ||||
|     return sd_savedata_source->Format(Kernel::g_current_process->codeset->program_id, format_info); | ||||
|     return sd_savedata_source->Format( | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id, format_info); | ||||
| } | ||||
| 
 | ||||
| ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { | ||||
|     return sd_savedata_source->GetFormatInfo(Kernel::g_current_process->codeset->program_id); | ||||
|     return sd_savedata_source->GetFormatInfo( | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id); | ||||
| } | ||||
| 
 | ||||
| } // namespace FileSys
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/swap.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/archive_selfncch.h" | ||||
| #include "core/file_sys/errors.h" | ||||
| #include "core/file_sys/ivfc_archive.h" | ||||
|  | @ -279,7 +280,7 @@ void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) { | |||
| 
 | ||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) { | ||||
|     auto archive = std::make_unique<SelfNCCHArchive>( | ||||
|         ncch_data[Kernel::g_current_process->codeset->program_id]); | ||||
|         ncch_data[Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id]); | ||||
|     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,9 +12,7 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| HandleTable g_handle_table; | ||||
| 
 | ||||
| HandleTable::HandleTable() { | ||||
| HandleTable::HandleTable(KernelSystem& kernel) : kernel(kernel) { | ||||
|     next_generation = 1; | ||||
|     Clear(); | ||||
| } | ||||
|  | @ -76,7 +74,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { | |||
|     if (handle == CurrentThread) { | ||||
|         return GetCurrentThread(); | ||||
|     } else if (handle == CurrentProcess) { | ||||
|         return g_current_process; | ||||
|         return kernel.GetCurrentProcess(); | ||||
|     } | ||||
| 
 | ||||
|     if (!IsValid(handle)) { | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ enum KernelHandle : Handle { | |||
|  */ | ||||
| class HandleTable final : NonCopyable { | ||||
| public: | ||||
|     HandleTable(); | ||||
|     explicit HandleTable(KernelSystem& kernel); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Allocates a handle for the given object. | ||||
|  | @ -119,8 +119,8 @@ private: | |||
| 
 | ||||
|     /// Head of the free slots linked list.
 | ||||
|     u16 next_free_slot; | ||||
| 
 | ||||
|     KernelSystem& kernel; | ||||
| }; | ||||
| 
 | ||||
| extern HandleTable g_handle_table; | ||||
| 
 | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread, | |||
|         std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff; | ||||
|         Memory::ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), | ||||
|                           cmd_buff.size() * sizeof(u32)); | ||||
|         context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process, Kernel::g_handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process); | ||||
|         // Copy the translated command buffer back into the thread's command buffer area.
 | ||||
|         Memory::WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), | ||||
|                            cmd_buff.size() * sizeof(u32)); | ||||
|  | @ -98,8 +98,7 @@ void HLERequestContext::AddStaticBuffer(u8 buffer_id, std::vector<u8> data) { | |||
| } | ||||
| 
 | ||||
| ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, | ||||
|                                                                 Process& src_process, | ||||
|                                                                 HandleTable& src_table) { | ||||
|                                                                 Process& src_process) { | ||||
|     IPC::Header header{src_cmdbuf[0]}; | ||||
| 
 | ||||
|     std::size_t untranslated_size = 1u + header.normal_params_size; | ||||
|  | @ -122,10 +121,10 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr | |||
|                 Handle handle = src_cmdbuf[i]; | ||||
|                 SharedPtr<Object> object = nullptr; | ||||
|                 if (handle != 0) { | ||||
|                     object = src_table.GetGeneric(handle); | ||||
|                     object = src_process.handle_table.GetGeneric(handle); | ||||
|                     ASSERT(object != nullptr); // TODO(yuriks): Return error
 | ||||
|                     if (descriptor == IPC::DescriptorType::MoveHandle) { | ||||
|                         src_table.Close(handle); | ||||
|                         src_process.handle_table.Close(handle); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|  | @ -163,8 +162,8 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr | |||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process, | ||||
|                                                            HandleTable& dst_table) const { | ||||
| ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, | ||||
|                                                            Process& dst_process) const { | ||||
|     IPC::Header header{cmd_buf[0]}; | ||||
| 
 | ||||
|     std::size_t untranslated_size = 1u + header.normal_params_size; | ||||
|  | @ -189,7 +188,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P | |||
|                 Handle handle = 0; | ||||
|                 if (object != nullptr) { | ||||
|                     // TODO(yuriks): Figure out the proper error handling for if this fails
 | ||||
|                     handle = dst_table.Create(object).Unwrap(); | ||||
|                     handle = dst_process.handle_table.Create(object).Unwrap(); | ||||
|                 } | ||||
|                 dst_cmdbuf[i++] = handle; | ||||
|             } | ||||
|  |  | |||
|  | @ -226,11 +226,9 @@ public: | |||
|     MappedBuffer& GetMappedBuffer(u32 id_from_cmdbuf); | ||||
| 
 | ||||
|     /// Populates this context with data from the requesting process/thread.
 | ||||
|     ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process, | ||||
|                                                  HandleTable& src_table); | ||||
|     ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process); | ||||
|     /// Writes data from this context back to the requesting process/thread.
 | ||||
|     ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process, | ||||
|                                             HandleTable& dst_table) const; | ||||
|     ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process) const; | ||||
| 
 | ||||
| private: | ||||
|     std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; | ||||
|  |  | |||
|  | @ -60,9 +60,9 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread | |||
|                 } else if (handle == CurrentProcess) { | ||||
|                     object = src_process; | ||||
|                 } else if (handle != 0) { | ||||
|                     object = g_handle_table.GetGeneric(handle); | ||||
|                     object = src_process->handle_table.GetGeneric(handle); | ||||
|                     if (descriptor == IPC::DescriptorType::MoveHandle) { | ||||
|                         g_handle_table.Close(handle); | ||||
|                         src_process->handle_table.Close(handle); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|  | @ -73,7 +73,7 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread | |||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 auto result = g_handle_table.Create(std::move(object)); | ||||
|                 auto result = dst_process->handle_table.Create(std::move(object)); | ||||
|                 cmd_buf[i++] = result.ValueOr(0); | ||||
|             } | ||||
|             break; | ||||
|  |  | |||
|  | @ -23,17 +23,11 @@ KernelSystem::KernelSystem(u32 system_mode) { | |||
|     resource_limits = std::make_unique<ResourceLimitList>(*this); | ||||
|     Kernel::ThreadingInit(); | ||||
|     Kernel::TimersInit(); | ||||
|     // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
 | ||||
|     // reserved for low-level services
 | ||||
|     Process::next_process_id = 10; | ||||
| } | ||||
| 
 | ||||
| /// Shutdown the kernel
 | ||||
| KernelSystem::~KernelSystem() { | ||||
|     g_handle_table.Clear(); // Free all kernel objects
 | ||||
| 
 | ||||
|     Kernel::ThreadingShutdown(); | ||||
|     g_current_process = nullptr; | ||||
| 
 | ||||
|     Kernel::TimersShutdown(); | ||||
|     Kernel::MemoryShutdown(); | ||||
|  | @ -51,4 +45,12 @@ u32 KernelSystem::GenerateObjectID() { | |||
|     return next_object_id++; | ||||
| } | ||||
| 
 | ||||
| SharedPtr<Process> KernelSystem::GetCurrentProcess() const { | ||||
|     return current_process; | ||||
| } | ||||
| 
 | ||||
| void KernelSystem::SetCurrentProcess(SharedPtr<Process> process) { | ||||
|     current_process = std::move(process); | ||||
| } | ||||
| 
 | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <atomic> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <boost/smart_ptr/intrusive_ptr.hpp> | ||||
| #include "common/common_types.h" | ||||
| #include "core/hle/result.h" | ||||
|  | @ -101,7 +102,7 @@ public: | |||
|      */ | ||||
|     ResultVal<SharedPtr<Thread>> CreateThread(std::string name, VAddr entry_point, u32 priority, | ||||
|                                               u32 arg, s32 processor_id, VAddr stack_top, | ||||
|                                               SharedPtr<Process> owner_process); | ||||
|                                               Process& owner_process); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Creates a semaphore. | ||||
|  | @ -155,7 +156,7 @@ public: | |||
|      * linear heap. | ||||
|      * @param name Optional object name, used for debugging purposes. | ||||
|      */ | ||||
|     SharedPtr<SharedMemory> CreateSharedMemory(SharedPtr<Process> owner_process, u32 size, | ||||
|     SharedPtr<SharedMemory> CreateSharedMemory(Process* owner_process, u32 size, | ||||
|                                                MemoryPermission permissions, | ||||
|                                                MemoryPermission other_permissions, | ||||
|                                                VAddr address = 0, | ||||
|  | @ -180,9 +181,24 @@ public: | |||
| 
 | ||||
|     u32 GenerateObjectID(); | ||||
| 
 | ||||
|     /// Retrieves a process from the current list of processes.
 | ||||
|     SharedPtr<Process> GetProcessById(u32 process_id) const; | ||||
| 
 | ||||
|     SharedPtr<Process> GetCurrentProcess() const; | ||||
|     void SetCurrentProcess(SharedPtr<Process> process); | ||||
| 
 | ||||
| private: | ||||
|     std::unique_ptr<ResourceLimitList> resource_limits; | ||||
|     std::atomic<u32> next_object_id{0}; | ||||
| 
 | ||||
|     // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
 | ||||
|     // reserved for low-level services
 | ||||
|     u32 next_process_id = 10; | ||||
| 
 | ||||
|     // Lists all processes that exist in the current session.
 | ||||
|     std::vector<SharedPtr<Process>> process_list; | ||||
| 
 | ||||
|     SharedPtr<Process> current_process; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -17,9 +17,6 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| // Lists all processes that exist in the current session.
 | ||||
| static std::vector<SharedPtr<Process>> process_list; | ||||
| 
 | ||||
| SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) { | ||||
|     SharedPtr<CodeSet> codeset(new CodeSet(*this)); | ||||
| 
 | ||||
|  | @ -32,8 +29,6 @@ SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) | |||
| CodeSet::CodeSet(KernelSystem& kernel) : Object(kernel) {} | ||||
| CodeSet::~CodeSet() {} | ||||
| 
 | ||||
| u32 Process::next_process_id; | ||||
| 
 | ||||
| SharedPtr<Process> KernelSystem::CreateProcess(SharedPtr<CodeSet> code_set) { | ||||
|     SharedPtr<Process> process(new Process(*this)); | ||||
| 
 | ||||
|  | @ -41,6 +36,7 @@ SharedPtr<Process> KernelSystem::CreateProcess(SharedPtr<CodeSet> code_set) { | |||
|     process->flags.raw = 0; | ||||
|     process->flags.memory_region.Assign(MemoryRegion::APPLICATION); | ||||
|     process->status = ProcessStatus::Created; | ||||
|     process->process_id = ++next_process_id; | ||||
| 
 | ||||
|     process_list.push_back(process); | ||||
|     return process; | ||||
|  | @ -304,14 +300,11 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { | |||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| Kernel::Process::Process(KernelSystem& kernel) : Object(kernel), kernel(kernel) {} | ||||
| Kernel::Process::Process(KernelSystem& kernel) | ||||
|     : Object(kernel), handle_table(kernel), kernel(kernel) {} | ||||
| Kernel::Process::~Process() {} | ||||
| 
 | ||||
| void ClearProcessList() { | ||||
|     process_list.clear(); | ||||
| } | ||||
| 
 | ||||
| SharedPtr<Process> GetProcessById(u32 process_id) { | ||||
| SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const { | ||||
|     auto itr = std::find_if( | ||||
|         process_list.begin(), process_list.end(), | ||||
|         [&](const SharedPtr<Process>& process) { return process->process_id == process_id; }); | ||||
|  | @ -321,6 +314,4 @@ SharedPtr<Process> GetProcessById(u32 process_id) { | |||
| 
 | ||||
|     return *itr; | ||||
| } | ||||
| 
 | ||||
| SharedPtr<Process> g_current_process; | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| #include <boost/container/static_vector.hpp> | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_types.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/object.h" | ||||
| #include "core/hle/kernel/vm_manager.h" | ||||
| 
 | ||||
|  | @ -123,7 +124,7 @@ public: | |||
|         return HANDLE_TYPE; | ||||
|     } | ||||
| 
 | ||||
|     static u32 next_process_id; | ||||
|     HandleTable handle_table; | ||||
| 
 | ||||
|     SharedPtr<CodeSet> codeset; | ||||
|     /// Resource limit descriptor for this process
 | ||||
|  | @ -145,7 +146,7 @@ public: | |||
|     ProcessStatus status; | ||||
| 
 | ||||
|     /// The id of this process
 | ||||
|     u32 process_id = next_process_id++; | ||||
|     u32 process_id; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them | ||||
|  | @ -199,11 +200,4 @@ private: | |||
|     friend class KernelSystem; | ||||
|     KernelSystem& kernel; | ||||
| }; | ||||
| 
 | ||||
| void ClearProcessList(); | ||||
| 
 | ||||
| /// Retrieves a process from the current list of processes.
 | ||||
| SharedPtr<Process> GetProcessById(u32 process_id); | ||||
| 
 | ||||
| extern SharedPtr<Process> g_current_process; | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ namespace Kernel { | |||
| SharedMemory::SharedMemory(KernelSystem& kernel) : Object(kernel) {} | ||||
| SharedMemory::~SharedMemory() {} | ||||
| 
 | ||||
| SharedPtr<SharedMemory> KernelSystem::CreateSharedMemory(SharedPtr<Process> owner_process, u32 size, | ||||
| SharedPtr<SharedMemory> KernelSystem::CreateSharedMemory(Process* owner_process, u32 size, | ||||
|                                                          MemoryPermission permissions, | ||||
|                                                          MemoryPermission other_permissions, | ||||
|                                                          VAddr address, MemoryRegion region, | ||||
|  | @ -52,8 +52,8 @@ SharedPtr<SharedMemory> KernelSystem::CreateSharedMemory(SharedPtr<Process> owne | |||
|         } | ||||
| 
 | ||||
|         // Refresh the address mappings for the current process.
 | ||||
|         if (Kernel::g_current_process != nullptr) { | ||||
|             Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | ||||
|         if (current_process != nullptr) { | ||||
|             current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | ||||
|         } | ||||
|     } else { | ||||
|         auto& vm_manager = shared_memory->owner_process->vm_manager; | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ public: | |||
|     u8* GetPointer(u32 offset = 0); | ||||
| 
 | ||||
|     /// Process that created this shared memory block.
 | ||||
|     SharedPtr<Process> owner_process; | ||||
|     Process* owner_process; | ||||
|     /// Address of shared memory block in the owner process if specified.
 | ||||
|     VAddr base_address; | ||||
|     /// Physical address of the shared memory block in the linear heap if no address was specified
 | ||||
|  |  | |||
|  | @ -83,7 +83,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add | |||
|     } | ||||
|     VMAPermission vma_permissions = (VMAPermission)permissions; | ||||
| 
 | ||||
|     auto& process = *g_current_process; | ||||
|     auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
| 
 | ||||
|     switch (operation & MEMOP_OPERATION_MASK) { | ||||
|     case MEMOP_FREE: { | ||||
|  | @ -145,16 +145,17 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add | |||
| } | ||||
| 
 | ||||
| static void ExitProcess() { | ||||
|     LOG_INFO(Kernel_SVC, "Process {} exiting", g_current_process->process_id); | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->process_id); | ||||
| 
 | ||||
|     ASSERT_MSG(g_current_process->status == ProcessStatus::Running, "Process has already exited"); | ||||
|     ASSERT_MSG(current_process->status == ProcessStatus::Running, "Process has already exited"); | ||||
| 
 | ||||
|     g_current_process->status = ProcessStatus::Exited; | ||||
|     current_process->status = ProcessStatus::Exited; | ||||
| 
 | ||||
|     // Stop all the process threads that are currently waiting for objects.
 | ||||
|     auto& thread_list = GetThreadList(); | ||||
|     for (auto& thread : thread_list) { | ||||
|         if (thread->owner_process != g_current_process) | ||||
|         if (thread->owner_process != current_process) | ||||
|             continue; | ||||
| 
 | ||||
|         if (thread == GetCurrentThread()) | ||||
|  | @ -181,7 +182,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o | |||
|               "otherpermission={}", | ||||
|               handle, addr, permissions, other_permissions); | ||||
| 
 | ||||
|     SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(handle); | ||||
|     SharedPtr<SharedMemory> shared_memory = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<SharedMemory>( | ||||
|             handle); | ||||
|     if (shared_memory == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -195,7 +198,8 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o | |||
|     case MemoryPermission::WriteExecute: | ||||
|     case MemoryPermission::ReadWriteExecute: | ||||
|     case MemoryPermission::DontCare: | ||||
|         return shared_memory->Map(g_current_process.get(), addr, permissions_type, | ||||
|         return shared_memory->Map(Core::System::GetInstance().Kernel().GetCurrentProcess().get(), | ||||
|                                   addr, permissions_type, | ||||
|                                   static_cast<MemoryPermission>(other_permissions)); | ||||
|     default: | ||||
|         LOG_ERROR(Kernel_SVC, "unknown permissions=0x{:08X}", permissions); | ||||
|  | @ -209,11 +213,12 @@ static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { | |||
| 
 | ||||
|     // TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
 | ||||
| 
 | ||||
|     SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(handle); | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     SharedPtr<SharedMemory> shared_memory = current_process->handle_table.Get<SharedMemory>(handle); | ||||
|     if (shared_memory == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|     return shared_memory->Unmap(g_current_process.get(), addr); | ||||
|     return shared_memory->Unmap(current_process.get(), addr); | ||||
| } | ||||
| 
 | ||||
| /// Connect to an OS service given the port name, returns the handle to the port to out
 | ||||
|  | @ -241,13 +246,17 @@ static ResultCode ConnectToPort(Handle* out_handle, VAddr port_name_address) { | |||
|     CASCADE_RESULT(client_session, client_port->Connect()); | ||||
| 
 | ||||
|     // Return the client session
 | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(client_session)); | ||||
|     CASCADE_RESULT(*out_handle, | ||||
|                    Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Create( | ||||
|                        client_session)); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /// Makes a blocking IPC call to an OS service.
 | ||||
| static ResultCode SendSyncRequest(Handle handle) { | ||||
|     SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle); | ||||
|     SharedPtr<ClientSession> session = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ClientSession>( | ||||
|             handle); | ||||
|     if (session == nullptr) { | ||||
|         return ERR_INVALID_HANDLE; | ||||
|     } | ||||
|  | @ -262,12 +271,14 @@ static ResultCode SendSyncRequest(Handle handle) { | |||
| /// Close a handle
 | ||||
| static ResultCode CloseHandle(Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); | ||||
|     return g_handle_table.Close(handle); | ||||
|     return Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Close(handle); | ||||
| } | ||||
| 
 | ||||
| /// Wait for a handle to synchronize, timeout after the specified nanoseconds
 | ||||
| static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { | ||||
|     auto object = g_handle_table.Get<WaitObject>(handle); | ||||
|     auto object = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<WaitObject>( | ||||
|             handle); | ||||
|     Thread* thread = GetCurrentThread(); | ||||
| 
 | ||||
|     if (object == nullptr) | ||||
|  | @ -338,7 +349,9 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand | |||
| 
 | ||||
|     for (int i = 0; i < handle_count; ++i) { | ||||
|         Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); | ||||
|         auto object = g_handle_table.Get<WaitObject>(handle); | ||||
|         auto object = | ||||
|             Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<WaitObject>( | ||||
|                 handle); | ||||
|         if (object == nullptr) | ||||
|             return ERR_INVALID_HANDLE; | ||||
|         objects[i] = object; | ||||
|  | @ -502,9 +515,11 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_ | |||
|     using ObjectPtr = SharedPtr<WaitObject>; | ||||
|     std::vector<ObjectPtr> objects(handle_count); | ||||
| 
 | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
| 
 | ||||
|     for (int i = 0; i < handle_count; ++i) { | ||||
|         Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); | ||||
|         auto object = g_handle_table.Get<WaitObject>(handle); | ||||
|         auto object = current_process->handle_table.Get<WaitObject>(handle); | ||||
|         if (object == nullptr) | ||||
|             return ERR_INVALID_HANDLE; | ||||
|         objects[i] = object; | ||||
|  | @ -515,7 +530,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_ | |||
|     u32* cmd_buff = GetCommandBuffer(); | ||||
|     IPC::Header header{cmd_buff[0]}; | ||||
|     if (reply_target != 0 && header.command_id != 0xFFFF) { | ||||
|         auto session = g_handle_table.Get<ServerSession>(reply_target); | ||||
|         auto session = current_process->handle_table.Get<ServerSession>(reply_target); | ||||
|         if (session == nullptr) | ||||
|             return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -615,8 +630,10 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_ | |||
| 
 | ||||
| /// Create an address arbiter (to allocate access to shared resources)
 | ||||
| static ResultCode CreateAddressArbiter(Handle* out_handle) { | ||||
|     SharedPtr<AddressArbiter> arbiter = Core::System::GetInstance().Kernel().CreateAddressArbiter(); | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(arbiter))); | ||||
|     KernelSystem& kernel = Core::System::GetInstance().Kernel(); | ||||
|     SharedPtr<AddressArbiter> arbiter = kernel.CreateAddressArbiter(); | ||||
|     CASCADE_RESULT(*out_handle, | ||||
|                    kernel.GetCurrentProcess()->handle_table.Create(std::move(arbiter))); | ||||
|     LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | @ -627,7 +644,9 @@ static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 val | |||
|     LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}, address=0x{:08X}, type=0x{:08X}, value=0x{:08X}", | ||||
|               handle, address, type, value); | ||||
| 
 | ||||
|     SharedPtr<AddressArbiter> arbiter = g_handle_table.Get<AddressArbiter>(handle); | ||||
|     SharedPtr<AddressArbiter> arbiter = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<AddressArbiter>( | ||||
|             handle); | ||||
|     if (arbiter == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -675,11 +694,12 @@ static void OutputDebugString(VAddr address, int len) { | |||
| static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle); | ||||
| 
 | ||||
|     SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     SharedPtr<Process> process = current_process->handle_table.Get<Process>(process_handle); | ||||
|     if (process == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|     CASCADE_RESULT(*resource_limit, g_handle_table.Create(process->resource_limit)); | ||||
|     CASCADE_RESULT(*resource_limit, current_process->handle_table.Create(process->resource_limit)); | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | @ -691,7 +711,8 @@ static ResultCode GetResourceLimitCurrentValues(VAddr values, Handle resource_li | |||
|               resource_limit_handle, names, name_count); | ||||
| 
 | ||||
|     SharedPtr<ResourceLimit> resource_limit = | ||||
|         g_handle_table.Get<ResourceLimit>(resource_limit_handle); | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ResourceLimit>( | ||||
|             resource_limit_handle); | ||||
|     if (resource_limit == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -711,7 +732,8 @@ static ResultCode GetResourceLimitLimitValues(VAddr values, Handle resource_limi | |||
|               resource_limit_handle, names, name_count); | ||||
| 
 | ||||
|     SharedPtr<ResourceLimit> resource_limit = | ||||
|         g_handle_table.Get<ResourceLimit>(resource_limit_handle); | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ResourceLimit>( | ||||
|             resource_limit_handle); | ||||
|     if (resource_limit == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -733,14 +755,16 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point | |||
|         return ERR_OUT_OF_RANGE; | ||||
|     } | ||||
| 
 | ||||
|     SharedPtr<ResourceLimit>& resource_limit = g_current_process->resource_limit; | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
| 
 | ||||
|     SharedPtr<ResourceLimit>& resource_limit = current_process->resource_limit; | ||||
|     if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) { | ||||
|         return ERR_NOT_AUTHORIZED; | ||||
|     } | ||||
| 
 | ||||
|     if (processor_id == ThreadProcessorIdDefault) { | ||||
|         // Set the target CPU to the one specified in the process' exheader.
 | ||||
|         processor_id = g_current_process->ideal_processor; | ||||
|         processor_id = current_process->ideal_processor; | ||||
|         ASSERT(processor_id != ThreadProcessorIdDefault); | ||||
|     } | ||||
| 
 | ||||
|  | @ -763,12 +787,12 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point | |||
| 
 | ||||
|     CASCADE_RESULT(SharedPtr<Thread> thread, Core::System::GetInstance().Kernel().CreateThread( | ||||
|                                                  name, entry_point, priority, arg, processor_id, | ||||
|                                                  stack_top, g_current_process)); | ||||
|                                                  stack_top, *current_process)); | ||||
| 
 | ||||
|     thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | | ||||
|                               FPSCR_ROUND_TOZERO); // 0x03C00000
 | ||||
| 
 | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(thread))); | ||||
|     CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(thread))); | ||||
| 
 | ||||
|     Core::System::GetInstance().PrepareReschedule(); | ||||
| 
 | ||||
|  | @ -790,7 +814,8 @@ static void ExitThread() { | |||
| 
 | ||||
| /// Gets the priority for the specified thread
 | ||||
| static ResultCode GetThreadPriority(u32* priority, Handle handle) { | ||||
|     const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); | ||||
|     const SharedPtr<Thread> thread = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle); | ||||
|     if (thread == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -804,13 +829,15 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) { | |||
|         return ERR_OUT_OF_RANGE; | ||||
|     } | ||||
| 
 | ||||
|     SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); | ||||
|     SharedPtr<Thread> thread = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle); | ||||
|     if (thread == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|     // Note: The kernel uses the current process's resource limit instead of
 | ||||
|     // the one from the thread owner's resource limit.
 | ||||
|     SharedPtr<ResourceLimit>& resource_limit = g_current_process->resource_limit; | ||||
|     SharedPtr<ResourceLimit>& resource_limit = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->resource_limit; | ||||
|     if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) { | ||||
|         return ERR_NOT_AUTHORIZED; | ||||
|     } | ||||
|  | @ -828,9 +855,10 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) { | |||
| 
 | ||||
| /// Create a mutex
 | ||||
| static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { | ||||
|     SharedPtr<Mutex> mutex = Core::System::GetInstance().Kernel().CreateMutex(initial_locked != 0); | ||||
|     KernelSystem& kernel = Core::System::GetInstance().Kernel(); | ||||
|     SharedPtr<Mutex> mutex = kernel.CreateMutex(initial_locked != 0); | ||||
|     mutex->name = fmt::format("mutex-{:08x}", Core::CPU().GetReg(14)); | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(mutex))); | ||||
|     CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(mutex))); | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called initial_locked={} : created handle=0x{:08X}", | ||||
|               initial_locked ? "true" : "false", *out_handle); | ||||
|  | @ -842,7 +870,8 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { | |||
| static ResultCode ReleaseMutex(Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle); | ||||
| 
 | ||||
|     SharedPtr<Mutex> mutex = g_handle_table.Get<Mutex>(handle); | ||||
|     SharedPtr<Mutex> mutex = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Mutex>(handle); | ||||
|     if (mutex == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -853,7 +882,9 @@ static ResultCode ReleaseMutex(Handle handle) { | |||
| static ResultCode GetProcessId(u32* process_id, Handle process_handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle); | ||||
| 
 | ||||
|     const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); | ||||
|     const SharedPtr<Process> process = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>( | ||||
|             process_handle); | ||||
|     if (process == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -865,7 +896,9 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) { | |||
| static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); | ||||
| 
 | ||||
|     const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); | ||||
|     const SharedPtr<Thread> thread = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>( | ||||
|             thread_handle); | ||||
|     if (thread == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -881,7 +914,8 @@ static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { | |||
| static ResultCode GetThreadId(u32* thread_id, Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", handle); | ||||
| 
 | ||||
|     const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); | ||||
|     const SharedPtr<Thread> thread = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle); | ||||
|     if (thread == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -891,10 +925,12 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) { | |||
| 
 | ||||
| /// Creates a semaphore
 | ||||
| static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) { | ||||
|     KernelSystem& kernel = Core::System::GetInstance().Kernel(); | ||||
|     CASCADE_RESULT(SharedPtr<Semaphore> semaphore, | ||||
|                    Core::System::GetInstance().Kernel().CreateSemaphore(initial_count, max_count)); | ||||
|                    kernel.CreateSemaphore(initial_count, max_count)); | ||||
|     semaphore->name = fmt::format("semaphore-{:08x}", Core::CPU().GetReg(14)); | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(semaphore))); | ||||
|     CASCADE_RESULT(*out_handle, | ||||
|                    kernel.GetCurrentProcess()->handle_table.Create(std::move(semaphore))); | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called initial_count={}, max_count={}, created handle=0x{:08X}", | ||||
|               initial_count, max_count, *out_handle); | ||||
|  | @ -905,7 +941,9 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max | |||
| static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { | ||||
|     LOG_TRACE(Kernel_SVC, "called release_count={}, handle=0x{:08X}", release_count, handle); | ||||
| 
 | ||||
|     SharedPtr<Semaphore> semaphore = g_handle_table.Get<Semaphore>(handle); | ||||
|     SharedPtr<Semaphore> semaphore = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Semaphore>( | ||||
|             handle); | ||||
|     if (semaphore == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -917,7 +955,9 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) | |||
| /// Query process memory
 | ||||
| static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, | ||||
|                                      Handle process_handle, u32 addr) { | ||||
|     SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); | ||||
|     SharedPtr<Process> process = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>( | ||||
|             process_handle); | ||||
|     if (process == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -943,9 +983,10 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32 | |||
| 
 | ||||
| /// Create an event
 | ||||
| static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { | ||||
|     SharedPtr<Event> evt = Core::System::GetInstance().Kernel().CreateEvent( | ||||
|         static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", Core::CPU().GetReg(14))); | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(evt))); | ||||
|     KernelSystem& kernel = Core::System::GetInstance().Kernel(); | ||||
|     SharedPtr<Event> evt = kernel.CreateEvent(static_cast<ResetType>(reset_type), | ||||
|                                               fmt::format("event-{:08x}", Core::CPU().GetReg(14))); | ||||
|     CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(evt))); | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, | ||||
|               *out_handle); | ||||
|  | @ -954,7 +995,9 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { | |||
| 
 | ||||
| /// Duplicates a kernel handle
 | ||||
| static ResultCode DuplicateHandle(Handle* out, Handle handle) { | ||||
|     CASCADE_RESULT(*out, g_handle_table.Duplicate(handle)); | ||||
|     CASCADE_RESULT( | ||||
|         *out, | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Duplicate(handle)); | ||||
|     LOG_TRACE(Kernel_SVC, "duplicated 0x{:08X} to 0x{:08X}", handle, *out); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | @ -963,7 +1006,8 @@ static ResultCode DuplicateHandle(Handle* out, Handle handle) { | |||
| static ResultCode SignalEvent(Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle); | ||||
| 
 | ||||
|     SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); | ||||
|     SharedPtr<Event> evt = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Event>(handle); | ||||
|     if (evt == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -976,7 +1020,8 @@ static ResultCode SignalEvent(Handle handle) { | |||
| static ResultCode ClearEvent(Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle); | ||||
| 
 | ||||
|     SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); | ||||
|     SharedPtr<Event> evt = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Event>(handle); | ||||
|     if (evt == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -986,9 +1031,10 @@ static ResultCode ClearEvent(Handle handle) { | |||
| 
 | ||||
| /// Creates a timer
 | ||||
| static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { | ||||
|     SharedPtr<Timer> timer = Core::System::GetInstance().Kernel().CreateTimer( | ||||
|     KernelSystem& kernel = Core::System::GetInstance().Kernel(); | ||||
|     SharedPtr<Timer> timer = kernel.CreateTimer( | ||||
|         static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", Core::CPU().GetReg(14))); | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(timer))); | ||||
|     CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(timer))); | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, | ||||
|               *out_handle); | ||||
|  | @ -999,7 +1045,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { | |||
| static ResultCode ClearTimer(Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle); | ||||
| 
 | ||||
|     SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle); | ||||
|     SharedPtr<Timer> timer = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle); | ||||
|     if (timer == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -1015,7 +1062,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { | |||
|         return ERR_OUT_OF_RANGE_KERNEL; | ||||
|     } | ||||
| 
 | ||||
|     SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle); | ||||
|     SharedPtr<Timer> timer = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle); | ||||
|     if (timer == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -1028,7 +1076,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { | |||
| static ResultCode CancelTimer(Handle handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle); | ||||
| 
 | ||||
|     SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle); | ||||
|     SharedPtr<Timer> timer = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle); | ||||
|     if (timer == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -1097,18 +1146,20 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 | |||
|         return ERR_INVALID_ADDRESS; | ||||
|     } | ||||
| 
 | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
| 
 | ||||
|     // When trying to create a memory block with address = 0,
 | ||||
|     // if the process has the Shared Device Memory flag in the exheader,
 | ||||
|     // then we have to allocate from the same region as the caller process instead of the BASE
 | ||||
|     // region.
 | ||||
|     MemoryRegion region = MemoryRegion::BASE; | ||||
|     if (addr == 0 && g_current_process->flags.shared_device_mem) | ||||
|         region = g_current_process->flags.memory_region; | ||||
|     if (addr == 0 && current_process->flags.shared_device_mem) | ||||
|         region = current_process->flags.memory_region; | ||||
| 
 | ||||
|     shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory( | ||||
|         g_current_process, size, static_cast<MemoryPermission>(my_permission), | ||||
|         current_process.get(), size, static_cast<MemoryPermission>(my_permission), | ||||
|         static_cast<MemoryPermission>(other_permission), addr, region); | ||||
|     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(shared_memory))); | ||||
|     CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(shared_memory))); | ||||
| 
 | ||||
|     LOG_WARNING(Kernel_SVC, "called addr=0x{:08X}", addr); | ||||
|     return RESULT_SUCCESS; | ||||
|  | @ -1119,48 +1170,58 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr nam | |||
|     // TODO(Subv): Implement named ports.
 | ||||
|     ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented"); | ||||
| 
 | ||||
|     auto ports = Core::System::GetInstance().Kernel().CreatePortPair(max_sessions); | ||||
|     CASCADE_RESULT(*client_port, | ||||
|                    g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); | ||||
|     KernelSystem& kernel = Core::System::GetInstance().Kernel(); | ||||
|     SharedPtr<Process> current_process = kernel.GetCurrentProcess(); | ||||
| 
 | ||||
|     auto ports = kernel.CreatePortPair(max_sessions); | ||||
|     CASCADE_RESULT(*client_port, current_process->handle_table.Create( | ||||
|                                      std::move(std::get<SharedPtr<ClientPort>>(ports)))); | ||||
|     // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
 | ||||
|     // created.
 | ||||
|     CASCADE_RESULT(*server_port, | ||||
|                    g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); | ||||
|     CASCADE_RESULT(*server_port, current_process->handle_table.Create( | ||||
|                                      std::move(std::get<SharedPtr<ServerPort>>(ports)))); | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static ResultCode CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) { | ||||
|     SharedPtr<ClientPort> client_port = g_handle_table.Get<ClientPort>(client_port_handle); | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     SharedPtr<ClientPort> client_port = | ||||
|         current_process->handle_table.Get<ClientPort>(client_port_handle); | ||||
|     if (client_port == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|     CASCADE_RESULT(auto session, client_port->Connect()); | ||||
|     CASCADE_RESULT(*out_client_session, g_handle_table.Create(std::move(session))); | ||||
|     CASCADE_RESULT(*out_client_session, current_process->handle_table.Create(std::move(session))); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static ResultCode CreateSession(Handle* server_session, Handle* client_session) { | ||||
|     auto sessions = Core::System::GetInstance().Kernel().CreateSessionPair(); | ||||
|     KernelSystem& kernel = Core::System::GetInstance().Kernel(); | ||||
|     auto sessions = kernel.CreateSessionPair(); | ||||
| 
 | ||||
|     SharedPtr<Process> current_process = kernel.GetCurrentProcess(); | ||||
| 
 | ||||
|     auto& server = std::get<SharedPtr<ServerSession>>(sessions); | ||||
|     CASCADE_RESULT(*server_session, g_handle_table.Create(std::move(server))); | ||||
|     CASCADE_RESULT(*server_session, current_process->handle_table.Create(std::move(server))); | ||||
| 
 | ||||
|     auto& client = std::get<SharedPtr<ClientSession>>(sessions); | ||||
|     CASCADE_RESULT(*client_session, g_handle_table.Create(std::move(client))); | ||||
|     CASCADE_RESULT(*client_session, current_process->handle_table.Create(std::move(client))); | ||||
| 
 | ||||
|     LOG_TRACE(Kernel_SVC, "called"); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static ResultCode AcceptSession(Handle* out_server_session, Handle server_port_handle) { | ||||
|     SharedPtr<ServerPort> server_port = g_handle_table.Get<ServerPort>(server_port_handle); | ||||
|     SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     SharedPtr<ServerPort> server_port = | ||||
|         current_process->handle_table.Get<ServerPort>(server_port_handle); | ||||
|     if (server_port == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|     CASCADE_RESULT(auto session, server_port->Accept()); | ||||
|     CASCADE_RESULT(*out_server_session, g_handle_table.Create(std::move(session))); | ||||
|     CASCADE_RESULT(*out_server_session, current_process->handle_table.Create(std::move(session))); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
|  | @ -1210,7 +1271,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) { | |||
| static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { | ||||
|     LOG_TRACE(Kernel_SVC, "called process=0x{:08X} type={}", process_handle, type); | ||||
| 
 | ||||
|     SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); | ||||
|     SharedPtr<Process> process = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>( | ||||
|             process_handle); | ||||
|     if (process == nullptr) | ||||
|         return ERR_INVALID_HANDLE; | ||||
| 
 | ||||
|  | @ -1407,7 +1470,8 @@ void CallSVC(u32 immediate) { | |||
|     // Lock the global kernel mutex when we enter the kernel HLE.
 | ||||
|     std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||||
| 
 | ||||
|     ASSERT_MSG(g_current_process->status == ProcessStatus::Running, | ||||
|     DEBUG_ASSERT_MSG(Core::System::GetInstance().Kernel().GetCurrentProcess()->status == | ||||
|                          ProcessStatus::Running, | ||||
|                      "Running threads from exiting processes is unimplemented"); | ||||
| 
 | ||||
|     const FunctionDef* info = GetSVCInfo(immediate); | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #include <algorithm> | ||||
| #include <list> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
|  | @ -37,9 +38,7 @@ void Thread::Acquire(Thread* thread) { | |||
|     ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); | ||||
| } | ||||
| 
 | ||||
| // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
 | ||||
| //               us to simply use a pool index or similar.
 | ||||
| static Kernel::HandleTable wakeup_callback_handle_table; | ||||
| static std::unordered_map<u64, Thread*> wakeup_callback_table; | ||||
| 
 | ||||
| // Lists all thread ids that aren't deleted/etc.
 | ||||
| static std::vector<SharedPtr<Thread>> thread_list; | ||||
|  | @ -69,9 +68,8 @@ Thread* GetCurrentThread() { | |||
| 
 | ||||
| void Thread::Stop() { | ||||
|     // Cancel any outstanding wakeup events for this thread
 | ||||
|     CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); | ||||
|     wakeup_callback_handle_table.Close(callback_handle); | ||||
|     callback_handle = 0; | ||||
|     CoreTiming::UnscheduleEvent(ThreadWakeupEventType, thread_id); | ||||
|     wakeup_callback_table.erase(thread_id); | ||||
| 
 | ||||
|     // Clean up thread from ready queue
 | ||||
|     // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
 | ||||
|  | @ -96,7 +94,7 @@ void Thread::Stop() { | |||
|     u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; | ||||
|     u32 tls_slot = | ||||
|         ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; | ||||
|     Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot); | ||||
|     owner_process->tls_slots[tls_page].reset(tls_slot); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -125,9 +123,9 @@ static void SwitchContext(Thread* new_thread) { | |||
|                    "Thread must be ready to become running."); | ||||
| 
 | ||||
|         // Cancel any outstanding wakeup events for this thread
 | ||||
|         CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); | ||||
|         CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->thread_id); | ||||
| 
 | ||||
|         auto previous_process = Kernel::g_current_process; | ||||
|         auto previous_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
| 
 | ||||
|         current_thread = new_thread; | ||||
| 
 | ||||
|  | @ -135,8 +133,8 @@ static void SwitchContext(Thread* new_thread) { | |||
|         new_thread->status = ThreadStatus::Running; | ||||
| 
 | ||||
|         if (previous_process != current_thread->owner_process) { | ||||
|             Kernel::g_current_process = current_thread->owner_process; | ||||
|             SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); | ||||
|             Core::System::GetInstance().Kernel().SetCurrentProcess(current_thread->owner_process); | ||||
|             SetCurrentPageTable(¤t_thread->owner_process->vm_manager.page_table); | ||||
|         } | ||||
| 
 | ||||
|         Core::CPU().LoadContext(new_thread->context); | ||||
|  | @ -185,13 +183,13 @@ void ExitCurrentThread() { | |||
| 
 | ||||
| /**
 | ||||
|  * Callback that will wake up the thread it was scheduled for | ||||
|  * @param thread_handle The handle of the thread that's been awoken | ||||
|  * @param thread_id The ID of the thread that's been awoken | ||||
|  * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time | ||||
|  */ | ||||
| static void ThreadWakeupCallback(u64 thread_handle, s64 cycles_late) { | ||||
|     SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle); | ||||
| static void ThreadWakeupCallback(u64 thread_id, s64 cycles_late) { | ||||
|     SharedPtr<Thread> thread = wakeup_callback_table.at(thread_id); | ||||
|     if (thread == nullptr) { | ||||
|         LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", (Handle)thread_handle); | ||||
|         LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", thread_id); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -217,7 +215,7 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { | |||
|     if (nanoseconds == -1) | ||||
|         return; | ||||
| 
 | ||||
|     CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle); | ||||
|     CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, thread_id); | ||||
| } | ||||
| 
 | ||||
| void Thread::ResumeFromWait() { | ||||
|  | @ -322,8 +320,7 @@ static void ResetThreadContext(const std::unique_ptr<ARM_Interface::ThreadContex | |||
| 
 | ||||
| ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point, | ||||
|                                                         u32 priority, u32 arg, s32 processor_id, | ||||
|                                                         VAddr stack_top, | ||||
|                                                         SharedPtr<Process> owner_process) { | ||||
|                                                         VAddr stack_top, Process& owner_process) { | ||||
|     // Check if priority is in ranged. Lowest priority -> highest priority id.
 | ||||
|     if (priority > ThreadPrioLowest) { | ||||
|         LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority); | ||||
|  | @ -337,7 +334,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr | |||
| 
 | ||||
|     // TODO(yuriks): Other checks, returning 0xD9001BEA
 | ||||
| 
 | ||||
|     if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) { | ||||
|     if (!Memory::IsValidVirtualAddress(owner_process, entry_point)) { | ||||
|         LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:08x}", name, entry_point); | ||||
|         // TODO: Verify error
 | ||||
|         return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | ||||
|  | @ -359,11 +356,11 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr | |||
|     thread->wait_objects.clear(); | ||||
|     thread->wait_address = 0; | ||||
|     thread->name = std::move(name); | ||||
|     thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); | ||||
|     thread->owner_process = owner_process; | ||||
|     wakeup_callback_table[thread->thread_id] = thread.get(); | ||||
|     thread->owner_process = &owner_process; | ||||
| 
 | ||||
|     // Find the next available TLS index, and mark it as used
 | ||||
|     auto& tls_slots = owner_process->tls_slots; | ||||
|     auto& tls_slots = owner_process.tls_slots; | ||||
| 
 | ||||
|     auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots); | ||||
| 
 | ||||
|  | @ -384,13 +381,13 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr | |||
|         // Allocate some memory from the end of the linear heap for this region.
 | ||||
|         linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0); | ||||
|         memory_region->used += Memory::PAGE_SIZE; | ||||
|         owner_process->linear_heap_used += Memory::PAGE_SIZE; | ||||
|         owner_process.linear_heap_used += Memory::PAGE_SIZE; | ||||
| 
 | ||||
|         tls_slots.emplace_back(0); // The page is completely available at the start
 | ||||
|         available_page = tls_slots.size() - 1; | ||||
|         available_slot = 0; // Use the first slot in the new page
 | ||||
| 
 | ||||
|         auto& vm_manager = owner_process->vm_manager; | ||||
|         auto& vm_manager = owner_process.vm_manager; | ||||
|         vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | ||||
| 
 | ||||
|         // Map the page to the current process' address space.
 | ||||
|  | @ -449,7 +446,7 @@ SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 pri | |||
|     // Initialize new "main" thread
 | ||||
|     auto thread_res = | ||||
|         kernel.CreateThread("main", entry_point, priority, 0, owner_process->ideal_processor, | ||||
|                             Memory::HEAP_VADDR_END, owner_process); | ||||
|                             Memory::HEAP_VADDR_END, *owner_process); | ||||
| 
 | ||||
|     SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); | ||||
| 
 | ||||
|  | @ -516,7 +513,6 @@ void ThreadingShutdown() { | |||
|     } | ||||
|     thread_list.clear(); | ||||
|     ready_queue.clear(); | ||||
|     ClearProcessList(); | ||||
| } | ||||
| 
 | ||||
| const std::vector<SharedPtr<Thread>>& GetThreadList() { | ||||
|  |  | |||
|  | @ -189,7 +189,7 @@ public: | |||
|     /// Mutexes that this thread is currently waiting for.
 | ||||
|     boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes; | ||||
| 
 | ||||
|     SharedPtr<Process> owner_process; ///< Process that owns this thread
 | ||||
|     Process* owner_process; ///< Process that owns this thread
 | ||||
| 
 | ||||
|     /// Objects that the thread is waiting on, in the same order as they were
 | ||||
|     // passed to WaitSynchronization1/N.
 | ||||
|  | @ -199,9 +199,6 @@ public: | |||
| 
 | ||||
|     std::string name; | ||||
| 
 | ||||
|     /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
 | ||||
|     Handle callback_handle; | ||||
| 
 | ||||
|     using WakeupCallback = void(ThreadWakeupReason reason, SharedPtr<Thread> thread, | ||||
|                                 SharedPtr<WaitObject> object); | ||||
|     // Callback that will be invoked when the thread is resumed from a waiting state. If the thread
 | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <cinttypes> | ||||
| #include <unordered_map> | ||||
| #include "common/assert.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core_timing.h" | ||||
|  | @ -15,12 +16,15 @@ namespace Kernel { | |||
| 
 | ||||
| /// The event type of the generic timer callback event
 | ||||
| static CoreTiming::EventType* timer_callback_event_type = nullptr; | ||||
| // TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
 | ||||
| //               us to simply use a pool index or similar.
 | ||||
| static Kernel::HandleTable timer_callback_handle_table; | ||||
| 
 | ||||
| static u64 next_timer_callback_id; | ||||
| static std::unordered_map<u64, Timer*> timer_callback_table; | ||||
| 
 | ||||
| Timer::Timer(KernelSystem& kernel) : WaitObject(kernel) {} | ||||
| Timer::~Timer() {} | ||||
| Timer::~Timer() { | ||||
|     Cancel(); | ||||
|     timer_callback_table.erase(callback_id); | ||||
| } | ||||
| 
 | ||||
| SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) { | ||||
|     SharedPtr<Timer> timer(new Timer(*this)); | ||||
|  | @ -30,7 +34,8 @@ SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string nam | |||
|     timer->name = std::move(name); | ||||
|     timer->initial_delay = 0; | ||||
|     timer->interval_delay = 0; | ||||
|     timer->callback_handle = timer_callback_handle_table.Create(timer).Unwrap(); | ||||
|     timer->callback_id = ++next_timer_callback_id; | ||||
|     timer_callback_table[timer->callback_id] = timer.get(); | ||||
| 
 | ||||
|     return timer; | ||||
| } | ||||
|  | @ -57,12 +62,12 @@ void Timer::Set(s64 initial, s64 interval) { | |||
|         // Immediately invoke the callback
 | ||||
|         Signal(0); | ||||
|     } else { | ||||
|         CoreTiming::ScheduleEvent(nsToCycles(initial), timer_callback_event_type, callback_handle); | ||||
|         CoreTiming::ScheduleEvent(nsToCycles(initial), timer_callback_event_type, callback_id); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Timer::Cancel() { | ||||
|     CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle); | ||||
|     CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_id); | ||||
| } | ||||
| 
 | ||||
| void Timer::Clear() { | ||||
|  | @ -87,17 +92,16 @@ void Timer::Signal(s64 cycles_late) { | |||
|     if (interval_delay != 0) { | ||||
|         // Reschedule the timer with the interval delay
 | ||||
|         CoreTiming::ScheduleEvent(nsToCycles(interval_delay) - cycles_late, | ||||
|                                   timer_callback_event_type, callback_handle); | ||||
|                                   timer_callback_event_type, callback_id); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The timer callback event, called when a timer is fired
 | ||||
| static void TimerCallback(u64 timer_handle, s64 cycles_late) { | ||||
|     SharedPtr<Timer> timer = | ||||
|         timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); | ||||
| static void TimerCallback(u64 callback_id, s64 cycles_late) { | ||||
|     SharedPtr<Timer> timer = timer_callback_table.at(callback_id); | ||||
| 
 | ||||
|     if (timer == nullptr) { | ||||
|         LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:08x}", timer_handle); | ||||
|         LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016x}", callback_id); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -105,7 +109,8 @@ static void TimerCallback(u64 timer_handle, s64 cycles_late) { | |||
| } | ||||
| 
 | ||||
| void TimersInit() { | ||||
|     timer_callback_handle_table.Clear(); | ||||
|     next_timer_callback_id = 0; | ||||
|     timer_callback_table.clear(); | ||||
|     timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -71,8 +71,8 @@ private: | |||
|     bool signaled;    ///< Whether the timer has been signaled or not
 | ||||
|     std::string name; ///< Name of timer (optional)
 | ||||
| 
 | ||||
|     /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
 | ||||
|     Handle callback_handle; | ||||
|     /// ID used as userdata to reference this object when inserting into the CoreTiming queue.
 | ||||
|     u64 callback_id; | ||||
| 
 | ||||
|     friend class KernelSystem; | ||||
| }; | ||||
|  |  | |||
|  | @ -258,7 +258,7 @@ ResultVal<AppletManager::InitializeResult> AppletManager::Initialize(AppletId ap | |||
|     slot_data->applet_id = static_cast<AppletId>(app_id); | ||||
|     // Note: In the real console the title id of a given applet slot is set by the APT module when
 | ||||
|     // calling StartApplication.
 | ||||
|     slot_data->title_id = Kernel::g_current_process->codeset->program_id; | ||||
|     slot_data->title_id = system.Kernel().GetCurrentProcess()->codeset->program_id; | ||||
|     slot_data->attributes.raw = attributes.raw; | ||||
| 
 | ||||
|     if (slot_data->applet_id == AppletId::Application || | ||||
|  |  | |||
|  | @ -97,7 +97,7 @@ void Module::Interface::Open(Kernel::HLERequestContext& ctx) { | |||
| 
 | ||||
|         if (path_type == CecDataPathType::MboxProgramId) { | ||||
|             std::vector<u8> program_id(8); | ||||
|             u64_le le_program_id = Kernel::g_current_process->codeset->program_id; | ||||
|             u64_le le_program_id = cecd->system.Kernel().GetCurrentProcess()->codeset->program_id; | ||||
|             std::memcpy(program_id.data(), &le_program_id, sizeof(u64)); | ||||
|             session_data->file->Write(0, sizeof(u64), true, program_id.data()); | ||||
|             session_data->file->Close(); | ||||
|  | @ -1351,7 +1351,7 @@ Module::SessionData::~SessionData() { | |||
| Module::Interface::Interface(std::shared_ptr<Module> cecd, const char* name, u32 max_session) | ||||
|     : ServiceFramework(name, max_session), cecd(std::move(cecd)) {} | ||||
| 
 | ||||
| Module::Module(Core::System& system) { | ||||
| Module::Module(Core::System& system) : system(system) { | ||||
|     using namespace Kernel; | ||||
|     cecinfo_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "CECD::cecinfo_event"); | ||||
|     change_state_event = | ||||
|  |  | |||
|  | @ -610,6 +610,8 @@ private: | |||
| 
 | ||||
|     Kernel::SharedPtr<Kernel::Event> cecinfo_event; | ||||
|     Kernel::SharedPtr<Kernel::Event> change_state_event; | ||||
| 
 | ||||
|     Core::System& system; | ||||
| }; | ||||
| 
 | ||||
| /// Initialize CECD service(s)
 | ||||
|  |  | |||
|  | @ -619,7 +619,7 @@ void FS_USER::GetProgramLaunchInfo(Kernel::HLERequestContext& ctx) { | |||
| 
 | ||||
|     // TODO(Subv): The real FS service manages its own process list and only checks the processes
 | ||||
|     // that were registered with the 'fs:REG' service.
 | ||||
|     auto process = Kernel::GetProcessById(process_id); | ||||
|     auto process = system.Kernel().GetProcessById(process_id); | ||||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); | ||||
| 
 | ||||
|  |  | |||
|  | @ -188,11 +188,13 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses | |||
|         return ReportUnimplementedFunction(cmd_buf, info); | ||||
|     } | ||||
| 
 | ||||
|     Kernel::SharedPtr<Kernel::Process> current_process = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
| 
 | ||||
|     // TODO(yuriks): The kernel should be the one handling this as part of translation after
 | ||||
|     // everything else is migrated
 | ||||
|     Kernel::HLERequestContext context(std::move(server_session)); | ||||
|     context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process, | ||||
|                                               Kernel::g_handle_table); | ||||
|     context.PopulateFromIncomingCommandBuffer(cmd_buf, *current_process); | ||||
| 
 | ||||
|     LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf)); | ||||
|     handler_invoker(this, info->handler_callback, context); | ||||
|  | @ -204,8 +206,7 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses | |||
|     // the thread to sleep then the writing of the command buffer will be deferred to the wakeup
 | ||||
|     // callback.
 | ||||
|     if (thread->status == Kernel::ThreadStatus::Running) { | ||||
|         context.WriteToOutgoingCommandBuffer(cmd_buf, *Kernel::g_current_process, | ||||
|                                              Kernel::g_handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -111,7 +111,7 @@ static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { | |||
|  * using a VMA from the current process. | ||||
|  */ | ||||
| static u8* GetPointerFromVMA(VAddr vaddr) { | ||||
|     return GetPointerFromVMA(*Kernel::g_current_process, vaddr); | ||||
|     return GetPointerFromVMA(*Core::System::GetInstance().Kernel().GetCurrentProcess(), vaddr); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -128,7 +128,8 @@ static MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr | |||
| } | ||||
| 
 | ||||
| static MMIORegionPointer GetMMIOHandler(VAddr vaddr) { | ||||
|     const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table; | ||||
|     const PageTable& page_table = | ||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->vm_manager.page_table; | ||||
|     return GetMMIOHandler(page_table, vaddr); | ||||
| } | ||||
| 
 | ||||
|  | @ -229,7 +230,7 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) { | |||
| } | ||||
| 
 | ||||
| bool IsValidVirtualAddress(const VAddr vaddr) { | ||||
|     return IsValidVirtualAddress(*Kernel::g_current_process, vaddr); | ||||
|     return IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), vaddr); | ||||
| } | ||||
| 
 | ||||
| bool IsValidPhysicalAddress(const PAddr paddr) { | ||||
|  | @ -524,7 +525,8 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_ | |||
| } | ||||
| 
 | ||||
| void ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) { | ||||
|     ReadBlock(*Kernel::g_current_process, src_addr, dest_buffer, size); | ||||
|     ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), src_addr, dest_buffer, | ||||
|               size); | ||||
| } | ||||
| 
 | ||||
| void Write8(const VAddr addr, const u8 data) { | ||||
|  | @ -592,7 +594,8 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi | |||
| } | ||||
| 
 | ||||
| void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { | ||||
|     WriteBlock(*Kernel::g_current_process, dest_addr, src_buffer, size); | ||||
|     WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, src_buffer, | ||||
|                size); | ||||
| } | ||||
| 
 | ||||
| void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | ||||
|  | @ -644,7 +647,7 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std: | |||
| } | ||||
| 
 | ||||
| void ZeroBlock(const VAddr dest_addr, const std::size_t size) { | ||||
|     ZeroBlock(*Kernel::g_current_process, dest_addr, size); | ||||
|     ZeroBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, size); | ||||
| } | ||||
| 
 | ||||
| void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||||
|  | @ -699,7 +702,7 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | |||
| } | ||||
| 
 | ||||
| void CopyBlock(VAddr dest_addr, VAddr src_addr, const std::size_t size) { | ||||
|     CopyBlock(*Kernel::g_current_process, dest_addr, src_addr, size); | ||||
|     CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, src_addr, size); | ||||
| } | ||||
| 
 | ||||
| template <> | ||||
|  | @ -778,7 +781,8 @@ std::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) { | |||
|     } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { | ||||
|         return addr - VRAM_PADDR + VRAM_VADDR; | ||||
|     } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { | ||||
|         return addr - FCRAM_PADDR + Kernel::g_current_process->GetLinearHeapAreaAddress(); | ||||
|         return addr - FCRAM_PADDR + | ||||
|                Core::System::GetInstance().Kernel().GetCurrentProcess()->GetLinearHeapAreaAddress(); | ||||
|     } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { | ||||
|         return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; | ||||
|     } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { | ||||
|  |  | |||
|  | @ -17,10 +17,14 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) | |||
|     : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { | ||||
| 
 | ||||
|     CoreTiming::Init(); | ||||
|     kernel = std::make_unique<Kernel::KernelSystem>(0); | ||||
|     // HACK: some memory functions are currently referring kernel from the global instance,
 | ||||
|     //       so we need to create the kernel object there.
 | ||||
|     //       Change this when all global states are eliminated.
 | ||||
|     Core::System::GetInstance().kernel = std::make_unique<Kernel::KernelSystem>(0); | ||||
|     kernel = Core::System::GetInstance().kernel.get(); | ||||
| 
 | ||||
|     Kernel::g_current_process = kernel->CreateProcess(kernel->CreateCodeSet("", 0)); | ||||
|     page_table = &Kernel::g_current_process->vm_manager.page_table; | ||||
|     kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0))); | ||||
|     page_table = &kernel->GetCurrentProcess()->vm_manager.page_table; | ||||
| 
 | ||||
|     page_table->pointers.fill(nullptr); | ||||
|     page_table->attributes.fill(Memory::PageType::Unmapped); | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ private: | |||
|     std::shared_ptr<TestMemory> test_memory; | ||||
|     std::vector<WriteRecord> write_records; | ||||
| 
 | ||||
|     std::unique_ptr<Kernel::KernelSystem> kernel; | ||||
|     Kernel::KernelSystem* kernel; | ||||
| }; | ||||
| 
 | ||||
| } // namespace ArmTests
 | ||||
|  |  | |||
|  | @ -26,14 +26,13 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|     HLERequestContext context(std::move(session)); | ||||
| 
 | ||||
|     auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); | ||||
|     HandleTable handle_table; | ||||
| 
 | ||||
|     SECTION("works with empty cmdbuf") { | ||||
|         const u32_le input[]{ | ||||
|             IPC::MakeHeader(0x1234, 0, 0), | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         REQUIRE(context.CommandBuffer()[0] == 0x12340000); | ||||
|     } | ||||
|  | @ -46,7 +45,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|             0xAABBCCDD, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         auto* output = context.CommandBuffer(); | ||||
|         REQUIRE(output[1] == 0x12345678); | ||||
|  | @ -56,34 +55,34 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
| 
 | ||||
|     SECTION("translates move handles") { | ||||
|         auto a = MakeObject(kernel); | ||||
|         Handle a_handle = handle_table.Create(a).Unwrap(); | ||||
|         Handle a_handle = process->handle_table.Create(a).Unwrap(); | ||||
|         const u32_le input[]{ | ||||
|             IPC::MakeHeader(0, 0, 2), | ||||
|             IPC::MoveHandleDesc(1), | ||||
|             a_handle, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         auto* output = context.CommandBuffer(); | ||||
|         REQUIRE(context.GetIncomingHandle(output[2]) == a); | ||||
|         REQUIRE(handle_table.GetGeneric(a_handle) == nullptr); | ||||
|         REQUIRE(process->handle_table.GetGeneric(a_handle) == nullptr); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("translates copy handles") { | ||||
|         auto a = MakeObject(kernel); | ||||
|         Handle a_handle = handle_table.Create(a).Unwrap(); | ||||
|         Handle a_handle = process->handle_table.Create(a).Unwrap(); | ||||
|         const u32_le input[]{ | ||||
|             IPC::MakeHeader(0, 0, 2), | ||||
|             IPC::CopyHandleDesc(1), | ||||
|             a_handle, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         auto* output = context.CommandBuffer(); | ||||
|         REQUIRE(context.GetIncomingHandle(output[2]) == a); | ||||
|         REQUIRE(handle_table.GetGeneric(a_handle) == a); | ||||
|         REQUIRE(process->handle_table.GetGeneric(a_handle) == a); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("translates multi-handle descriptors") { | ||||
|  | @ -91,12 +90,15 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|         auto b = MakeObject(kernel); | ||||
|         auto c = MakeObject(kernel); | ||||
|         const u32_le input[]{ | ||||
|             IPC::MakeHeader(0, 0, 5),        IPC::MoveHandleDesc(2), | ||||
|             handle_table.Create(a).Unwrap(), handle_table.Create(b).Unwrap(), | ||||
|             IPC::MoveHandleDesc(1),          handle_table.Create(c).Unwrap(), | ||||
|             IPC::MakeHeader(0, 0, 5), | ||||
|             IPC::MoveHandleDesc(2), | ||||
|             process->handle_table.Create(a).Unwrap(), | ||||
|             process->handle_table.Create(b).Unwrap(), | ||||
|             IPC::MoveHandleDesc(1), | ||||
|             process->handle_table.Create(c).Unwrap(), | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         auto* output = context.CommandBuffer(); | ||||
|         REQUIRE(context.GetIncomingHandle(output[2]) == a); | ||||
|  | @ -111,7 +113,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|             0, | ||||
|         }; | ||||
| 
 | ||||
|         auto result = context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         auto result = context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         REQUIRE(result == RESULT_SUCCESS); | ||||
|         auto* output = context.CommandBuffer(); | ||||
|  | @ -125,7 +127,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|             0x98989898, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         REQUIRE(context.CommandBuffer()[2] == process->process_id); | ||||
|     } | ||||
|  | @ -145,7 +147,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|             target_address, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         CHECK(context.GetStaticBuffer(0) == *buffer); | ||||
| 
 | ||||
|  | @ -166,7 +168,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|             target_address, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         std::vector<u8> other_buffer(buffer->size()); | ||||
|         context.GetMappedBuffer(0).Read(other_buffer.data(), 0, buffer->size()); | ||||
|  | @ -199,7 +201,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|             0x12345678, | ||||
|             0xABCDEF00, | ||||
|             IPC::MoveHandleDesc(1), | ||||
|             handle_table.Create(a).Unwrap(), | ||||
|             process->handle_table.Create(a).Unwrap(), | ||||
|             IPC::CallingPidDesc(), | ||||
|             0, | ||||
|             IPC::StaticBufferDesc(buffer_static->size(), 0), | ||||
|  | @ -208,7 +210,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|             target_address_mapped, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input, *process); | ||||
| 
 | ||||
|         auto* output = context.CommandBuffer(); | ||||
|         CHECK(output[1] == 0x12345678); | ||||
|  | @ -236,14 +238,13 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|     HLERequestContext context(std::move(session)); | ||||
| 
 | ||||
|     auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); | ||||
|     HandleTable handle_table; | ||||
|     auto* input = context.CommandBuffer(); | ||||
|     u32_le output[IPC::COMMAND_BUFFER_LENGTH]; | ||||
| 
 | ||||
|     SECTION("works with empty cmdbuf") { | ||||
|         input[0] = IPC::MakeHeader(0x1234, 0, 0); | ||||
| 
 | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process, handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process); | ||||
| 
 | ||||
|         REQUIRE(output[0] == 0x12340000); | ||||
|     } | ||||
|  | @ -254,7 +255,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|         input[2] = 0x21122112; | ||||
|         input[3] = 0xAABBCCDD; | ||||
| 
 | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process, handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process); | ||||
| 
 | ||||
|         REQUIRE(output[1] == 0x12345678); | ||||
|         REQUIRE(output[2] == 0x21122112); | ||||
|  | @ -270,10 +271,10 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|         input[3] = IPC::CopyHandleDesc(1); | ||||
|         input[4] = context.AddOutgoingHandle(b); | ||||
| 
 | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process, handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process); | ||||
| 
 | ||||
|         REQUIRE(handle_table.GetGeneric(output[2]) == a); | ||||
|         REQUIRE(handle_table.GetGeneric(output[4]) == b); | ||||
|         REQUIRE(process->handle_table.GetGeneric(output[2]) == a); | ||||
|         REQUIRE(process->handle_table.GetGeneric(output[4]) == b); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("translates null handles") { | ||||
|  | @ -281,7 +282,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|         input[1] = IPC::MoveHandleDesc(1); | ||||
|         input[2] = context.AddOutgoingHandle(nullptr); | ||||
| 
 | ||||
|         auto result = context.WriteToOutgoingCommandBuffer(output, *process, handle_table); | ||||
|         auto result = context.WriteToOutgoingCommandBuffer(output, *process); | ||||
| 
 | ||||
|         REQUIRE(result == RESULT_SUCCESS); | ||||
|         REQUIRE(output[2] == 0); | ||||
|  | @ -298,11 +299,11 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|         input[4] = IPC::CopyHandleDesc(1); | ||||
|         input[5] = context.AddOutgoingHandle(c); | ||||
| 
 | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process, handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process); | ||||
| 
 | ||||
|         REQUIRE(handle_table.GetGeneric(output[2]) == a); | ||||
|         REQUIRE(handle_table.GetGeneric(output[3]) == b); | ||||
|         REQUIRE(handle_table.GetGeneric(output[5]) == c); | ||||
|         REQUIRE(process->handle_table.GetGeneric(output[2]) == a); | ||||
|         REQUIRE(process->handle_table.GetGeneric(output[3]) == b); | ||||
|         REQUIRE(process->handle_table.GetGeneric(output[5]) == c); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("translates StaticBuffer descriptors") { | ||||
|  | @ -329,7 +330,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|             IPC::StaticBufferDesc(output_buffer->size(), 0); | ||||
|         output_cmdbuff[IPC::COMMAND_BUFFER_LENGTH + 1] = target_address; | ||||
| 
 | ||||
|         context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process, handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process); | ||||
| 
 | ||||
|         CHECK(*output_buffer == input_buffer); | ||||
|         REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer->size()) == | ||||
|  | @ -352,7 +353,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|             target_address, | ||||
|         }; | ||||
| 
 | ||||
|         context.PopulateFromIncomingCommandBuffer(input_cmdbuff, *process, handle_table); | ||||
|         context.PopulateFromIncomingCommandBuffer(input_cmdbuff, *process); | ||||
| 
 | ||||
|         context.GetMappedBuffer(0).Write(input_buffer.data(), 0, input_buffer.size()); | ||||
| 
 | ||||
|  | @ -360,7 +361,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
|         input[1] = IPC::MappedBufferDesc(output_buffer->size(), IPC::W); | ||||
|         input[2] = 0; | ||||
| 
 | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process, handle_table); | ||||
|         context.WriteToOutgoingCommandBuffer(output, *process); | ||||
| 
 | ||||
|         CHECK(output[1] == IPC::MappedBufferDesc(output_buffer->size(), IPC::W)); | ||||
|         CHECK(output[2] == target_address); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue