|
5 | 5 | #include <mach/clock.h> |
6 | 6 | #include <mach/clock_types.h> |
7 | 7 | #include <mach/clock_reply.h> |
| 8 | +#include <mach/thread_state.h> |
8 | 9 | #include <mach/mach_traps.h> |
9 | 10 | #include <mach/task.h> |
10 | 11 | #include <mach/mig_errors.h> |
@@ -891,3 +892,54 @@ JL_DLLEXPORT void jl_profile_stop_timer(void) |
891 | 892 | profile_all_tasks = 0; |
892 | 893 | uv_mutex_unlock(&bt_data_prof_lock); |
893 | 894 | } |
| 895 | + |
| 896 | +// The mprotect implementation in signals-unix.c does not work on macOS/aarch64, as mentioned. |
| 897 | +// This implementation comes from dotnet, but is similarly dependent on undocumented behavior of the OS. |
| 898 | +// Copyright (c) .NET Foundation and Contributors |
| 899 | +// MIT LICENSE |
| 900 | +JL_DLLEXPORT void jl_membarrier(void) { |
| 901 | + mach_msg_type_number_t cThreads; |
| 902 | + thread_act_t *pThreads; |
| 903 | + kern_return_t machret = task_threads(mach_task_self(), &pThreads, &cThreads); |
| 904 | + HANDLE_MACH_ERROR("task_threads()", machret); |
| 905 | + |
| 906 | + uintptr_t sp; |
| 907 | + uintptr_t registerValues[128]; |
| 908 | + |
| 909 | + // Iterate through each of the threads in the list. |
| 910 | + for (mach_msg_type_number_t i = 0; i < cThreads; i++) |
| 911 | + { |
| 912 | + if (__builtin_available (macOS 10.14, iOS 12, tvOS 9, *)) |
| 913 | + { |
| 914 | + // Request the threads pointer values to force the thread to emit a memory barrier |
| 915 | + size_t registers = 128; |
| 916 | + machret = thread_get_register_pointer_values(pThreads[i], &sp, ®isters, registerValues); |
| 917 | + } |
| 918 | + else |
| 919 | + { |
| 920 | + // fallback implementation for older OS versions |
| 921 | +#if defined(_CPU_X86_64_) |
| 922 | + x86_thread_state64_t threadState; |
| 923 | + mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; |
| 924 | + machret = thread_get_state(pThreads[i], x86_THREAD_STATE64, (thread_state_t)&threadState, &count); |
| 925 | +#elif defined(_CPU_AARCH64_) |
| 926 | + arm_thread_state64_t threadState; |
| 927 | + mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT; |
| 928 | + machret = thread_get_state(pThreads[i], ARM_THREAD_STATE64, (thread_state_t)&threadState, &count); |
| 929 | +#else |
| 930 | + #error Unexpected architecture |
| 931 | +#endif |
| 932 | + } |
| 933 | + |
| 934 | + if (machret == KERN_INSUFFICIENT_BUFFER_SIZE) |
| 935 | + { |
| 936 | + HANDLE_MACH_ERROR("thread_get_register_pointer_values()", machret); |
| 937 | + } |
| 938 | + |
| 939 | + machret = mach_port_deallocate(mach_task_self(), pThreads[i]); |
| 940 | + HANDLE_MACH_ERROR("mach_port_deallocate()", machret); |
| 941 | + } |
| 942 | + // Deallocate the thread list now we're done with it. |
| 943 | + machret = vm_deallocate(mach_task_self(), (vm_address_t)pThreads, cThreads * sizeof(thread_act_t)); |
| 944 | + HANDLE_MACH_ERROR("vm_deallocate()", machret); |
| 945 | +} |
0 commit comments