mem: implement most of StandardAllocator (#860)

This was tested using `https://github.com/node-dot-cpp/alloc-test` plus a few other by-hand tests.

It seems to work for the case we care about (sysmodules without thread cache-ing).

External users are advised to build with assertions on and contact SciresM if you find issues.

This is a lot of code to have gotten right in one go, and it was written mostly after midnight while sick, so there are probably un-noticed issues.
This commit is contained in:
SciresM 2020-03-29 14:43:16 -07:00 committed by GitHub
parent 7502e2174f
commit 87ec045a98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 5473 additions and 43 deletions

View file

@ -0,0 +1,23 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::os::impl {
void SetMemoryPermissionImpl(uintptr_t address, size_t size, MemoryPermission perm);
}

View file

@ -0,0 +1,55 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
namespace ams::os::impl {
namespace {
void SetMemoryPermissionBySvc(uintptr_t start, size_t size, svc::MemoryPermission perm) {
uintptr_t cur_address = start;
size_t remaining_size = size;
while (remaining_size > 0) {
svc::MemoryInfo mem_info;
svc::PageInfo page_info;
R_ABORT_UNLESS(svc::QueryMemory(std::addressof(mem_info), std::addressof(page_info), cur_address));
size_t cur_size = std::min(mem_info.addr + mem_info.size - cur_address, remaining_size);
if (mem_info.perm != perm) {
R_ABORT_UNLESS(svc::SetMemoryPermission(cur_address, cur_size, perm));
}
cur_address += cur_size;
remaining_size -= cur_size;
}
}
}
void SetMemoryPermissionImpl(uintptr_t address, size_t size, MemoryPermission perm) {
switch (perm) {
case MemoryPermission_None:
return SetMemoryPermissionBySvc(address, size, svc::MemoryPermission_None);
case MemoryPermission_ReadOnly:
return SetMemoryPermissionBySvc(address, size, svc::MemoryPermission_Read);
case MemoryPermission_ReadWrite:
return SetMemoryPermissionBySvc(address, size, svc::MemoryPermission_ReadWrite);
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
}

View file

@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
namespace ams::os {
Result AllocateMemoryBlock(uintptr_t *out_address, size_t size) {
AMS_ABORT("Not implemented yet");
}
void FreeMemoryBlock(uintptr_t address, size_t size) {
AMS_ABORT("Not implemented yet");
}
}

View file

@ -0,0 +1,25 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "impl/os_memory_permission_impl.hpp"
namespace ams::os {
void SetMemoryPermission(uintptr_t address, size_t size, MemoryPermission perm) {
return impl::SetMemoryPermissionImpl(address, size, perm);
}
}

View file

@ -0,0 +1,48 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
namespace ams::os {
/* TODO: How will this work without libnx? */
namespace {
using LibnxTlsDestructor = void (*)(void *);
}
Result AllocateTlsSlot(TlsSlot *out, TlsDestructor destructor) {
s32 slot = ::threadTlsAlloc(reinterpret_cast<LibnxTlsDestructor>(destructor));
R_UNLESS(slot >= 0, os::ResultOutOfResource());
*out = { static_cast<u32>(slot) };
return ResultSuccess();
}
void FreeTlsSlot(TlsSlot slot) {
::threadTlsFree(static_cast<s32>(slot._value));
}
uintptr_t GetTlsValue(TlsSlot slot) {
return reinterpret_cast<uintptr_t>(::threadTlsGet(static_cast<s32>(slot._value)));
}
void SetTlsValue(TlsSlot slot, uintptr_t value) {
::threadTlsSet(static_cast<s32>(slot._value), reinterpret_cast<void *>(value));
}
}

View file

@ -0,0 +1,38 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
namespace ams::os {
namespace {
/* TODO: Remove, add VammManager */
size_t GetSystemResourceSize() {
u64 v;
if (R_SUCCEEDED(svcGetInfo(std::addressof(v), InfoType_SystemResourceSizeTotal, CUR_PROCESS_HANDLE, 0))) {
return v;
} else {
return 0;
}
}
}
bool IsVirtualAddressMemoryEnabled() {
return GetSystemResourceSize() > 0;
}
}