From 9e520e8f1233cb4e586b076cd5cc8b7c22ec85ce Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 12 Feb 2021 16:21:12 -0800 Subject: hle: kernel: Migrate SlabHeap to KSlabHeap. --- src/core/hle/kernel/k_slab_heap.h | 160 ++++++++++++++++++++++++++++++++ src/core/hle/kernel/kernel.cpp | 10 +- src/core/hle/kernel/kernel.h | 10 +- src/core/hle/kernel/memory/slab_heap.h | 163 --------------------------------- 4 files changed, 171 insertions(+), 172 deletions(-) create mode 100644 src/core/hle/kernel/k_slab_heap.h delete mode 100644 src/core/hle/kernel/memory/slab_heap.h (limited to 'src/core/hle') diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h new file mode 100644 index 000000000..aa4471d2f --- /dev/null +++ b/src/core/hle/kernel/k_slab_heap.h @@ -0,0 +1,160 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/assert.h" +#include "common/common_types.h" + +namespace Kernel { + +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(obj); + + Node* cur_head = head.load(); + do { + node->next = cur_head; + } while (!head.compare_exchange_weak(cur_head, node)); + } + +private: + std::atomic 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(obj) - start) / GetObjectSize(); + } + + std::size_t GetPeakIndex() const { + return GetObjectIndexImpl(reinterpret_cast(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(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(memory); + end = start + num_obj * obj_size; + peak = start; + + // Free the objects + u8* cur = reinterpret_cast(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 +class KSlabHeap final : public KSlabHeapBase { +public: + constexpr KSlabHeap() : KSlabHeapBase() {} + + void Initialize(void* memory, std::size_t memory_size) { + InitializeImpl(sizeof(T), memory, memory_size); + } + + T* Allocate() { + T* obj = static_cast(AllocateImpl()); + if (obj != nullptr) { + new (obj) T(); + } + return obj; + } + + void Free(T* obj) { + FreeImpl(obj); + } + + constexpr std::size_t GetObjectIndex(const T* obj) const { + return GetObjectIndexImpl(obj); + } +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 98b3ec712..e4de3f3bf 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -31,10 +31,10 @@ #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/kernel/k_slab_heap.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory/memory_manager.h" -#include "core/hle/kernel/memory/slab_heap.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/service_thread.h" @@ -306,7 +306,7 @@ struct KernelCore::Impl { Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory"); // Allocate slab heaps - user_slab_heap_pages = std::make_unique>(); + user_slab_heap_pages = std::make_unique>(); constexpr u64 user_slab_heap_size{0x1ef000}; // Reserve slab heaps @@ -349,7 +349,7 @@ struct KernelCore::Impl { // Kernel memory management std::unique_ptr memory_manager; - std::unique_ptr> user_slab_heap_pages; + std::unique_ptr> user_slab_heap_pages; // Shared memory for services std::shared_ptr hid_shared_mem; @@ -581,11 +581,11 @@ const Memory::MemoryManager& KernelCore::MemoryManager() const { return *impl->memory_manager; } -Memory::SlabHeap& KernelCore::GetUserSlabHeapPages() { +KSlabHeap& KernelCore::GetUserSlabHeapPages() { return *impl->user_slab_heap_pages; } -const Memory::SlabHeap& KernelCore::GetUserSlabHeapPages() const { +const KSlabHeap& KernelCore::GetUserSlabHeapPages() const { return *impl->user_slab_heap_pages; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index c5b32b260..5488c962a 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -29,8 +29,7 @@ namespace Kernel { namespace Memory { class MemoryManager; -template -class SlabHeap; + } // namespace Memory class ClientPort; @@ -46,6 +45,9 @@ class Synchronization; class KThread; class TimeManager; +template +class KSlabHeap; + using EmuThreadHandle = uintptr_t; constexpr EmuThreadHandle EmuThreadHandleInvalid{}; constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63}; @@ -184,10 +186,10 @@ public: const Memory::MemoryManager& MemoryManager() const; /// Gets the slab heap allocated for user space pages. - Memory::SlabHeap& GetUserSlabHeapPages(); + KSlabHeap& GetUserSlabHeapPages(); /// Gets the slab heap allocated for user space pages. - const Memory::SlabHeap& GetUserSlabHeapPages() const; + const KSlabHeap& GetUserSlabHeapPages() const; /// Gets the shared memory object for HID services. Kernel::KSharedMemory& GetHidSharedMem(); diff --git a/src/core/hle/kernel/memory/slab_heap.h b/src/core/hle/kernel/memory/slab_heap.h deleted file mode 100644 index 465eaddb3..000000000 --- a/src/core/hle/kernel/memory/slab_heap.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2020 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -// This file references various implementation details from Atmosphere, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. - -#pragma once - -#include - -#include "common/assert.h" -#include "common/common_types.h" - -namespace Kernel::Memory { - -namespace impl { - -class SlabHeapImpl final : NonCopyable { -public: - struct Node { - Node* next{}; - }; - - constexpr SlabHeapImpl() = 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(obj); - - Node* cur_head = head.load(); - do { - node->next = cur_head; - } while (!head.compare_exchange_weak(cur_head, node)); - } - -private: - std::atomic head{}; - std::size_t obj_size{}; -}; - -} // namespace impl - -class SlabHeapBase : NonCopyable { -public: - constexpr SlabHeapBase() = 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(obj) - start) / GetObjectSize(); - } - - std::size_t GetPeakIndex() const { - return GetObjectIndexImpl(reinterpret_cast(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(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(memory); - end = start + num_obj * obj_size; - peak = start; - - // Free the objects - u8* cur = reinterpret_cast(end); - - for (std::size_t i{}; i < num_obj; i++) { - cur -= obj_size; - impl.Free(cur); - } - } - -private: - using Impl = impl::SlabHeapImpl; - - Impl impl; - uintptr_t peak{}; - uintptr_t start{}; - uintptr_t end{}; -}; - -template -class SlabHeap final : public SlabHeapBase { -public: - constexpr SlabHeap() : SlabHeapBase() {} - - void Initialize(void* memory, std::size_t memory_size) { - InitializeImpl(sizeof(T), memory, memory_size); - } - - T* Allocate() { - T* obj = static_cast(AllocateImpl()); - if (obj != nullptr) { - new (obj) T(); - } - return obj; - } - - void Free(T* obj) { - FreeImpl(obj); - } - - constexpr std::size_t GetObjectIndex(const T* obj) const { - return GetObjectIndexImpl(obj); - } -}; - -} // namespace Kernel::Memory -- cgit v1.2.3