diff options
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/object.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/readable_event.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 89 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 8 |
10 files changed, 88 insertions, 66 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index fe710eb6e..f3da525d6 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -43,7 +43,7 @@ void SessionRequestHandler::ClientDisconnected(const SharedPtr<ServerSession>& s } SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( - SharedPtr<Thread> thread, const std::string& reason, u64 timeout, WakeupCallback&& callback, + const std::string& reason, u64 timeout, WakeupCallback&& callback, SharedPtr<WritableEvent> writable_event) { // Put the client thread to sleep until the wait event is signaled or the timeout expires. thread->SetWakeupCallback([context = *this, callback]( @@ -58,7 +58,7 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( auto& kernel = Core::System::GetInstance().Kernel(); if (!writable_event) { // Create event if not provided - const auto pair = WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + const auto pair = WritableEvent::CreateEventPair(kernel, ResetType::Automatic, "HLE Pause Event: " + reason); writable_event = pair.writable; } @@ -76,8 +76,9 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( return writable_event; } -HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session) - : server_session(std::move(server_session)) { +HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session, + SharedPtr<Thread> thread) + : server_session(std::move(server_session)), thread(std::move(thread)) { cmd_buf[0] = 0; } diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 2bdd9f02c..ccf5e56aa 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -97,7 +97,7 @@ protected: */ class HLERequestContext { public: - explicit HLERequestContext(SharedPtr<ServerSession> session); + explicit HLERequestContext(SharedPtr<ServerSession> session, SharedPtr<Thread> thread); ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. @@ -119,7 +119,6 @@ public: /** * Puts the specified guest thread to sleep until the returned event is signaled or until the * specified timeout expires. - * @param thread Thread to be put to sleep. * @param reason Reason for pausing the thread, to be used for debugging purposes. * @param timeout Timeout in nanoseconds after which the thread will be awoken and the callback * invoked with a Timeout reason. @@ -130,8 +129,8 @@ public: * created. * @returns Event that when signaled will resume the thread and call the callback function. */ - SharedPtr<WritableEvent> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason, - u64 timeout, WakeupCallback&& callback, + SharedPtr<WritableEvent> SleepClientThread(const std::string& reason, u64 timeout, + WakeupCallback&& callback, SharedPtr<WritableEvent> writable_event = nullptr); /// Populates this context with data from the requesting process/thread. @@ -268,6 +267,7 @@ private: std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; SharedPtr<Kernel::ServerSession> server_session; + SharedPtr<Thread> thread; // TODO(yuriks): Check common usage of this and optimize size accordingly boost::container::small_vector<SharedPtr<Object>, 8> move_objects; boost::container::small_vector<SharedPtr<Object>, 8> copy_objects; diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 332876c27..2821176a7 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h @@ -33,8 +33,8 @@ enum class HandleType : u32 { }; enum class ResetType { - OneShot, ///< Reset automatically on object acquisition - Sticky, ///< Never reset automatically + Automatic, ///< Reset automatically on object acquisition + Manual, ///< Never reset automatically }; class Object : NonCopyable { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 20d01fc88..0775a89fb 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -241,7 +241,8 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) { } Process::Process(Core::System& system) - : WaitObject{system.Kernel()}, address_arbiter{system}, mutex{system}, system{system} {} + : WaitObject{system.Kernel()}, vm_manager{system}, + address_arbiter{system}, mutex{system}, system{system} {} Process::~Process() = default; diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp index c2b798a4e..06463cd26 100644 --- a/src/core/hle/kernel/readable_event.cpp +++ b/src/core/hle/kernel/readable_event.cpp @@ -21,8 +21,9 @@ bool ReadableEvent::ShouldWait(const Thread* thread) const { void ReadableEvent::Acquire(Thread* thread) { ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); - if (reset_type == ResetType::OneShot) + if (reset_type == ResetType::Automatic) { signaled = false; + } } void ReadableEvent::Signal() { diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 696a82cd9..30b2bfb5a 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -130,7 +130,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { // The ServerSession received a sync request, this means that there's new data available // from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or // similar. - Kernel::HLERequestContext context(this); + Kernel::HLERequestContext context(this, thread); u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress()); context.PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 2dcf174c5..5a5851f66 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1255,8 +1255,8 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand return vm_manager.MapCodeMemory(dst_address, src_address, size); } -ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address, - u64 src_address, u64 size) { +static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, + u64 dst_address, u64 src_address, u64 size) { LOG_DEBUG(Kernel_SVC, "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, " "size=0x{:016X}", @@ -1342,7 +1342,7 @@ static void ExitProcess(Core::System& system) { /// Creates a new thread static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top, u32 priority, s32 processor_id) { - LOG_TRACE(Kernel_SVC, + LOG_DEBUG(Kernel_SVC, "called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, " "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}", entry_point, arg, stack_top, priority, processor_id, *out_handle); @@ -1402,7 +1402,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e /// Starts the thread for the provided handle static ResultCode StartThread(Core::System& system, Handle thread_handle) { - LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); + LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); @@ -1425,7 +1425,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { /// Called when a thread exits static void ExitThread(Core::System& system) { - LOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); + LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); current_thread->Stop(); @@ -1435,7 +1435,7 @@ static void ExitThread(Core::System& system) { /// Sleep the current thread static void SleepThread(Core::System& system, s64 nanoseconds) { - LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); + LOG_DEBUG(Kernel_SVC, "called nanoseconds={}", nanoseconds); enum class SleepType : s64 { YieldWithoutLoadBalancing = 0, @@ -1880,52 +1880,59 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, } static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, - u64 mask) { - LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:016X}, core=0x{:X}", thread_handle, - mask, core); + u64 affinity_mask) { + LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}", + thread_handle, core, affinity_mask); - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", - thread_handle); - return ERR_INVALID_HANDLE; - } + const auto* const current_process = system.Kernel().CurrentProcess(); if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) { - const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore(); + const u8 ideal_cpu_core = current_process->GetIdealCore(); ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL)); // Set the target CPU to the ideal core specified by the process. core = ideal_cpu_core; - mask = 1ULL << core; - } - - if (mask == 0) { - LOG_ERROR(Kernel_SVC, "Mask is 0"); - return ERR_INVALID_COMBINATION; - } + affinity_mask = 1ULL << core; + } else { + const u64 core_mask = current_process->GetCoreMask(); + + if ((core_mask | affinity_mask) != core_mask) { + LOG_ERROR( + Kernel_SVC, + "Invalid processor ID specified (core_mask=0x{:08X}, affinity_mask=0x{:016X})", + core_mask, affinity_mask); + return ERR_INVALID_PROCESSOR_ID; + } - /// This value is used to only change the affinity mask without changing the current ideal core. - static constexpr u32 OnlyChangeMask = static_cast<u32>(-3); + if (affinity_mask == 0) { + LOG_ERROR(Kernel_SVC, "Specfified affinity mask is zero."); + return ERR_INVALID_COMBINATION; + } - if (core == OnlyChangeMask) { - core = thread->GetIdealCore(); - } else if (core >= Core::NUM_CPU_CORES && core != static_cast<u32>(-1)) { - LOG_ERROR(Kernel_SVC, "Invalid core specified, got {}", core); - return ERR_INVALID_PROCESSOR_ID; + if (core < Core::NUM_CPU_CORES) { + if ((affinity_mask & (1ULL << core)) == 0) { + LOG_ERROR(Kernel_SVC, + "Core is not enabled for the current mask, core={}, mask={:016X}", core, + affinity_mask); + return ERR_INVALID_COMBINATION; + } + } else if (core != static_cast<u32>(THREADPROCESSORID_DONT_CARE) && + core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) { + LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core); + return ERR_INVALID_PROCESSOR_ID; + } } - // Error out if the input core isn't enabled in the input mask. - if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) { - LOG_ERROR(Kernel_SVC, "Core is not enabled for the current mask, core={}, mask={:016X}", - core, mask); - return ERR_INVALID_COMBINATION; + const auto& handle_table = current_process->GetHandleTable(); + const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", + thread_handle); + return ERR_INVALID_HANDLE; } - thread->ChangeCore(core, mask); - + thread->ChangeCore(core, affinity_mask); return RESULT_SUCCESS; } @@ -1980,7 +1987,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle auto& kernel = system.Kernel(); const auto [readable_event, writable_event] = - WritableEvent::CreateEventPair(kernel, ResetType::Sticky, "CreateEvent"); + WritableEvent::CreateEventPair(kernel, ResetType::Manual, "CreateEvent"); HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); @@ -2183,8 +2190,8 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes, return RESULT_SUCCESS; } -ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids, - u32 out_thread_ids_size, Handle debug_handle) { +static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids, + u32 out_thread_ids_size, Handle debug_handle) { // TODO: Handle this case when debug events are supported. UNIMPLEMENTED_IF(debug_handle != InvalidHandle); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index f07332f02..b4b9cda7c 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -30,12 +30,21 @@ enum ThreadPriority : u32 { }; enum ThreadProcessorId : s32 { - THREADPROCESSORID_IDEAL = -2, ///< Run thread on the ideal core specified by the process. - THREADPROCESSORID_0 = 0, ///< Run thread on core 0 - THREADPROCESSORID_1 = 1, ///< Run thread on core 1 - THREADPROCESSORID_2 = 2, ///< Run thread on core 2 - THREADPROCESSORID_3 = 3, ///< Run thread on core 3 - THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this + /// Indicates that no particular processor core is preferred. + THREADPROCESSORID_DONT_CARE = -1, + + /// Run thread on the ideal core specified by the process. + THREADPROCESSORID_IDEAL = -2, + + /// Indicates that the preferred processor ID shouldn't be updated in + /// a core mask setting operation. + THREADPROCESSORID_DONT_UPDATE = -3, + + THREADPROCESSORID_0 = 0, ///< Run thread on core 0 + THREADPROCESSORID_1 = 1, ///< Run thread on core 1 + THREADPROCESSORID_2 = 2, ///< Run thread on core 2 + THREADPROCESSORID_3 = 3, ///< Run thread on core 3 + THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this /// Allowed CPU mask THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) | diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index f0c0c12fc..48b13cfdd 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -62,7 +62,7 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { return true; } -VMManager::VMManager() { +VMManager::VMManager(Core::System& system) : system{system} { // Default to assuming a 39-bit address space. This way we have a sane // starting point with executables that don't provide metadata. Reset(FileSys::ProgramAddressSpaceType::Is39Bit); @@ -111,7 +111,6 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, VirtualMemoryArea& final_vma = vma_handle->second; ASSERT(final_vma.size == size); - auto& system = Core::System::GetInstance(); system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset, VMAPermission::ReadWriteExecute); system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset, @@ -140,7 +139,6 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me VirtualMemoryArea& final_vma = vma_handle->second; ASSERT(final_vma.size == size); - auto& system = Core::System::GetInstance(); system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); @@ -223,7 +221,6 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) { ASSERT(FindVMA(target)->second.size >= size); - auto& system = Core::System::GetInstance(); system.ArmInterface(0).UnmapMemory(target, size); system.ArmInterface(1).UnmapMemory(target, size); system.ArmInterface(2).UnmapMemory(target, size); @@ -376,7 +373,7 @@ ResultCode VMManager::UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 Reprotect(src_vma_iter, VMAPermission::ReadWrite); if (dst_memory_state == MemoryState::ModuleCode) { - Core::System::GetInstance().InvalidateCpuInstructionCaches(); + system.InvalidateCpuInstructionCaches(); } return unmap_result; diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 288eb9450..ec84d9a70 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -14,6 +14,10 @@ #include "core/hle/result.h" #include "core/memory.h" +namespace Core { +class System; +} + namespace FileSys { enum class ProgramAddressSpaceType : u8; } @@ -321,7 +325,7 @@ class VMManager final { public: using VMAHandle = VMAMap::const_iterator; - VMManager(); + explicit VMManager(Core::System& system); ~VMManager(); /// Clears the address space map, re-initializing with a single free area. @@ -712,5 +716,7 @@ private: // The end of the currently allocated heap. This is not an inclusive // end of the range. This is essentially 'base_address + current_size'. VAddr heap_end = 0; + + Core::System& system; }; } // namespace Kernel |
