@@ -1275,48 +1275,15 @@ JL_DLLEXPORT int jl_repl_raise_sigtstp(void)
12751275 return raise (SIGTSTP );
12761276}
12771277
1278- // Linux and FreeBSD have compatible membarrier support
1279- #if defined(_OS_LINUX_ ) || defined(_OS_FREEBSD_ )
1280- #if defined(_OS_LINUX_ )
1281- # include <sys/syscall.h>
1282- # if defined(__has_include )
1283- # if __has_include (< linux /membarrier .h > )
1284- # include <linux/membarrier.h>
1285- # define membarrier (...) syscall(__NR_membarrier, __VA_ARGS__)
1286- # else
1287- # if defined(__NR_membarrier )
1288- enum membarrier_cmd {
1289- MEMBARRIER_CMD_QUERY = 0 ,
1290- MEMBARRIER_CMD_PRIVATE_EXPEDITED = (1 << 3 ),
1291- MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4 ),
1292- };
1293- # define membarrier (...) syscall(__NR_membarrier, __VA_ARGS__)
1294- # else
1295- # warning "Missing linux kernel headers for membarrier syscall, support disabled"
1296- # define membarrier (...) -ENOSYS
1297- # endif
1298- # endif
1299- # else
1300- # include <linux/membarrier.h>
1301- # endif
1302- #elif defined(_OS_FREEBSD_ )
1303- # include <sys/param.h>
1304- # if __FreeBSD_version >= 1401500
1305- # include <sys/membarrier.h>
1306- # else
1307- # define MEMBARRIER_CMD_QUERY 0x00
1308- # define MEMBARRIER_CMD_PRIVATE_EXPEDITED 0x08
1309- # define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED 0x10
1310- # define membarrier (...) -ENOSYS
1311- # endif
1312- #endif
1313-
1278+ #if !defined(_OS_DARWIN_ )
13141279// Implementation of the `mprotect` based membarrier fallback.
13151280// This is a common fallback based on the observation that `mprotect` happens to
13161281// issue the necessary memory barriers. However, there is no spec that
1317- // guarantees this behavior, and indeed AArch64 macos does not. However, we
1318- // only use it as a fallback here for older versions of Linux and FreeBSD where
1319- // we know that it happens to work.
1282+ // guarantees this behavior, and indeed AArch64 Darwin does not (so we don't use it
1283+ // there). However, we only use it as a fallback here for older versions of
1284+ // Linux and FreeBSD where we know that it happens to work. We also use it as a
1285+ // fallback for unknown Unix systems under the assumption that it will work,
1286+ // but this is not guaranteed.
13201287static pthread_mutex_t mprotect_barrier_lock = PTHREAD_MUTEX_INITIALIZER ;
13211288static _Atomic (uint64_t ) * mprotect_barrier_page = NULL ;
13221289static void jl_init_mprotect_membarrier (void )
@@ -1335,7 +1302,7 @@ static void jl_init_mprotect_membarrier(void)
13351302 }
13361303 result = mlock (mprotect_barrier_page , pagesize );
13371304 if (result != 0 ) {
1338- jl_safe_printf ("fatal: failed to mlock barrier page.\n" );
1305+ jl_safe_printf ("fatal: failed to mlock barrier page (try increasing RLIMIT_MEMLOCK with `ulimit -l`) .\n" );
13391306 abort ();
13401307 }
13411308 }
@@ -1349,15 +1316,43 @@ static void jl_mprotect_membarrier(void)
13491316 int result = pthread_mutex_lock (& mprotect_barrier_lock );
13501317 assert (result == 0 );
13511318 size_t pagesize = jl_getpagesize ();
1352- result = mprotect (mprotect_barrier_page , pagesize , PROT_NONE );
1319+ result = mprotect (mprotect_barrier_page , pagesize , PROT_READ | PROT_WRITE );
13531320 jl_atomic_fetch_add_relaxed (mprotect_barrier_page , 1 );
13541321 assert (result == 0 );
1355- result = mprotect (mprotect_barrier_page , pagesize , PROT_READ | PROT_WRITE );
1322+ result = mprotect (mprotect_barrier_page , pagesize , PROT_NONE );
13561323 assert (result == 0 );
13571324 result = pthread_mutex_unlock (& mprotect_barrier_lock );
13581325 assert (result == 0 );
13591326 (void )result ;
13601327}
1328+ #endif
1329+
1330+ // Linux and FreeBSD have compatible membarrier support
1331+ #if defined(_OS_LINUX_ ) || defined(_OS_FREEBSD_ )
1332+ #if defined(_OS_LINUX_ )
1333+ # include <sys/syscall.h>
1334+ # if defined(__NR_membarrier )
1335+ enum membarrier_cmd {
1336+ MEMBARRIER_CMD_QUERY = 0 ,
1337+ MEMBARRIER_CMD_PRIVATE_EXPEDITED = (1 << 3 ),
1338+ MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4 ),
1339+ };
1340+ # define membarrier (...) syscall(__NR_membarrier, __VA_ARGS__)
1341+ # else
1342+ # warning "Missing linux kernel headers for membarrier syscall, support disabled"
1343+ # define membarrier (...) (errno = ENOSYS, -1)
1344+ # endif
1345+ #elif defined(_OS_FREEBSD_ )
1346+ # include <sys/param.h>
1347+ # if __FreeBSD_version >= 1401500
1348+ # include <sys/membarrier.h>
1349+ # else
1350+ # define MEMBARRIER_CMD_QUERY 0x00
1351+ # define MEMBARRIER_CMD_PRIVATE_EXPEDITED 0x08
1352+ # define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED 0x10
1353+ # define membarrier (...) (errno = ENOSYS, -1)
1354+ # endif
1355+ #endif
13611356
13621357// Implementation of `jl_membarrier`
13631358enum membarrier_implementation {
@@ -1391,11 +1386,17 @@ JL_DLLEXPORT void jl_membarrier(void) {
13911386 }
13921387 if (impl == MEMBARRIER_IMPLEMENTATION_SYS_MEMBARRIER ) {
13931388 int ret = membarrier (MEMBARRIER_CMD_PRIVATE_EXPEDITED , 0 );
1394- assert (ret );
1389+ assert (ret == 0 );
13951390 (void )ret ;
13961391 } else {
13971392 assert (impl == MEMBARRIER_IMPLEMENTATION_MPROTECT );
13981393 jl_mprotect_membarrier ();
13991394 }
14001395}
1396+ #elif !defined(_OS_DARWIN_ )
1397+ JL_DLLEXPORT void jl_membarrier (void ) {
1398+ if (!mprotect_barrier_page )
1399+ jl_init_mprotect_membarrier ();
1400+ jl_mprotect_membarrier ();
1401+ }
14011402#endif
0 commit comments