Introduce common generic header file
[librseq.git] / include / rseq / compiler.h
index d09e770ce4ceecdc9cec16548d66709041217fd3..3df18cdbf84082417dd1725abd94e21df7b7bf5a 100644 (file)
@@ -7,8 +7,33 @@
  * Work-around asm goto compiler bugs.
  */
 
-#ifndef RSEQ_COMPILER_H
-#define RSEQ_COMPILER_H
+#ifndef _RSEQ_COMPILER_H
+#define _RSEQ_COMPILER_H
+
+#if defined __cplusplus
+# include <type_traits>        /* for std::remove_cv */
+#endif
+
+#define rseq_likely(x)         __builtin_expect(!!(x), 1)
+#define rseq_unlikely(x)       __builtin_expect(!!(x), 0)
+#define rseq_barrier()         __asm__ __volatile__("" : : : "memory")
+
+/*
+ * Instruct the compiler to perform only a single access to a variable
+ * (prohibits merging and refetching). The compiler is also forbidden to reorder
+ * successive instances of RSEQ_ACCESS_ONCE(), but only when the compiler is aware of
+ * particular ordering. Compiler ordering can be ensured, for example, by
+ * putting two RSEQ_ACCESS_ONCE() in separate C statements.
+ *
+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
+ * merging, or refetching absolutely anything at any time.  Its main intended
+ * use is to mediate communication between process-level code and irq/NMI
+ * handlers, all running on the same CPU.
+ */
+#define RSEQ_ACCESS_ONCE(x)    (*(__volatile__  __typeof__(x) *)&(x))
+
+#define RSEQ_WRITE_ONCE(x, v)  __extension__ ({ RSEQ_ACCESS_ONCE(x) = (v); })
+#define RSEQ_READ_ONCE(x)      RSEQ_ACCESS_ONCE(x)
 
 /*
  * gcc prior to 4.8.2 miscompiles asm goto.
  * label target.  Emit this for all compilers in case other similar
  * issues are found in the future.
  */
-#define rseq_after_asm_goto()  asm volatile ("" : : : "memory")
+#define rseq_after_asm_goto()  __asm__ __volatile__ ("" : : : "memory")
+
+/* Combine two tokens. */
+#define RSEQ__COMBINE_TOKENS(_tokena, _tokenb) \
+       _tokena##_tokenb
+#define RSEQ_COMBINE_TOKENS(_tokena, _tokenb)  \
+       RSEQ__COMBINE_TOKENS(_tokena, _tokenb)
+
+#if defined(__SIZEOF_LONG__)
+#define RSEQ_BITS_PER_LONG     (__SIZEOF_LONG__ * 8)
+#elif defined(_LP64)
+#define RSEQ_BITS_PER_LONG     64
+#else
+#define RSEQ_BITS_PER_LONG     32
+#endif
+
+#ifdef __cplusplus
+#define rseq_unqual_scalar_typeof(x)                                   \
+       std::remove_cv<std::remove_reference<decltype(x)>::type>::type
+#else
+#define rseq_scalar_type_to_expr(type)                                 \
+       unsigned type: (unsigned type)0,                                \
+       signed type: (signed type)0
+
+/*
+ * Use C11 _Generic to express unqualified type from expression. This removes
+ * volatile qualifier from expression type.
+ */
+#define rseq_unqual_scalar_typeof(x)                                   \
+       __typeof__(                                                     \
+               _Generic((x),                                           \
+                       char: (char)0,                                  \
+                       rseq_scalar_type_to_expr(char),                 \
+                       rseq_scalar_type_to_expr(short),                \
+                       rseq_scalar_type_to_expr(int),                  \
+                       rseq_scalar_type_to_expr(long),                 \
+                       rseq_scalar_type_to_expr(long long),            \
+                       default: (x)                                    \
+               )                                                       \
+       )
+#endif
 
-#endif  /* RSEQ_COMPILER_H_ */
+#endif  /* _RSEQ_COMPILER_H */
This page took 0.024189 seconds and 4 git commands to generate.