// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_auto_object_container.h" #include "core/hle/kernel/kernel.h" namespace Kernel { template class KSlabAllocated { public: constexpr KSlabAllocated() = default; size_t GetSlabIndex(KernelCore& kernel) const { return kernel.SlabHeap().GetIndex(static_cast(this)); } public: static void InitializeSlabHeap(KernelCore& kernel, void* memory, size_t memory_size) { kernel.SlabHeap().Initialize(memory, memory_size); } static Derived* Allocate(KernelCore& kernel) { return kernel.SlabHeap().Allocate(kernel); } static void Free(KernelCore& kernel, Derived* obj) { kernel.SlabHeap().Free(obj); } static size_t GetObjectSize(KernelCore& kernel) { return kernel.SlabHeap().GetObjectSize(); } static size_t GetSlabHeapSize(KernelCore& kernel) { return kernel.SlabHeap().GetSlabHeapSize(); } static size_t GetPeakIndex(KernelCore& kernel) { return kernel.SlabHeap().GetPeakIndex(); } static uintptr_t GetSlabHeapAddress(KernelCore& kernel) { return kernel.SlabHeap().GetSlabHeapAddress(); } static size_t GetNumRemaining(KernelCore& kernel) { return kernel.SlabHeap().GetNumRemaining(); } }; template class KAutoObjectWithSlabHeapAndContainer : public Base { static_assert(std::is_base_of::value); private: static Derived* Allocate(KernelCore& kernel) { return kernel.SlabHeap().Allocate(kernel); } static void Free(KernelCore& kernel, Derived* obj) { kernel.SlabHeap().Free(obj); } public: KAutoObjectWithSlabHeapAndContainer(KernelCore& kernel_) : Base(kernel_), kernel(kernel_) {} virtual ~KAutoObjectWithSlabHeapAndContainer() {} virtual void Destroy() override { const bool is_initialized = this->IsInitialized(); uintptr_t arg = 0; if (is_initialized) { kernel.ObjectListContainer().Unregister(this); arg = this->GetPostDestroyArgument(); this->Finalize(); } Free(kernel, static_cast(this)); if (is_initialized) { Derived::PostDestroy(arg); } } virtual bool IsInitialized() const { return true; } virtual uintptr_t GetPostDestroyArgument() const { return 0; } size_t GetSlabIndex() const { return SlabHeap(kernel).GetObjectIndex(static_cast(this)); } public: static void InitializeSlabHeap(KernelCore& kernel, void* memory, size_t memory_size) { kernel.SlabHeap().Initialize(memory, memory_size); kernel.ObjectListContainer().Initialize(); } static Derived* Create(KernelCore& kernel) { Derived* obj = Allocate(kernel); if (obj != nullptr) { KAutoObject::Create(obj); } return obj; } static void Register(KernelCore& kernel, Derived* obj) { return kernel.ObjectListContainer().Register(obj); } static size_t GetObjectSize(KernelCore& kernel) { return kernel.SlabHeap().GetObjectSize(); } static size_t GetSlabHeapSize(KernelCore& kernel) { return kernel.SlabHeap().GetSlabHeapSize(); } static size_t GetPeakIndex(KernelCore& kernel) { return kernel.SlabHeap().GetPeakIndex(); } static uintptr_t GetSlabHeapAddress(KernelCore& kernel) { return kernel.SlabHeap().GetSlabHeapAddress(); } static size_t GetNumRemaining(KernelCore& kernel) { return kernel.SlabHeap().GetNumRemaining(); } protected: KernelCore& kernel; }; } // namespace Kernel