~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/include/linux/ring_buffer.h

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef _TOOLS_LINUX_RING_BUFFER_H_
  2 #define _TOOLS_LINUX_RING_BUFFER_H_
  3 
  4 #include <asm/barrier.h>
  5 #include <linux/perf_event.h>
  6 
  7 /*
  8  * Contract with kernel for walking the perf ring buffer from
  9  * user space requires the following barrier pairing (quote
 10  * from kernel/events/ring_buffer.c):
 11  *
 12  *   Since the mmap() consumer (userspace) can run on a
 13  *   different CPU:
 14  *
 15  *   kernel                             user
 16  *
 17  *   if (LOAD ->data_tail) {            LOAD ->data_head
 18  *                      (A)             smp_rmb()       (C)
 19  *      STORE $data                     LOAD $data
 20  *      smp_wmb()       (B)             smp_mb()        (D)
 21  *      STORE ->data_head               STORE ->data_tail
 22  *   }
 23  *
 24  *   Where A pairs with D, and B pairs with C.
 25  *
 26  *   In our case A is a control dependency that separates the
 27  *   load of the ->data_tail and the stores of $data. In case
 28  *   ->data_tail indicates there is no room in the buffer to
 29  *   store $data we do not.
 30  *
 31  *   D needs to be a full barrier since it separates the data
 32  *   READ from the tail WRITE.
 33  *
 34  *   For B a WMB is sufficient since it separates two WRITEs,
 35  *   and for C an RMB is sufficient since it separates two READs.
 36  *
 37  * Note, instead of B, C, D we could also use smp_store_release()
 38  * in B and D as well as smp_load_acquire() in C.
 39  *
 40  * However, this optimization does not make sense for all kernel
 41  * supported architectures since for a fair number it would
 42  * resolve into READ_ONCE() + smp_mb() pair for smp_load_acquire(),
 43  * and smp_mb() + WRITE_ONCE() pair for smp_store_release().
 44  *
 45  * Thus for those smp_wmb() in B and smp_rmb() in C would still
 46  * be less expensive. For the case of D this has either the same
 47  * cost or is less expensive, for example, due to TSO x86 can
 48  * avoid the CPU barrier entirely.
 49  */
 50 
 51 static inline u64 ring_buffer_read_head(struct perf_event_mmap_page *base)
 52 {
 53 /*
 54  * Architectures where smp_load_acquire() does not fallback to
 55  * READ_ONCE() + smp_mb() pair.
 56  */
 57 #if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \
 58     defined(__ia64__) || defined(__sparc__) && defined(__arch64__) || defined(__riscv)
 59         return smp_load_acquire(&base->data_head);
 60 #else
 61         u64 head = READ_ONCE(base->data_head);
 62 
 63         smp_rmb();
 64         return head;
 65 #endif
 66 }
 67 
 68 static inline void ring_buffer_write_tail(struct perf_event_mmap_page *base,
 69                                           u64 tail)
 70 {
 71         smp_store_release(&base->data_tail, tail);
 72 }
 73 
 74 #endif /* _TOOLS_LINUX_RING_BUFFER_H_ */
 75 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php