Simplify MMAP machinery for Win/Lin/Mac/Android

This gets rid of the bloated memmap_win32.c in favour of a much simpler
wrapper. This will be needed in the future since the wrapper does not
support MAP_FIXED maps (necessary for some platforms)
This commit is contained in:
David Guillen Fandos 2021-11-05 18:23:05 +01:00
parent 3368ad6f8e
commit 3a7fedb8fb
12 changed files with 67 additions and 272 deletions

View File

@ -1,8 +1,7 @@
DEBUG=0
FRONTEND_SUPPORTS_RGB565=1
FORCE_32BIT_ARCH=0
HAVE_MMAP=0
HAVE_MMAP_WIN32=0
MMAP_JIT_CACHE=0
UNAME=$(shell uname -a)
@ -75,7 +74,7 @@ ifeq ($(platform), unix)
CFLAGS += $(FORCE_32BIT)
LDFLAGS += -Wl,--no-undefined
ifeq ($(HAVE_DYNAREC),1)
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
endif
# Linux portable
@ -86,7 +85,7 @@ else ifeq ($(platform), linux-portable)
LIBM :=
CFLAGS += $(FORCE_32BIT)
ifeq ($(HAVE_DYNAREC),1)
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
endif
# OS X
@ -101,7 +100,7 @@ else ifeq ($(platform), osx)
fpic += -mmacosx-version-min=10.1
SHARED := -dynamiclib
ifeq ($(HAVE_DYNAREC),1)
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
endif
ifeq ($(CROSS_COMPILE),1)
@ -172,7 +171,7 @@ else ifeq ($(platform), qnx)
TARGET := $(TARGET_NAME)_libretro_qnx.so
fpic := -fPIC
SHARED := -shared -Wl,--version-script=link.T
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
CPU_ARCH := arm
CC = qcc -Vgcc_ntoarmv7le
@ -257,7 +256,7 @@ else ifeq ($(platform), rpi3)
CFLAGS += -fomit-frame-pointer -ffast-math
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
CPU_ARCH := arm
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
HAVE_DYNAREC = 1
# Raspberry Pi 2
@ -269,7 +268,7 @@ else ifeq ($(platform), rpi2)
CFLAGS += -fomit-frame-pointer -ffast-math
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
CPU_ARCH := arm
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
HAVE_DYNAREC = 1
# Raspberry Pi 1
@ -282,7 +281,7 @@ else ifeq ($(platform), rpi1)
CFLAGS += -fomit-frame-pointer -ffast-math
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
CPU_ARCH := arm
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
HAVE_DYNAREC = 1
# Classic Platforms ####################
@ -310,7 +309,7 @@ else ifeq ($(platform), classic_armv7_a7)
ARCH = arm
BUILTIN_GPU = neon
CPU_ARCH := arm
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
HAVE_DYNAREC = 1
ifeq ($(shell echo `$(CC) -dumpversion` "< 4.9" | bc -l), 1)
CFLAGS += -march=armv7-a
@ -352,7 +351,7 @@ else ifneq (,$(findstring armv,$(platform)))
TARGET := $(TARGET_NAME)_libretro.so
SHARED := -shared -Wl,--version-script=link.T
CPU_ARCH := arm
HAVE_MMAP = 1
MMAP_JIT_CACHE = 1
fpic := -fPIC
ifneq (,$(findstring cortexa5,$(platform)))
CFLAGS += -marm -mcpu=cortex-a5
@ -463,14 +462,13 @@ else
SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T
CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__
ifeq ($(HAVE_DYNAREC),1)
HAVE_MMAP = 1
HAVE_MMAP_WIN32 = 1
MMAP_JIT_CACHE = 1
endif
endif
ifeq ($(HAVE_MMAP), 1)
CFLAGS += -DHAVE_MMAP
ifeq ($(MMAP_JIT_CACHE), 1)
CFLAGS += -DMMAP_JIT_CACHE
endif
# Add -DTRACE_INSTRUCTIONS to trace instruction execution
@ -487,11 +485,11 @@ DEFINES += -DHAVE_DYNAREC
endif
ifeq ($(CPU_ARCH), arm)
DEFINES += -DARM_ARCH
DEFINES += -DARM_ARCH
else ifeq ($(CPU_ARCH), mips)
DEFINES += -DMIPS_ARCH
DEFINES += -DMIPS_ARCH
else ifeq ($(CPU_ARCH), x86_32)
DEFINES += -DX86_ARCH
DEFINES += -DX86_ARCH
endif
include Makefile.common

View File

@ -12,6 +12,7 @@ SOURCES_C := $(CORE_DIR)/main.c \
$(CORE_DIR)/input.c \
$(CORE_DIR)/sound.c \
$(CORE_DIR)/cheats.c \
$(CORE_DIR)/memmap.c \
$(CORE_DIR)/libretro/libretro.c \
$(CORE_DIR)/gba_cc_lut.c \
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
@ -51,7 +52,3 @@ endif
endif
ifeq ($(HAVE_MMAP_WIN32),1)
SOURCES_C += $(CORE_DIR)/memmap_win32.c
endif

View File

@ -840,7 +840,7 @@ defsymbl(palette_ram_converted)
@ Vita and 3DS (and of course mmap) map their own cache sections through some
@ platform-speficic mechanisms.
#if !defined(HAVE_MMAP) && !defined(VITA) && !defined(_3DS)
#if !defined(MMAP_JIT_CACHE) && !defined(VITA) && !defined(_3DS)
@ Make this section executable!
.text

2
cpu.h
View File

@ -131,7 +131,7 @@ s32 translate_block_arm(u32 pc, translation_region_type translation_region,
s32 translate_block_thumb(u32 pc, translation_region_type translation_region,
u32 smc_enable);
#if defined(HAVE_MMAP)
#if defined(MMAP_JIT_CACHE)
extern u8* rom_translation_cache;
extern u8* ram_translation_cache;
#elif defined(_3DS)

View File

@ -32,7 +32,7 @@
u8 *last_rom_translation_ptr = NULL;
u8 *last_ram_translation_ptr = NULL;
#if defined(HAVE_MMAP)
#if defined(MMAP_JIT_CACHE)
u8* rom_translation_cache;
u8* ram_translation_cache;
u8 *rom_translation_ptr;

View File

@ -9,11 +9,11 @@ HAVE_DYNAREC :=
COREFLAGS := -DINLINE=inline -D__LIBRETRO__ -DFRONTEND_SUPPORTS_RGB565
ifeq ($(TARGET_ARCH),arm)
COREFLAGS += -DARM_ARCH -DHAVE_MMAP
COREFLAGS += -DARM_ARCH -DMMAP_JIT_CACHE
CPU_ARCH := arm
HAVE_DYNAREC := 1
else ifeq ($(TARGET_ARCH),x86)
COREFLAGS += -DHAVE_MMAP
COREFLAGS += -DMMAP_JIT_CACHE
CPU_ARCH := x86_32
HAVE_DYNAREC := 1
endif

View File

@ -458,9 +458,9 @@ void retro_get_system_av_info(struct retro_system_av_info* info)
void retro_init(void)
{
#if defined(HAVE_DYNAREC)
#if defined(HAVE_MMAP)
rom_translation_cache = mmap(NULL, ROM_TRANSLATION_CACHE_SIZE + RAM_TRANSLATION_CACHE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
#if defined(MMAP_JIT_CACHE)
rom_translation_cache = map_jit_block(ROM_TRANSLATION_CACHE_SIZE + RAM_TRANSLATION_CACHE_SIZE);
printf("rom_translation_cache %llx\n", (unsigned long long)rom_translation_cache);
ram_translation_cache = &rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE];
#elif defined(_3DS)
if (__ctr_svchax && !translation_caches_inited)
@ -548,8 +548,8 @@ void retro_deinit(void)
perf_cb.perf_log();
memory_term();
#if defined(HAVE_MMAP) && defined(HAVE_DYNAREC)
munmap(rom_translation_cache, ROM_TRANSLATION_CACHE_SIZE + RAM_TRANSLATION_CACHE_SIZE);
#if defined(MMAP_JIT_CACHE) && defined(HAVE_DYNAREC)
unmap_jit_block(rom_translation_cache, ROM_TRANSLATION_CACHE_SIZE + RAM_TRANSLATION_CACHE_SIZE);
#endif
#if defined(_3DS) && defined(HAVE_DYNAREC)

35
memmap.c Normal file
View File

@ -0,0 +1,35 @@
#include "memmap.h"
#ifdef MMAP_JIT_CACHE
#ifdef WIN32
#include <windows.h>
#include <io.h>
void *map_jit_block(unsigned size) {
return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
void unmap_jit_block(void *bufptr, unsigned size) {
VirtualFree(bufptr, 0, MEM_RELEASE);
}
#else
#include <sys/mman.h>
// Posix implementation
void *map_jit_block(unsigned size) {
return mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
}
void unmap_jit_block(void *bufptr, unsigned size) {
munmap(bufptr, size);
}
#endif /* WIN32 */
#endif /* MMAP_JIT_CACHE */

View File

@ -1,60 +1,7 @@
#ifndef _MEMMAP_H
#define _MEMMAP_H
#ifdef HAVE_MMAP
#ifdef _WIN32
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
/* All the headers include this file. */
#ifndef _MSC_VER
#include <_mingw.h>
#endif
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PROT_NONE 0
#define PROT_READ 1
#define PROT_WRITE 2
#define PROT_EXEC 4
#define MAP_FILE 0
#define MAP_SHARED 1
#define MAP_PRIVATE 2
#define MAP_TYPE 0xf
#define MAP_FIXED 0x10
#define MAP_ANONYMOUS 0x20
#define MAP_ANON MAP_ANONYMOUS
#define MAP_FAILED ((void *)-1)
/* Flags for msync. */
#define MS_ASYNC 1
#define MS_SYNC 2
#define MS_INVALIDATE 4
void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
int munmap(void *addr, size_t len);
int mprotect(void *addr, size_t len, int prot);
int msync(void *addr, size_t len, int flags);
int mlock(const void *addr, size_t len);
int munlock(const void *addr, size_t len);
#ifdef __cplusplus
};
#endif
#else
#include <sys/mman.h>
#endif
#endif
void *map_jit_block(unsigned size);
void unmap_jit_block(void *bufptr, unsigned size);
#endif

View File

@ -1,173 +0,0 @@
#include <windows.h>
#include <errno.h>
#include <io.h>
#include "mman.h"
#ifndef FILE_MAP_EXECUTE
#define FILE_MAP_EXECUTE 0x0020
#endif /* FILE_MAP_EXECUTE */
static int __map_mman_error(const DWORD err, const int deferr)
{
if (err == 0)
return 0;
/* TODO: implement */
return err;
}
static DWORD __map_mmap_prot_page(const int prot)
{
DWORD protect = 0;
if (prot == PROT_NONE)
return 0;
if ((prot & PROT_EXEC) != 0)
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
else
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_READWRITE : PAGE_READONLY;
return protect;
}
static DWORD __map_mmap_prot_file(const int prot)
{
DWORD desiredAccess = 0;
if (prot == PROT_NONE)
return 0;
if ((prot & PROT_READ) != 0)
desiredAccess |= FILE_MAP_READ;
if ((prot & PROT_WRITE) != 0)
desiredAccess |= FILE_MAP_WRITE;
if ((prot & PROT_EXEC) != 0)
desiredAccess |= FILE_MAP_EXECUTE;
return desiredAccess;
}
void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
HANDLE fm, h;
void * map = MAP_FAILED;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4293)
#endif
const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
const DWORD protect = __map_mmap_prot_page(prot);
const DWORD desiredAccess = __map_mmap_prot_file(prot);
const off_t maxSize = off + (off_t)len;
const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
errno = 0;
if (len == 0
/* Unsupported flag combinations */
|| (flags & MAP_FIXED) != 0
/* Usupported protection combinations */
|| prot == PROT_EXEC)
{
errno = EINVAL;
return MAP_FAILED;
}
h = ((flags & MAP_ANONYMOUS) == 0) ?
(HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE;
if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return MAP_FAILED;
}
fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);
if (!fm)
goto error;
map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);
CloseHandle(fm);
if (!map)
goto error;
return map;
error:
errno = __map_mman_error(GetLastError(), EPERM);
return MAP_FAILED;
}
int munmap(void *addr, size_t len)
{
if (UnmapViewOfFile(addr))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int mprotect(void *addr, size_t len, int prot)
{
DWORD newProtect = __map_mmap_prot_page(prot);
DWORD oldProtect = 0;
if (VirtualProtect(addr, len, newProtect, &oldProtect))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int msync(void *addr, size_t len, int flags)
{
if (FlushViewOfFile(addr, len))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int mlock(const void *addr, size_t len)
{
if (VirtualLock((LPVOID)addr, len))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int munlock(const void *addr, size_t len)
{
if (VirtualUnlock((LPVOID)addr, len))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}

View File

@ -595,7 +595,7 @@ fnptrs:
.long execute_store_cpsr_body # 7
.long process_cheats # 8
#if !defined(HAVE_MMAP)
#if !defined(MMAP_JIT_CACHE)
# Make this section executable!
.text

View File

@ -585,16 +585,7 @@ defsymbl(reg_mode)
defsymbl(memory_map_read)
.space 0x8000
#if !defined(HAVE_MMAP)
# Make this section executable!
.text
.section .jit,"awx",%nobits
.align 4
defsymbl(rom_translation_cache)
.space ROM_TRANSLATION_CACHE_SIZE
defsymbl(ram_translation_cache)
.space RAM_TRANSLATION_CACHE_SIZE
#ifndef MMAP_JIT_CACHE
#error "x86 dynarec builds *require* MMAP_JIT_CACHE"
#endif