Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

membarrier(2)

FieldValue
Numbers (x64 / i386 / arm64-generic / arm32)324 / 375 / 283 / 389 (hub)
Since (kernel)3.17 (hub; syscalls(2) row “3.17”; membarrier.2 VERSIONS instead says “added in Linux 4.3” – the command API including QUERY landed 4.3; both recorded, see notes)
Man pageman2/membarrier.2 (cached, dated 2021-08-27)
glibc wrappernone (“glibc provides no wrapper for membarrier(), necessitating the use of syscall(2)”, man page)
Aliases coverednone
Ledger IDSC-membarrier

Purpose

membarrier() executes memory barriers across a set of threads so that fast paths in synchronization algorithms can use plain compiler barriers (asm volatile("" : : : "memory")) while the matching slow-side barrier becomes a membarrier() call. After the call returns, targeted running threads are guaranteed to have passed through a state where all user-space memory accesses match program order between entry and return (man DESCRIPTION; designed for RCU libraries and garbage collectors).

Synopsis

#include <linux/membarrier.h>
#include <sys/syscall.h>
#include <unistd.h>
int syscall(SYS_membarrier, int cmd, unsigned int flags, int cpu_id);

Before 5.10 the prototype was int membarrier(int cmd, int flags); the cpu_id argument was added with the rseq command (man VERSIONS).

Arguments and behavior

cmd selects the operation (values verified in installed /usr/include/linux/membarrier.h):

CommandValueSinceEffect
MEMBARRIER_CMD_QUERY04.3return bitmask of supported commands (QUERY itself not included)
MEMBARRIER_CMD_GLOBAL (=MEMBARRIER_CMD_SHARED)1 << 04.16 (alias 4.3)barrier on all running threads of all processes
MEMBARRIER_CMD_GLOBAL_EXPEDITED1 << 14.16barrier on registered processes’ running threads
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED1 << 24.16register intent for GLOBAL_EXPEDITED
MEMBARRIER_CMD_PRIVATE_EXPEDITED1 << 34.14barrier on running threads of the calling process
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED1 << 44.14register intent for PRIVATE_EXPEDITED
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE1 << 54.16additionally core-serializing instruction on siblings
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE1 << 64.16register intent for SYNC_CORE
MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ1 << 75.10restart running rseq critical sections; flags may select one CPU
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ1 << 85.10register intent for RSEQ
MEMBARRIER_CMD_GET_REGISTRATIONS1 << 9headerbitmask of prior registration commands

flags must be 0 except with the RSEQ command, where MEMBARRIER_CMD_FLAG_CPU (1 << 0) makes cpu_id select the target CPU. With flags 0 the call is deterministic per command: same result until reboot, so error handling is needed only on the first call (man).

Return value and errors

QUERY returns the bitmask; other commands return 0. On failure -1 with errno: EINVAL (invalid cmd, nonzero flags, GLOBAL disabled under nohz_full, SYNC_CORE unimplemented on the architecture), ENOSYS (syscall absent), EPERM (private expedited used without registration).

Flags and constants

MEMBARRIER_CMD_FLAG_CPU (1 << 0) is the only flag (linux/membarrier.h).

Security and notes

  • Since conflict: ledger/hub record 3.17 (syscalls(2) row), while the individual man page VERSIONS says “added in Linux 4.3”; the man page also stamps each command with 4.3/4.14/4.16/5.10. Both cited here; worklog 1-b flags such table-vs-page discrepancies.
  • Expedited commands never block but impose overhead on the target threads (man).

References

  • Cached man page: source-cache/man-pages-sparse/man2/membarrier.2.
  • Command values: /usr/include/linux/membarrier.h (installed); kernel uapi copy source-cache/fetched/master-include-uapi-linux-membarrier.h.
  • Numbers/Since: hub overview; ledger SC-membarrier.