From f3cf1da7b771d9077e68987dc845aa1eb2952fd1 Mon Sep 17 00:00:00 2001 From: schm1dtmac Date: Wed, 29 Apr 2026 17:41:02 +0100 Subject: [PATCH] Revert "Fix race condition in memory_decommit/memory_reset on Apple ARM64" This reverts commit 4cac76caadda064ea5cafc6f530133acb2302c50. --- rpcs3/util/vm_native.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rpcs3/util/vm_native.cpp b/rpcs3/util/vm_native.cpp index d569a26645..5821300fc3 100644 --- a/rpcs3/util/vm_native.cpp +++ b/rpcs3/util/vm_native.cpp @@ -347,11 +347,12 @@ namespace utils #else const u64 ptr64 = reinterpret_cast(pointer); #if defined(__APPLE__) && defined(ARCH_ARM64) - // Use MAP_FIXED without MAP_JIT to atomically replace the mapping. - // Apple rejects MAP_FIXED | MAP_JIT, but MAP_FIXED alone works and - // avoids the race condition of the previous munmap+mmap approach - // where another thread could claim the address range between the two calls. - ensure(::mmap(pointer, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE | c_map_noreserve, -1, 0) != reinterpret_cast(uptr{umax})); + // Hack: on macOS, Apple explicitly fails mmap if you combine MAP_FIXED and MAP_JIT. + // So we unmap the space and just hope it maps to the same address we got before instead. + // The Xcode manpage says the pointer is a hint and the OS will try to map at the hint location + // so this isn't completely undefined behavior. + ensure(::munmap(pointer, size) != -1); + ensure(::mmap(pointer, size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0) == pointer); #else ensure(::mmap(pointer, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE | c_map_noreserve, -1, 0) != reinterpret_cast(uptr{umax})); #endif @@ -380,9 +381,8 @@ namespace utils #else const u64 ptr64 = reinterpret_cast(pointer); #if defined(__APPLE__) && defined(ARCH_ARM64) - // Use MAP_FIXED without MAP_JIT to atomically replace the mapping. - // See memory_decommit for details on why the munmap+mmap approach is unsafe. - ensure(::mmap(pointer, size, +prot, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != reinterpret_cast(uptr{umax})); + ensure(::munmap(pointer, size) != -1); + ensure(::mmap(pointer, size, +prot, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0) == pointer); #else ensure(::mmap(pointer, size, +prot, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != reinterpret_cast(uptr{umax})); #endif