Skip to content

Commit

Permalink
Cleanup membarrier portability (#111943)
Browse files Browse the repository at this point in the history
Fixes #111776
  • Loading branch information
jkotas authored Jan 29, 2025
1 parent 29d286b commit 1b71136
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 56 deletions.
1 change: 1 addition & 0 deletions src/coreclr/gc/unix/config.gc.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#cmakedefine01 HAVE_SYS_TIME_H
#cmakedefine01 HAVE_SYS_MMAN_H
#cmakedefine01 HAVE_SYS_MEMBARRIER_H
#cmakedefine01 HAVE_PTHREAD_THREADID_NP
#cmakedefine01 HAVE_PTHREAD_GETTHREADID_NP
#cmakedefine01 HAVE_VM_FLAGS_SUPERPAGE_SIZE_ANY
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/unix/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ include(CheckLibraryExists)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_include_files(sys/mman.h HAVE_SYS_MMAN_H)
check_include_files(pthread_np.h HAVE_PTHREAD_NP_H)
check_include_files(sys/membarrier.h HAVE_SYS_MEMBARRIER_H)

check_function_exists(vm_allocate HAVE_VM_ALLOCATE)
check_function_exists(sysctlbyname HAVE_SYSCTLBYNAME)
Expand Down
46 changes: 17 additions & 29 deletions src/coreclr/gc/unix/gcenv.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
#include <sys/swap.h>
#endif

#ifdef __linux__
#include <linux/membarrier.h>
#include <sys/syscall.h>
#define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__)
#elif HAVE_SYS_MEMBARRIER_H
#include <sys/membarrier.h>
#endif

#include <sys/resource.h>

#undef min
Expand Down Expand Up @@ -94,10 +102,6 @@ extern "C"
#include <OS.h>
#endif // __HAIKU__

#ifdef __linux__
#include <sys/syscall.h> // __NR_membarrier
#endif

#if HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
Expand Down Expand Up @@ -132,29 +136,9 @@ typedef cpuset_t cpu_set_t;
// The cached total number of CPUs that can be used in the OS.
static uint32_t g_totalCpuCount = 0;

//
// Helper membarrier function
//
#ifdef __NR_membarrier
# define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__)
#else
# define membarrier(...) -ENOSYS
#endif

enum membarrier_cmd
{
MEMBARRIER_CMD_QUERY = 0,
MEMBARRIER_CMD_GLOBAL = (1 << 0),
MEMBARRIER_CMD_GLOBAL_EXPEDITED = (1 << 1),
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED = (1 << 2),
MEMBARRIER_CMD_PRIVATE_EXPEDITED = (1 << 3),
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4),
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE = (1 << 5),
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = (1 << 6)
};

bool CanFlushUsingMembarrier()
{
#if defined(__linux__) || HAVE_SYS_MEMBARRIER_H

#ifdef TARGET_ANDROID
// Avoid calling membarrier on older Android versions where membarrier
Expand All @@ -169,15 +153,16 @@ bool CanFlushUsingMembarrier()
// Starting with Linux kernel 4.14, process memory barriers can be generated
// using MEMBARRIER_CMD_PRIVATE_EXPEDITED.

int mask = membarrier(MEMBARRIER_CMD_QUERY, 0);
int mask = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);

if (mask >= 0 &&
mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED &&
// Register intent to use the private expedited command.
membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0) == 0)
membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0, 0) == 0)
{
return true;
}
#endif

return false;
}
Expand Down Expand Up @@ -423,12 +408,15 @@ bool GCToOSInterface::CanGetCurrentProcessorNumber()
// Flush write buffers of processors that are executing threads of the current process
void GCToOSInterface::FlushProcessWriteBuffers()
{
#if defined(__linux__) || HAVE_SYS_MEMBARRIER_H
if (s_flushUsingMemBarrier)
{
int status = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0);
int status = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0, 0);
assert(status == 0 && "Failed to flush using membarrier");
}
else if (g_helperPage != 0)
else
#endif
if (g_helperPage != 0)
{
int status = pthread_mutex_lock(&g_flushProcessWriteBuffersMutex);
assert(status == 0 && "Failed to lock the flushProcessWriteBuffersMutex lock");
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/pal/src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
#cmakedefine01 HAVE_CRT_EXTERNS_H
#cmakedefine01 HAVE_SYS_TIME_H
#cmakedefine01 HAVE_PTHREAD_NP_H
#cmakedefine01 HAVE_SYS_MEMBARRIER_H
#cmakedefine01 HAVE_SYS_LWP_H
#cmakedefine01 HAVE_LWP_H
#cmakedefine01 HAVE_RUNETYPE_H
#cmakedefine01 HAVE_GNU_LIBNAMES_H
#cmakedefine01 HAVE_PRCTL_H
#cmakedefine01 HAVE_PTHREAD_NP_H
#cmakedefine01 HAVE_AUXV_HWCAP_H
#cmakedefine01 HAVE_SYS_PTRACE_H
#cmakedefine01 HAVE_SYS_UCONTEXT_H
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/pal/src/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ check_include_files(procfs.h HAVE_PROCFS_H)
check_include_files(crt_externs.h HAVE_CRT_EXTERNS_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_include_files(pthread_np.h HAVE_PTHREAD_NP_H)
check_include_files(sys/membarrier.h HAVE_SYS_MEMBARRIER_H)
check_include_files(sys/lwp.h HAVE_SYS_LWP_H)
check_include_files(lwp.h HAVE_LWP_H)
check_include_files(runetype.h HAVE_RUNETYPE_H)
Expand Down
40 changes: 14 additions & 26 deletions src/coreclr/pal/src/thread/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d
#include <vector>

#ifdef __linux__
#include <sys/syscall.h> // __NR_membarrier
#include <linux/membarrier.h>
#include <sys/syscall.h>
#define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__)
#elif HAVE_SYS_MEMBARRIER_H
#include <sys/membarrier.h>
#endif

#ifdef __APPLE__
Expand Down Expand Up @@ -125,27 +129,6 @@ CObjectType CorUnix::otProcess(
CObjectType::NoOwner
);

//
// Helper membarrier function
//
#ifdef __NR_membarrier
# define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__)
#else
# define membarrier(...) -ENOSYS
#endif

enum membarrier_cmd
{
MEMBARRIER_CMD_QUERY = 0,
MEMBARRIER_CMD_GLOBAL = (1 << 0),
MEMBARRIER_CMD_GLOBAL_EXPEDITED = (1 << 1),
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED = (1 << 2),
MEMBARRIER_CMD_PRIVATE_EXPEDITED = (1 << 3),
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4),
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE = (1 << 5),
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = (1 << 6)
};

//
// Tracks if the OS supports FlushProcessWriteBuffers using membarrier
//
Expand Down Expand Up @@ -2581,19 +2564,21 @@ InitializeFlushProcessWriteBuffers()
_ASSERTE(s_helperPage == 0);
_ASSERTE(s_flushUsingMemBarrier == 0);

#if defined(__linux__) || HAVE_SYS_MEMBARRIER_H
// Starting with Linux kernel 4.14, process memory barriers can be generated
// using MEMBARRIER_CMD_PRIVATE_EXPEDITED.
int mask = membarrier(MEMBARRIER_CMD_QUERY, 0);
int mask = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);
if (mask >= 0 &&
mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED)
{
// Register intent to use the private expedited command.
if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0) == 0)
if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0, 0) == 0)
{
s_flushUsingMemBarrier = TRUE;
return TRUE;
}
}
#endif

#ifdef TARGET_APPLE
return TRUE;
Expand Down Expand Up @@ -2649,12 +2634,15 @@ VOID
PALAPI
FlushProcessWriteBuffers()
{
#if defined(__linux__) || HAVE_SYS_MEMBARRIER_H
if (s_flushUsingMemBarrier)
{
int status = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0);
int status = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0, 0);
FATAL_ASSERT(status == 0, "Failed to flush using membarrier");
}
else if (s_helperPage != 0)
else
#endif
if (s_helperPage != 0)
{
int status = pthread_mutex_lock(&flushProcessWriteBuffersMutex);
FATAL_ASSERT(status == 0, "Failed to lock the flushProcessWriteBuffersMutex lock");
Expand Down

0 comments on commit 1b71136

Please sign in to comment.