mm: implement the membarrier(2) syscall - #1414
Closed
gburd wants to merge 1 commit into
Closed
Conversation
membarrier() was missing entirely: not in the syscall table, no libc entry,
no prototype. Runtimes that rely on it for cheap asymmetric synchronization
(Go, .NET, some JVMs and RCU-style user libraries) could not use it.
OSv is a single process whose threads all share one address space, so a
"global" and a "private" membarrier are equivalent here. Implement the
expedited barrier by forcing every other CPU through an IPI: mmu::flush_tlb_all()
already broadcasts an IPI and waits for each CPU to run its handler, which is a
full memory barrier on that CPU, and we add a local seq_cst fence. This is a
correct superset of what membarrier promises (it also flushes TLBs, which is
harmless), and it reuses a proven, arch-portable primitive rather than adding a
dedicated per-arch IPI (x64 inter_processor_interrupt vs aarch64 sgi_interrupt).
A lighter dedicated IPI can replace it if membarrier ever shows up hot.
- MEMBARRIER_CMD_QUERY returns the supported command mask.
- REGISTER_{GLOBAL,PRIVATE}_EXPEDITED are accepted as no-ops (any thread may
issue the barrier).
- {GLOBAL, GLOBAL_EXPEDITED, PRIVATE_EXPEDITED} run the barrier.
- SYNC_CORE / RSEQ / CPU-flag variants and unknown commands return EINVAL,
as does a nonzero flags argument.
Wire it as syscall SYS_membarrier (adding __NR_membarrier / SYS_membarrier for
x86-64) with a tracepoint, add the sys/membarrier.h header with the command
enum and prototype, and export the symbol from libc.so.6 and ld-musl.so.1.
Add tests/tst-membarrier.cc covering QUERY, register, the three barrier
commands, and the EINVAL paths. Passes on OSv under KVM with 1, 2 and 4 vCPUs
(exercising the cross-CPU IPI broadcast).
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Implements the
membarrier(2)syscall, which was missing entirely (not in thesyscall table, no libc entry, no prototype). Runtimes that use it for cheap
asymmetric synchronization (Go, .NET, some JVMs, RCU-style user libraries) could
not use it on OSv.
How
OSv is a single process whose threads all share one address space, so a "global"
and a "private" membarrier are equivalent here. The expedited barrier forces
every other CPU through an IPI:
mmu::flush_tlb_all()already broadcasts an IPIand waits for each CPU to run its handler (a full memory barrier on that CPU),
and we add a local
seq_cstfence. This is a correct superset of whatmembarrier promises (it also flushes TLBs, which is harmless), and reuses a
proven, arch-portable primitive rather than adding a dedicated per-arch IPI (x64
inter_processor_interruptvs aarch64sgi_interrupt). A lighter dedicated IPIcan replace it if membarrier ever shows up hot in a profile.
MEMBARRIER_CMD_QUERYreturns the supported command mask.REGISTER_{GLOBAL,PRIVATE}_EXPEDITEDare accepted as no-ops (any thread mayissue the barrier).
{GLOBAL, GLOBAL_EXPEDITED, PRIVATE_EXPEDITED}run the barrier.SYNC_CORE/RSEQ/ CPU-flag variants and unknown commands returnEINVAL,as does a nonzero
flagsargument.Wired as syscall
SYS_membarrier(adding__NR_membarrier/SYS_membarrierfor x86-64) with a tracepoint, plus the
sys/membarrier.hheader with thecommand enum and prototype, and the symbol exported from
libc.so.6andld-musl.so.1.Testing
tests/tst-membarrier.cccovers QUERY, register, the three barrier commands,and the EINVAL paths. Passes on OSv under KVM with 1, 2 and 4 vCPUs (exercising
the cross-CPU IPI broadcast).