diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/kernel/client_session.cpp | 5 | ||||
-rw-r--r-- | src/core/hle/kernel/client_session.h | 7 | ||||
-rw-r--r-- | src/core/hle/kernel/handle_table.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 74 | ||||
-rw-r--r-- | src/core/hle/kernel/physical_core.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/kernel/process.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 18 | ||||
-rw-r--r-- | src/core/hle/kernel/scheduler.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/server_session.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/server_session.h | 11 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 17 |
13 files changed, 88 insertions, 81 deletions
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index 5ab204b9b..be9eba519 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -48,14 +48,15 @@ ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kern } ResultCode ClientSession::SendSyncRequest(std::shared_ptr<Thread> thread, - Core::Memory::Memory& memory) { + Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing) { // Keep ServerSession alive until we're done working with it. if (!parent->Server()) { return ERR_SESSION_CLOSED_BY_REMOTE; } // Signal the server session that new data is available - return parent->Server()->HandleSyncRequest(std::move(thread), memory); + return parent->Server()->HandleSyncRequest(std::move(thread), memory, core_timing); } } // namespace Kernel diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index c5f760d7d..e5e0690c2 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -16,6 +16,10 @@ namespace Core::Memory { class Memory; } +namespace Core::Timing { +class CoreTiming; +} + namespace Kernel { class KernelCore; @@ -42,7 +46,8 @@ public: return HANDLE_TYPE; } - ResultCode SendSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory); + ResultCode SendSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing); bool ShouldWait(const Thread* thread) const override; diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index fb30b6f8b..3e745c18b 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -118,7 +118,7 @@ std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const { void HandleTable::Clear() { for (u16 i = 0; i < table_size; ++i) { - generations[i] = i + 1; + generations[i] = static_cast<u16>(i + 1); objects[i] = nullptr; } next_free_slot = 0; diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index f3277b766..c31a65476 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -24,6 +24,10 @@ namespace Core::Memory { class Memory; } +namespace IPC { +class ResponseBuilder; +} + namespace Service { class ServiceFrameworkBase; } @@ -287,6 +291,8 @@ public: } private: + friend class IPC::ResponseBuilder; + void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming); std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index cabe8d418..bb3e312a7 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -7,7 +7,6 @@ #include <bitset> #include <functional> #include <memory> -#include <mutex> #include <thread> #include <unordered_map> #include <utility> @@ -87,8 +86,6 @@ struct KernelCore::Impl { } cores.clear(); - registered_core_threads.reset(); - process_list.clear(); current_process = nullptr; @@ -107,7 +104,11 @@ struct KernelCore::Impl { cores.clear(); exclusive_monitor.reset(); - host_thread_ids.clear(); + + num_host_threads = 0; + std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(), + std::thread::id{}); + std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0); } void InitializePhysicalCores() { @@ -177,53 +178,58 @@ struct KernelCore::Impl { void MakeCurrentProcess(Process* process) { current_process = process; - if (process == nullptr) { return; } - - u32 core_id = GetCurrentHostThreadID(); + const u32 core_id = GetCurrentHostThreadID(); if (core_id < Core::Hardware::NUM_CPU_CORES) { system.Memory().SetCurrentPageTable(*process, core_id); } } void RegisterCoreThread(std::size_t core_id) { - std::unique_lock lock{register_thread_mutex}; + const std::thread::id this_id = std::this_thread::get_id(); if (!is_multicore) { - single_core_thread_id = std::this_thread::get_id(); + single_core_thread_id = this_id; } - const std::thread::id this_id = std::this_thread::get_id(); - const auto it = host_thread_ids.find(this_id); + const auto end = + register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads); + const auto it = std::find(register_host_thread_keys.begin(), end, this_id); ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); - ASSERT(it == host_thread_ids.end()); - ASSERT(!registered_core_threads[core_id]); - host_thread_ids[this_id] = static_cast<u32>(core_id); - registered_core_threads.set(core_id); + ASSERT(it == end); + InsertHostThread(static_cast<u32>(core_id)); } void RegisterHostThread() { - std::unique_lock lock{register_thread_mutex}; const std::thread::id this_id = std::this_thread::get_id(); - const auto it = host_thread_ids.find(this_id); - if (it != host_thread_ids.end()) { - return; + const auto end = + register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads); + const auto it = std::find(register_host_thread_keys.begin(), end, this_id); + if (it == end) { + InsertHostThread(registered_thread_ids++); } - host_thread_ids[this_id] = registered_thread_ids++; } - u32 GetCurrentHostThreadID() const { + void InsertHostThread(u32 value) { + const size_t index = num_host_threads++; + ASSERT_MSG(index < NUM_REGISTRABLE_HOST_THREADS, "Too many host threads"); + register_host_thread_values[index] = value; + register_host_thread_keys[index] = std::this_thread::get_id(); + } + + [[nodiscard]] u32 GetCurrentHostThreadID() const { const std::thread::id this_id = std::this_thread::get_id(); - if (!is_multicore) { - if (single_core_thread_id == this_id) { - return static_cast<u32>(system.GetCpuManager().CurrentCore()); - } + if (!is_multicore && single_core_thread_id == this_id) { + return static_cast<u32>(system.GetCpuManager().CurrentCore()); } - const auto it = host_thread_ids.find(this_id); - if (it == host_thread_ids.end()) { + const auto end = + register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads); + const auto it = std::find(register_host_thread_keys.begin(), end, this_id); + if (it == end) { return Core::INVALID_HOST_THREAD_ID; } - return it->second; + return register_host_thread_values[static_cast<size_t>( + std::distance(register_host_thread_keys.begin(), it))]; } Core::EmuThreadHandle GetCurrentEmuThreadID() const { @@ -321,10 +327,14 @@ struct KernelCore::Impl { std::vector<Kernel::PhysicalCore> cores; // 0-3 IDs represent core threads, >3 represent others - std::unordered_map<std::thread::id, u32> host_thread_ids; - u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; - std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; - std::mutex register_thread_mutex; + std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; + + // Number of host threads is a relatively high number to avoid overflowing + static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64; + std::atomic<size_t> num_host_threads{0}; + std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS> + register_host_thread_keys{}; + std::array<std::atomic<u32>, NUM_REGISTRABLE_HOST_THREADS> register_host_thread_values{}; // Kernel memory management std::unique_ptr<Memory::MemoryManager> memory_manager; diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index c6bbdb080..6e04d025f 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -2,30 +2,18 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/assert.h" -#include "common/logging/log.h" #include "common/spin_lock.h" -#include "core/arm/arm_interface.h" -#ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic_32.h" -#include "core/arm/dynarmic/arm_dynarmic_64.h" -#endif #include "core/arm/cpu_interrupt_handler.h" -#include "core/arm/exclusive_monitor.h" -#include "core/arm/unicorn/arm_unicorn.h" #include "core/core.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/scheduler.h" -#include "core/hle/kernel/thread.h" namespace Kernel { PhysicalCore::PhysicalCore(Core::System& system, std::size_t id, Kernel::Scheduler& scheduler, Core::CPUInterruptHandler& interrupt_handler) - : interrupt_handler{interrupt_handler}, core_index{id}, scheduler{scheduler} { - - guard = std::make_unique<Common::SpinLock>(); -} + : interrupt_handler{interrupt_handler}, + core_index{id}, scheduler{scheduler}, guard{std::make_unique<Common::SpinLock>()} {} PhysicalCore::~PhysicalCore() = default; diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index ff9d9248b..b17529dee 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -4,6 +4,7 @@ #include <algorithm> #include <bitset> +#include <ctime> #include <memory> #include <random> #include "common/alignment.h" @@ -123,7 +124,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, : kernel.CreateNewUserProcessID(); process->capabilities.InitializeForMetadatalessProcess(); - std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(0)); + std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))); std::uniform_int_distribution<u64> distribution; std::generate(process->random_entropy.begin(), process->random_entropy.end(), [&] { return distribution(rng); }); diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index a4b234424..6b7db5372 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -72,7 +72,7 @@ u32 GlobalScheduler::SelectThreads() { if (top_thread != nullptr) { // TODO(Blinkhawk): Implement Thread Pinning } else { - idle_cores |= (1ul << core); + idle_cores |= (1U << core); } top_threads[core] = top_thread; } @@ -126,7 +126,7 @@ u32 GlobalScheduler::SelectThreads() { top_threads[core_id] = suggested; } - idle_cores &= ~(1ul << core_id); + idle_cores &= ~(1U << core_id); } u32 cores_needing_context_switch{}; for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { @@ -134,7 +134,7 @@ u32 GlobalScheduler::SelectThreads() { ASSERT(top_threads[core] == nullptr || static_cast<u32>(top_threads[core]->GetProcessorID()) == core); if (update_thread(top_threads[core], sched)) { - cores_needing_context_switch |= (1ul << core); + cores_needing_context_switch |= (1U << core); } } return cores_needing_context_switch; @@ -364,7 +364,7 @@ void GlobalScheduler::EnableInterruptAndSchedule(u32 cores_pending_reschedule, } else { must_context_switch = true; } - cores_pending_reschedule &= ~(1ul << core); + cores_pending_reschedule &= ~(1U << core); } if (must_context_switch) { auto& core_scheduler = kernel.CurrentScheduler(); @@ -756,14 +756,18 @@ void Scheduler::SwitchToCurrent() { current_thread = selected_thread; is_context_switch_pending = false; } - while (!is_context_switch_pending) { + const auto is_switch_pending = [this] { + std::scoped_lock lock{guard}; + return is_context_switch_pending; + }; + do { if (current_thread != nullptr && !current_thread->IsHLEThread()) { current_thread->context_guard.lock(); if (!current_thread->IsRunnable()) { current_thread->context_guard.unlock(); break; } - if (current_thread->GetProcessorID() != core_id) { + if (static_cast<u32>(current_thread->GetProcessorID()) != core_id) { current_thread->context_guard.unlock(); break; } @@ -775,7 +779,7 @@ void Scheduler::SwitchToCurrent() { next_context = &idle_thread->GetHostContext(); } Common::Fiber::YieldTo(switch_fiber, *next_context); - } + } while (!is_switch_pending()); } } diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 36e3c26fb..b6f04dcea 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -188,7 +188,7 @@ private: /// Scheduler lock mechanisms. bool is_locked{}; - Common::SpinLock inner_lock{}; + std::mutex inner_lock; std::atomic<s64> scope_lock{}; Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()}; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 7e6391c6c..8c19f2534 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -8,7 +8,6 @@ #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" -#include "core/core.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" @@ -185,10 +184,11 @@ ResultCode ServerSession::CompleteSyncRequest() { } ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, - Core::Memory::Memory& memory) { + Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing) { const ResultCode result = QueueSyncRequest(std::move(thread), memory); const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000}; - Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {}); + core_timing.ScheduleEvent(delay, request_event, {}); return result; } diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 403aaf10b..d23e9ec68 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -18,8 +18,9 @@ class Memory; } namespace Core::Timing { +class CoreTiming; struct EventType; -} +} // namespace Core::Timing namespace Kernel { @@ -87,12 +88,14 @@ public: /** * Handle a sync request from the emulated application. * - * @param thread Thread that initiated the request. - * @param memory Memory context to handle the sync request under. + * @param thread Thread that initiated the request. + * @param memory Memory context to handle the sync request under. + * @param core_timing Core timing context to schedule the request event under. * * @returns ResultCode from the operation. */ - ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory); + ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory, + Core::Timing::CoreTiming& core_timing); bool ShouldWait(const Thread* thread) const override; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 01ae57053..bafd1ced7 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -346,7 +346,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { SchedulerLock lock(system.Kernel()); thread->InvalidateHLECallback(); thread->SetStatus(ThreadStatus::WaitIPC); - session->SendSyncRequest(SharedFrom(thread), system.Memory()); + session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); } if (thread->HasHLECallback()) { diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d132aba34..da0cb26b6 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -13,7 +13,6 @@ #include "common/logging/log.h" #include "common/thread_queue_list.h" #include "core/arm/arm_interface.h" -#include "core/arm/unicorn/arm_unicorn.h" #include "core/core.h" #include "core/cpu_manager.h" #include "core/hardware_properties.h" @@ -217,8 +216,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy } else { thread->tls_address = 0; } - // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used - // to initialize the context + thread->arm_interface.reset(); if ((type_flags & THREADTYPE_HLE) == 0) { #ifdef ARCHITECTURE_x86_64 @@ -231,19 +229,10 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy system, kernel.Interrupts(), kernel.IsMulticore(), kernel.GetExclusiveMonitor(), processor_id); } - #else - if (owner_process && !owner_process->Is64BitProcess()) { - thread->arm_interface = std::make_shared<Core::ARM_Unicorn>( - system, kernel.Interrupts(), kernel.IsMulticore(), ARM_Unicorn::Arch::AArch32, - processor_id); - } else { - thread->arm_interface = std::make_shared<Core::ARM_Unicorn>( - system, kernel.Interrupts(), kernel.IsMulticore(), ARM_Unicorn::Arch::AArch64, - processor_id); - } - LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); +#error Platform not supported yet. #endif + ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top), static_cast<u32>(entry_point), static_cast<u32>(arg)); ResetThreadContext64(thread->context_64, stack_top, entry_point, arg); |