diff options
author | bunnei <bunneidev@gmail.com> | 2022-03-11 09:36:33 +0100 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2022-03-15 02:14:53 +0100 |
commit | 91819726b1517d24fe02ba24edaadc9ec974fd1d (patch) | |
tree | a176f075030116f59e361cb2d47f5656b7a38fee /src/core/hle/kernel/k_thread_local_page.cpp | |
parent | core: hle: kernel: k_page_buffer: Add KPageBuffer primitive. (diff) | |
download | yuzu-91819726b1517d24fe02ba24edaadc9ec974fd1d.tar yuzu-91819726b1517d24fe02ba24edaadc9ec974fd1d.tar.gz yuzu-91819726b1517d24fe02ba24edaadc9ec974fd1d.tar.bz2 yuzu-91819726b1517d24fe02ba24edaadc9ec974fd1d.tar.lz yuzu-91819726b1517d24fe02ba24edaadc9ec974fd1d.tar.xz yuzu-91819726b1517d24fe02ba24edaadc9ec974fd1d.tar.zst yuzu-91819726b1517d24fe02ba24edaadc9ec974fd1d.zip |
Diffstat (limited to 'src/core/hle/kernel/k_thread_local_page.cpp')
-rw-r--r-- | src/core/hle/kernel/k_thread_local_page.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/core/hle/kernel/k_thread_local_page.cpp b/src/core/hle/kernel/k_thread_local_page.cpp new file mode 100644 index 000000000..4653c29f6 --- /dev/null +++ b/src/core/hle/kernel/k_thread_local_page.cpp @@ -0,0 +1,65 @@ +// Copyright 2022 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/scope_exit.h" +#include "core/hle/kernel/k_memory_block.h" +#include "core/hle/kernel/k_page_table.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_thread_local_page.h" +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +ResultCode KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) { + // Set that this process owns us. + m_owner = process; + m_kernel = &kernel; + + // Allocate a new page. + KPageBuffer* page_buf = KPageBuffer::Allocate(kernel); + R_UNLESS(page_buf != nullptr, ResultOutOfMemory); + auto page_buf_guard = SCOPE_GUARD({ KPageBuffer::Free(kernel, page_buf); }); + + // Map the address in. + const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf); + R_TRY(m_owner->PageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr, + KMemoryState::ThreadLocal, + KMemoryPermission::UserReadWrite)); + + // We succeeded. + page_buf_guard.Cancel(); + + return ResultSuccess; +} + +ResultCode KThreadLocalPage::Finalize() { + // Get the physical address of the page. + const PAddr phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr); + ASSERT(phys_addr); + + // Unmap the page. + R_TRY(m_owner->PageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal)); + + // Free the page. + KPageBuffer::Free(*m_kernel, KPageBuffer::FromPhysicalAddress(m_kernel->System(), phys_addr)); + + return ResultSuccess; +} + +VAddr KThreadLocalPage::Reserve() { + for (size_t i = 0; i < m_is_region_free.size(); i++) { + if (m_is_region_free[i]) { + m_is_region_free[i] = false; + return this->GetRegionAddress(i); + } + } + + return 0; +} + +void KThreadLocalPage::Release(VAddr addr) { + m_is_region_free[this->GetRegionIndex(addr)] = true; +} + +} // namespace Kernel |