Movatterモバイル変換


[0]ホーム

URL:


man7.org > Linux >man-pages

Linux/UNIX system programming training


membarrier(2) — Linux manual page

NAME |LIBRARY |SYNOPSIS |DESCRIPTION |RETURN VALUE |ERRORS |STANDARDS |HISTORY |NOTES |EXAMPLES |COLOPHON

membarrier(2)              System Calls Manualmembarrier(2)

NAME        top

       membarrier - issue memory barriers on a set of threads

LIBRARY        top

       Standard C library (libc,-lc)

SYNOPSIS        top

#include <linux/membarrier.h>/* Definition ofMEMBARRIER_*constants */#include <sys/syscall.h>/* Definition ofSYS_*constants */#include <unistd.h>int syscall(SYS_membarrier, intcmd, unsigned intflags, intcpu_id);Note: glibc provides no wrapper formembarrier(), necessitating       the use ofsyscall(2).

DESCRIPTION        top

       Themembarrier() system call helps reducing the overhead of the       memory barrier instructions required to order memory accesses on       multi-core systems.  However, this system call is heavier than a       memory barrier, so using it effectively isnot as simple as       replacing memory barriers with this system call, but requires       understanding of the details below.       Use of memory barriers needs to be done taking into account that a       memory barrier always needs to be either matched with its memory       barrier counterparts, or that the architecture's memory model       doesn't require the matching barriers.       There are cases where one side of the matching barriers (which we       will refer to as "fast side") is executed much more often than the       other (which we will refer to as "slow side").  This is a prime       target for the use ofmembarrier().  The key idea is to replace,       for these matching barriers, the fast-side memory barriers by       simple compiler barriers, for example:           asm volatile ("" : : : "memory")       and replace the slow-side memory barriers by calls tomembarrier().       This will add overhead to the slow side, and remove overhead from       the fast side, thus resulting in an overall performance increase       as long as the slow side is infrequent enough that the overhead of       themembarrier() calls does not outweigh the performance gain on       the fast side.       Thecmd argument is one of the following: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.MEMBARRIER_CMD_QUERY, which has the value 0, is not itself              included in this bit mask.  This command is always              supported (on kernels wheremembarrier() is provided).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 themembarrier() system call.  All threads on              the system are targeted by this command.MEMBARRIER_CMD_GLOBAL_EXPEDITED(since Linux 4.16)              Execute a memory barrier on all running threads of all              processes that previously registered withMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED.              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 guarantee is provided only for the threads of              processes that previously registered withMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED.              Given that registration is about the intent to receive the              barriers, it is valid to invokeMEMBARRIER_CMD_GLOBAL_EXPEDITEDfrom a process that has not              employedMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED.              The "expedited" commands complete faster than the non-              expedited ones; they never block, but have the downside of              causing extra overhead.MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED(since Linux 4.16)              Register the process's intent to receiveMEMBARRIER_CMD_GLOBAL_EXPEDITEDmemory barriers.MEMBARRIER_CMD_PRIVATE_EXPEDITED(since Linux 4.14)              Execute a memory barrier on each running thread belonging              to the same process as the calling thread.              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 guarantee is provided only for threads              in the same process as the calling thread.              The "expedited" commands complete faster than the non-              expedited ones; they never block, but have the downside of              causing extra overhead.              A process must register its intent to use the private              expedited command prior to using it.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED(since Linux 4.14)              Register the process's intent to useMEMBARRIER_CMD_PRIVATE_EXPEDITED.MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE(since Linux 4.16)              In addition to providing the memory ordering guarantees              described inMEMBARRIER_CMD_PRIVATE_EXPEDITED, 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.              The "expedited" commands complete faster than the non-              expedited ones, they never block, but have the downside of              causing extra overhead.              A process must register its intent to use the private              expedited sync core command prior to using it.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE(since Linux       4.16)              Register the process's intent to useMEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE.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 ifflags parameter              is 0; ifflags parameter isMEMBARRIER_CMD_FLAG_CPU, then              this operation is performed only on CPU indicated bycpu_id.  This guarantee is provided only for threads in the              same process as the calling thread.              RSEQ membarrier is only available in the "private              expedited" form.              A process must register its intent to use the private              expedited rseq command prior to using it.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ(since Linux 5.10)              Register the process's intent to useMEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ.MEMBARRIER_CMD_SHARED(since Linux 4.3)              This is an alias forMEMBARRIER_CMD_GLOBALthat exists for              header backward compatibility.       Theflags argument must be specified as 0 unless the command isMEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ, in which caseflags can be       either 0 orMEMBARRIER_CMD_FLAG_CPU.       Thecpu_id argument is ignored unlessflags isMEMBARRIER_CMD_FLAG_CPU, in which case it must specify the CPU       targeted by this membarrier command.       All memory accesses performed in program order from each targeted       thread are guaranteed to be ordered with respect tomembarrier().       If we use the semanticbarrier() to represent a compiler barrier       forcing memory accesses to be performed in program order across       the barrier, andsmp_mb() to represent explicit memory barriers       forcing full memory ordering across the barrier, we have the       following ordering table for each pairing ofbarrier(),membarrier(), andsmp_mb().  The pair ordering is detailed as (O:       ordered, X: not ordered):                             barrier()   smp_mb()   membarrier()              barrier()          X          X            O              smp_mb()           X          O            O              membarrier()       O          O            O

RETURN VALUE        top

       On success, theMEMBARRIER_CMD_QUERYoperation returns a bit mask       of supported commands, and theMEMBARRIER_CMD_GLOBAL,MEMBARRIER_CMD_GLOBAL_EXPEDITED,MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,MEMBARRIER_CMD_PRIVATE_EXPEDITED,MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE, andMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_COREoperations       return zero.  On error, -1 is returned, anderrno is set to       indicate the error.       For a given command, withflags set to 0, this system call is       guaranteed to always return the same value until reboot.  Further       calls with the same arguments will lead to the same result.       Therefore, withflags set to 0, error handling is required only       for the first call tomembarrier().

ERRORS        top

EINVALcmd is invalid, orflags is nonzero, or theMEMBARRIER_CMD_GLOBALcommand is disabled because thenohz_full CPU parameter has been set, or theMEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_COREandMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE              commands are not implemented by the architecture.ENOSYSThemembarrier() system call is not implemented by this              kernel.EPERMThe current process was not registered prior to using              private expedited commands.

STANDARDS        top

       Linux.

HISTORY        top

       Linux 4.3.       Before Linux 5.10, the prototype was:int membarrier(intcmd, intflags);

NOTES        top

       A memory barrier instruction is part of the instruction set of       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.  For instance, a load fence       can order loads prior to and following that fence with respect to       stores ordered by store fences.       Program order is the order in which instructions are ordered in       the program assembly code.       Examples wheremembarrier() can be useful include implementations       of Read-Copy-Update libraries and garbage collectors.

EXAMPLES        top

       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 usingmembarrier():           #include <stdlib.h>           static volatile int a, b;           static void           fast_path(int *read_b)           {               a = 1;               asm volatile ("mfence" : : : "memory");               *read_b = b;           }           static void           slow_path(int *read_a)           {               b = 1;               asm volatile ("mfence" : : : "memory");               *read_a = a;           }           int           main(void)           {               int read_a, read_b;               /*                * Real applications would call fast_path() and slow_path()                * from different threads. Call those from main() to keep                * this example short.                */               slow_path(&read_a);               fast_path(&read_b);               /*                * read_b == 0 implies read_a == 1 and                * read_a == 0 implies read_b == 1.                */               if (read_b == 0 && read_a == 0)                   abort();               exit(EXIT_SUCCESS);           }       The code above transformed to usemembarrier() becomes:           #define _GNU_SOURCE           #include <stdlib.h>           #include <stdio.h>           #include <unistd.h>           #include <sys/syscall.h>           #include <linux/membarrier.h>           static volatile int a, b;           static int           membarrier(int cmd, unsigned int flags, int cpu_id)           {               return syscall(__NR_membarrier, cmd, flags, cpu_id);           }           static int           init_membarrier(void)           {               int ret;               /* Check that membarrier() is supported. */               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");                   return -1;               }               return 0;           }           static void           fast_path(int *read_b)           {               a = 1;               asm volatile ("" : : : "memory");               *read_b = b;           }           static void           slow_path(int *read_a)           {               b = 1;               membarrier(MEMBARRIER_CMD_GLOBAL, 0, 0);               *read_a = a;           }           int           main(int argc, char *argv[])           {               int read_a, read_b;               if (init_membarrier())                   exit(EXIT_FAILURE);               /*                * Real applications would call fast_path() and slow_path()                * from different threads. Call those from main() to keep                * this example short.                */               slow_path(&read_a);               fast_path(&read_b);               /*                * read_b == 0 implies read_a == 1 and                * read_a == 0 implies read_b == 1.                */               if (read_b == 0 && read_a == 0)                   abort();               exit(EXIT_SUCCESS);           }

COLOPHON        top

       This page is part of theman-pages (Linux kernel and C library       user-space interface documentation) project.  Information about       the project can be found at        ⟨https://www.kernel.org/doc/man-pages/⟩.  If you have a bug report       for this manual page, see       ⟨https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/CONTRIBUTING⟩.       This page was obtained from the tarball man-pages-6.15.tar.gz       fetched from       ⟨https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/⟩ on       2025-08-11.  If you discover any rendering problems in this HTML       version of the page, or you believe there is a better or more up-       to-date source for the page, or you have corrections or       improvements to the information in this COLOPHON (which isnot       part of the original manual page), send a mail to       man-pages@man7.orgLinux man-pages 6.15            2025-05-17membarrier(2)

Pages that refer to this page:syscalls(2)



HTML rendering created 2025-09-06 byMichael Kerrisk, author ofThe Linux Programming Interface.

For details of in-depthLinux/UNIX system programming training courses that I teach, lookhere.

Hosting byjambit GmbH.

Cover of TLPI


[8]ページ先頭

©2009-2025 Movatter.jp