diff options
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 46 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 30 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 5 | ||||
-rw-r--r-- | src/core/hle/kernel/memory/page_table.cpp | 23 | ||||
-rw-r--r-- | src/core/hle/kernel/memory/system_control.cpp | 21 | ||||
-rw-r--r-- | src/core/hle/kernel/memory/system_control.h | 5 | ||||
-rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 39 | ||||
-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/time_manager.cpp | 10 |
11 files changed, 98 insertions, 91 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index df0debe1b..b882eaa0f 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -81,7 +81,7 @@ ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 do { current_value = monitor.ExclusiveRead32(current_core, address); - if (current_value != value) { + if (current_value != static_cast<u32>(value)) { return ERR_INVALID_STATE; } current_value++; diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 9277b5d08..81f85643b 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -293,13 +293,15 @@ std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { BufferDescriptorA()[buffer_index].Size()}; if (is_buffer_a) { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return buffer; }, - "BufferDescriptorA invalid buffer_index {}", buffer_index); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorA().size() > buffer_index, { return buffer; }, + "BufferDescriptorA invalid buffer_index {}", buffer_index); buffer.resize(BufferDescriptorA()[buffer_index].Size()); memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); } else { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return buffer; }, - "BufferDescriptorX invalid buffer_index {}", buffer_index); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorX().size() > buffer_index, { return buffer; }, + "BufferDescriptorX invalid buffer_index {}", buffer_index); buffer.resize(BufferDescriptorX()[buffer_index].Size()); memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); } @@ -324,16 +326,16 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, } if (is_buffer_b) { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index && - BufferDescriptorB()[buffer_index].Size() >= size, - { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", - buffer_index, size); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorB().size() > buffer_index && + BufferDescriptorB()[buffer_index].Size() >= size, + { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", buffer_index, size); memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); } else { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index && - BufferDescriptorC()[buffer_index].Size() >= size, - { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", - buffer_index, size); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorC().size() > buffer_index && + BufferDescriptorC()[buffer_index].Size() >= size, + { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", buffer_index, size); memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); } @@ -344,12 +346,14 @@ std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && BufferDescriptorA()[buffer_index].Size()}; if (is_buffer_a) { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return 0; }, - "BufferDescriptorA invalid buffer_index {}", buffer_index); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorA().size() > buffer_index, { return 0; }, + "BufferDescriptorA invalid buffer_index {}", buffer_index); return BufferDescriptorA()[buffer_index].Size(); } else { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return 0; }, - "BufferDescriptorX invalid buffer_index {}", buffer_index); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorX().size() > buffer_index, { return 0; }, + "BufferDescriptorX invalid buffer_index {}", buffer_index); return BufferDescriptorX()[buffer_index].Size(); } } @@ -358,12 +362,14 @@ std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) cons const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && BufferDescriptorB()[buffer_index].Size()}; if (is_buffer_b) { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index, { return 0; }, - "BufferDescriptorB invalid buffer_index {}", buffer_index); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorB().size() > buffer_index, { return 0; }, + "BufferDescriptorB invalid buffer_index {}", buffer_index); return BufferDescriptorB()[buffer_index].Size(); } else { - ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index, { return 0; }, - "BufferDescriptorC invalid buffer_index {}", buffer_index); + ASSERT_OR_EXECUTE_MSG( + BufferDescriptorC().size() > buffer_index, { return 0; }, + "BufferDescriptorC invalid buffer_index {}", buffer_index); return BufferDescriptorC()[buffer_index].Size(); } return 0; diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index b31673928..f3277b766 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -13,6 +13,7 @@ #include <vector> #include <boost/container/small_vector.hpp> #include "common/common_types.h" +#include "common/concepts.h" #include "common/swap.h" #include "core/hle/ipc.h" #include "core/hle/kernel/object.h" @@ -193,23 +194,24 @@ public: /* Helper function to write a buffer using the appropriate buffer descriptor * - * @tparam ContiguousContainer an arbitrary container that satisfies the - * ContiguousContainer concept in the C++ standard library. + * @tparam T an arbitrary container that satisfies the + * ContiguousContainer concept in the C++ standard library or a trivially copyable type. * - * @param container The container to write the data of into a buffer. + * @param data The container/data to write into a buffer. * @param buffer_index The buffer in particular to write to. */ - template <typename ContiguousContainer, - typename = std::enable_if_t<!std::is_pointer_v<ContiguousContainer>>> - std::size_t WriteBuffer(const ContiguousContainer& container, - std::size_t buffer_index = 0) const { - using ContiguousType = typename ContiguousContainer::value_type; - - static_assert(std::is_trivially_copyable_v<ContiguousType>, - "Container to WriteBuffer must contain trivially copyable objects"); - - return WriteBuffer(std::data(container), std::size(container) * sizeof(ContiguousType), - buffer_index); + template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>> + std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const { + if constexpr (Common::IsSTLContainer<T>) { + using ContiguousType = typename T::value_type; + static_assert(std::is_trivially_copyable_v<ContiguousType>, + "Container to WriteBuffer must contain trivially copyable objects"); + return WriteBuffer(std::data(data), std::size(data) * sizeof(ContiguousType), + buffer_index); + } else { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable"); + return WriteBuffer(&data, sizeof(T), buffer_index); + } } /// Helper function to get the size of the input buffer diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 8dd4a2637..f2b0fe2fd 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -145,7 +145,7 @@ struct KernelCore::Impl { void InitializePreemption(KernelCore& kernel) { preemption_event = Core::Timing::CreateEvent( - "PreemptionCallback", [this, &kernel](u64, std::chrono::nanoseconds) { + "PreemptionCallback", [this, &kernel](std::uintptr_t, std::chrono::nanoseconds) { { SchedulerLock lock(kernel); global_scheduler.PreemptThreads(); @@ -219,6 +219,7 @@ struct KernelCore::Impl { return static_cast<u32>(system.GetCpuManager().CurrentCore()); } } + std::unique_lock lock{register_thread_mutex}; const auto it = host_thread_ids.find(this_id); if (it == host_thread_ids.end()) { return Core::INVALID_HOST_THREAD_ID; @@ -324,7 +325,7 @@ struct KernelCore::Impl { 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; + mutable std::mutex register_thread_mutex; // Kernel memory management std::unique_ptr<Memory::MemoryManager> memory_manager; diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index 5d6aac00f..a3fadb533 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp @@ -604,7 +604,6 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis if (const auto result{ Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())}; result.IsError()) { - const MemoryInfo info{block_manager->FindBlock(cur_addr).GetMemoryInfo()}; const std::size_t num_pages{(addr - cur_addr) / PageSize}; ASSERT( @@ -852,11 +851,12 @@ ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { return result; } - block_manager->UpdateLock(addr, size / PageSize, - [](MemoryBlockManager::iterator block, MemoryPermission perm) { - block->ShareToDevice(perm); - }, - perm); + block_manager->UpdateLock( + addr, size / PageSize, + [](MemoryBlockManager::iterator block, MemoryPermission perm) { + block->ShareToDevice(perm); + }, + perm); return RESULT_SUCCESS; } @@ -874,11 +874,12 @@ ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) return result; } - block_manager->UpdateLock(addr, size / PageSize, - [](MemoryBlockManager::iterator block, MemoryPermission perm) { - block->UnshareToDevice(perm); - }, - perm); + block_manager->UpdateLock( + addr, size / PageSize, + [](MemoryBlockManager::iterator block, MemoryPermission perm) { + block->UnshareToDevice(perm); + }, + perm); return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/memory/system_control.cpp b/src/core/hle/kernel/memory/system_control.cpp index 2f98e9c4c..11d204bc2 100644 --- a/src/core/hle/kernel/memory/system_control.cpp +++ b/src/core/hle/kernel/memory/system_control.cpp @@ -7,22 +7,15 @@ #include "core/hle/kernel/memory/system_control.h" namespace Kernel::Memory::SystemControl { - -u64 GenerateRandomU64ForInit() { - static std::random_device device; - static std::mt19937 gen(device()); - static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); - return distribution(gen); -} - +namespace { template <typename F> u64 GenerateUniformRange(u64 min, u64 max, F f) { - /* Handle the case where the difference is too large to represent. */ + // Handle the case where the difference is too large to represent. if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) { return f(); } - /* Iterate until we get a value in range. */ + // Iterate until we get a value in range. const u64 range_size = ((max + 1) - min); const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size; while (true) { @@ -32,6 +25,14 @@ u64 GenerateUniformRange(u64 min, u64 max, F f) { } } +u64 GenerateRandomU64ForInit() { + static std::random_device device; + static std::mt19937 gen(device()); + static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); + return distribution(gen); +} +} // Anonymous namespace + u64 GenerateRandomRange(u64 min, u64 max) { return GenerateUniformRange(min, max, GenerateRandomU64ForInit); } diff --git a/src/core/hle/kernel/memory/system_control.h b/src/core/hle/kernel/memory/system_control.h index 3fa93111d..19cab8cbc 100644 --- a/src/core/hle/kernel/memory/system_control.h +++ b/src/core/hle/kernel/memory/system_control.h @@ -8,11 +8,6 @@ namespace Kernel::Memory::SystemControl { -u64 GenerateRandomU64ForInit(); - -template <typename F> -u64 GenerateUniformRange(u64 min, u64 max, F f); - u64 GenerateRandomRange(u64 min, u64 max); } // namespace Kernel::Memory::SystemControl diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index f93e5e4b0..5cbd3b912 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -131,7 +131,8 @@ u32 GlobalScheduler::SelectThreads() { u32 cores_needing_context_switch{}; for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { Scheduler& sched = kernel.Scheduler(core); - ASSERT(top_threads[core] == nullptr || top_threads[core]->GetProcessorID() == core); + 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); } @@ -663,32 +664,26 @@ void Scheduler::Reload() { } void Scheduler::SwitchContextStep2() { - Thread* previous_thread = current_thread_prev.get(); - Thread* new_thread = selected_thread.get(); - // Load context of new thread - Process* const previous_process = - previous_thread != nullptr ? previous_thread->GetOwnerProcess() : nullptr; - - if (new_thread) { - ASSERT_MSG(new_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, + if (selected_thread) { + ASSERT_MSG(selected_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, "Thread must be runnable."); // Cancel any outstanding wakeup events for this thread - new_thread->SetIsRunning(true); - new_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); - new_thread->SetWasRunning(false); + selected_thread->SetIsRunning(true); + selected_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); + selected_thread->SetWasRunning(false); auto* const thread_owner_process = current_thread->GetOwnerProcess(); if (thread_owner_process != nullptr) { system.Kernel().MakeCurrentProcess(thread_owner_process); } - if (!new_thread->IsHLEThread()) { - Core::ARM_Interface& cpu_core = new_thread->ArmInterface(); - cpu_core.LoadContext(new_thread->GetContext32()); - cpu_core.LoadContext(new_thread->GetContext64()); - cpu_core.SetTlsAddress(new_thread->GetTLSAddress()); - cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); + if (!selected_thread->IsHLEThread()) { + Core::ARM_Interface& cpu_core = selected_thread->ArmInterface(); + cpu_core.LoadContext(selected_thread->GetContext32()); + cpu_core.LoadContext(selected_thread->GetContext64()); + cpu_core.SetTlsAddress(selected_thread->GetTLSAddress()); + cpu_core.SetTPIDR_EL0(selected_thread->GetTPIDR_EL0()); cpu_core.ChangeProcessorID(this->core_id); cpu_core.ClearExclusiveState(); } @@ -761,7 +756,11 @@ 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()) { @@ -780,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 b3b4b5169..36e3c26fb 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -289,7 +289,7 @@ private: class SchedulerLock { public: - explicit SchedulerLock(KernelCore& kernel); + [[nodiscard]] explicit SchedulerLock(KernelCore& kernel); ~SchedulerLock(); protected: diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index af22f4c33..7e6391c6c 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -33,8 +33,10 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern std::string name) { std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; - session->request_event = Core::Timing::CreateEvent( - name, [session](u64, std::chrono::nanoseconds) { session->CompleteSyncRequest(); }); + session->request_event = + Core::Timing::CreateEvent(name, [session](std::uintptr_t, std::chrono::nanoseconds) { + session->CompleteSyncRequest(); + }); session->name = std::move(name); session->parent = std::move(parent); diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 88b01b751..95f2446c9 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp @@ -16,14 +16,14 @@ namespace Kernel { TimeManager::TimeManager(Core::System& system_) : system{system_} { time_manager_event_type = Core::Timing::CreateEvent( - "Kernel::TimeManagerCallback", [this](u64 thread_handle, std::chrono::nanoseconds) { - SchedulerLock lock(system.Kernel()); - Handle proper_handle = static_cast<Handle>(thread_handle); + "Kernel::TimeManagerCallback", + [this](std::uintptr_t thread_handle, std::chrono::nanoseconds) { + const SchedulerLock lock(system.Kernel()); + const auto proper_handle = static_cast<Handle>(thread_handle); if (cancelled_events[proper_handle]) { return; } - std::shared_ptr<Thread> thread = - this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); + auto thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); thread->OnWakeUp(); }); } |