Skip to content

Commit

Permalink
Merge pull request #17610 from m4xw/memory_arena
Browse files Browse the repository at this point in the history
[Switch] Mem Arena impl and MemMap improvements
  • Loading branch information
hrydgard committed Jun 21, 2023
2 parents 14586d6 + 436b55d commit 101128a
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Common/MemArena.h
Expand Up @@ -39,7 +39,7 @@ class MemArena {
bool GrabMemSpace(size_t size);
void ReleaseSpace();
void *CreateView(s64 offset, size_t size, void *base = 0);
void ReleaseView(void *view, size_t size);
void ReleaseView(s64 offset, void *view, size_t size);

// This only finds 1 GB in 32-bit
u8 *Find4GBBase();
Expand Down
2 changes: 1 addition & 1 deletion Common/MemArenaAndroid.cpp
Expand Up @@ -129,7 +129,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) {
return retval;
}

void MemArena::ReleaseView(void* view, size_t size) {
void MemArena::ReleaseView(s64 offset, void* view, size_t size) {
munmap(view, size);
}

Expand Down
2 changes: 1 addition & 1 deletion Common/MemArenaDarwin.cpp
Expand Up @@ -79,7 +79,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base) {
return (void *)target;
}

void MemArena::ReleaseView(void* view, size_t size) {
void MemArena::ReleaseView(s64 offset, void* view, size_t size) {
vm_address_t addr = (vm_address_t)view;
vm_deallocate(mach_task_self(), addr, size);
}
Expand Down
83 changes: 83 additions & 0 deletions Common/MemArenaHorizon.cpp
@@ -0,0 +1,83 @@
// Copyright (C) 2023 M4xw

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.

// This program is distributed in the hope that 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 2.0 for more details.

// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/

#include "ppsspp_config.h"
#if PPSSPP_PLATFORM(SWITCH)

#include <stdio.h>
#include <malloc.h> // memalign
#include <switch.h>

#include "Common/MemArena.h"

static uintptr_t memoryBase = 0;
static uintptr_t memoryCodeBase = 0;
static uintptr_t memorySrcBase = 0;

size_t MemArena::roundup(size_t x) {
return x;
}

bool MemArena::NeedsProbing() {
return false;
}

bool MemArena::GrabMemSpace(size_t size) {
return true;
}

void MemArena::ReleaseSpace() {
if (R_FAILED(svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)memoryCodeBase, (u64)memorySrcBase, 0x10000000)))
printf("Failed to release view space...\n");

free((void *)memorySrcBase);
memorySrcBase = 0;
}

void *MemArena::CreateView(s64 offset, size_t size, void *base) {
Result rc = svcMapProcessMemory(base, envGetOwnProcessHandle(), (u64)(memoryCodeBase + offset), size);
if (R_FAILED(rc)) {
printf("Fatal error creating the view... base: %p offset: %p size: %p src: %p err: %d\n",
(void *)base, (void *)offset, (void *)size, (void *)(memoryCodeBase + offset), rc);
} else {
printf("Created the view... base: %p offset: %p size: %p src: %p err: %d\n",
(void *)base, (void *)offset, (void *)size, (void *)(memoryCodeBase + offset), rc);
}

return base;
}

void MemArena::ReleaseView(s64 offset, void *view, size_t size) {
if (R_FAILED(svcUnmapProcessMemory(view, envGetOwnProcessHandle(), (u64)(memoryCodeBase + offset), size)))
printf("Failed to unmap view...\n");
}

u8 *MemArena::Find4GBBase() {
memorySrcBase = (uintptr_t)memalign(0x1000, 0x10000000);

if (!memoryBase)
memoryBase = (uintptr_t)virtmemReserve(0x10000000);

if (!memoryCodeBase)
memoryCodeBase = (uintptr_t)virtmemReserve(0x10000000);

if (R_FAILED(svcMapProcessCodeMemory(envGetOwnProcessHandle(), (u64)memoryCodeBase, (u64)memorySrcBase, 0x10000000)))
printf("Failed to map memory...\n");
if (R_FAILED(svcSetProcessMemoryPermission(envGetOwnProcessHandle(), memoryCodeBase, 0x10000000, Perm_Rx)))
printf("Failed to set perms...\n");

return (u8 *)memoryBase;
}

#endif // PPSSPP_PLATFORM(SWITCH)
2 changes: 1 addition & 1 deletion Common/MemArenaPosix.cpp
Expand Up @@ -121,7 +121,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base)
return retval;
}

void MemArena::ReleaseView(void* view, size_t size) {
void MemArena::ReleaseView(s64 offset, void* view, size_t size) {
munmap(view, size);
}

Expand Down
2 changes: 1 addition & 1 deletion Common/MemArenaWin32.cpp
Expand Up @@ -54,7 +54,7 @@ void *MemArena::CreateView(s64 offset, size_t size, void *viewbase) {
return ptr;
}

void MemArena::ReleaseView(void* view, size_t size) {
void MemArena::ReleaseView(s64 offset, void* view, size_t size) {
#if PPSSPP_PLATFORM(UWP)
#else
UnmapViewOfFile(view);
Expand Down
15 changes: 13 additions & 2 deletions Core/MemMap.cpp
Expand Up @@ -187,7 +187,7 @@ static bool Memory_TryBase(u32 flags) {
SKIP(flags, views[i].flags);
if (*views[j].out_ptr) {
if (!CanIgnoreView(views[j])) {
g_arena.ReleaseView(*views[j].out_ptr, views[j].size);
g_arena.ReleaseView(0, *views[j].out_ptr, views[j].size);
}
*views[j].out_ptr = NULL;
}
Expand Down Expand Up @@ -265,13 +265,24 @@ bool MemoryMap_Setup(u32 flags) {
}

void MemoryMap_Shutdown(u32 flags) {
size_t position = 0;
size_t last_position = 0;

for (int i = 0; i < num_views; i++) {
if (views[i].size == 0)
continue;
SKIP(flags, views[i].flags);

if (views[i].flags & MV_MIRROR_PREVIOUS) {
position = last_position;
}

if (*views[i].out_ptr)
g_arena.ReleaseView(*views[i].out_ptr, views[i].size);
g_arena.ReleaseView(position, *views[i].out_ptr, views[i].size);
*views[i].out_ptr = nullptr;

last_position = position;
position += g_arena.roundup(views[i].size);
}
g_arena.ReleaseSpace();

Expand Down

0 comments on commit 101128a

Please sign in to comment.