diff options
-rw-r--r-- | src/core/hle/kernel/k_client_port.h | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/k_client_session.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_event.h | 14 | ||||
-rw-r--r-- | src/core/hle/kernel/k_port.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.h | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/k_readable_event.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_resource_limit.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_server_port.h | 12 | ||||
-rw-r--r-- | src/core/hle/kernel/k_server_session.h | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/k_session.h | 10 | ||||
-rw-r--r-- | src/core/hle/kernel/k_shared_memory.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_slab_heap.h | 199 | ||||
-rw-r--r-- | src/core/hle/kernel/k_synchronization_object.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 10 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread.h | 10 | ||||
-rw-r--r-- | src/core/hle/kernel/k_transfer_memory.h | 10 | ||||
-rw-r--r-- | src/core/hle/kernel/k_writable_event.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 5 | ||||
-rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 4 |
19 files changed, 247 insertions, 72 deletions
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index 8501156e8..f2fff3b01 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h @@ -22,7 +22,7 @@ class KClientPort final : public KSynchronizationObject { public: explicit KClientPort(KernelCore& kernel_); - virtual ~KClientPort() override; + ~KClientPort() override; void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_); void OnSessionFinalized(); @@ -49,8 +49,8 @@ public: bool IsServerClosed() const; // Overridden virtual functions. - virtual void Destroy() override; - virtual bool IsSignaled() const override; + void Destroy() override; + bool IsSignaled() const override; ResultCode CreateSession(KClientSession** out); diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index 720a8c243..b11d5b4e3 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h @@ -34,7 +34,7 @@ class KClientSession final public: explicit KClientSession(KernelCore& kernel_); - virtual ~KClientSession(); + ~KClientSession() override; void Initialize(KSession* parent_, std::string&& name_) { // Set member variables. @@ -42,7 +42,7 @@ public: name = std::move(name_); } - virtual void Destroy() override; + void Destroy() override; static void PostDestroy([[maybe_unused]] uintptr_t arg) {} KSession* GetParent() const { diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 9a59ffb70..3d3ec99e2 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h @@ -20,23 +20,21 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj public: explicit KEvent(KernelCore& kernel_); - virtual ~KEvent(); + ~KEvent() override; void Initialize(std::string&& name); - virtual void Finalize() override; + void Finalize() override; - virtual bool IsInitialized() const override { + bool IsInitialized() const override { return initialized; } - virtual uintptr_t GetPostDestroyArgument() const override { + uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(owner); } - static void PostDestroy(uintptr_t arg); - - virtual KProcess* GetOwner() const override { + KProcess* GetOwner() const override { return owner; } @@ -48,6 +46,8 @@ public: return writable_event; } + static void PostDestroy(uintptr_t arg); + private: KReadableEvent readable_event; KWritableEvent writable_event; diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h index 960f1f3a3..4018ea2df 100644 --- a/src/core/hle/kernel/k_port.h +++ b/src/core/hle/kernel/k_port.h @@ -22,7 +22,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjec public: explicit KPort(KernelCore& kernel_); - virtual ~KPort(); + ~KPort() override; static void PostDestroy([[maybe_unused]] uintptr_t arg) {} @@ -59,7 +59,6 @@ private: ServerClosed = 3, }; -private: KServerPort server; KClientPort client; State state{State::Invalid}; diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 123d71cd3..c0656b9af 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -331,19 +331,19 @@ public: void LoadModule(CodeSet code_set, VAddr base_addr); - virtual bool IsInitialized() const override { + bool IsInitialized() const override { return is_initialized; } static void PostDestroy([[maybe_unused]] uintptr_t arg) {} - virtual void Finalize(); + void Finalize() override; - virtual u64 GetId() const override final { + u64 GetId() const override { return GetProcessID(); } - virtual bool IsSignaled() const override; + bool IsSignaled() const override; void PinCurrentThread(); void UnpinCurrentThread(); diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index 33cd1dd3e..b2850ac7b 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h @@ -31,8 +31,8 @@ public: return parent; } - virtual bool IsSignaled() const override; - virtual void Destroy() override; + bool IsSignaled() const override; + void Destroy() override; ResultCode Signal(); ResultCode Clear(); diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 0debbbb51..fab6005ff 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -37,10 +37,10 @@ class KResourceLimit final public: explicit KResourceLimit(KernelCore& kernel_); - virtual ~KResourceLimit(); + ~KResourceLimit() override; void Initialize(const Core::Timing::CoreTiming* core_timing_); - virtual void Finalize() override; + void Finalize() override; s64 GetLimitValue(LimitableResource which) const; s64 GetCurrentValue(LimitableResource which) const; diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index d1a757ec3..55481d63f 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h @@ -25,12 +25,9 @@ class SessionRequestHandler; class KServerPort final : public KSynchronizationObject { KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject); -private: - using SessionList = boost::intrusive::list<KServerSession>; - public: explicit KServerPort(KernelCore& kernel_); - virtual ~KServerPort() override; + ~KServerPort() override; void Initialize(KPort* parent_, std::string&& name_); @@ -63,13 +60,14 @@ public: bool IsLight() const; // Overridden virtual functions. - virtual void Destroy() override; - virtual bool IsSignaled() const override; + void Destroy() override; + bool IsSignaled() const override; private: + using SessionList = boost::intrusive::list<KServerSession>; + void CleanupSessions(); -private: SessionList session_list; SessionRequestHandlerPtr session_handler; KPort* parent{}; diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index dd4de2904..27b757ad2 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h @@ -42,9 +42,9 @@ class KServerSession final : public KSynchronizationObject, public: explicit KServerSession(KernelCore& kernel_); - virtual ~KServerSession() override; + ~KServerSession() override; - virtual void Destroy() override; + void Destroy() override; void Initialize(KSession* parent_, std::string&& name_); @@ -56,7 +56,7 @@ public: return parent; } - virtual bool IsSignaled() const override; + bool IsSignaled() const override; void OnClientClosed(); diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index a981fd1f6..4ddd080d2 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h @@ -18,17 +18,17 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAut public: explicit KSession(KernelCore& kernel_); - virtual ~KSession() override; + ~KSession() override; void Initialize(KClientPort* port_, const std::string& name_); - virtual void Finalize() override; + void Finalize() override; - virtual bool IsInitialized() const override { + bool IsInitialized() const override { return initialized; } - virtual uintptr_t GetPostDestroyArgument() const override { + uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(process); } @@ -78,7 +78,6 @@ private: ServerClosed = 3, }; -private: void SetState(State state) { atomic_state = static_cast<u8>(state); } @@ -87,7 +86,6 @@ private: return static_cast<State>(atomic_state.load(std::memory_order_relaxed)); } -private: KServerSession server; KClientSession client; std::atomic<std::underlying_type_t<State>> atomic_state{ diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 553a56327..e9815f90b 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h @@ -68,9 +68,9 @@ public: return device_memory->GetPointer(physical_address + offset); } - virtual void Finalize() override; + void Finalize() override; - virtual bool IsInitialized() const override { + bool IsInitialized() const override { return is_initialized; } static void PostDestroy([[maybe_unused]] uintptr_t arg) {} diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index 81d472a3e..0ad74b0a0 100644 --- a/src/core/hle/kernel/k_slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h @@ -4,34 +4,213 @@ #pragma once +#include <atomic> + +#include "common/assert.h" +#include "common/common_types.h" + namespace Kernel { class KernelCore; -/// This is a placeholder class to manage slab heaps for kernel objects. For now, we just allocate -/// these with new/delete, but this can be re-implemented later to allocate these in emulated -/// memory. +namespace impl { + +class KSlabHeapImpl final : NonCopyable { +public: + struct Node { + Node* next{}; + }; + + constexpr KSlabHeapImpl() = default; + + void Initialize(std::size_t size) { + ASSERT(head == nullptr); + obj_size = size; + } + + constexpr std::size_t GetObjectSize() const { + return obj_size; + } + + Node* GetHead() const { + return head; + } + + void* Allocate() { + Node* ret = head.load(); + + do { + if (ret == nullptr) { + break; + } + } while (!head.compare_exchange_weak(ret, ret->next)); + + return ret; + } + + void Free(void* obj) { + Node* node = static_cast<Node*>(obj); + + Node* cur_head = head.load(); + do { + node->next = cur_head; + } while (!head.compare_exchange_weak(cur_head, node)); + } + +private: + std::atomic<Node*> head{}; + std::size_t obj_size{}; +}; + +} // namespace impl + +class KSlabHeapBase : NonCopyable { +public: + constexpr KSlabHeapBase() = default; + + constexpr bool Contains(uintptr_t addr) const { + return start <= addr && addr < end; + } + + constexpr std::size_t GetSlabHeapSize() const { + return (end - start) / GetObjectSize(); + } + + constexpr std::size_t GetObjectSize() const { + return impl.GetObjectSize(); + } + + constexpr uintptr_t GetSlabHeapAddress() const { + return start; + } + + std::size_t GetObjectIndexImpl(const void* obj) const { + return (reinterpret_cast<uintptr_t>(obj) - start) / GetObjectSize(); + } + + std::size_t GetPeakIndex() const { + return GetObjectIndexImpl(reinterpret_cast<const void*>(peak)); + } + + void* AllocateImpl() { + return impl.Allocate(); + } + + void FreeImpl(void* obj) { + // Don't allow freeing an object that wasn't allocated from this heap + ASSERT(Contains(reinterpret_cast<uintptr_t>(obj))); + + impl.Free(obj); + } + + void InitializeImpl(std::size_t obj_size, void* memory, std::size_t memory_size) { + // Ensure we don't initialize a slab using null memory + ASSERT(memory != nullptr); + + // Initialize the base allocator + impl.Initialize(obj_size); + + // Set our tracking variables + const std::size_t num_obj = (memory_size / obj_size); + start = reinterpret_cast<uintptr_t>(memory); + end = start + num_obj * obj_size; + peak = start; + + // Free the objects + u8* cur = reinterpret_cast<u8*>(end); + + for (std::size_t i{}; i < num_obj; i++) { + cur -= obj_size; + impl.Free(cur); + } + } + +private: + using Impl = impl::KSlabHeapImpl; + + Impl impl; + uintptr_t peak{}; + uintptr_t start{}; + uintptr_t end{}; +}; template <typename T> -class KSlabHeap final : NonCopyable { +class KSlabHeap final : public KSlabHeapBase { public: - KSlabHeap() = default; + enum class AllocationType { + Host, + Guest, + }; - void Initialize([[maybe_unused]] void* memory, [[maybe_unused]] std::size_t memory_size) { - // Placeholder that should initialize the backing slab heap implementation. + explicit constexpr KSlabHeap(AllocationType allocation_type_ = AllocationType::Host) + : KSlabHeapBase(), allocation_type{allocation_type_} {} + + void Initialize(void* memory, std::size_t memory_size) { + if (allocation_type == AllocationType::Guest) { + InitializeImpl(sizeof(T), memory, memory_size); + } } T* Allocate() { - return new T(); + switch (allocation_type) { + case AllocationType::Host: + // Fallback for cases where we do not yet support allocating guest memory from the slab + // heap, such as for kernel memory regions. + return new T; + + case AllocationType::Guest: + T* obj = static_cast<T*>(AllocateImpl()); + if (obj != nullptr) { + new (obj) T(); + } + return obj; + } + + UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type); + return nullptr; } T* AllocateWithKernel(KernelCore& kernel) { - return new T(kernel); + switch (allocation_type) { + case AllocationType::Host: + // Fallback for cases where we do not yet support allocating guest memory from the slab + // heap, such as for kernel memory regions. + return new T(kernel); + + case AllocationType::Guest: + T* obj = static_cast<T*>(AllocateImpl()); + if (obj != nullptr) { + new (obj) T(kernel); + } + return obj; + } + + UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type); + return nullptr; } void Free(T* obj) { - delete obj; + switch (allocation_type) { + case AllocationType::Host: + // Fallback for cases where we do not yet support allocating guest memory from the slab + // heap, such as for kernel memory regions. + delete obj; + return; + + case AllocationType::Guest: + FreeImpl(obj); + return; + } + + UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type); } + + constexpr std::size_t GetObjectIndex(const T* obj) const { + return GetObjectIndexImpl(obj); + } + +private: + const AllocationType allocation_type; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index a41dd1220..3d4ce1fbc 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -29,7 +29,7 @@ public: KSynchronizationObject** objects, const s32 num_objects, s64 timeout); - virtual void Finalize() override; + void Finalize() override; [[nodiscard]] virtual bool IsSignaled() const = 0; @@ -37,7 +37,7 @@ public: protected: explicit KSynchronizationObject(KernelCore& kernel); - virtual ~KSynchronizationObject(); + ~KSynchronizationObject() override; virtual void OnFinalizeSynchronizationObject() {} diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index e3f08f256..3cf43d290 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -168,13 +168,13 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0, sizeof(StackParameters)); - // Setup the TLS, if needed. - if (type == ThreadType::User) { - tls_address = owner->CreateTLSRegion(); - } - // Set parent, if relevant. if (owner != nullptr) { + // Setup the TLS, if needed. + if (type == ThreadType::User) { + tls_address = owner->CreateTLSRegion(); + } + parent = owner; parent->Open(); parent->IncrementThreadCount(); diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 4abfc2b49..01eebb165 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -358,21 +358,21 @@ public: return termination_requested || GetRawState() == ThreadState::Terminated; } - [[nodiscard]] virtual u64 GetId() const override final { + [[nodiscard]] u64 GetId() const override { return this->GetThreadID(); } - [[nodiscard]] virtual bool IsInitialized() const override { + [[nodiscard]] bool IsInitialized() const override { return initialized; } - [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override { + [[nodiscard]] uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0); } - virtual void Finalize() override; + void Finalize() override; - [[nodiscard]] virtual bool IsSignaled() const override; + [[nodiscard]] bool IsSignaled() const override; static void PostDestroy(uintptr_t arg); diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index c2d0f1eaf..31029a5c2 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h @@ -27,23 +27,23 @@ class KTransferMemory final public: explicit KTransferMemory(KernelCore& kernel_); - virtual ~KTransferMemory() override; + ~KTransferMemory() override; ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); - virtual void Finalize() override; + void Finalize() override; - virtual bool IsInitialized() const override { + bool IsInitialized() const override { return is_initialized; } - virtual uintptr_t GetPostDestroyArgument() const override { + uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(owner); } static void PostDestroy(uintptr_t arg); - KProcess* GetOwner() const { + KProcess* GetOwner() const override { return owner; } diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h index 607b0eadb..858d982c4 100644 --- a/src/core/hle/kernel/k_writable_event.h +++ b/src/core/hle/kernel/k_writable_event.h @@ -21,7 +21,7 @@ public: explicit KWritableEvent(KernelCore& kernel_); ~KWritableEvent() override; - virtual void Destroy() override; + void Destroy() override; static void PostDestroy([[maybe_unused]] uintptr_t arg) {} diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 8b55df82e..0ffb78d51 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -258,7 +258,7 @@ struct KernelCore::Impl { KAutoObject::Create(thread.get()); ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess()); thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); - return std::move(thread); + return thread; }; thread_local auto thread = make_thread(); @@ -620,7 +620,8 @@ struct KernelCore::Impl { void InitializePageSlab() { // Allocate slab heaps - user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); + user_slab_heap_pages = + std::make_unique<KSlabHeap<Page>>(KSlabHeap<Page>::AllocationType::Guest); // TODO(ameerj): This should be derived, not hardcoded within the kernel constexpr u64 user_slab_heap_size{0x3de000}; diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index de971041f..9e6b87960 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -596,7 +596,7 @@ void BufferCache<P>::PopAsyncFlushes() { runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies); } runtime.Finish(); - for (const auto [copy, buffer_id] : downloads) { + for (const auto& [copy, buffer_id] : downloads) { const Buffer& buffer = slot_buffers[buffer_id]; const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; // Undo the modified offset @@ -606,7 +606,7 @@ void BufferCache<P>::PopAsyncFlushes() { } } else { const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); - for (const auto [copy, buffer_id] : downloads) { + for (const auto& [copy, buffer_id] : downloads) { Buffer& buffer = slot_buffers[buffer_id]; buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size)); const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; |