diff options
| author | Skyler Saleh <skylersaleh@gmail.com> | 2021-01-16 20:31:48 -0800 |
|---|---|---|
| committer | Skyler Saleh <skylersaleh@gmail.com> | 2021-05-22 15:25:17 -0700 |
| commit | 948764d37bdbb89e84886e233dea47fba0cb1017 (patch) | |
| tree | 5b6b7a51c8013fd8158a9bf06cf6ae20cc28b4c3 /Source/Core/Common/MemoryUtil.cpp | |
| parent | 4ecb3084b70b5581115703b517b9005f608ffb18 (diff) | |
Apple M1: Build, Analytics, and Memory Management
Analytics:
- Incorporated fix to allow the full set of analytics that was recommended by
spotlightishere
BuildMacOSUniversalBinary:
- The x86_64 slice for a universal binary is now built for 10.12
- The universal binary build script now can be configured though command line
options instead of modifying the script itself.
- os.system calls were replaced with equivalent subprocess calls
- Formatting was reworked to be more PEP 8 compliant
- The script was refactored to make it more modular
- The com.apple.security.cs.disable-library-validation entitlement was removed
Memory Management:
- Changed the JITPageWrite*Execute*() functions to incorporate support for
nesting
Other:
- Fixed several small lint errors
- Fixed doc and formatting mistakes
- Several small refactors to make things clearer
Diffstat (limited to 'Source/Core/Common/MemoryUtil.cpp')
| -rw-r--r-- | Source/Core/Common/MemoryUtil.cpp | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/Source/Core/Common/MemoryUtil.cpp b/Source/Core/Common/MemoryUtil.cpp index b91faeeb91..d1e9d25785 100644 --- a/Source/Core/Common/MemoryUtil.cpp +++ b/Source/Core/Common/MemoryUtil.cpp @@ -39,12 +39,11 @@ void* AllocateExecutableMemory(size_t size) #if defined(_WIN32) void* ptr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - int map_flags =MAP_ANON | MAP_PRIVATE; + int map_flags = MAP_ANON | MAP_PRIVATE; #if defined(_M_ARM_64) && defined(__APPLE__) map_flags |= MAP_JIT; #endif - void* ptr = - mmap(nullptr, size, PROT_READ | PROT_WRITE |PROT_EXEC , map_flags, -1, 0); + void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, map_flags, -1, 0); if (ptr == MAP_FAILED) ptr = nullptr; #endif @@ -54,7 +53,19 @@ void* AllocateExecutableMemory(size_t size) return ptr; } -// Certain platforms (Mac OS X on ARM) enforce that a single thread can only have write or +// This function is used to provide a counter for the JITPageWrite*Execute* +// functions to enable nesting. The static variable is wrapped in a a function +// to allow those functions to be called inside of the constructor of a static +// variable portably. +// +// The variable is thread_local as the W^X mode is specific to each running thread. +static int& JITPageWriteNestCounter() +{ + static thread_local int nest_counter = 0; + return nest_counter; +} + +// Certain platforms (Mac OS on ARM) enforce that a single thread can only have write or // execute permissions to pages at any given point of time. The two below functions // are used to toggle between having write permissions or execute permissions. // @@ -66,20 +77,52 @@ void* AllocateExecutableMemory(size_t size) // PrepareInstructionStreamForJIT(); // JITPageWriteDisableExecuteEnable(); -//Allows a thread to write to executable memory, but not execute the data. -void JITPageWriteEnableExecuteDisable(){ +// These functions can be nested, in which case execution will only be enabled +// after the call to the JITPageWriteDisableExecuteEnable from the top most +// nesting level. Example: + +// [JIT page is in execute mode for the thread] +// JITPageWriteEnableExecuteDisable(); +// [JIT page is in write mode for the thread] +// JITPageWriteEnableExecuteDisable(); +// [JIT page is in write mode for the thread] +// JITPageWriteDisableExecuteEnable(); +// [JIT page is in write mode for the thread] +// JITPageWriteDisableExecuteEnable(); +// [JIT page is in execute mode for the thread] + +// Allows a thread to write to executable memory, but not execute the data. +void JITPageWriteEnableExecuteDisable() +{ #if defined(_M_ARM_64) && defined(__APPLE__) - if (__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(0); + if (JITPageWriteNestCounter() == 0) + { + if (__builtin_available(macOS 11.0, *)) + { + pthread_jit_write_protect_np(0); + } } #endif - + JITPageWriteNestCounter()++; } -//Allows a thread to execute memory allocated for execution, but not write to it. -void JITPageWriteDisableExecuteEnable(){ +// Allows a thread to execute memory allocated for execution, but not write to it. +void JITPageWriteDisableExecuteEnable() +{ + JITPageWriteNestCounter()--; + + // Sanity check the NestCounter to identify underflow + // This can indicate the calls to JITPageWriteDisableExecuteEnable() + // are not matched with previous calls to JITPageWriteEnableExecuteDisable() + if (JITPageWriteNestCounter() < 0) + PanicAlertFmt("JITPageWriteNestCounter() underflowed"); + #if defined(_M_ARM_64) && defined(__APPLE__) - if (__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(1); + if (JITPageWriteNestCounter() == 0) + { + if (__builtin_available(macOS 11.0, *)) + { + pthread_jit_write_protect_np(1); + } } #endif } |
