Merge remote-tracking branch 'bwr/linux_memory' into canary
This commit is contained in:
commit
f40a34eb53
|
@ -99,7 +99,7 @@ typedef void* FileMappingHandle;
|
|||
|
||||
FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length,
|
||||
PageAccess access, bool commit);
|
||||
void CloseFileMappingHandle(FileMappingHandle handle);
|
||||
void CloseFileMappingHandle(FileMappingHandle handle, std::wstring path);
|
||||
void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
|
||||
PageAccess access, size_t file_offset);
|
||||
bool UnmapFileView(FileMappingHandle handle, void* base_address, size_t length);
|
||||
|
|
|
@ -87,7 +87,8 @@ FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length,
|
|||
}
|
||||
|
||||
oflag |= O_CREAT;
|
||||
int ret = shm_open(xe::to_string(path).c_str(), oflag, 0777);
|
||||
std::string full_path = "/" + xe::to_string(path);
|
||||
int ret = shm_open(full_path.c_str(), oflag, 0777);
|
||||
if (ret > 0) {
|
||||
ftruncate64(ret, length);
|
||||
}
|
||||
|
@ -95,8 +96,9 @@ FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length,
|
|||
return ret <= 0 ? nullptr : reinterpret_cast<FileMappingHandle>(ret);
|
||||
}
|
||||
|
||||
void CloseFileMappingHandle(FileMappingHandle handle) {
|
||||
close(static_cast<int>(reinterpret_cast<int64_t>(handle)));
|
||||
void CloseFileMappingHandle(FileMappingHandle handle, std::wstring path) {
|
||||
std::string full_path = "/" + xe::to_string(path);
|
||||
shm_unlink(full_path.c_str());
|
||||
}
|
||||
|
||||
void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
|
||||
|
|
|
@ -146,12 +146,15 @@ FileMappingHandle CreateFileMappingHandle(std::wstring path, size_t length,
|
|||
PageAccess access, bool commit) {
|
||||
DWORD protect =
|
||||
ToWin32ProtectFlags(access) | (commit ? SEC_COMMIT : SEC_RESERVE);
|
||||
std::wstring full_path = L"Local\\" + path;
|
||||
return CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, protect,
|
||||
static_cast<DWORD>(length >> 32),
|
||||
static_cast<DWORD>(length), path.c_str());
|
||||
static_cast<DWORD>(length), full_path.c_str());
|
||||
}
|
||||
|
||||
void CloseFileMappingHandle(FileMappingHandle handle) { CloseHandle(handle); }
|
||||
void CloseFileMappingHandle(FileMappingHandle handle, std::wstring path) {
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
|
||||
PageAccess access, size_t file_offset) {
|
||||
|
|
|
@ -414,6 +414,55 @@ TEST_CASE("copy_and_swap_16_in_32_unaligned", "Copy and Swap") {
|
|||
REQUIRE(true == true);
|
||||
}
|
||||
|
||||
TEST_CASE("create_and_close_file_mapping", "Virtual Memory Mapping") {
|
||||
auto memory = xe::memory::CreateFileMappingHandle(
|
||||
L"test", 0x100, xe::memory::PageAccess::kReadWrite, false);
|
||||
REQUIRE(memory);
|
||||
xe::memory::CloseFileMappingHandle(memory, L"test");
|
||||
}
|
||||
|
||||
TEST_CASE("map_view", "Virtual Memory Mapping") {
|
||||
const size_t length = 0x100;
|
||||
auto memory = xe::memory::CreateFileMappingHandle(
|
||||
L"test", length, xe::memory::PageAccess::kReadWrite, false);
|
||||
REQUIRE(memory);
|
||||
|
||||
uintptr_t address = 0x100000000;
|
||||
auto view =
|
||||
xe::memory::MapFileView(memory, reinterpret_cast<void*>(address), length,
|
||||
xe::memory::PageAccess::kReadWrite, 0);
|
||||
REQUIRE(reinterpret_cast<uintptr_t>(view) == address);
|
||||
|
||||
xe::memory::UnmapFileView(memory, reinterpret_cast<void*>(address), length);
|
||||
xe::memory::CloseFileMappingHandle(memory, L"test");
|
||||
}
|
||||
|
||||
TEST_CASE("read_write_view", "Virtual Memory Mapping") {
|
||||
const size_t length = 0x100;
|
||||
auto memory = xe::memory::CreateFileMappingHandle(
|
||||
L"test", length, xe::memory::PageAccess::kReadWrite, false);
|
||||
REQUIRE(memory);
|
||||
|
||||
uintptr_t address = 0x100000000;
|
||||
auto view =
|
||||
xe::memory::MapFileView(memory, reinterpret_cast<void*>(address), length,
|
||||
xe::memory::PageAccess::kReadWrite, 0);
|
||||
REQUIRE(reinterpret_cast<uintptr_t>(view) == address);
|
||||
|
||||
for (uint32_t i = 0; i < length; i += sizeof(uint8_t)) {
|
||||
auto p_value = reinterpret_cast<uint8_t*>(address + i);
|
||||
*p_value = i;
|
||||
}
|
||||
for (uint32_t i = 0; i < length; i += sizeof(uint8_t)) {
|
||||
auto p_value = reinterpret_cast<uint8_t*>(address + i);
|
||||
uint8_t value = *p_value;
|
||||
REQUIRE(value == i);
|
||||
}
|
||||
|
||||
xe::memory::UnmapFileView(memory, reinterpret_cast<void*>(address), length);
|
||||
xe::memory::CloseFileMappingHandle(memory, L"test");
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace base
|
||||
} // namespace xe
|
||||
|
|
|
@ -42,7 +42,7 @@ X64CodeCache::~X64CodeCache() {
|
|||
if (mapping_) {
|
||||
xe::memory::UnmapFileView(mapping_, generated_code_base_,
|
||||
kGeneratedCodeSize);
|
||||
xe::memory::CloseFileMappingHandle(mapping_);
|
||||
xe::memory::CloseFileMappingHandle(mapping_, file_name_);
|
||||
mapping_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ bool X64CodeCache::Initialize() {
|
|||
}
|
||||
|
||||
// Create mmap file. This allows us to share the code cache with the debugger.
|
||||
file_name_ = std::wstring(L"Local\\xenia_code_cache_") +
|
||||
file_name_ = std::wstring(L"xenia_code_cache_") +
|
||||
std::to_wstring(Clock::QueryHostTickCount());
|
||||
mapping_ = xe::memory::CreateFileMappingHandle(
|
||||
file_name_, kGeneratedCodeSize, xe::memory::PageAccess::kExecuteReadWrite,
|
||||
|
|
|
@ -147,7 +147,7 @@ class Param {
|
|||
|
||||
protected:
|
||||
Param() : ordinal_(-1) {}
|
||||
explicit Param(Init& init) : ordinal_(--init.ordinal) {}
|
||||
explicit Param(Init& init) : ordinal_(init.ordinal++) {}
|
||||
|
||||
template <typename V>
|
||||
void LoadValue(Init& init, V* out_value) {
|
||||
|
@ -518,10 +518,13 @@ xe::cpu::Export* RegisterExport(R (*fn)(Ps&...), const char* name,
|
|||
++export_entry->function_data.call_count;
|
||||
Param::Init init = {
|
||||
ppc_context,
|
||||
sizeof...(Ps),
|
||||
0,
|
||||
};
|
||||
auto params = std::make_tuple<Ps...>(Ps(init)...);
|
||||
// Using braces initializer instead of make_tuple because braces
|
||||
// enforce execution order across compilers.
|
||||
// The make_tuple order is undefined per the C++ standard and
|
||||
// cause inconsitencies between msvc and clang.
|
||||
std::tuple<Ps...> params = {Ps(init)...};
|
||||
if (export_entry->tags & xe::cpu::ExportTag::kLog &&
|
||||
(!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) ||
|
||||
cvars::log_high_frequency_kernel_calls)) {
|
||||
|
@ -553,9 +556,13 @@ xe::cpu::Export* RegisterExport(void (*fn)(Ps&...), const char* name,
|
|||
++export_entry->function_data.call_count;
|
||||
Param::Init init = {
|
||||
ppc_context,
|
||||
sizeof...(Ps),
|
||||
0,
|
||||
};
|
||||
auto params = std::make_tuple<Ps...>(Ps(init)...);
|
||||
// Using braces initializer instead of make_tuple because braces
|
||||
// enforce execution order across compilers.
|
||||
// The make_tuple order is undefined per the C++ standard and
|
||||
// cause inconsitencies between msvc and clang.
|
||||
std::tuple<Ps...> params = {Ps(init)...};
|
||||
if (export_entry->tags & xe::cpu::ExportTag::kLog &&
|
||||
(!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) ||
|
||||
cvars::log_high_frequency_kernel_calls)) {
|
||||
|
|
|
@ -112,7 +112,7 @@ Memory::~Memory() {
|
|||
// Unmap all views and close mapping.
|
||||
if (mapping_) {
|
||||
UnmapViews();
|
||||
xe::memory::CloseFileMappingHandle(mapping_);
|
||||
xe::memory::CloseFileMappingHandle(mapping_, file_name_);
|
||||
mapping_base_ = nullptr;
|
||||
mapping_ = nullptr;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ Memory::~Memory() {
|
|||
}
|
||||
|
||||
bool Memory::Initialize() {
|
||||
file_name_ = std::wstring(L"Local\\xenia_memory_") +
|
||||
file_name_ = std::wstring(L"xenia_memory_") +
|
||||
std::to_wstring(Clock::QueryHostTickCount());
|
||||
|
||||
// Create main page file-backed mapping. This is all reserved but
|
||||
|
|
Loading…
Reference in New Issue