forked from eden-emu/eden
[compat] fix solaris shm_open syscall causing crashes with SHM_ANON, implement portable posix shm_open_anon (#187)
Reviewed-on: eden-emu/eden#187 Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
9966da9ff3
commit
3b72c29303
1 changed files with 67 additions and 12 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -9,7 +12,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "common/dynamic_library.h"
|
#include "common/dynamic_library.h"
|
||||||
|
|
||||||
#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
|
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
@ -21,9 +24,14 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
|
||||||
|
// FreeBSD
|
||||||
#ifndef MAP_NORESERVE
|
#ifndef MAP_NORESERVE
|
||||||
#define MAP_NORESERVE 0
|
#define MAP_NORESERVE 0
|
||||||
#endif
|
#endif
|
||||||
|
// Solaris 11 and illumos
|
||||||
|
#ifndef MAP_ALIGNED_SUPER
|
||||||
|
#define MAP_ALIGNED_SUPER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // ^^^ Linux ^^^
|
#endif // ^^^ Linux ^^^
|
||||||
|
|
||||||
|
@ -364,7 +372,7 @@ private:
|
||||||
std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset
|
std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
|
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv
|
||||||
|
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
|
|
||||||
|
@ -409,22 +417,65 @@ static void* ChooseVirtualBase(size_t virtual_size) {
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static void* ChooseVirtualBase(size_t virtual_size) {
|
static void* ChooseVirtualBase(size_t virtual_size) {
|
||||||
#if defined(__FreeBSD__)
|
void* virtual_base = mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0);
|
||||||
void* virtual_base =
|
if (virtual_base != MAP_FAILED)
|
||||||
mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE,
|
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0);
|
|
||||||
|
|
||||||
if (virtual_base != MAP_FAILED) {
|
|
||||||
return virtual_base;
|
return virtual_base;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE,
|
return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__sun__) || defined(__HAIKU__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||||
|
/// Most Unices don't have a portable shm_open (AIX, OpenBSD, NetBSD, Solaris 11, OpenIndiana)
|
||||||
|
/// Portable implementation of shm_open(SHM_ANON, ...) - roughly equivalent but without
|
||||||
|
/// OS support - may fail sporadically, beware!
|
||||||
|
static int shm_open_anon(int flags, mode_t mode) {
|
||||||
|
char name[16] = "/shm-";
|
||||||
|
char *const limit = name + sizeof(name) - 1;
|
||||||
|
*limit = '\0';
|
||||||
|
char *start = name + strlen(name);
|
||||||
|
for (int tries = 0; tries < 4; tries++) {
|
||||||
|
struct timespec tv;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tv);
|
||||||
|
unsigned long r = (unsigned long)tv.tv_sec + (unsigned long)tv.tv_nsec;
|
||||||
|
for (char *fill = start; fill < limit; r /= 8)
|
||||||
|
*fill++ = '0' + (r % 8);
|
||||||
|
int fd = shm_open(name, flags, mode);
|
||||||
|
if (fd != -1)
|
||||||
|
return ([](const char *name, int fd) {
|
||||||
|
if (shm_unlink(name) == -1) {
|
||||||
|
int tmp = errno;
|
||||||
|
close(fd);
|
||||||
|
errno = tmp;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
})(name, fd);
|
||||||
|
if (errno != EEXIST)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
/// Except OpenBSD which explicitly uses shm_mkstemp instead (as a more secure alternative)
|
||||||
|
static int shm_open_anon(int flags, mode_t mode) {
|
||||||
|
char name[16] = "/shm-XXXXXXXXXX";
|
||||||
|
int fd;
|
||||||
|
if ((fd = shm_mkstemp(name)) == -1)
|
||||||
|
return -1;
|
||||||
|
return ([](const char *name, int fd) {
|
||||||
|
if (shm_unlink(name) == -1) {
|
||||||
|
int tmp = errno;
|
||||||
|
close(fd);
|
||||||
|
errno = tmp;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
})(name, fd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class HostMemory::Impl {
|
class HostMemory::Impl {
|
||||||
public:
|
public:
|
||||||
explicit Impl(size_t backing_size_, size_t virtual_size_)
|
explicit Impl(size_t backing_size_, size_t virtual_size_)
|
||||||
|
@ -443,7 +494,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backing memory initialization
|
// Backing memory initialization
|
||||||
#if defined(__FreeBSD__) && __FreeBSD__ < 13
|
#if defined(__sun__) || defined(__HAIKU__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||||
|
fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
|
||||||
|
#elif defined(__FreeBSD__) && __FreeBSD__ < 13
|
||||||
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
|
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
|
||||||
fd = shm_open(SHM_ANON, O_RDWR, 0600);
|
fd = shm_open(SHM_ANON, O_RDWR, 0600);
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue