From 970b85bf9a21b86df3f57eb8eaa8c5d2ab331cde Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 26 Apr 2020 02:35:10 -0700 Subject: [PATCH] kern: implement KUnsafeMemory --- .../libmesosphere/include/mesosphere.hpp | 1 + .../mesosphere/kern_k_unsafe_memory.hpp | 78 +++++++++++++++++++ .../include/mesosphere/kern_kernel.hpp | 6 ++ .../source/kern_kernel_instantiations.cpp | 1 + 4 files changed, 86 insertions(+) create mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_unsafe_memory.hpp diff --git a/libraries/libmesosphere/include/mesosphere.hpp b/libraries/libmesosphere/include/mesosphere.hpp index ab2d02bcd..279eb2a0a 100644 --- a/libraries/libmesosphere/include/mesosphere.hpp +++ b/libraries/libmesosphere/include/mesosphere.hpp @@ -79,6 +79,7 @@ /* More Miscellaneous objects. */ #include +#include #include /* Supervisor Calls. */ diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_unsafe_memory.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_unsafe_memory.hpp new file mode 100644 index 000000000..713d240fd --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/kern_k_unsafe_memory.hpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include + +namespace ams::kern { + + class KUnsafeMemory { + private: + mutable KLightLock lock; + size_t limit_size; + size_t current_size; + public: + constexpr KUnsafeMemory() : lock(), limit_size(), current_size() { /* ... */ } + + bool TryReserve(size_t size) { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); + + /* Test for overflow. */ + if (this->current_size > this->current_size + size) { + return false; + } + + /* Test for limit allowance. */ + if (this->current_size + size > this->limit_size) { + return false; + } + + /* Reserve the size. */ + this->current_size += size; + return true; + } + + void Release(size_t size) { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); + + MESOSPHERE_ABORT_UNLESS(this->current_size >= size); + this->current_size -= size; + } + + size_t GetLimitSize() const { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); + return this->limit_size; + } + + size_t GetCurrentSize() const { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); + return this->current_size; + } + + Result SetLimitSize(size_t size) { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); + + R_UNLESS(size >= this->current_size, svc::ResultLimitReached()); + this->limit_size = size; + return ResultSuccess(); + } + }; +} diff --git a/libraries/libmesosphere/include/mesosphere/kern_kernel.hpp b/libraries/libmesosphere/include/mesosphere/kern_kernel.hpp index 5fba52000..4d4845240 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_kernel.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_kernel.hpp @@ -35,6 +35,7 @@ namespace ams::kern { class KMemoryBlockSlabManager; class KBlockInfoManager; class KSynchronization; + class KUnsafeMemory; @@ -72,6 +73,7 @@ namespace ams::kern { static KBlockInfoManager s_block_info_manager; static KSupervisorPageTable s_supervisor_page_table; static KSynchronization s_synchronization; + static KUnsafeMemory s_unsafe_memory; static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count]; private: static ALWAYS_INLINE KCoreLocalContext &GetCoreLocalContext() { @@ -144,6 +146,10 @@ namespace ams::kern { return s_synchronization; } + static ALWAYS_INLINE KUnsafeMemory &GetUnsafeMemory() { + return s_unsafe_memory; + } + static ALWAYS_INLINE KWorkerTaskManager &GetWorkerTaskManager(KWorkerTaskManager::WorkerType type) { MESOSPHERE_ASSERT(type <= KWorkerTaskManager::WorkerType_Count); return s_worker_task_managers[type]; diff --git a/mesosphere/kernel/source/kern_kernel_instantiations.cpp b/mesosphere/kernel/source/kern_kernel_instantiations.cpp index 33272a4f2..743dc5596 100644 --- a/mesosphere/kernel/source/kern_kernel_instantiations.cpp +++ b/mesosphere/kernel/source/kern_kernel_instantiations.cpp @@ -27,6 +27,7 @@ namespace ams::kern { KBlockInfoManager Kernel::s_block_info_manager; KSupervisorPageTable Kernel::s_supervisor_page_table; KSynchronization Kernel::s_synchronization; + KUnsafeMemory Kernel::s_unsafe_memory; KWorkerTaskManager Kernel::s_worker_task_managers[KWorkerTaskManager::WorkerType_Count]; namespace {