You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, you define real wrappers for membarrier on Linux (and wherever you randomly pick up a definition for __NR_membarrier), and everywhere else (except maybe Windows) you define fake wrappers that just fails1.
Then, if membarrier doesn't claim to support MEMBARRIER_CMD_PRIVATE_EXPEDITED (including the case where we don't know how to call it on a given OS), the calling code to falls back to a hack using mlock(2) and mprotect(2), which unfortunately does not work on ARM/ARM64 Linux or FreeBSD (Apple don't distribute the relevant sources so I have no clue about Mac running on Apple Silicon - not even for x86-64 programs!).
This is a bit hard to spot because it's in two pieces:
An explicitly Linux-only bit makes sure you have __NR_membarrier:
But this misses FreeBSD, which has membarrier(2) too. Apparently they have an actual stub in libc, but have a syscall function too. The stub is declared in sys/membarrier.h and the system call number in sys/syscall.h:
#defineSYS_membarrier 584
The constants are:
enummembarrier_cmd {
MEMBARRIER_CMD_QUERY=0x00000000,
MEMBARRIER_CMD_GLOBAL=0x00000001,
MEMBARRIER_CMD_SHARED=MEMBARRIER_CMD_GLOBAL,
MEMBARRIER_CMD_GLOBAL_EXPEDITED=0x00000002,
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED=0x00000004,
MEMBARRIER_CMD_PRIVATE_EXPEDITED=0x00000008,
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED=0x00000010,
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE=0x00000020,
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE=0x00000040,
/* * RSEQ constants are defined for source compatibility but are * not yet supported, MEMBARRIER_CMD_QUERY does not return * them in the mask. */MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ=0x00000080,
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ=0x00000100,
};
Which is a great way to avoid boring, repetitive, and therefore bug prone code, though I note that glibc's syscall() function would set errno = ENOSYS and return -1 rather than returning -ENOSYS if the syscall is not supported. This would only truly matter if you actually had callers that distinguished between negative values or read errno, which you don'tx ↩
The text was updated successfully, but these errors were encountered:
Currently, you define real wrappers for
membarrier
on Linux (and wherever you randomly pick up a definition for__NR_membarrier
), and everywhere else (except maybe Windows) you define fake wrappers that just fails1.Then, if membarrier doesn't claim to support
MEMBARRIER_CMD_PRIVATE_EXPEDITED
(including the case where we don't know how to call it on a given OS), the calling code to falls back to a hack using mlock(2) and mprotect(2), which unfortunately does not work on ARM/ARM64 Linux or FreeBSD (Apple don't distribute the relevant sources so I have no clue about Mac running on Apple Silicon - not even for x86-64 programs!).This is a bit hard to spot because it's in two pieces:
An explicitly Linux-only bit makes sure you have
__NR_membarrier
:runtime/src/coreclr/pal/src/thread/process.cpp
Lines 66 to 84 in f196875
The actual wrappers
runtime/src/coreclr/pal/src/thread/process.cpp
Lines 146 to 153 in f196875
But this misses FreeBSD, which has membarrier(2) too. Apparently they have an actual stub in libc, but have a syscall function too. The stub is declared in sys/membarrier.h and the system call number in sys/syscall.h:
The constants are:
which appear to match the values for Linux:
runtime/src/coreclr/pal/src/thread/process.cpp
Lines 155 to 165 in f196875
(Curiously, they don't actually implement Linux compatibility for this syscall despite using the same flag bits.)
Note: for some reason, the same exact code appears in https://github.com/dotnet/runtime/blob/f196875c5d0441364f6538d2dd8fc4e3eb1ff108/src/coreclr/gc/unix/gcenv.unix.cpp, though with different line numbers.
Footnotes
Which is a great way to avoid boring, repetitive, and therefore bug prone code, though I note that glibc's syscall() function would set
errno = ENOSYS
and return-1
rather than returning-ENOSYS
if the syscall is not supported. This would only truly matter if you actually had callers that distinguished between negative values or read errno, which you don'tx ↩The text was updated successfully, but these errors were encountered: