diff options
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_auto_object_container.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_handle_table.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_priority_queue.h | 27 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.cpp | 54 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_scheduler.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_scoped_lock.h | 15 | ||||
-rw-r--r-- | src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_shared_memory_info.h | 46 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 23 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 5 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 16 |
15 files changed, 154 insertions, 49 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index ca68fc325..cee96dd9b 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -15,6 +15,7 @@ #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_handle_table.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_readable_event.h" diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index a61870f8b..55e6fb9f7 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -17,7 +17,6 @@ #include "common/concepts.h" #include "common/swap.h" #include "core/hle/ipc.h" -#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/svc_common.h" union ResultCode; @@ -38,6 +37,7 @@ namespace Kernel { class Domain; class HLERequestContext; +class KAutoObject; class KernelCore; class KHandleTable; class KProcess; diff --git a/src/core/hle/kernel/k_auto_object_container.cpp b/src/core/hle/kernel/k_auto_object_container.cpp index 010006bb7..d5f80d5b2 100644 --- a/src/core/hle/kernel/k_auto_object_container.cpp +++ b/src/core/hle/kernel/k_auto_object_container.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> + #include "core/hle/kernel/k_auto_object_container.h" namespace Kernel { diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 6a420d5b0..44d13169f 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -7,7 +7,7 @@ namespace Kernel { KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {} -KHandleTable ::~KHandleTable() = default; +KHandleTable::~KHandleTable() = default; ResultCode KHandleTable::Finalize() { // Get the table and clear our record of it. diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 701268545..5e0b620c2 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp @@ -363,6 +363,8 @@ ResultCode KPageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, st block_manager->Update(src_addr, num_pages, KMemoryState::Normal, KMemoryPermission::ReadAndWrite); + system.InvalidateCpuInstructionCacheRange(dst_addr, size); + return ResultSuccess; } diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h index 4aa669d95..f4d71ad7e 100644 --- a/src/core/hle/kernel/k_priority_queue.h +++ b/src/core/hle/kernel/k_priority_queue.h @@ -22,12 +22,10 @@ class KThread; template <typename T> concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) { - { t.GetAffinityMask() } - ->Common::ConvertibleTo<u64>; + { t.GetAffinityMask() } -> Common::ConvertibleTo<u64>; {t.SetAffinityMask(0)}; - { t.GetAffinity(0) } - ->std::same_as<bool>; + { t.GetAffinity(0) } -> std::same_as<bool>; {t.SetAffinity(0, false)}; {t.SetAll()}; }; @@ -38,25 +36,20 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) { {(typename T::QueueEntry()).Initialize()}; {(typename T::QueueEntry()).SetPrev(std::addressof(t))}; {(typename T::QueueEntry()).SetNext(std::addressof(t))}; - { (typename T::QueueEntry()).GetNext() } - ->std::same_as<T*>; - { (typename T::QueueEntry()).GetPrev() } - ->std::same_as<T*>; - { t.GetPriorityQueueEntry(0) } - ->std::same_as<typename T::QueueEntry&>; + { (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>; + { (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>; + { t.GetPriorityQueueEntry(0) } -> std::same_as<typename T::QueueEntry&>; {t.GetAffinityMask()}; - { std::remove_cvref_t<decltype(t.GetAffinityMask())>() } - ->KPriorityQueueAffinityMask; + { std::remove_cvref_t<decltype(t.GetAffinityMask())>() } -> KPriorityQueueAffinityMask; - { t.GetActiveCore() } - ->Common::ConvertibleTo<s32>; - { t.GetPriority() } - ->Common::ConvertibleTo<s32>; + { t.GetActiveCore() } -> Common::ConvertibleTo<s32>; + { t.GetPriority() } -> Common::ConvertibleTo<s32>; }; template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority> -requires KPriorityQueueMember<Member> class KPriorityQueue { +requires KPriorityQueueMember<Member> +class KPriorityQueue { public: using AffinityMaskType = std::remove_cv_t< std::remove_reference_t<decltype(std::declval<Member>().GetAffinityMask())>>; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 8ead1a769..211157ccc 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -23,6 +23,7 @@ #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/kernel/k_shared_memory_info.h" #include "core/hle/kernel/k_slab_heap.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" @@ -254,10 +255,26 @@ ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAdd // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(state_lock); - // TODO(bunnei): Manage KSharedMemoryInfo list here. + // Try to find an existing info for the memory. + KSharedMemoryInfo* shemen_info = nullptr; + const auto iter = std::find_if( + shared_memory_list.begin(), shared_memory_list.end(), + [shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; }); + if (iter != shared_memory_list.end()) { + shemen_info = *iter; + } + + if (shemen_info == nullptr) { + shemen_info = KSharedMemoryInfo::Allocate(kernel); + R_UNLESS(shemen_info != nullptr, ResultOutOfMemory); + + shemen_info->Initialize(shmem); + shared_memory_list.push_back(shemen_info); + } - // Open a reference to the shared memory. + // Open a reference to the shared memory and its info. shmem->Open(); + shemen_info->Open(); return ResultSuccess; } @@ -267,7 +284,20 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(state_lock); - // TODO(bunnei): Manage KSharedMemoryInfo list here. + KSharedMemoryInfo* shemen_info = nullptr; + const auto iter = std::find_if( + shared_memory_list.begin(), shared_memory_list.end(), + [shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; }); + if (iter != shared_memory_list.end()) { + shemen_info = *iter; + } + + ASSERT(shemen_info != nullptr); + + if (shemen_info->Close()) { + shared_memory_list.erase(iter); + KSharedMemoryInfo::Free(kernel, shemen_info); + } // Close a reference to the shared memory. shmem->Close(); @@ -412,6 +442,24 @@ void KProcess::Finalize() { // Finalize the handle table and close any open handles. handle_table.Finalize(); + // Free all shared memory infos. + { + auto it = shared_memory_list.begin(); + while (it != shared_memory_list.end()) { + KSharedMemoryInfo* info = *it; + KSharedMemory* shmem = info->GetSharedMemory(); + + while (!info->Close()) { + shmem->Close(); + } + + shmem->Close(); + + it = shared_memory_list.erase(it); + KSharedMemoryInfo::Free(kernel, info); + } + } + // Perform inherited finalization. KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); } diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index a03c074fb..1a53e2be7 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -34,6 +34,7 @@ class KernelCore; class KPageTable; class KResourceLimit; class KThread; +class KSharedMemoryInfo; class TLSPage; struct CodeSet; @@ -448,6 +449,9 @@ private: /// List of threads that are running with this process as their owner. std::list<const KThread*> thread_list; + /// List of shared memory that are running with this process as their owner. + std::list<KSharedMemoryInfo*> shared_memory_list; + /// Address of the top of the main thread's stack VAddr main_thread_stack_top{}; diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index 12cfae919..c8ccc1ae4 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h @@ -197,7 +197,7 @@ private: class [[nodiscard]] KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> { public: - explicit KScopedSchedulerLock(KernelCore & kernel); + explicit KScopedSchedulerLock(KernelCore& kernel); ~KScopedSchedulerLock(); }; diff --git a/src/core/hle/kernel/k_scoped_lock.h b/src/core/hle/kernel/k_scoped_lock.h index 72c3b0252..4fb180fc6 100644 --- a/src/core/hle/kernel/k_scoped_lock.h +++ b/src/core/hle/kernel/k_scoped_lock.h @@ -13,19 +13,18 @@ namespace Kernel { template <typename T> concept KLockable = !std::is_reference_v<T> && requires(T & t) { - { t.Lock() } - ->std::same_as<void>; - { t.Unlock() } - ->std::same_as<void>; + { t.Lock() } -> std::same_as<void>; + { t.Unlock() } -> std::same_as<void>; }; template <typename T> -requires KLockable<T> class [[nodiscard]] KScopedLock { +requires KLockable<T> +class [[nodiscard]] KScopedLock { public: - explicit KScopedLock(T * l) : lock_ptr(l) { + explicit KScopedLock(T* l) : lock_ptr(l) { this->lock_ptr->Lock(); } - explicit KScopedLock(T & l) : KScopedLock(std::addressof(l)) {} + explicit KScopedLock(T& l) : KScopedLock(std::addressof(l)) {} ~KScopedLock() { this->lock_ptr->Unlock(); @@ -34,7 +33,7 @@ public: KScopedLock(const KScopedLock&) = delete; KScopedLock& operator=(const KScopedLock&) = delete; - KScopedLock(KScopedLock &&) = delete; + KScopedLock(KScopedLock&&) = delete; KScopedLock& operator=(KScopedLock&&) = delete; private: diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h index a86af56dd..f6c75f2d9 100644 --- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h +++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h @@ -17,7 +17,7 @@ namespace Kernel { class [[nodiscard]] KScopedSchedulerLockAndSleep { public: - explicit KScopedSchedulerLockAndSleep(KernelCore & kernel_, KThread * t, s64 timeout) + explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KThread* t, s64 timeout) : kernel(kernel_), thread(t), timeout_tick(timeout) { // Lock the scheduler. kernel.GlobalSchedulerContext().scheduler_lock.Lock(); diff --git a/src/core/hle/kernel/k_shared_memory_info.h b/src/core/hle/kernel/k_shared_memory_info.h new file mode 100644 index 000000000..bf97a0184 --- /dev/null +++ b/src/core/hle/kernel/k_shared_memory_info.h @@ -0,0 +1,46 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> + +#include <boost/intrusive/list.hpp> + +#include "common/assert.h" +#include "core/hle/kernel/slab_helpers.h" + +namespace Kernel { + +class KSharedMemory; + +class KSharedMemoryInfo final : public KSlabAllocated<KSharedMemoryInfo>, + public boost::intrusive::list_base_hook<> { + +public: + explicit KSharedMemoryInfo() = default; + + constexpr void Initialize(KSharedMemory* shmem) { + shared_memory = shmem; + } + + constexpr KSharedMemory* GetSharedMemory() const { + return shared_memory; + } + + constexpr void Open() { + ++reference_count; + } + + constexpr bool Close() { + return (--reference_count) == 0; + } + +private: + KSharedMemory* shared_memory{}; + size_t reference_count{}; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 92fbc5532..bea945301 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -267,20 +267,23 @@ struct KernelCore::Impl { } } - /// Creates a new host thread ID, should only be called by GetHostThreadId - u32 AllocateHostThreadId(std::optional<std::size_t> core_id) { - if (core_id) { - // The first for slots are reserved for CPU core threads - ASSERT(*core_id < Core::Hardware::NUM_CPU_CORES); - return static_cast<u32>(*core_id); - } else { - return next_host_thread_id++; + static inline thread_local u32 host_thread_id = UINT32_MAX; + + /// Gets the host thread ID for the caller, allocating a new one if this is the first time + u32 GetHostThreadId(std::size_t core_id) { + if (host_thread_id == UINT32_MAX) { + // The first four slots are reserved for CPU core threads + ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); + host_thread_id = static_cast<u32>(core_id); } + return host_thread_id; } /// Gets the host thread ID for the caller, allocating a new one if this is the first time - u32 GetHostThreadId(std::optional<std::size_t> core_id = std::nullopt) { - const thread_local auto host_thread_id{AllocateHostThreadId(core_id)}; + u32 GetHostThreadId() { + if (host_thread_id == UINT32_MAX) { + host_thread_id = next_host_thread_id++; + } return host_thread_id; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3a6db0b1c..b6658b437 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <functional> #include <memory> #include <string> #include <unordered_map> @@ -48,6 +49,7 @@ class KScheduler; class KServerSession; class KSession; class KSharedMemory; +class KSharedMemoryInfo; class KThread; class KTransferMemory; class KWritableEvent; @@ -308,6 +310,8 @@ public: return slab_heap_container->session; } else if constexpr (std::is_same_v<T, KSharedMemory>) { return slab_heap_container->shared_memory; + } else if constexpr (std::is_same_v<T, KSharedMemoryInfo>) { + return slab_heap_container->shared_memory_info; } else if constexpr (std::is_same_v<T, KThread>) { return slab_heap_container->thread; } else if constexpr (std::is_same_v<T, KTransferMemory>) { @@ -361,6 +365,7 @@ private: KSlabHeap<KResourceLimit> resource_limit; KSlabHeap<KSession> session; KSlabHeap<KSharedMemory> shared_memory; + KSlabHeap<KSharedMemoryInfo> shared_memory_info; KSlabHeap<KThread> thread; KSlabHeap<KTransferMemory> transfer_memory; KSlabHeap<KWritableEvent> writeable_event; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 2eb532472..f98f24a60 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -320,17 +320,19 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { auto& kernel = system.Kernel(); - KScopedAutoObject session = - kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle); - R_UNLESS(session.IsNotNull(), ResultInvalidHandle); - LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); - auto thread = kernel.CurrentScheduler()->GetCurrentThread(); { KScopedSchedulerLock lock(kernel); thread->SetState(ThreadState::Waiting); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - session->SendSyncRequest(thread, system.Memory(), system.CoreTiming()); + + { + KScopedAutoObject session = + kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle); + R_UNLESS(session.IsNotNull(), ResultInvalidHandle); + LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); + session->SendSyncRequest(thread, system.Memory(), system.CoreTiming()); + } } KSynchronizationObject* dummy{}; @@ -1078,8 +1080,8 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) { current = true; + break; } - break; } // If the thread is current, retry until it isn't. |