.\" Copyright 2015-2017 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
.\"
-.\" %%%LICENSE_START(VERBATIM)
-.\" Permission is granted to make and distribute verbatim copies of this
-.\" manual provided the copyright notice and this permission notice are
-.\" preserved on all copies.
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
.\"
-.\" Permission is granted to copy and distribute modified versions of this
-.\" manual under the conditions for verbatim copying, provided that the
-.\" entire resulting derived work is distributed under the terms of a
-.\" permission notice identical to this one.
-.\"
-.\" Since the Linux kernel and libraries are constantly changing, this
-.\" manual page may be incorrect or out-of-date. The author(s) assume no
-.\" responsibility for errors or omissions, or for damages resulting from
-.\" the use of the information contained herein. The author(s) may not
-.\" have taken the same level of care in the production of this manual,
-.\" which is licensed free of charge, as they might when working
-.\" professionally.
-.\"
-.\" Formatted or processed versions of this manual, if unaccompanied by
-.\" the source, must acknowledge the copyright and authors of this work.
-.\" %%%LICENSE_END
-.\"
-.TH MEMBARRIER 2 2017-11-15 "Linux" "Linux Programmer's Manual"
+.TH MEMBARRIER 2 (date) "Linux man-pages (unreleased)"
.SH NAME
membarrier \- issue memory barriers on a set of threads
+.SH LIBRARY
+Standard C library
+.RI ( libc ", " \-lc )
.SH SYNOPSIS
-.B #include <linux/membarrier.h>
+.nf
.PP
-.BI "int membarrier(int " cmd ", int " flags ");
+.BR "#include <linux/membarrier.h>" \
+" /* Definition of " MEMBARRIER_* " constants */"
+.BR "#include <sys/syscall.h>" " /* Definition of " SYS_* " constants */"
+.B #include <unistd.h>
+.PP
+.BI "int syscall(SYS_membarrier, int " cmd ", unsigned int " flags \
+", int " cpu_id );
+.fi
+.PP
+.IR Note :
+glibc provides no wrapper for
+.BR membarrier (),
+necessitating the use of
+.BR syscall (2).
.SH DESCRIPTION
The
.BR membarrier ()
barriers, the fast-side memory barriers by simple compiler barriers,
for example:
.PP
- asm volatile ("" : : : "memory")
+.in +4n
+.EX
+asm volatile ("" : : : "memory")
+.EE
+.in
.PP
and replace the slow-side memory barriers by calls to
.BR membarrier ().
.I cmd
argument is one of the following:
.TP
-.B MEMBARRIER_CMD_QUERY
+.BR MEMBARRIER_CMD_QUERY " (since Linux 4.3)"
Query the set of supported commands.
The return value of the call is a bit mask of supported
commands.
.BR membarrier ()
is provided).
.TP
-.B MEMBARRIER_CMD_GLOBAL " (since Linux 4.16)"
+.BR MEMBARRIER_CMD_GLOBAL " (since Linux 4.16)"
Ensure that all threads from all processes on the system pass through a
state where all memory accesses to user-space addresses match program
order between entry to and return from the
system call.
All threads on the system are targeted by this command.
.TP
-.B MEMBARRIER_CMD_GLOBAL_EXPEDITED " (since Linux 4.16)"
-Execute a memory barrier on all running threads of all processes which
+.BR MEMBARRIER_CMD_GLOBAL_EXPEDITED " (since Linux 4.16)"
+Execute a memory barrier on all running threads of all processes that
previously registered with
.BR MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED .
-Upon return from system call, the caller thread is ensured that all
+.IP
+Upon return from the system call, the calling thread has a guarantee that all
running threads have passed through a state where all memory accesses to
user-space addresses match program order between entry to and return
from the system call (non-running threads are de facto in such a state).
-This only covers threads from processes which registered with
+This guarantee is provided only for the threads of processes that
+previously registered with
.BR MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED .
+.IP
Given that registration is about the intent to receive the barriers, it
is valid to invoke
-.BR MEMBARRIER_CMD_GLOBAL_EXPEDITED
-from a non-registered process.
+.B MEMBARRIER_CMD_GLOBAL_EXPEDITED
+from a process that has not employed
+.BR MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED .
.IP
The "expedited" commands complete faster than the non-expedited ones;
they never block, but have the downside of causing extra overhead.
.TP
-.B MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED " (since Linux 4.16)"
-Register the process intent to receive
-.BR MEMBARRIER_CMD_GLOBAL_EXPEDITED
+.BR MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED " (since Linux 4.16)"
+Register the process's intent to receive
+.B MEMBARRIER_CMD_GLOBAL_EXPEDITED
memory barriers.
.TP
-.B MEMBARRIER_CMD_PRIVATE_EXPEDITED " (since Linux 4.14)"
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED " (since Linux 4.14)"
Execute a memory barrier on each running thread belonging to the same
-process as the current thread.
-Upon return from system call, the calling
-thread is assured that all its running threads siblings have passed
+process as the calling thread.
+.IP
+Upon return from the system call, the calling
+thread has a guarantee that all its running thread siblings have passed
through a state where all memory accesses to user-space addresses match
program order between entry to and return from the system call
(non-running threads are de facto in such a state).
-This covers only threads from the same process as the calling thread.
+This guarantee is provided only for threads in
+the same process as the calling thread.
.IP
The "expedited" commands complete faster than the non-expedited ones;
they never block, but have the downside of causing extra overhead.
-A process needs to register its intent to use the private
+.IP
+A process must register its intent to use the private
expedited command prior to using it.
.TP
-.B MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED " (since Linux 4.14)"
+.BR MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED " (since Linux 4.14)"
Register the process's intent to use
-.B MEMBARRIER_CMD_PRIVATE_EXPEDITED .
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED .
.TP
-.B MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE " (since Linux 4.16)"
-In addition to provide memory ordering guarantees described in
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE " (since Linux 4.16)"
+In addition to providing the memory ordering guarantees described in
.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED ,
-ensure the caller thread, upon return from system call, that all its
-running threads siblings have executed a core serializing instruction.
-This only covers threads from the same process as the caller thread.
+upon return from system call the calling thread has a guarantee that all its
+running thread siblings have executed a core serializing instruction.
+This guarantee is provided only for threads in
+the same process as the calling thread.
+.IP
The "expedited" commands complete faster than the non-expedited ones,
-they never block, but have the downside of causing extra overhead. A
-process needs to register its intent to use the private expedited sync
+they never block, but have the downside of causing extra overhead.
+.IP
+A process must register its intent to use the private expedited sync
core command prior to using it.
.TP
-.B MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE " (since Linux 4.16)"
-Register the process intent to use
+.BR MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE " (since Linux 4.16)"
+Register the process's intent to use
.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE .
.TP
-.B MEMBARRIER_CMD_SHARED
- Alias to
-.BR MEMBARRIER_CMD_GLOBAL .
-Provided for header backward compatibility.
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ " (since Linux 5.10)"
+Ensure the caller thread, upon return from system call, that all its
+running thread siblings have any currently running rseq critical sections
+restarted if
+.I flags
+parameter is 0; if
+.I flags
+parameter is
+.BR MEMBARRIER_CMD_FLAG_CPU ,
+then this operation is performed only on CPU indicated by
+.IR cpu_id .
+This guarantee is provided only for threads in
+the same process as the calling thread.
+.IP
+RSEQ membarrier is only available in the "private expedited" form.
+.IP
+A process must register its intent to use the private expedited rseq
+command prior to using it.
+.TP
+.BR MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ " (since Linux 5.10)"
+Register the process's intent to use
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ .
+.TP
+.BR MEMBARRIER_CMD_SHARED " (since Linux 4.3)"
+This is an alias for
+.B MEMBARRIER_CMD_GLOBAL
+that exists for header backward compatibility.
.PP
The
.I flags
-argument is currently unused and must be specified as 0.
+argument must be specified as 0 unless the command is
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ ,
+in which case
+.I flags
+can be either 0 or
+.BR MEMBARRIER_CMD_FLAG_CPU .
+.PP
+The
+.I cpu_id
+argument is ignored unless
+.I flags
+is
+.BR MEMBARRIER_CMD_FLAG_CPU ,
+in which case it must specify the CPU targeted by this membarrier
+command.
.PP
All memory accesses performed in program order from each targeted thread
are guaranteed to be ordered with respect to
ordering across the barrier, we have the following ordering table for
each pairing of
.IR barrier() ,
-.BR membarrier ()
+.BR membarrier (),
and
.IR smp_mb() .
The pair ordering is detailed as (O: ordered, X: not ordered):
.PP
- barrier() smp_mb() membarrier()
- barrier() X X O
- smp_mb() X O O
- membarrier() O O O
+.RS
+.TS
+l c c c.
+\& barrier() smp_mb() membarrier()
+barrier() X X O
+smp_mb() X O O
+membarrier() O O O
+.TE
+.RE
.SH RETURN VALUE
On success, the
.B MEMBARRIER_CMD_QUERY
operation returns a bit mask of supported commands, and the
-.B MEMBARRIER_CMD_GLOBAL ,
-.B MEMBARRIER_CMD_GLOBAL_EXPEDITED ,
-.B MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED ,
-.B MEMBARRIER_CMD_PRIVATE_EXPEDITED ,
-.B MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED ,
-.B MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE ,
+.BR MEMBARRIER_CMD_GLOBAL ,
+.BR MEMBARRIER_CMD_GLOBAL_EXPEDITED ,
+.BR MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED ,
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED ,
+.BR MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED ,
+.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE ,
and
.B MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
operations return zero.
On error, \-1 is returned,
and
.I errno
-is set appropriately.
+is set to indicate the error.
.PP
For a given command, with
.I flags
is invalid, or
.I flags
is nonzero, or the
-.BR MEMBARRIER_CMD_GLOBAL
+.B MEMBARRIER_CMD_GLOBAL
command is disabled because the
.I nohz_full
CPU parameter has been set, or the
-.BR MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE
+.B MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE
and
-.BR MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
+.B MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
commands are not implemented by the architecture.
.TP
.B ENOSYS
The
.BR membarrier ()
system call was added in Linux 4.3.
-.\"
-.SH CONFORMING TO
+.PP
+Before Linux 5.10, the prototype for
+.BR membarrier ()
+was:
+.PP
+.in +4n
+.EX
+.BI "int membarrier(int " cmd ", int " flags );
+.EE
+.in
+.SH STANDARDS
.BR membarrier ()
is Linux-specific.
.\" .SH SEE ALSO
.\" .BR rseq (2)
.SH NOTES
A memory barrier instruction is part of the instruction set of
-architectures with weakly-ordered memory models.
+architectures with weakly ordered memory models.
It orders memory
accesses prior to the barrier and after the barrier with respect to
matching barriers on other cores.
.BR membarrier ()
can be useful include implementations
of Read-Copy-Update libraries and garbage collectors.
-.SH EXAMPLE
+.SH EXAMPLES
Assuming a multithreaded application where "fast_path()" is executed
very frequently, and where "slow_path()" is executed infrequently, the
following code (x86) can be transformed using
.BR membarrier ():
.PP
.in +4n
+.\" SRC BEGIN (membarrier.c)
.EX
#include <stdlib.h>
}
int
-main(int argc, char **argv)
+main(void)
{
int read_a, read_b;
exit(EXIT_SUCCESS);
}
.EE
+.\" SRC END
.in
.PP
The code above transformed to use
static volatile int a, b;
static int
-membarrier(int cmd, int flags)
+membarrier(int cmd, unsigned int flags, int cpu_id)
{
- return syscall(__NR_membarrier, cmd, flags);
+ return syscall(__NR_membarrier, cmd, flags, cpu_id);
}
static int
/* Check that membarrier() is supported. */
- ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
+ ret = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);
if (ret < 0) {
perror("membarrier");
return \-1;
if (!(ret & MEMBARRIER_CMD_GLOBAL)) {
fprintf(stderr,
- "membarrier does not support MEMBARRIER_CMD_GLOBAL\\n");
+ "membarrier does not support MEMBARRIER_CMD_GLOBAL\en");
return \-1;
}
slow_path(int *read_a)
{
b = 1;
- membarrier(MEMBARRIER_CMD_GLOBAL, 0);
+ membarrier(MEMBARRIER_CMD_GLOBAL, 0, 0);
*read_a = a;
}
int
-main(int argc, char **argv)
+main(int argc, char *argv[])
{
int read_a, read_b;