Update tools/include/linux/compiler.h so that the definition of
noinline can be updated to avoid an LLVM libc breakage. Fix build
issues and try to synchronize other pieces on the way. For atomic.h,
don't try to synchronize and just punt to stdatomic.h that we can
assume is present since the move to C11.
Ian Rogers (13):
tools bpf: Synchronize bpf.h with kernel uapi version
libbpf: Make __printf define conditional
libperf xyarray: Use correct stddef.h include
perf expr: Add missing stdbool.h include
perf expr: Tidy up header guard
perf debug: Add missing linux/types.h include
perf cacheline: Add missing linux/types.h include
perf arm-spe: Add missing linux/types.h include
tools headers: Rewrite linux/atomic.h using C11's stdatomic.h
asm-generic: Avoid transitive dependency for unaligned.h
tools headers: Sync linux/overflow.h
tools headers: Sync compiler.h headers
tools headers: Rename noinline to __noinline
include/asm-generic/unaligned.h | 2 +
tools/arch/x86/include/asm/atomic.h | 84 ----
tools/include/asm-generic/atomic-gcc.h | 95 ----
tools/include/asm-generic/bitops/non-atomic.h | 1 +
tools/include/asm-generic/unaligned.h | 2 +
tools/include/asm/atomic.h | 11 -
tools/include/asm/rwonce.h | 63 +++
tools/include/linux/atomic.h | 107 ++++-
tools/include/linux/compiler-clang.h | 124 +++++
tools/include/linux/compiler-gcc.h | 145 +++++-
tools/include/linux/compiler.h | 221 ++-------
tools/include/linux/compiler_attributes.h | 449 ++++++++++++++++++
tools/include/linux/compiler_types.h | 171 ++++++-
tools/include/linux/overflow.h | 331 ++++++++++---
tools/include/linux/rbtree.h | 1 +
tools/include/linux/string.h | 1 +
tools/include/linux/types.h | 17 +-
tools/include/uapi/linux/bpf.h | 1 +
tools/lib/bpf/libbpf.c | 4 +-
tools/lib/perf/include/internal/xyarray.h | 2 +-
tools/perf/arch/x86/tests/bp-modify.c | 4 +-
tools/perf/bench/find-bit-bench.c | 2 +-
tools/perf/check-headers.sh | 4 +
tools/perf/tests/bp_account.c | 2 +-
tools/perf/tests/bp_signal.c | 2 +-
tools/perf/tests/bp_signal_overflow.c | 2 +-
tools/perf/tests/dwarf-unwind.c | 12 +-
tools/perf/tests/workloads/leafloop.c | 8 +-
tools/perf/tests/workloads/thloop.c | 4 +-
.../util/arm-spe-decoder/arm-spe-decoder.h | 1 +
.../arm-spe-decoder/arm-spe-pkt-decoder.c | 8 +-
tools/perf/util/cacheline.h | 1 +
tools/perf/util/debug.h | 1 +
tools/perf/util/expr.h | 8 +-
.../selftests/kvm/include/kvm_util_base.h | 3 +-
35 files changed, 1388 insertions(+), 506 deletions(-)
delete mode 100644 tools/arch/x86/include/asm/atomic.h
delete mode 100644 tools/include/asm-generic/atomic-gcc.h
delete mode 100644 tools/include/asm/atomic.h
create mode 100644 tools/include/asm/rwonce.h
create mode 100644 tools/include/linux/compiler-clang.h
create mode 100644 tools/include/linux/compiler_attributes.h
--
2.44.0.278.ge034bb2e1d-goog
Commit 91051f003948 ("tcp: Dump bound-only sockets in inet_diag.")
added BPF_TCP_BOUND_INACTIVE to the enum of tcp states in uapi's
bpf.h. Synchronize the tools version of the file.
To avoid future divergence add uapi/linux/bpf.h,
include/uapi/linux/bpf_common.h and
include/uapi/linux/bpf_perf_event.h to the check-headers.sh script.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/include/uapi/linux/bpf.h | 1 +
tools/perf/check-headers.sh | 3 +++
2 files changed, 4 insertions(+)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 7f24d898efbb..754e68ca8744 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -6904,6 +6904,7 @@ enum {
BPF_TCP_LISTEN,
BPF_TCP_CLOSING, /* Now a valid state */
BPF_TCP_NEW_SYN_RECV,
+ BPF_TCP_BOUND_INACTIVE,
BPF_TCP_MAX_STATES /* Leave at the end! */
};
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 66ba33dbcef2..64dbf199dff9 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -6,6 +6,9 @@ NC='\033[0m' # No Color
declare -a FILES
FILES=(
+ "include/uapi/linux/bpf.h"
+ "include/uapi/linux/bpf_common.h"
+ "include/uapi/linux/bpf_perf_event.h"
"include/uapi/linux/const.h"
"include/uapi/drm/drm.h"
"include/uapi/drm/i915_drm.h"
--
2.44.0.278.ge034bb2e1d-goog
libbpf depends upon linux/err.h which has a linux/compiler.h
dependency. In the kernel includes, as opposed to the tools version,
linux/compiler.h includes linux/compiler_attributes.h which defines
__printf. As the libbpf.c __printf definition isn't guarded by an
ifndef, this leads to a duplicate definition compilation error when
trying to update the tools/include/linux/compiler.h. Fix this by
adding the missing ifndef.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/lib/bpf/libbpf.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index afd09571c482..2152360b4b18 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -66,7 +66,9 @@
*/
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-#define __printf(a, b) __attribute__((format(printf, a, b)))
+#ifndef __printf
+# define __printf(a, b) __attribute__((format(printf, a, b)))
+#endif
static struct bpf_map *bpf_object__add_map(struct bpf_object *obj);
static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog);
--
2.44.0.278.ge034bb2e1d-goog
sys/types.h may not define both NULL and size_t used in this
file. Change the dependency to the correct stddef.h one.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/lib/perf/include/internal/xyarray.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/lib/perf/include/internal/xyarray.h b/tools/lib/perf/include/internal/xyarray.h
index f10af3da7b21..947804fb8c85 100644
--- a/tools/lib/perf/include/internal/xyarray.h
+++ b/tools/lib/perf/include/internal/xyarray.h
@@ -3,7 +3,7 @@
#define __LIBPERF_INTERNAL_XYARRAY_H
#include <linux/compiler.h>
-#include <sys/types.h>
+#include <stddef.h>
struct xyarray {
size_t row_size;
--
2.44.0.278.ge034bb2e1d-goog
bool is used in this header and so stdbool.h is necessary. Add to
avoid compilation errors that aren't currently seen due to transitive
dependencies.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/perf/util/expr.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
index c0cec29ddc29..d4166b3eb654 100644
--- a/tools/perf/util/expr.h
+++ b/tools/perf/util/expr.h
@@ -2,6 +2,8 @@
#ifndef PARSE_CTX_H
#define PARSE_CTX_H 1
+#include <stdbool.h>
+
struct hashmap;
struct metric_ref;
--
2.44.0.278.ge034bb2e1d-goog
Make the header guard reflect the name of the file and add a comment
to the terminating endif.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/perf/util/expr.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
index d4166b3eb654..cd53ee7989fd 100644
--- a/tools/perf/util/expr.h
+++ b/tools/perf/util/expr.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef PARSE_CTX_H
-#define PARSE_CTX_H 1
+#ifndef __PERF_EXPR_H
+#define __PERF_EXPR_H 1
#include <stdbool.h>
@@ -59,4 +59,4 @@ double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx
double expr__has_event(const struct expr_parse_ctx *ctx, bool compute_ids, const char *id);
double expr__strcmp_cpuid_str(const struct expr_parse_ctx *ctx, bool compute_ids, const char *id);
-#endif
+#endif /* __PERF_EXPR_H */
--
2.44.0.278.ge034bb2e1d-goog
u64 is used in this header for eprintf_time and so linux/types.h is
necessary. Add to avoid compilation errors that aren't currently seen
due to transitive dependencies.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/perf/util/debug.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 35a7a5ae762e..4160e633311d 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -7,6 +7,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <linux/compiler.h>
+#include <linux/types.h>
extern int verbose;
extern int debug_kmaps;
--
2.44.0.278.ge034bb2e1d-goog
u64 is used in this header for cl_address and cl_offset, so
linux/types.h is necessary. Add to avoid compilation errors that
aren't currently seen due to transitive dependencies.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/perf/util/cacheline.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/perf/util/cacheline.h b/tools/perf/util/cacheline.h
index fe6d5b60a031..50b77129e1a4 100644
--- a/tools/perf/util/cacheline.h
+++ b/tools/perf/util/cacheline.h
@@ -3,6 +3,7 @@
#define PERF_CACHELINE_H
#include <linux/compiler.h>
+#include <linux/types.h>
int __pure cacheline_size(void);
--
2.44.0.278.ge034bb2e1d-goog
u64 is used for various structs in arm-spe-decoder.h, while uint64_t
is used in arm-spe-pkt-decoder.h. Avoid transitive dependencies
bringing in linux/types.h and directly depend upon it in
arm-spe-decoder.h. Fix arm-spe-decoder.c to use uint64_t, as the
header file does.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 1 +
tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
index 1443c28545a9..da5c5816c948 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
@@ -10,6 +10,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <linux/types.h>
#include "arm-spe-pkt-decoder.h"
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
index a454c6737563..e035f49f28ad 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
@@ -292,7 +292,7 @@ static int arm_spe_pkt_out_string(int *err, char **buf_p, size_t *blen,
static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet,
char *buf, size_t buf_len)
{
- u64 payload = packet->payload;
+ uint64_t payload = packet->payload;
int err = 0;
arm_spe_pkt_out_string(&err, &buf, &buf_len, "EV");
@@ -332,7 +332,7 @@ static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet,
static int arm_spe_pkt_desc_op_type(const struct arm_spe_pkt *packet,
char *buf, size_t buf_len)
{
- u64 payload = packet->payload;
+ uint64_t payload = packet->payload;
int err = 0;
switch (packet->index) {
@@ -429,7 +429,7 @@ static int arm_spe_pkt_desc_addr(const struct arm_spe_pkt *packet,
{
int ns, el, idx = packet->index;
int ch, pat;
- u64 payload = packet->payload;
+ uint64_t payload = packet->payload;
int err = 0;
static const char *idx_name[] = {"PC", "TGT", "VA", "PA", "PBT"};
@@ -469,7 +469,7 @@ static int arm_spe_pkt_desc_addr(const struct arm_spe_pkt *packet,
static int arm_spe_pkt_desc_counter(const struct arm_spe_pkt *packet,
char *buf, size_t buf_len)
{
- u64 payload = packet->payload;
+ uint64_t payload = packet->payload;
const char *name = arm_spe_pkt_name(packet->type);
int err = 0;
--
2.44.0.278.ge034bb2e1d-goog
Code in tools tries to follow the patterns of the kernel, so the
atomic functions names match. However, having include/linux/atomic.h
in tools complicates building code in tools as assembly and other
functions are necessary - these are often configured in the kernel
using CONFIG options. As tools C code is compiled with the -std=gnu11
flag, it is possible to use stdatomic.h and move the build and other
complications to the compiler/libc.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/arch/x86/include/asm/atomic.h | 84 --------------
tools/include/asm-generic/atomic-gcc.h | 95 ----------------
tools/include/asm/atomic.h | 11 --
tools/include/linux/atomic.h | 107 ++++++++++++++++--
tools/include/linux/types.h | 15 ++-
.../selftests/kvm/include/kvm_util_base.h | 3 +-
6 files changed, 110 insertions(+), 205 deletions(-)
delete mode 100644 tools/arch/x86/include/asm/atomic.h
delete mode 100644 tools/include/asm-generic/atomic-gcc.h
delete mode 100644 tools/include/asm/atomic.h
diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/asm/atomic.h
deleted file mode 100644
index 365cf182df12..000000000000
--- a/tools/arch/x86/include/asm/atomic.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H
-#define _TOOLS_LINUX_ASM_X86_ATOMIC_H
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include "rmwcc.h"
-
-#define LOCK_PREFIX "\n\tlock; "
-
-#include <asm/asm.h>
-#include <asm/cmpxchg.h>
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i) { (i) }
-
-/**
- * atomic_read - read atomic variable
- * @v: pointer of type atomic_t
- *
- * Atomically reads the value of @v.
- */
-static inline int atomic_read(const atomic_t *v)
-{
- return READ_ONCE((v)->counter);
-}
-
-/**
- * atomic_set - set atomic variable
- * @v: pointer of type atomic_t
- * @i: required value
- *
- * Atomically sets the value of @v to @i.
- */
-static inline void atomic_set(atomic_t *v, int i)
-{
- v->counter = i;
-}
-
-/**
- * atomic_inc - increment atomic variable
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1.
- */
-static inline void atomic_inc(atomic_t *v)
-{
- asm volatile(LOCK_PREFIX "incl %0"
- : "+m" (v->counter));
-}
-
-/**
- * atomic_dec_and_test - decrement and test
- * @v: pointer of type atomic_t
- *
- * Atomically decrements @v by 1 and
- * returns true if the result is 0, or false for all other
- * cases.
- */
-static inline int atomic_dec_and_test(atomic_t *v)
-{
- GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
-}
-
-static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
- return cmpxchg(&v->counter, old, new);
-}
-
-static inline int test_and_set_bit(long nr, unsigned long *addr)
-{
- GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, "Ir", nr, "%0", "c");
-}
-
-static inline int test_and_clear_bit(long nr, unsigned long *addr)
-{
- GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, "Ir", nr, "%0", "c");
-}
-
-#endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */
diff --git a/tools/include/asm-generic/atomic-gcc.h b/tools/include/asm-generic/atomic-gcc.h
deleted file mode 100644
index 9b3c528bab92..000000000000
--- a/tools/include/asm-generic/atomic-gcc.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __TOOLS_ASM_GENERIC_ATOMIC_H
-#define __TOOLS_ASM_GENERIC_ATOMIC_H
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/bitops.h>
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- *
- * Excerpts obtained from the Linux kernel sources.
- */
-
-#define ATOMIC_INIT(i) { (i) }
-
-/**
- * atomic_read - read atomic variable
- * @v: pointer of type atomic_t
- *
- * Atomically reads the value of @v.
- */
-static inline int atomic_read(const atomic_t *v)
-{
- return READ_ONCE((v)->counter);
-}
-
-/**
- * atomic_set - set atomic variable
- * @v: pointer of type atomic_t
- * @i: required value
- *
- * Atomically sets the value of @v to @i.
- */
-static inline void atomic_set(atomic_t *v, int i)
-{
- v->counter = i;
-}
-
-/**
- * atomic_inc - increment atomic variable
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1.
- */
-static inline void atomic_inc(atomic_t *v)
-{
- __sync_add_and_fetch(&v->counter, 1);
-}
-
-/**
- * atomic_dec_and_test - decrement and test
- * @v: pointer of type atomic_t
- *
- * Atomically decrements @v by 1 and
- * returns true if the result is 0, or false for all other
- * cases.
- */
-static inline int atomic_dec_and_test(atomic_t *v)
-{
- return __sync_sub_and_fetch(&v->counter, 1) == 0;
-}
-
-#define cmpxchg(ptr, oldval, newval) \
- __sync_val_compare_and_swap(ptr, oldval, newval)
-
-static inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval)
-{
- return cmpxchg(&(v)->counter, oldval, newval);
-}
-
-static inline int test_and_set_bit(long nr, unsigned long *addr)
-{
- unsigned long mask = BIT_MASK(nr);
- long old;
-
- addr += BIT_WORD(nr);
-
- old = __sync_fetch_and_or(addr, mask);
- return !!(old & mask);
-}
-
-static inline int test_and_clear_bit(long nr, unsigned long *addr)
-{
- unsigned long mask = BIT_MASK(nr);
- long old;
-
- addr += BIT_WORD(nr);
-
- old = __sync_fetch_and_and(addr, ~mask);
- return !!(old & mask);
-}
-
-#endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
diff --git a/tools/include/asm/atomic.h b/tools/include/asm/atomic.h
deleted file mode 100644
index 8c9bfffd4191..000000000000
--- a/tools/include/asm/atomic.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __TOOLS_LINUX_ASM_ATOMIC_H
-#define __TOOLS_LINUX_ASM_ATOMIC_H
-
-#if defined(__i386__) || defined(__x86_64__)
-#include "../../arch/x86/include/asm/atomic.h"
-#else
-#include <asm-generic/atomic-gcc.h>
-#endif
-
-#endif /* __TOOLS_LINUX_ASM_ATOMIC_H */
diff --git a/tools/include/linux/atomic.h b/tools/include/linux/atomic.h
index 01907b33537e..2cf4791ddd5d 100644
--- a/tools/include/linux/atomic.h
+++ b/tools/include/linux/atomic.h
@@ -2,14 +2,107 @@
#ifndef __TOOLS_LINUX_ATOMIC_H
#define __TOOLS_LINUX_ATOMIC_H
-#include <asm/atomic.h>
+#include <stdatomic.h>
+#include <linux/types.h> // For atomic_t
-void atomic_long_set(atomic_long_t *v, long i);
+/*
+ * Reimplementation of the kernel's atomic.h using C11's stdatomic.h to avoid
+ * build logic around compilers, inline assembler, etc.
+ */
-/* atomic_cmpxchg_relaxed */
-#ifndef atomic_cmpxchg_relaxed
-#define atomic_cmpxchg_relaxed atomic_cmpxchg
-#define atomic_cmpxchg_release atomic_cmpxchg
-#endif /* atomic_cmpxchg_relaxed */
+#define ATOMIC_OP(op, c_op) \
+static inline void generic_atomic_##op(int i, atomic_t *v) \
+{ \
+ atomic_fetch_##op(v, i); \
+}
+
+#define ATOMIC_OP_RETURN(op, c_op) \
+static inline int generic_atomic_##op##_return(int i, atomic_t *v) \
+{ \
+ int c = atomic_fetch_##op(v, i); \
+ \
+ return c c_op i; \
+}
+
+#define ATOMIC_FETCH_OP(op, c_op) \
+static inline int generic_atomic_fetch_##op(int i, atomic_t *v) \
+{ \
+ return atomic_fetch_##op(v, i); \
+}
+
+static inline int generic_atomic_read(const atomic_t *v)
+{
+ return atomic_load(v);
+}
+
+static inline void generic_atomic_set(atomic_t *v, int i)
+{
+ atomic_store(v, i);
+}
+
+static inline int generic_atomic_cmpxchg_relaxed(atomic_t *v, int old, int new)
+{
+ int expected = old;
+
+ atomic_compare_exchange_weak_explicit(v, &expected, new,
+ memory_order_relaxed, memory_order_relaxed);
+ return expected;
+}
+
+static inline int generic_atomic_cmpxchg_release(atomic_t *v, int old, int new)
+{
+ int expected = old;
+
+ /*
+ * Note, the stricter memory_order_seq_cst is used as
+ * memory_order_release fails with an invalid-memory-model error.
+ */
+ atomic_compare_exchange_weak_explicit(v, &expected, new,
+ memory_order_seq_cst, memory_order_seq_cst);
+ return expected;
+}
+
+ATOMIC_OP_RETURN(add, +)
+ATOMIC_OP_RETURN(sub, -)
+
+ATOMIC_FETCH_OP(add, +)
+ATOMIC_FETCH_OP(sub, -)
+ATOMIC_FETCH_OP(and, &)
+ATOMIC_FETCH_OP(or, |)
+ATOMIC_FETCH_OP(xor, ^)
+
+ATOMIC_OP(add, +)
+ATOMIC_OP(sub, -)
+ATOMIC_OP(and, &)
+ATOMIC_OP(or, |)
+ATOMIC_OP(xor, ^)
+
+#undef ATOMIC_FETCH_OP
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
+
+#define arch_atomic_add_return generic_atomic_add_return
+#define arch_atomic_sub_return generic_atomic_sub_return
+
+#define arch_atomic_fetch_add generic_atomic_fetch_add
+#define arch_atomic_fetch_sub generic_atomic_fetch_sub
+#define arch_atomic_fetch_and generic_atomic_fetch_and
+#define arch_atomic_fetch_or generic_atomic_fetch_or
+#define arch_atomic_fetch_xor generic_atomic_fetch_xor
+
+#define arch_atomic_add generic_atomic_add
+#define arch_atomic_sub generic_atomic_sub
+#define arch_atomic_and generic_atomic_and
+#define arch_atomic_or generic_atomic_or
+#define arch_atomic_xor generic_atomic_xor
+
+#define arch_atomic_read(v) generic_atomic_read(v)
+#define arch_atomic_set(v, i) generic_atomic_set(v, i)
+#define atomic_set(v, i) generic_atomic_set(v, i)
+#define atomic_read(v) generic_atomic_read(v)
+#define atomic_cmpxchg_relaxed(v, o, n) generic_atomic_cmpxchg_relaxed(v, o, n)
+#define atomic_cmpxchg_release(v, o, n) generic_atomic_cmpxchg_release(v, o, n)
+#define atomic_inc(v) generic_atomic_add(1, v)
+#define atomic_dec(v) generic_atomic_sub(1, v)
#endif /* __TOOLS_LINUX_ATOMIC_H */
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index 8519386acd23..cb1f44f1ed5e 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -74,13 +74,16 @@ typedef u64 phys_addr_t;
typedef u32 phys_addr_t;
#endif
-typedef struct {
- int counter;
-} atomic_t;
+#ifndef __cplusplus
+/* C++17 doesn't support stdatomic.h but C++23 does. */
+#include <stdatomic.h>
-typedef struct {
- long counter;
-} atomic_long_t;
+typedef atomic_int atomic_t;
+
+#define ATOMIC_INIT(i) (i)
+
+typedef atomic_long atomic_long_t;
+#endif
#ifndef __aligned_u64
# define __aligned_u64 __u64 __attribute__((aligned(8)))
diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
index 9e5afc472c14..7c81da425abc 100644
--- a/tools/testing/selftests/kvm/include/kvm_util_base.h
+++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
@@ -9,6 +9,7 @@
#include "test_util.h"
+#include <linux/atomic.h>
#include <linux/compiler.h>
#include "linux/hashtable.h"
#include "linux/list.h"
@@ -17,8 +18,6 @@
#include "linux/rbtree.h"
#include <linux/types.h>
-#include <asm/atomic.h>
-
#include <sys/ioctl.h>
#include "sparsebit.h"
--
2.44.0.278.ge034bb2e1d-goog
unaligned.h uses types from linux/types.h such as u64, but doesn't
directly import linux/types.h. This can cause breakages when the
declarations of the types is reliant on a transitive dependency and
the dependencies change. Add the missing header file to avoid this.
Signed-off-by: Ian Rogers <[email protected]>
---
include/asm-generic/unaligned.h | 2 ++
tools/include/asm-generic/unaligned.h | 2 ++
2 files changed, 4 insertions(+)
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index a84c64e5f11e..0cbe118e25db 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -2,6 +2,8 @@
#ifndef __ASM_GENERIC_UNALIGNED_H
#define __ASM_GENERIC_UNALIGNED_H
+#include <linux/types.h>
+
/*
* This is the most generic implementation of unaligned accesses
* and should work almost anywhere.
diff --git a/tools/include/asm-generic/unaligned.h b/tools/include/asm-generic/unaligned.h
index cdd2fd078027..768cafe6702e 100644
--- a/tools/include/asm-generic/unaligned.h
+++ b/tools/include/asm-generic/unaligned.h
@@ -2,6 +2,8 @@
#ifndef __ASM_GENERIC_UNALIGNED_H
#define __ASM_GENERIC_UNALIGNED_H
+#include <linux/types.h>
+
/*
* This is the most generic implementation of unaligned accesses
* and should work almost anywhere.
--
2.44.0.278.ge034bb2e1d-goog
Bring in the changes:
26dd68d293fd overflow: add DEFINE_FLEX() for on-stack allocs
d67790ddf021 overflow: Add struct_size_t() helper
4b21d25bf519 overflow: Introduce overflows_type() and castable_to_type()
31970608a6d3 overflow: Fix kern-doc markup for functions
d219d2a9a92e overflow: Allow mixed type arguments
92d23c6e9415 overflow, tracing: Define the is_signed_type() macro once
230f6fa2c1db overflow: Provide constant expression struct_size
e1be43d9b5d0 overflow: Implement size_t saturating arithmetic helpers
Add file to check-headers.sh, so there is a warning if the tools
version of the file drifts from the kernel's version.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/include/linux/overflow.h | 331 ++++++++++++++++++++++++++-------
tools/perf/check-headers.sh | 1 +
2 files changed, 268 insertions(+), 64 deletions(-)
diff --git a/tools/include/linux/overflow.h b/tools/include/linux/overflow.h
index dcb0c1bf6866..7b5cf4a5cd19 100644
--- a/tools/include/linux/overflow.h
+++ b/tools/include/linux/overflow.h
@@ -3,6 +3,8 @@
#define __LINUX_OVERFLOW_H
#include <linux/compiler.h>
+#include <linux/limits.h>
+#include <linux/const.h>
/*
* We need to compute the minimum and maximum values representable in a given
@@ -28,117 +30,318 @@
* https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
* credit to Christian Biere.
*/
-#define is_signed_type(type) (((type)(-1)) < (type)1)
#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
#define type_min(T) ((T)((T)-type_max(T)-(T)1))
/*
- * For simplicity and code hygiene, the fallback code below insists on
- * a, b and *d having the same type (similar to the min() and max()
- * macros), whereas gcc's type-generic overflow checkers accept
- * different types. Hence we don't just make check_add_overflow an
- * alias for __builtin_add_overflow, but add type checks similar to
- * below.
- */
-#define check_add_overflow(a, b, d) ({ \
- typeof(a) __a = (a); \
- typeof(b) __b = (b); \
- typeof(d) __d = (d); \
- (void) (&__a == &__b); \
- (void) (&__a == __d); \
- __builtin_add_overflow(__a, __b, __d); \
-})
+ * Avoids triggering -Wtype-limits compilation warning,
+ * while using unsigned data types to check a < 0.
+ */
+#define is_non_negative(a) ((a) > 0 || (a) == 0)
+#define is_negative(a) (!(is_non_negative(a)))
-#define check_sub_overflow(a, b, d) ({ \
- typeof(a) __a = (a); \
- typeof(b) __b = (b); \
- typeof(d) __d = (d); \
- (void) (&__a == &__b); \
- (void) (&__a == __d); \
- __builtin_sub_overflow(__a, __b, __d); \
-})
+/*
+ * Allows for effectively applying __must_check to a macro so we can have
+ * both the type-agnostic benefits of the macros while also being able to
+ * enforce that the return value is, in fact, checked.
+ */
+static inline bool __must_check __must_check_overflow(bool overflow)
+{
+ return unlikely(overflow);
+}
+
+/**
+ * check_add_overflow() - Calculate addition with overflow checking
+ * @a: first addend
+ * @b: second addend
+ * @d: pointer to store sum
+ *
+ * Returns 0 on success.
+ *
+ * *@d holds the results of the attempted addition, but is not considered
+ * "safe for use" on a non-zero return value, which indicates that the
+ * sum has overflowed or been truncated.
+ */
+#define check_add_overflow(a, b, d) \
+ __must_check_overflow(__builtin_add_overflow(a, b, d))
+
+/**
+ * check_sub_overflow() - Calculate subtraction with overflow checking
+ * @a: minuend; value to subtract from
+ * @b: subtrahend; value to subtract from @a
+ * @d: pointer to store difference
+ *
+ * Returns 0 on success.
+ *
+ * *@d holds the results of the attempted subtraction, but is not considered
+ * "safe for use" on a non-zero return value, which indicates that the
+ * difference has underflowed or been truncated.
+ */
+#define check_sub_overflow(a, b, d) \
+ __must_check_overflow(__builtin_sub_overflow(a, b, d))
+
+/**
+ * check_mul_overflow() - Calculate multiplication with overflow checking
+ * @a: first factor
+ * @b: second factor
+ * @d: pointer to store product
+ *
+ * Returns 0 on success.
+ *
+ * *@d holds the results of the attempted multiplication, but is not
+ * considered "safe for use" on a non-zero return value, which indicates
+ * that the product has overflowed or been truncated.
+ */
+#define check_mul_overflow(a, b, d) \
+ __must_check_overflow(__builtin_mul_overflow(a, b, d))
+
+/**
+ * check_shl_overflow() - Calculate a left-shifted value and check overflow
+ * @a: Value to be shifted
+ * @s: How many bits left to shift
+ * @d: Pointer to where to store the result
+ *
+ * Computes *@d = (@a << @s)
+ *
+ * Returns true if '*@d' cannot hold the result or when '@a << @s' doesn't
+ * make sense. Example conditions:
+ *
+ * - '@a << @s' causes bits to be lost when stored in *@d.
+ * - '@s' is garbage (e.g. negative) or so large that the result of
+ * '@a << @s' is guaranteed to be 0.
+ * - '@a' is negative.
+ * - '@a << @s' sets the sign bit, if any, in '*@d'.
+ *
+ * '*@d' will hold the results of the attempted shift, but is not
+ * considered "safe for use" if true is returned.
+ */
+#define check_shl_overflow(a, s, d) __must_check_overflow(({ \
+ typeof(a) _a = a; \
+ typeof(s) _s = s; \
+ typeof(d) _d = d; \
+ u64 _a_full = _a; \
+ unsigned int _to_shift = \
+ is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \
+ *_d = (_a_full << _to_shift); \
+ (_to_shift != _s || is_negative(*_d) || is_negative(_a) || \
+ (*_d >> _to_shift) != _a); \
+}))
-#define check_mul_overflow(a, b, d) ({ \
- typeof(a) __a = (a); \
- typeof(b) __b = (b); \
- typeof(d) __d = (d); \
- (void) (&__a == &__b); \
- (void) (&__a == __d); \
- __builtin_mul_overflow(__a, __b, __d); \
+#define __overflows_type_constexpr(x, T) ( \
+ is_unsigned_type(typeof(x)) ? \
+ (x) > type_max(typeof(T)) : \
+ is_unsigned_type(typeof(T)) ? \
+ (x) < 0 || (x) > type_max(typeof(T)) : \
+ (x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))
+
+#define __overflows_type(x, T) ({ \
+ typeof(T) v = 0; \
+ check_add_overflow((x), v, &v); \
})
/**
- * array_size() - Calculate size of 2-dimensional array.
+ * overflows_type - helper for checking the overflows between value, variables,
+ * or data type
*
- * @a: dimension one
- * @b: dimension two
+ * @n: source constant value or variable to be checked
+ * @T: destination variable or data type proposed to store @x
*
- * Calculates size of 2-dimensional array: @a * @b.
+ * Compares the @x expression for whether or not it can safely fit in
+ * the storage of the type in @T. @x and @T can have different types.
+ * If @x is a constant expression, this will also resolve to a constant
+ * expression.
*
- * Returns: number of bytes needed to represent the array or SIZE_MAX on
- * overflow.
+ * Returns: true if overflow can occur, false otherwise.
+ */
+#define overflows_type(n, T) \
+ __builtin_choose_expr(__is_constexpr(n), \
+ __overflows_type_constexpr(n, T), \
+ __overflows_type(n, T))
+
+/**
+ * castable_to_type - like __same_type(), but also allows for casted literals
+ *
+ * @n: variable or constant value
+ * @T: variable or data type
+ *
+ * Unlike the __same_type() macro, this allows a constant value as the
+ * first argument. If this value would not overflow into an assignment
+ * of the second argument's type, it returns true. Otherwise, this falls
+ * back to __same_type().
*/
-static inline __must_check size_t array_size(size_t a, size_t b)
+#define castable_to_type(n, T) \
+ __builtin_choose_expr(__is_constexpr(n), \
+ !__overflows_type_constexpr(n, T), \
+ __same_type(n, T))
+
+/**
+ * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX
+ * @factor1: first factor
+ * @factor2: second factor
+ *
+ * Returns: calculate @factor1 * @factor2, both promoted to size_t,
+ * with any overflow causing the return value to be SIZE_MAX. The
+ * lvalue must be size_t to avoid implicit type conversion.
+ */
+static inline size_t __must_check size_mul(size_t factor1, size_t factor2)
{
size_t bytes;
- if (check_mul_overflow(a, b, &bytes))
+ if (check_mul_overflow(factor1, factor2, &bytes))
return SIZE_MAX;
return bytes;
}
/**
- * array3_size() - Calculate size of 3-dimensional array.
+ * size_add() - Calculate size_t addition with saturation at SIZE_MAX
+ * @addend1: first addend
+ * @addend2: second addend
*
- * @a: dimension one
- * @b: dimension two
- * @c: dimension three
- *
- * Calculates size of 3-dimensional array: @a * @b * @c.
- *
- * Returns: number of bytes needed to represent the array or SIZE_MAX on
- * overflow.
+ * Returns: calculate @addend1 + @addend2, both promoted to size_t,
+ * with any overflow causing the return value to be SIZE_MAX. The
+ * lvalue must be size_t to avoid implicit type conversion.
*/
-static inline __must_check size_t array3_size(size_t a, size_t b, size_t c)
+static inline size_t __must_check size_add(size_t addend1, size_t addend2)
{
size_t bytes;
- if (check_mul_overflow(a, b, &bytes))
- return SIZE_MAX;
- if (check_mul_overflow(bytes, c, &bytes))
+ if (check_add_overflow(addend1, addend2, &bytes))
return SIZE_MAX;
return bytes;
}
-static inline __must_check size_t __ab_c_size(size_t n, size_t size, size_t c)
+/**
+ * size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX
+ * @minuend: value to subtract from
+ * @subtrahend: value to subtract from @minuend
+ *
+ * Returns: calculate @minuend - @subtrahend, both promoted to size_t,
+ * with any overflow causing the return value to be SIZE_MAX. For
+ * composition with the size_add() and size_mul() helpers, neither
+ * argument may be SIZE_MAX (or the result with be forced to SIZE_MAX).
+ * The lvalue must be size_t to avoid implicit type conversion.
+ */
+static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
{
size_t bytes;
- if (check_mul_overflow(n, size, &bytes))
- return SIZE_MAX;
- if (check_add_overflow(bytes, c, &bytes))
+ if (minuend == SIZE_MAX || subtrahend == SIZE_MAX ||
+ check_sub_overflow(minuend, subtrahend, &bytes))
return SIZE_MAX;
return bytes;
}
/**
- * struct_size() - Calculate size of structure with trailing array.
+ * array_size() - Calculate size of 2-dimensional array.
+ * @a: dimension one
+ * @b: dimension two
+ *
+ * Calculates size of 2-dimensional array: @a * @b.
+ *
+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
+ * overflow.
+ */
+#define array_size(a, b) size_mul(a, b)
+
+/**
+ * array3_size() - Calculate size of 3-dimensional array.
+ * @a: dimension one
+ * @b: dimension two
+ * @c: dimension three
+ *
+ * Calculates size of 3-dimensional array: @a * @b * @c.
+ *
+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
+ * overflow.
+ */
+#define array3_size(a, b, c) size_mul(size_mul(a, b), c)
+
+/**
+ * flex_array_size() - Calculate size of a flexible array member
+ * within an enclosing structure.
* @p: Pointer to the structure.
+ * @member: Name of the flexible array member.
+ * @count: Number of elements in the array.
+ *
+ * Calculates size of a flexible array of @count number of @member
+ * elements, at the end of structure @p.
+ *
+ * Return: number of bytes needed or SIZE_MAX on overflow.
+ */
+#define flex_array_size(p, member, count) \
+ __builtin_choose_expr(__is_constexpr(count), \
+ (count) * sizeof(*(p)->member) + __must_be_array((p)->member), \
+ size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member)))
+
+/**
+ * struct_size() - Calculate size of structure with trailing flexible array.
+ * @p: Pointer to the structure.
+ * @member: Name of the array member.
+ * @count: Number of elements in the array.
+ *
+ * Calculates size of memory needed for structure of @p followed by an
+ * array of @count number of @member elements.
+ *
+ * Return: number of bytes needed or SIZE_MAX on overflow.
+ */
+#define struct_size(p, member, count) \
+ __builtin_choose_expr(__is_constexpr(count), \
+ sizeof(*(p)) + flex_array_size(p, member, count), \
+ size_add(sizeof(*(p)), flex_array_size(p, member, count)))
+
+/**
+ * struct_size_t() - Calculate size of structure with trailing flexible array
+ * @type: structure type name.
* @member: Name of the array member.
- * @n: Number of elements in the array.
+ * @count: Number of elements in the array.
*
- * Calculates size of memory needed for structure @p followed by an
- * array of @n @member elements.
+ * Calculates size of memory needed for structure @type followed by an
+ * array of @count number of @member elements. Prefer using struct_size()
+ * when possible instead, to keep calculations associated with a specific
+ * instance variable of type @type.
*
* Return: number of bytes needed or SIZE_MAX on overflow.
*/
-#define struct_size(p, member, n) \
- __ab_c_size(n, \
- sizeof(*(p)->member) + __must_be_array((p)->member),\
- sizeof(*(p)))
+#define struct_size_t(type, member, count) \
+ struct_size((type *)NULL, member, count)
+
+/**
+ * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
+ * Enables caller macro to pass (different) initializer.
+ *
+ * @type: structure type name, including "struct" keyword.
+ * @name: Name for a variable to define.
+ * @member: Name of the array member.
+ * @count: Number of elements in the array; must be compile-time const.
+ * @initializer: initializer expression (could be empty for no init).
+ */
+#define _DEFINE_FLEX(type, name, member, count, initializer) \
+ _Static_assert(__builtin_constant_p(count), \
+ "onstack flex array members require compile-time const count"); \
+ union { \
+ u8 bytes[struct_size_t(type, member, count)]; \
+ type obj; \
+ } name##_u initializer; \
+ type *name = (type *)&name##_u
+
+/**
+ * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
+ * flexible array member.
+ *
+ * @type: structure type name, including "struct" keyword.
+ * @name: Name for a variable to define.
+ * @member: Name of the array member.
+ * @count: Number of elements in the array; must be compile-time const.
+ *
+ * Define a zeroed, on-stack, instance of @type structure with a trailing
+ * flexible array member.
+ * Use __struct_size(@name) to get compile-time size of it afterwards.
+ */
+#define DEFINE_FLEX(type, name, member, count) \
+ _DEFINE_FLEX(type, name, member, count, = {})
#endif /* __LINUX_OVERFLOW_H */
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 64dbf199dff9..272a37d8e1c4 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -35,6 +35,7 @@ FILES=(
"include/vdso/const.h"
"include/linux/hash.h"
"include/linux/list-sort.h"
+ "include/linux/overflow.h"
"include/uapi/linux/hw_breakpoint.h"
"arch/x86/include/asm/disabled-features.h"
"arch/x86/include/asm/required-features.h"
--
2.44.0.278.ge034bb2e1d-goog
An issue was reported with clang and llvm libc where the noinline
attribute [1] was being expanded due to the #define in
linux/compiler.h (now in compiler_attributes.h). The expansion caused
the __attribute__ to appear twice and break the build. To avoid this
conflict, rename noinline to __noinline which is more consistent with
other compiler attributes.
[1] https://clang.llvm.org/docs/AttributeReference.html#noinline
Reported-by: Christopher Di Bella <[email protected]>
Signed-off-by: Ian Rogers <[email protected]>
---
tools/include/linux/compiler_attributes.h | 4 ++--
tools/perf/arch/x86/tests/bp-modify.c | 4 ++--
tools/perf/bench/find-bit-bench.c | 2 +-
tools/perf/tests/bp_account.c | 2 +-
tools/perf/tests/bp_signal.c | 2 +-
tools/perf/tests/bp_signal_overflow.c | 2 +-
tools/perf/tests/dwarf-unwind.c | 12 ++++++------
tools/perf/tests/workloads/leafloop.c | 8 ++++----
tools/perf/tests/workloads/thloop.c | 4 ++--
9 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/tools/include/linux/compiler_attributes.h b/tools/include/linux/compiler_attributes.h
index 9bfaec783e48..1ff3d85f5af3 100644
--- a/tools/include/linux/compiler_attributes.h
+++ b/tools/include/linux/compiler_attributes.h
@@ -267,12 +267,12 @@
# define __flatten __attribute__((flatten))
/*
- * Note the missing underscores.
+ * Note, the kernel version is missing the underscores.
*
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute
* clang: mentioned
*/
-#define noinline __attribute__((__noinline__))
+#define __noinline __attribute__((__noinline__))
/*
* Optional: only supported since gcc >= 8
diff --git a/tools/perf/arch/x86/tests/bp-modify.c b/tools/perf/arch/x86/tests/bp-modify.c
index 0924ccd9e36d..65493ff7a76f 100644
--- a/tools/perf/arch/x86/tests/bp-modify.c
+++ b/tools/perf/arch/x86/tests/bp-modify.c
@@ -15,13 +15,13 @@
#include "tests/tests.h"
#include "arch-tests.h"
-static noinline int bp_1(void)
+static __noinline int bp_1(void)
{
pr_debug("in %s\n", __func__);
return 0;
}
-static noinline int bp_2(void)
+static __noinline int bp_2(void)
{
pr_debug("in %s\n", __func__);
return 0;
diff --git a/tools/perf/bench/find-bit-bench.c b/tools/perf/bench/find-bit-bench.c
index 7e25b0e413f6..dd97a51649bc 100644
--- a/tools/perf/bench/find-bit-bench.c
+++ b/tools/perf/bench/find-bit-bench.c
@@ -31,7 +31,7 @@ static const char *const bench_usage[] = {
static unsigned int accumulator;
static unsigned int use_of_val;
-static noinline void workload(int val)
+static __noinline void workload(int val)
{
use_of_val += val;
accumulator++;
diff --git a/tools/perf/tests/bp_account.c b/tools/perf/tests/bp_account.c
index 6f921db33cf9..459f61752a71 100644
--- a/tools/perf/tests/bp_account.c
+++ b/tools/perf/tests/bp_account.c
@@ -34,7 +34,7 @@
static volatile long the_var;
-static noinline int test_function(void)
+static __noinline int test_function(void)
{
return 0;
}
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
index 1f2908f02389..484a7e7f96ee 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -59,7 +59,7 @@ static void __test_function(volatile long *ptr)
}
#endif
-static noinline int test_function(void)
+static __noinline int test_function(void)
{
__test_function(&the_var);
the_var++;
diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c
index 4e897c2cf26b..9436bf2973f8 100644
--- a/tools/perf/tests/bp_signal_overflow.c
+++ b/tools/perf/tests/bp_signal_overflow.c
@@ -30,7 +30,7 @@
static int overflows;
-static noinline int test_function(void)
+static __noinline int test_function(void)
{
return time(NULL);
}
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index d01aa931fe81..a669c69a9242 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -109,7 +109,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
return strcmp((const char *) symbol, funcs[idx]);
}
-NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thread)
+NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__thread(struct thread *thread)
{
struct perf_sample sample;
unsigned long cnt = 0;
@@ -140,7 +140,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thr
static int global_unwind_retval = -INT_MAX;
-NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__compare(void *p1, void *p2)
+NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__compare(void *p1, void *p2)
{
/* Any possible value should be 'thread' */
struct thread *thread = *(struct thread **)p1;
@@ -159,7 +159,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__compare(void *p1, void *p
return p1 - p2;
}
-NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_3(struct thread *thread)
+NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__krava_3(struct thread *thread)
{
struct thread *array[2] = {thread, thread};
void *fp = &bsearch;
@@ -178,7 +178,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_3(struct thread *th
return global_unwind_retval;
}
-NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_2(struct thread *thread)
+NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__krava_2(struct thread *thread)
{
int ret;
@@ -187,7 +187,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_2(struct thread *th
return ret;
}
-NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *thread)
+NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__krava_1(struct thread *thread)
{
int ret;
@@ -196,7 +196,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *th
return ret;
}
-noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
+__noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct machine *machine;
diff --git a/tools/perf/tests/workloads/leafloop.c b/tools/perf/tests/workloads/leafloop.c
index 1bf5cc97649b..89d2cec2f461 100644
--- a/tools/perf/tests/workloads/leafloop.c
+++ b/tools/perf/tests/workloads/leafloop.c
@@ -4,18 +4,18 @@
#include "../tests.h"
/* We want to check these symbols in perf script */
-noinline void leaf(volatile int b);
-noinline void parent(volatile int b);
+__noinline void leaf(volatile int b);
+__noinline void parent(volatile int b);
static volatile int a;
-noinline void leaf(volatile int b)
+__noinline void leaf(volatile int b)
{
for (;;)
a += b;
}
-noinline void parent(volatile int b)
+__noinline void parent(volatile int b)
{
leaf(b);
}
diff --git a/tools/perf/tests/workloads/thloop.c b/tools/perf/tests/workloads/thloop.c
index 457b29f91c3e..e252efb76203 100644
--- a/tools/perf/tests/workloads/thloop.c
+++ b/tools/perf/tests/workloads/thloop.c
@@ -9,14 +9,14 @@
static volatile sig_atomic_t done;
/* We want to check this symbol in perf report */
-noinline void test_loop(void);
+__noinline void test_loop(void);
static void sighandler(int sig __maybe_unused)
{
done = 1;
}
-noinline void test_loop(void)
+__noinline void test_loop(void)
{
while (!done);
}
--
2.44.0.278.ge034bb2e1d-goog
compiler.h - synced from include/linux/compiler.h, guards were
added to definitions to avoid redefinition of macros
in libc. ftrace, CONFIG_OBJTOOL and kentry logic was removed as
redundant.
compiler-gcc.h - synced from include/linux/compiler-gcc.h
compiler-clang.h - added from include/linux/compiler-gcc.h
compiler_attributes.h - added from
include/linux/compiler_attributes.h,
guards were added to definitions to avoid redefinition of macros
in libc.
compiler_types.h - added from include/linux/compiler_types.h,
guards were added to definitions to avoid redefinition of macros
in libc.
asm/rwonce.h - added as dependency of compiler.h but added from
asm-generic/rwonce.h.
asm-generic/bitops/non-atomic.h - add linux/types.h so that bool
is defined. This file is heavily forked from the kernel one and
so synchronizing with the kernel version was infeasible.
rbtree.h - add linux/types.h so that bool is defined. This file
is heavily forked from the kernel one and so synchronizing with
the kernel version was infeasible.
string.h - add compiler.h include as definitions from types.h
were removed to avoid compiler.h collisions. This file is
heavily forked from the kernel one and so synchronizing with the
kernel version was infeasible.
types.h - remove __must_check definition that conflicts with
compiler.h.
Signed-off-by: Ian Rogers <[email protected]>
---
tools/include/asm-generic/bitops/non-atomic.h | 1 +
tools/include/asm/rwonce.h | 63 +++
tools/include/linux/compiler-clang.h | 124 +++++
tools/include/linux/compiler-gcc.h | 145 +++++-
tools/include/linux/compiler.h | 221 ++-------
tools/include/linux/compiler_attributes.h | 449 ++++++++++++++++++
tools/include/linux/compiler_types.h | 171 ++++++-
tools/include/linux/rbtree.h | 1 +
tools/include/linux/string.h | 1 +
tools/include/linux/types.h | 2 +-
10 files changed, 968 insertions(+), 210 deletions(-)
create mode 100644 tools/include/asm/rwonce.h
create mode 100644 tools/include/linux/compiler-clang.h
create mode 100644 tools/include/linux/compiler_attributes.h
diff --git a/tools/include/asm-generic/bitops/non-atomic.h b/tools/include/asm-generic/bitops/non-atomic.h
index 0c472a833408..5266796df48c 100644
--- a/tools/include/asm-generic/bitops/non-atomic.h
+++ b/tools/include/asm-generic/bitops/non-atomic.h
@@ -3,6 +3,7 @@
#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
#include <linux/bits.h>
+#include <linux/types.h> /* for bool */
/**
* ___set_bit - Set a bit in memory
diff --git a/tools/include/asm/rwonce.h b/tools/include/asm/rwonce.h
new file mode 100644
index 000000000000..9d61f0c87371
--- /dev/null
+++ b/tools/include/asm/rwonce.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Prevent the compiler from merging or refetching reads or writes. The
+ * compiler is also forbidden from reordering successive instances of
+ * READ_ONCE and WRITE_ONCE, but only when the compiler is aware of some
+ * particular ordering. One way to make the compiler aware of ordering is to
+ * put the two invocations of READ_ONCE or WRITE_ONCE in different C
+ * statements.
+ *
+ * These two macros will also work on aggregate data types like structs or
+ * unions.
+ *
+ * Their two major use cases are: (1) Mediating communication between
+ * process-level code and irq/NMI handlers, all running on the same CPU,
+ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
+ * mutilate accesses that either do not require ordering or that interact
+ * with an explicit memory barrier or atomic instruction that provides the
+ * required ordering.
+ */
+#ifndef __ASM_GENERIC_RWONCE_H
+#define __ASM_GENERIC_RWONCE_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler_types.h>
+
+/*
+ * Yes, this permits 64-bit accesses on 32-bit architectures. These will
+ * actually be atomic in some cases (namely Armv7 + LPAE), but for others we
+ * rely on the access being split into 2x32-bit accesses for a 32-bit quantity
+ * (e.g. a virtual address) and a strong prevailing wind.
+ */
+#define compiletime_assert_rwonce_type(t) \
+ compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
+ "Unsupported access size for {READ,WRITE}_ONCE().")
+
+/*
+ * Use __READ_ONCE() instead of READ_ONCE() if you do not require any
+ * atomicity. Note that this may result in tears!
+ */
+#ifndef __READ_ONCE
+#define __READ_ONCE(x) (*(const volatile __unqual_scalar_typeof(x) *)&(x))
+#endif
+
+#define READ_ONCE(x) \
+({ \
+ compiletime_assert_rwonce_type(x); \
+ __READ_ONCE(x); \
+})
+
+#define __WRITE_ONCE(x, val) \
+do { \
+ *(volatile typeof(x) *)&(x) = (val); \
+} while (0)
+
+#define WRITE_ONCE(x, val) \
+do { \
+ compiletime_assert_rwonce_type(x); \
+ __WRITE_ONCE(x, val); \
+} while (0)
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_GENERIC_RWONCE_H */
diff --git a/tools/include/linux/compiler-clang.h b/tools/include/linux/compiler-clang.h
new file mode 100644
index 000000000000..ddab1ef22bee
--- /dev/null
+++ b/tools/include/linux/compiler-clang.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_TYPES_H
+#error "Please don't include <linux/compiler-clang.h> directly, include <linux/compiler.h> instead."
+#endif
+
+/* Compiler specific definitions for Clang compiler */
+
+/*
+ * Clang prior to 17 is being silly and considers many __cleanup() variables
+ * as unused (because they are, their sole purpose is to go out of scope).
+ *
+ * https://reviews.llvm.org/D152180
+ */
+#undef __cleanup
+#define __cleanup(func) __maybe_unused __attribute__((__cleanup__(func)))
+
+/* all clang versions usable with the kernel support KASAN ABI version 5 */
+#define KASAN_ABI_VERSION 5
+
+/*
+ * Note: Checking __has_feature(*_sanitizer) is only true if the feature is
+ * enabled. Therefore it is not required to additionally check defined(CONFIG_*)
+ * to avoid adding redundant attributes in other configurations.
+ */
+
+#if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer)
+/* Emulate GCC's __SANITIZE_ADDRESS__ flag */
+#define __SANITIZE_ADDRESS__
+#define __no_sanitize_address \
+ __attribute__((no_sanitize("address", "hwaddress")))
+#else
+#define __no_sanitize_address
+#endif
+
+#if __has_feature(thread_sanitizer)
+/* emulate gcc's __SANITIZE_THREAD__ flag */
+#define __SANITIZE_THREAD__
+#define __no_sanitize_thread \
+ __attribute__((no_sanitize("thread")))
+#else
+#define __no_sanitize_thread
+#endif
+
+#if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP)
+#define __HAVE_BUILTIN_BSWAP32__
+#define __HAVE_BUILTIN_BSWAP64__
+#define __HAVE_BUILTIN_BSWAP16__
+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
+
+#if __has_feature(undefined_behavior_sanitizer)
+/* GCC does not have __SANITIZE_UNDEFINED__ */
+#define __no_sanitize_undefined \
+ __attribute__((no_sanitize("undefined")))
+#else
+#define __no_sanitize_undefined
+#endif
+
+#if __has_feature(memory_sanitizer)
+#define __SANITIZE_MEMORY__
+/*
+ * Unlike other sanitizers, KMSAN still inserts code into functions marked with
+ * no_sanitize("kernel-memory"). Using disable_sanitizer_instrumentation
+ * provides the behavior consistent with other __no_sanitize_ attributes,
+ * guaranteeing that __no_sanitize_memory functions remain uninstrumented.
+ */
+#define __no_sanitize_memory __disable_sanitizer_instrumentation
+
+/*
+ * The __no_kmsan_checks attribute ensures that a function does not produce
+ * false positive reports by:
+ * - initializing all local variables and memory stores in this function;
+ * - skipping all shadow checks;
+ * - passing initialized arguments to this function's callees.
+ */
+#define __no_kmsan_checks __attribute__((no_sanitize("kernel-memory")))
+#else
+#define __no_sanitize_memory
+#define __no_kmsan_checks
+#endif
+
+/*
+ * Support for __has_feature(coverage_sanitizer) was added in Clang 13 together
+ * with no_sanitize("coverage"). Prior versions of Clang support coverage
+ * instrumentation, but cannot be queried for support by the preprocessor.
+ */
+#if __has_feature(coverage_sanitizer)
+#define __no_sanitize_coverage __attribute__((no_sanitize("coverage")))
+#else
+#define __no_sanitize_coverage
+#endif
+
+#if __has_feature(shadow_call_stack)
+# define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
+#endif
+
+#if __has_feature(kcfi)
+/* Disable CFI checking inside a function. */
+#define __nocfi __attribute__((__no_sanitize__("kcfi")))
+#endif
+
+/*
+ * Turn individual warnings and errors on and off locally, depending
+ * on version.
+ */
+#define __diag_clang(version, severity, s) \
+ __diag_clang_ ## version(__diag_clang_ ## severity s)
+
+/* Severity used in pragma directives */
+#define __diag_clang_ignore ignored
+#define __diag_clang_warn warning
+#define __diag_clang_error error
+
+#define __diag_str1(s) #s
+#define __diag_str(s) __diag_str1(s)
+#define __diag(s) _Pragma(__diag_str(clang diagnostic s))
+
+#if CONFIG_CLANG_VERSION >= 110000
+#define __diag_clang_11(s) __diag(s)
+#else
+#define __diag_clang_11(s)
+#endif
+
+#define __diag_ignore_all(option, comment) \
+ __diag_clang(11, ignore, option)
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h
index 62e7c901ac28..aebb65bf95a7 100644
--- a/tools/include/linux/compiler-gcc.h
+++ b/tools/include/linux/compiler-gcc.h
@@ -1,42 +1,147 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _TOOLS_LINUX_COMPILER_H_
+#ifndef __LINUX_COMPILER_TYPES_H
#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
#endif
/*
* Common definitions for all gcc versions go here.
*/
-#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
+
+/*
+ * This macro obfuscates arithmetic on a variable address so that gcc
+ * shouldn't recognize the original var, and make assumptions about it.
+ *
+ * This is needed because the C standard makes it undefined to do
+ * pointer arithmetic on "objects" outside their boundaries and the
+ * gcc optimizers assume this is the case. In particular they
+ * assume such arithmetic does not wrap.
+ *
+ * A miscompilation has been observed because of this on PPC.
+ * To work around it we hide the relationship of the pointer and the object
+ * using this macro.
+ *
+ * Versions of the ppc64 compiler before 4.1 had a bug where use of
+ * RELOC_HIDE could trash r30. The bug can be worked around by changing
+ * the inline assembly constraint from =g to =r, in this particular
+ * case either is valid.
+ */
+#define RELOC_HIDE(ptr, off) \
+({ \
+ unsigned long __ptr; \
+ __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \
+ (typeof(ptr)) (__ptr + (off)); \
+})
+
+#ifdef CONFIG_RETPOLINE
+#define __noretpoline __attribute__((__indirect_branch__("keep")))
+#endif
+
+#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
+#define __latent_entropy __attribute__((latent_entropy))
#endif
-#if __has_attribute(__fallthrough__)
-# define fallthrough __attribute__((__fallthrough__))
+/*
+ * calling noreturn functions, __builtin_unreachable() and __builtin_trap()
+ * confuse the stack allocation in gcc, leading to overly large stack
+ * frames, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365
+ *
+ * Adding an empty inline assembly before it works around the problem
+ */
+#define barrier_before_unreachable() asm volatile("")
+
+/*
+ * Mark a position in code as unreachable. This can be used to
+ * suppress control flow warnings after asm blocks that transfer
+ * control elsewhere.
+ */
+#define unreachable() \
+ do { \
+ annotate_unreachable(); \
+ barrier_before_unreachable(); \
+ __builtin_unreachable(); \
+ } while (0)
+
+#if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP)
+#define __HAVE_BUILTIN_BSWAP32__
+#define __HAVE_BUILTIN_BSWAP64__
+#define __HAVE_BUILTIN_BSWAP16__
+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
+
+#if GCC_VERSION >= 70000
+#define KASAN_ABI_VERSION 5
#else
-# define fallthrough do {} while (0) /* fallthrough */
+#define KASAN_ABI_VERSION 4
#endif
-#if __has_attribute(__error__)
-# define __compiletime_error(message) __attribute__((error(message)))
+#ifdef CONFIG_SHADOW_CALL_STACK
+#define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
#endif
-/* &a[0] degrades to a pointer: a different type from an array */
-#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
+#define __no_sanitize_address __attribute__((__no_sanitize_address__))
-#ifndef __pure
-#define __pure __attribute__((pure))
+#if defined(__SANITIZE_THREAD__)
+#define __no_sanitize_thread __attribute__((__no_sanitize_thread__))
+#else
+#define __no_sanitize_thread
#endif
-#define noinline __attribute__((noinline))
-#ifndef __packed
-#define __packed __attribute__((packed))
+
+#define __no_sanitize_undefined __attribute__((__no_sanitize_undefined__))
+
+/*
+ * Only supported since gcc >= 12
+ */
+#if defined(CONFIG_KCOV) && __has_attribute(__no_sanitize_coverage__)
+#define __no_sanitize_coverage __attribute__((__no_sanitize_coverage__))
+#else
+#define __no_sanitize_coverage
#endif
-#ifndef __noreturn
-#define __noreturn __attribute__((noreturn))
+
+/*
+ * Treat __SANITIZE_HWADDRESS__ the same as __SANITIZE_ADDRESS__ in the kernel,
+ * matching the defines used by Clang.
+ */
+#ifdef __SANITIZE_HWADDRESS__
+#define __SANITIZE_ADDRESS__
+#endif
+
+/*
+ * GCC does not support KMSAN.
+ */
+#define __no_sanitize_memory
+#define __no_kmsan_checks
+
+/*
+ * Turn individual warnings and errors on and off locally, depending
+ * on version.
+ */
+#define __diag_GCC(version, severity, s) \
+ __diag_GCC_ ## version(__diag_GCC_ ## severity s)
+
+/* Severity used in pragma directives */
+#define __diag_GCC_ignore ignored
+#define __diag_GCC_warn warning
+#define __diag_GCC_error error
+
+#define __diag_str1(s) #s
+#define __diag_str(s) __diag_str1(s)
+#define __diag(s) _Pragma(__diag_str(GCC diagnostic s))
+
+#if GCC_VERSION >= 80000
+#define __diag_GCC_8(s) __diag(s)
+#else
+#define __diag_GCC_8(s)
#endif
-#ifndef __aligned
-#define __aligned(x) __attribute__((aligned(x)))
+
+#define __diag_ignore_all(option, comment) \
+ __diag(__diag_GCC_ignore option)
+
+/*
+ * Prior to 9.1, -Wno-alloc-size-larger-than (and therefore the "alloc_size"
+ * attribute) do not work, and must be disabled.
+ */
+#if GCC_VERSION < 90100
+#undef __alloc_size__
#endif
-#define __printf(a, b) __attribute__((format(printf, a, b)))
-#define __scanf(a, b) __attribute__((format(scanf, a, b)))
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 7b65566f3e42..968d025ca8c1 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -4,65 +4,49 @@
#include <linux/compiler_types.h>
-#ifndef __compiletime_error
-# define __compiletime_error(message)
+#ifndef likely
+# define likely(x) __builtin_expect(!!(x), 1)
#endif
-
-#ifdef __OPTIMIZE__
-# define __compiletime_assert(condition, msg, prefix, suffix) \
- do { \
- extern void prefix ## suffix(void) __compiletime_error(msg); \
- if (!(condition)) \
- prefix ## suffix(); \
- } while (0)
-#else
-# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
+#ifndef unlikely
+# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
-#define _compiletime_assert(condition, msg, prefix, suffix) \
- __compiletime_assert(condition, msg, prefix, suffix)
-
-/**
- * compiletime_assert - break build and emit msg if condition is false
- * @condition: a compile-time constant condition to check
- * @msg: a message to emit if condition is false
- *
- * In tradition of POSIX assert, this macro will break the build if the
- * supplied condition is *false*, emitting the supplied error message if the
- * compiler has support to do so.
- */
-#define compiletime_assert(condition, msg) \
- _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
-
/* Optimization barrier */
+#ifndef barrier
/* The "volatile" is due to gcc bugs */
-#define barrier() __asm__ __volatile__("": : :"memory")
-
-#ifndef __always_inline
-# define __always_inline inline __attribute__((always_inline))
-#endif
-
-#ifndef __always_unused
-#define __always_unused __attribute__((__unused__))
+# define barrier() __asm__ __volatile__("": : :"memory")
#endif
-#ifndef __noreturn
-#define __noreturn __attribute__((__noreturn__))
+#ifndef barrier_data
+/*
+ * This version is i.e. to prevent dead stores elimination on @ptr
+ * where gcc and llvm may behave differently when otherwise using
+ * normal barrier(): while gcc behavior gets along with a normal
+ * barrier(), llvm needs an explicit input variable to be assumed
+ * clobbered. The issue is as follows: while the inline asm might
+ * access any memory it wants, the compiler could have fit all of
+ * @ptr into memory registers instead, and since @ptr never escaped
+ * from that, it proved that the inline asm wasn't touching any of
+ * it. This version works well with both compilers, i.e. we're telling
+ * the compiler that the inline asm absolutely may see the contents
+ * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
+ */
+# define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
#endif
#ifndef unreachable
-#define unreachable() __builtin_unreachable()
-#endif
-
-#ifndef noinline
-#define noinline
+# define unreachable() do { \
+ annotate_unreachable(); \
+ __builtin_unreachable(); \
+} while (0)
#endif
-/* Are two types/vars the same type (ignoring qualifiers)? */
-#ifndef __same_type
-# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+#ifndef __must_be_array
+/* &a[0] degrades to a pointer: a different type from an array */
+# define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#endif
+#ifndef __is_constexpr
/*
* This returns a constant expression while determining if an argument is
* a constant expression, most importantly without evaluating the argument.
@@ -70,150 +54,19 @@
*/
#define __is_constexpr(x) \
(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
+#endif
-#ifdef __ANDROID__
/*
- * FIXME: Big hammer to get rid of tons of:
- * "warning: always_inline function might not be inlinable"
- *
- * At least on android-ndk-r12/platforms/android-24/arch-arm
+ * Whether 'type' is a signed type or an unsigned type. Supports scalar types,
+ * bool and also pointer types.
*/
-#undef __always_inline
-#define __always_inline inline
-#endif
-
-#define __user
-#define __rcu
-#define __read_mostly
-
-#ifndef __attribute_const__
-# define __attribute_const__
-#endif
-
-#ifndef __maybe_unused
-# define __maybe_unused __attribute__((unused))
-#endif
-
-#ifndef __used
-# define __used __attribute__((__unused__))
-#endif
-
-#ifndef __packed
-# define __packed __attribute__((__packed__))
-#endif
-
-#ifndef __force
-# define __force
-#endif
-
-#ifndef __weak
-# define __weak __attribute__((weak))
-#endif
-
-#ifndef likely
-# define likely(x) __builtin_expect(!!(x), 1)
+#ifndef is_signed_type
+# define is_signed_type(type) (((type)(-1)) < (__force type)1)
#endif
-
-#ifndef unlikely
-# define unlikely(x) __builtin_expect(!!(x), 0)
-#endif
-
-#ifndef __init
-# define __init
+#ifndef is_unsigned_type
+# define is_unsigned_type(type) (!is_signed_type(type))
#endif
-#include <linux/types.h>
-
-/*
- * Following functions are taken from kernel sources and
- * break aliasing rules in their original form.
- *
- * While kernel is compiled with -fno-strict-aliasing,
- * perf uses -Wstrict-aliasing=3 which makes build fail
- * under gcc 4.4.
- *
- * Using extra __may_alias__ type to allow aliasing
- * in this case.
- */
-typedef __u8 __attribute__((__may_alias__)) __u8_alias_t;
-typedef __u16 __attribute__((__may_alias__)) __u16_alias_t;
-typedef __u32 __attribute__((__may_alias__)) __u32_alias_t;
-typedef __u64 __attribute__((__may_alias__)) __u64_alias_t;
-
-static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
-{
- switch (size) {
- case 1: *(__u8_alias_t *) res = *(volatile __u8_alias_t *) p; break;
- case 2: *(__u16_alias_t *) res = *(volatile __u16_alias_t *) p; break;
- case 4: *(__u32_alias_t *) res = *(volatile __u32_alias_t *) p; break;
- case 8: *(__u64_alias_t *) res = *(volatile __u64_alias_t *) p; break;
- default:
- barrier();
- __builtin_memcpy((void *)res, (const void *)p, size);
- barrier();
- }
-}
-
-static __always_inline void __write_once_size(volatile void *p, void *res, int size)
-{
- switch (size) {
- case 1: *(volatile __u8_alias_t *) p = *(__u8_alias_t *) res; break;
- case 2: *(volatile __u16_alias_t *) p = *(__u16_alias_t *) res; break;
- case 4: *(volatile __u32_alias_t *) p = *(__u32_alias_t *) res; break;
- case 8: *(volatile __u64_alias_t *) p = *(__u64_alias_t *) res; break;
- default:
- barrier();
- __builtin_memcpy((void *)p, (const void *)res, size);
- barrier();
- }
-}
-
-/*
- * Prevent the compiler from merging or refetching reads or writes. The
- * compiler is also forbidden from reordering successive instances of
- * READ_ONCE and WRITE_ONCE, but only when the compiler is aware of some
- * particular ordering. One way to make the compiler aware of ordering is to
- * put the two invocations of READ_ONCE or WRITE_ONCE in different C
- * statements.
- *
- * These two macros will also work on aggregate data types like structs or
- * unions. If the size of the accessed data type exceeds the word size of
- * the machine (e.g., 32 bits or 64 bits) READ_ONCE() and WRITE_ONCE() will
- * fall back to memcpy and print a compile-time warning.
- *
- * Their two major use cases are: (1) Mediating communication between
- * process-level code and irq/NMI handlers, all running on the same CPU,
- * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
- * mutilate accesses that either do not require ordering or that interact
- * with an explicit memory barrier or atomic instruction that provides the
- * required ordering.
- */
-
-#define READ_ONCE(x) \
-({ \
- union { typeof(x) __val; char __c[1]; } __u = \
- { .__c = { 0 } }; \
- __read_once_size(&(x), __u.__c, sizeof(x)); \
- __u.__val; \
-})
-
-#define WRITE_ONCE(x, val) \
-({ \
- union { typeof(x) __val; char __c[1]; } __u = \
- { .__val = (val) }; \
- __write_once_size(&(x), __u.__c, sizeof(x)); \
- __u.__val; \
-})
-
-
-/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
-#define ___PASTE(a, b) a##b
-#define __PASTE(a, b) ___PASTE(a, b)
-
-#ifndef OPTIMIZER_HIDE_VAR
-/* Make the optimizer believe the variable can be manipulated arbitrarily. */
-#define OPTIMIZER_HIDE_VAR(var) \
- __asm__ ("" : "=r" (var) : "0" (var))
-#endif
+#include <asm/rwonce.h>
#endif /* _TOOLS_LINUX_COMPILER_H */
diff --git a/tools/include/linux/compiler_attributes.h b/tools/include/linux/compiler_attributes.h
new file mode 100644
index 000000000000..9bfaec783e48
--- /dev/null
+++ b/tools/include/linux/compiler_attributes.h
@@ -0,0 +1,449 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_ATTRIBUTES_H
+#define __LINUX_COMPILER_ATTRIBUTES_H
+
+/*
+ * The attributes in this file are unconditionally defined and they directly
+ * map to compiler attribute(s), unless one of the compilers does not support
+ * the attribute. In that case, __has_attribute is used to check for support
+ * and the reason is stated in its comment ("Optional: ...").
+ *
+ * Note, in the tools/include version the definitions are conditional to avoid
+ * conflicts with libc.
+ *
+ * Any other "attributes" (i.e. those that depend on a configuration option,
+ * on a compiler, on an architecture, on plugins, on other attributes...)
+ * should be defined elsewhere (e.g. compiler_types.h or compiler-*.h).
+ * The intention is to keep this file as simple as possible, as well as
+ * compiler- and version-agnostic (e.g. avoiding GCC_VERSION checks).
+ *
+ * This file is meant to be sorted (by actual attribute name,
+ * not by #define identifier). Use the __attribute__((__name__)) syntax
+ * (i.e. with underscores) to avoid future collisions with other macros.
+ * Provide links to the documentation of each supported compiler, if it exists.
+ */
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alias-function-attribute
+ */
+#ifndef __alias
+# define __alias(symbol) __attribute__((__alias__(#symbol)))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-aligned-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-aligned-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-aligned-variable-attribute
+ */
+#ifndef __aligned
+# define __aligned(x) __attribute__((__aligned__(x)))
+#endif
+#ifndef __aligned_largest
+# define __aligned_largest __attribute__((__aligned__))
+#endif
+
+/*
+ * Note: do not use this directly. Instead, use __alloc_size() since it is conditionally
+ * available and includes other attributes. For GCC < 9.1, __alloc_size__ gets undefined
+ * in compiler-gcc.h, due to misbehaviors.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#alloc-size
+ */
+//#ifndef __alloc_size__
+//# define __alloc_size__(x, ...) __attribute__((__alloc_size__(x, ## __VA_ARGS__)))
+//#endif
+
+/*
+ * Note: users of __always_inline currently do not write "inline" themselves,
+ * which seems to be required by gcc to apply the attribute according
+ * to its docs (and also "warning: always_inline function might not be
+ * inlinable [-Wattributes]" is emitted).
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute
+ * clang: mentioned
+ */
+#ifndef __always_inline
+# define __always_inline inline __attribute__((__always_inline__))
+#endif
+
+/*
+ * The second argument is optional (default 0), so we use a variadic macro
+ * to make the shorthand.
+ *
+ * Beware: Do not apply this to functions which may return
+ * ERR_PTRs. Also, it is probably unwise to apply it to functions
+ * returning extra information in the low bits (but in that case the
+ * compiler should see some alignment anyway, when the return value is
+ * massaged by 'flags = ptr & 3; ptr &= ~3;').
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-assume_005faligned-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#assume-aligned
+ */
+#ifndef __assume_aligned
+# define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#cleanup
+ */
+#ifndef __cleanup
+# define __cleanup(func) __attribute__((__cleanup__(func)))
+#endif
+
+/*
+ * Note the long name.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
+ */
+#ifndef __attribute_const__
+# define __attribute_const__ __attribute__((__const__))
+#endif
+
+/*
+ * Optional: only supported since gcc >= 9
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute
+ */
+#if __has_attribute(__copy__)
+# define __copy(symbol) __attribute__((__copy__(symbol)))
+#else
+# define __copy(symbol)
+#endif
+
+/*
+ * Optional: only supported since gcc >= 14
+ * Optional: only supported since clang >= 18
+ *
+ * gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
+ * clang: https://reviews.llvm.org/D148381
+ */
+#if __has_attribute(__counted_by__)
+# define __counted_by(member) __attribute__((__counted_by__(member)))
+#else
+# define __counted_by(member)
+#endif
+
+/*
+ * Optional: not supported by gcc
+ * Optional: only supported since clang >= 14.0
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#diagnose_as_builtin
+ */
+#if __has_attribute(__diagnose_as_builtin__)
+# define __diagnose_as(builtin...) __attribute__((__diagnose_as_builtin__(builtin)))
+#else
+# define __diagnose_as(builtin...)
+#endif
+
+/*
+ * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
+ * attribute warnings entirely and for good") for more information.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-deprecated-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-deprecated-variable-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html#index-deprecated-enumerator-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#deprecated
+ */
+#ifndef __deprecated
+# define __deprecated
+#endif
+
+/*
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-designated_005finit-type-attribute
+ */
+#if __has_attribute(__designated_init__)
+# define __designated_init __attribute__((__designated_init__))
+#else
+# define __designated_init
+#endif
+
+/*
+ * Optional: only supported since clang >= 14.0
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-error-function-attribute
+ */
+#if __has_attribute(__error__)
+# define __compiletime_error(msg) __attribute__((__error__(msg)))
+#else
+# define __compiletime_error(msg)
+#endif
+
+/*
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute
+ */
+#if __has_attribute(__externally_visible__)
+# define __visible __attribute__((__externally_visible__))
+#else
+# define __visible
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-format-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#format
+ */
+#ifndef __printf
+# define __printf(a, b) __attribute__((__format__(printf, a, b)))
+#endif
+#ifndef __scanf
+# define __scanf(a, b) __attribute__((__format__(scanf, a, b)))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-gnu_005finline-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#gnu-inline
+ */
+#ifndef __gnu_inline
+# define __gnu_inline __attribute__((__gnu_inline__))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#malloc
+ */
+#ifndef __malloc
+# define __malloc __attribute__((__malloc__))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-mode-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-mode-variable-attribute
+ */
+#ifndef __mode
+# define __mode(x) __attribute__((__mode__(x)))
+#endif
+
+/*
+ * Optional: only supported since gcc >= 7
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-no_005fcaller_005fsaved_005fregisters-function-attribute_002c-x86
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#no-caller-saved-registers
+ */
+#if __has_attribute(__no_caller_saved_registers__)
+# define __no_caller_saved_registers __attribute__((__no_caller_saved_registers__))
+#else
+# define __no_caller_saved_registers
+#endif
+
+/*
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noclone-function-attribute
+ */
+#if __has_attribute(__noclone__)
+# define __noclone __attribute__((__noclone__))
+#else
+# define __noclone
+#endif
+
+/*
+ * Add the pseudo keyword 'fallthrough' so case statement blocks
+ * must end with any of these keywords:
+ * break;
+ * fallthrough;
+ * continue;
+ * goto <label>;
+ * return [expression];
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes
+ */
+#if __has_attribute(__fallthrough__)
+# define fallthrough __attribute__((__fallthrough__))
+#else
+# define fallthrough do {} while (0) /* fallthrough */
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#flatten
+ */
+# define __flatten __attribute__((flatten))
+
+/*
+ * Note the missing underscores.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute
+ * clang: mentioned
+ */
+#define noinline __attribute__((__noinline__))
+
+/*
+ * Optional: only supported since gcc >= 8
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-nonstring-variable-attribute
+ */
+#if __has_attribute(__nonstring__)
+# define __nonstring __attribute__((__nonstring__))
+#else
+# define __nonstring
+#endif
+
+/*
+ * Optional: only supported since GCC >= 7.1, clang >= 13.0.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005fprofile_005finstrument_005ffunction-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#no-profile-instrument-function
+ */
+#if __has_attribute(__no_profile_instrument_function__)
+# define __no_profile __attribute__((__no_profile_instrument_function__))
+#else
+# define __no_profile
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noreturn-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#noreturn
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#id1
+ */
+#define __noreturn __attribute__((__noreturn__))
+
+/*
+ * Optional: only supported since GCC >= 11.1, clang >= 7.0.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005fstack_005fprotector-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#no-stack-protector-safebuffers
+ */
+#if __has_attribute(__no_stack_protector__)
+# define __no_stack_protector __attribute__((__no_stack_protector__))
+#else
+# define __no_stack_protector
+#endif
+
+/*
+ * Optional: not supported by gcc.
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#overloadable
+ */
+#if __has_attribute(__overloadable__)
+# define __overloadable __attribute__((__overloadable__))
+#else
+# define __overloadable
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
+ * clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
+ */
+#ifndef __packed
+# define __packed __attribute__((__packed__))
+#endif
+
+/*
+ * Note: the "type" argument should match any __builtin_object_size(p, type) usage.
+ *
+ * Optional: not supported by gcc.
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
+ */
+#if __has_attribute(__pass_dynamic_object_size__)
+# define __pass_dynamic_object_size(type) __attribute__((__pass_dynamic_object_size__(type)))
+#else
+# define __pass_dynamic_object_size(type)
+#endif
+#if __has_attribute(__pass_object_size__)
+# define __pass_object_size(type) __attribute__((__pass_object_size__(type)))
+#else
+# define __pass_object_size(type)
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
+ */
+#ifndef __pure
+# define __pure __attribute__((__pure__))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-section-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#section-declspec-allocate
+ */
+#ifndef __section
+# define __section(section) __attribute__((__section__(section)))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-unused-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-unused-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-unused-variable-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-unused-label-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#maybe-unused-unused
+ */
+#ifndef __always_unused
+# define __always_unused __attribute__((__unused__))
+#endif
+#ifndef __maybe_unused
+# define __maybe_unused __attribute__((__unused__))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-used-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-used-variable-attribute
+ */
+#ifndef __used
+# define __used __attribute__((__used__))
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-warn_005funused_005fresult-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#nodiscard-warn-unused-result
+ */
+#ifndef __must_check
+# define __must_check __attribute__((__warn_unused_result__))
+#endif
+
+/*
+ * Optional: only supported since clang >= 14.0
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-warning-function-attribute
+ */
+#if __has_attribute(__warning__)
+# define __compiletime_warning(msg) __attribute__((__warning__(msg)))
+#else
+# define __compiletime_warning(msg)
+#endif
+
+/*
+ * Optional: only supported since clang >= 14.0
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#disable-sanitizer-instrumentation
+ *
+ * disable_sanitizer_instrumentation is not always similar to
+ * no_sanitize((<sanitizer-name>)): the latter may still let specific sanitizers
+ * insert code into functions to prevent false positives. Unlike that,
+ * disable_sanitizer_instrumentation prevents all kinds of instrumentation to
+ * functions with the attribute.
+ */
+#if __has_attribute(disable_sanitizer_instrumentation)
+# define __disable_sanitizer_instrumentation \
+ __attribute__((disable_sanitizer_instrumentation))
+#else
+# define __disable_sanitizer_instrumentation
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-weak-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-weak-variable-attribute
+ */
+#ifndef __weak
+# define __weak __attribute__((__weak__))
+#endif
+
+/*
+ * Used by functions that use '__builtin_return_address'. These function
+ * don't want to be splited or made inline, which can make
+ * the '__builtin_return_address' get unexpected address.
+ */
+#ifndef __fix_address
+# define __fix_address noinline __noclone
+#endif
+
+#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
diff --git a/tools/include/linux/compiler_types.h b/tools/include/linux/compiler_types.h
index 1bdd834bdd57..6f7217110e05 100644
--- a/tools/include/linux/compiler_types.h
+++ b/tools/include/linux/compiler_types.h
@@ -2,8 +2,6 @@
#ifndef __LINUX_COMPILER_TYPES_H
#define __LINUX_COMPILER_TYPES_H
-/* Builtins */
-
/*
* __has_builtin is supported on gcc >= 10, clang >= 3 and icc >= 21.
* In the meantime, to support gcc < 10, we implement __has_builtin
@@ -13,31 +11,194 @@
#define __has_builtin(x) (0)
#endif
+/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
#ifdef __CHECKER__
+/* address spaces */
+# define __kernel __attribute__((address_space(0)))
+# define __user __attribute__((noderef, address_space(__user)))
+# define __iomem __attribute__((noderef, address_space(__iomem)))
+# define __percpu __attribute__((noderef, address_space(__percpu)))
+# define __rcu __attribute__((noderef, address_space(__rcu)))
+static inline void __chk_user_ptr(const volatile void __user *ptr) { }
+static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
/* context/locking */
# define __must_hold(x) __attribute__((context(x,1,1)))
# define __acquires(x) __attribute__((context(x,0,1)))
+# define __cond_acquires(x) __attribute__((context(x,0,-1)))
# define __releases(x) __attribute__((context(x,1,0)))
# define __acquire(x) __context__(x,1)
# define __release(x) __context__(x,-1)
# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
+/* other */
+# define __force __attribute__((force))
+# define __nocast __attribute__((nocast))
+# define __safe __attribute__((safe))
+# define __private __attribute__((noderef))
+# define ACCESS_PRIVATE(p, member) (*((typeof((p)->member) __force *) &(p)->member))
#else /* __CHECKER__ */
+/* address spaces */
+# define __kernel
+# ifdef STRUCTLEAK_PLUGIN
+# define __user __attribute__((user))
+# else
+//# define __user BTF_TYPE_TAG(user)
+# endif
+# define __iomem
+# define __percpu BTF_TYPE_TAG(percpu)
+# define __rcu BTF_TYPE_TAG(rcu)
+
+# define __chk_user_ptr(x) (void)0
+# define __chk_io_ptr(x) (void)0
/* context/locking */
# define __must_hold(x)
# define __acquires(x)
+# define __cond_acquires(x)
# define __releases(x)
# define __acquire(x) (void)0
# define __release(x) (void)0
# define __cond_lock(x,c) (c)
+/* other */
+# define __force
+# define __nocast
+# define __safe
+# define __private
+# define ACCESS_PRIVATE(p, member) ((p)->member)
+# define __builtin_warning(x, y...) (1)
#endif /* __CHECKER__ */
+/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
+#define ___PASTE(a,b) a##b
+#define __PASTE(a,b) ___PASTE(a,b)
+
+/* Attributes */
+#include <linux/compiler_attributes.h>
+
/* Compiler specific macros. */
-#ifdef __GNUC__
+#ifdef __clang__
+#include <linux/compiler-clang.h>
+#elif defined(__GNUC__)
+/* The above compilers also define __GNUC__, so order is important here. */
#include <linux/compiler-gcc.h>
+#else
+#error "Unknown compiler"
+#endif
+
+/*
+ * Any place that could be marked with the "alloc_size" attribute is also
+ * a place to be marked with the "malloc" attribute, except those that may
+ * be performing a _reallocation_, as that may alias the existing pointer.
+ * For these, use __realloc_size().
+ */
+#ifdef __alloc_size__
+# define __alloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__) __malloc
+# define __realloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__)
+#else
+# define __alloc_size(x, ...) __malloc
+# define __realloc_size(x, ...)
+#endif
+
+/*
+ * When the size of an allocated object is needed, use the best available
+ * mechanism to find it. (For cases where sizeof() cannot be used.)
+ */
+#if __has_builtin(__builtin_dynamic_object_size)
+#define __struct_size(p) __builtin_dynamic_object_size(p, 0)
+#define __member_size(p) __builtin_dynamic_object_size(p, 1)
+#else
+#define __struct_size(p) __builtin_object_size(p, 0)
+#define __member_size(p) __builtin_object_size(p, 1)
+#endif
+
+/* Are two types/vars the same type (ignoring qualifiers)? */
+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+
+/*
+ * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
+ * non-scalar types unchanged.
+ */
+/*
+ * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
+ * is not type-compatible with 'signed char', and we define a separate case.
+ */
+#define __scalar_type_to_expr_cases(type) \
+ unsigned type: (unsigned type)0, \
+ signed type: (signed type)0
+
+#define __unqual_scalar_typeof(x) typeof( \
+ _Generic((x), \
+ char: (char)0, \
+ __scalar_type_to_expr_cases(char), \
+ __scalar_type_to_expr_cases(short), \
+ __scalar_type_to_expr_cases(int), \
+ __scalar_type_to_expr_cases(long), \
+ __scalar_type_to_expr_cases(long long), \
+ default: (x)))
+
+/* Is this type a native word size -- useful for atomic operations */
+#define __native_word(t) \
+ (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
+ sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+
+#ifndef NDEBUG
+# ifndef __cplusplus
+# pragma GCC diagnostic ignored "-Wnested-externs"
+# endif
+# define __compiletime_assert(condition, msg, prefix, suffix) \
+ do { \
+ /* \
+ * __noreturn is needed to give the compiler enough \
+ * information to avoid certain possibly-uninitialized \
+ * warnings (regardless of the build failing). \
+ */ \
+ __noreturn extern void prefix ## suffix(void) \
+ __compiletime_error(msg); \
+ if (!(condition)) \
+ prefix ## suffix(); \
+ } while (0)
+#else
+# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
+#endif
+
+#define _compiletime_assert(condition, msg, prefix, suffix) \
+ __compiletime_assert(condition, msg, prefix, suffix)
+
+/**
+ * compiletime_assert - break build and emit msg if condition is false
+ * @condition: a compile-time constant condition to check
+ * @msg: a message to emit if condition is false
+ *
+ * In tradition of POSIX assert, this macro will break the build if the
+ * supplied condition is *false*, emitting the supplied error message if the
+ * compiler has support to do so.
+ */
+#define compiletime_assert(condition, msg) \
+ _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
+
+#define compiletime_assert_atomic_type(t) \
+ compiletime_assert(__native_word(t), \
+ "Need native word sized stores/loads for atomicity.")
+
+/* Helpers for emitting diagnostics in pragmas. */
+#ifndef __diag
+#define __diag(string)
#endif
-#ifndef asm_volatile_goto
-#define asm_volatile_goto(x...) asm goto(x)
+#ifndef __diag_GCC
+#define __diag_GCC(version, severity, string)
+#endif
+
+#define __diag_push() __diag(push)
+#define __diag_pop() __diag(pop)
+
+#define __diag_ignore(compiler, version, option, comment) \
+ __diag_ ## compiler(version, ignore, option)
+#define __diag_warn(compiler, version, option, comment) \
+ __diag_ ## compiler(version, warn, option)
+#define __diag_error(compiler, version, option, comment) \
+ __diag_ ## compiler(version, error, option)
+
+#ifndef __diag_ignore_all
+#define __diag_ignore_all(option, comment)
#endif
#endif /* __LINUX_COMPILER_TYPES_H */
diff --git a/tools/include/linux/rbtree.h b/tools/include/linux/rbtree.h
index 2680f2edb837..446345a10918 100644
--- a/tools/include/linux/rbtree.h
+++ b/tools/include/linux/rbtree.h
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/stddef.h>
+#include <linux/types.h> /* for bool */
struct rb_node {
unsigned long __rb_parent_color;
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index db5c99318c79..38289a2caa40 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
#define _TOOLS_LINUX_STRING_H_
#include <linux/types.h> /* for size_t */
+#include <linux/compiler.h>
#include <string.h>
void *memdup(const void *src, size_t len);
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index cb1f44f1ed5e..2ea932fcd575 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -55,7 +55,7 @@ typedef __s8 s8;
#ifndef __user
#define __user
#endif
-#define __must_check
+
#define __cold
typedef __u16 __bitwise __le16;
--
2.44.0.278.ge034bb2e1d-goog
On Sun, Mar 10, 2024 at 3:06 AM Ian Rogers <[email protected]> wrote:
>
> [1] https://clang.llvm.org/docs/AttributeReference.html#noinline
> Reported-by: Christopher Di Bella <[email protected]>
Out of curiosity, was this due to the `[[gnu::noinline]]` or similar
in e.g. `src/string/memset_explicit.h`?
> -#define noinline __attribute__((__noinline__))
> +#define __noinline __attribute__((__noinline__))
I guess it does not matter since I don't see it used in `tools/`, but
should the one inside `__fix_address` be updated too? Or is the idea
to keep the diff as minimal as possible?
Cheers,
Miguel
On Sun, Mar 10, 2024 at 3:06 AM Ian Rogers <[email protected]> wrote:
>
> compiler_attributes.h - added from
> include/linux/compiler_attributes.h,
> guards were added to definitions to avoid redefinition of macros
> in libc.
Do you have an example for context?
Thanks!
Cheers,
Miguel
On Sun, Mar 10, 2024 at 4:25 AM Miguel Ojeda
<[email protected]> wrote:
>
> On Sun, Mar 10, 2024 at 3:06 AM Ian Rogers <[email protected]> wrote:
> >
> > [1] https://clang.llvm.org/docs/AttributeReference.html#noinline
> > Reported-by: Christopher Di Bella <[email protected]>
>
> Out of curiosity, was this due to the `[[gnu::noinline]]` or similar
> in e.g. `src/string/memset_explicit.h`?
Yes, and in src/__support/threads/linux/thread.cpp's definition of
start_thread().
Thanks for the patch!
Acked-by: Nick Desaulniers <[email protected]>
--
Thanks,
~Nick Desaulniers
On Sat, Mar 09, 2024 at 06:05:08PM -0800, Ian Rogers wrote:
> An issue was reported with clang and llvm libc where the noinline
> attribute [1] was being expanded due to the #define in
> linux/compiler.h (now in compiler_attributes.h). The expansion caused
> the __attribute__ to appear twice and break the build. To avoid this
> conflict, rename noinline to __noinline which is more consistent with
> other compiler attributes.
>
> [1] https://clang.llvm.org/docs/AttributeReference.html#noinline
Following this link, I don't see __noinline there - only __noinline__ and
noinline. What's up?
Als, pls add an empty line before tags.
> Reported-by: Christopher Di Bella <[email protected]>
>
> Signed-off-by: Ian Rogers <[email protected]>
tags should not have empty lines between them.
> ---
> tools/include/linux/compiler_attributes.h | 4 ++--
> tools/perf/arch/x86/tests/bp-modify.c | 4 ++--
> tools/perf/bench/find-bit-bench.c | 2 +-
> tools/perf/tests/bp_account.c | 2 +-
> tools/perf/tests/bp_signal.c | 2 +-
> tools/perf/tests/bp_signal_overflow.c | 2 +-
> tools/perf/tests/dwarf-unwind.c | 12 ++++++------
> tools/perf/tests/workloads/leafloop.c | 8 ++++----
> tools/perf/tests/workloads/thloop.c | 4 ++--
> 9 files changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/tools/include/linux/compiler_attributes.h b/tools/include/linux/compiler_attributes.h
> index 9bfaec783e48..1ff3d85f5af3 100644
> --- a/tools/include/linux/compiler_attributes.h
> +++ b/tools/include/linux/compiler_attributes.h
> @@ -267,12 +267,12 @@
> # define __flatten __attribute__((flatten))
>
> /*
> - * Note the missing underscores.
> + * Note, the kernel version is missing the underscores.
> *
> * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute
> * clang: mentioned
> */
> -#define noinline __attribute__((__noinline__))
> +#define __noinline __attribute__((__noinline__))
>
> /*
> * Optional: only supported since gcc >= 8
> diff --git a/tools/perf/arch/x86/tests/bp-modify.c b/tools/perf/arch/x86/tests/bp-modify.c
> index 0924ccd9e36d..65493ff7a76f 100644
> --- a/tools/perf/arch/x86/tests/bp-modify.c
> +++ b/tools/perf/arch/x86/tests/bp-modify.c
> @@ -15,13 +15,13 @@
> #include "tests/tests.h"
> #include "arch-tests.h"
>
> -static noinline int bp_1(void)
> +static __noinline int bp_1(void)
> {
> pr_debug("in %s\n", __func__);
> return 0;
> }
>
> -static noinline int bp_2(void)
> +static __noinline int bp_2(void)
> {
> pr_debug("in %s\n", __func__);
> return 0;
> diff --git a/tools/perf/bench/find-bit-bench.c b/tools/perf/bench/find-bit-bench.c
> index 7e25b0e413f6..dd97a51649bc 100644
> --- a/tools/perf/bench/find-bit-bench.c
> +++ b/tools/perf/bench/find-bit-bench.c
> @@ -31,7 +31,7 @@ static const char *const bench_usage[] = {
> static unsigned int accumulator;
> static unsigned int use_of_val;
>
> -static noinline void workload(int val)
> +static __noinline void workload(int val)
> {
> use_of_val += val;
> accumulator++;
> diff --git a/tools/perf/tests/bp_account.c b/tools/perf/tests/bp_account.c
> index 6f921db33cf9..459f61752a71 100644
> --- a/tools/perf/tests/bp_account.c
> +++ b/tools/perf/tests/bp_account.c
> @@ -34,7 +34,7 @@
>
> static volatile long the_var;
>
> -static noinline int test_function(void)
> +static __noinline int test_function(void)
> {
> return 0;
> }
> diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
> index 1f2908f02389..484a7e7f96ee 100644
> --- a/tools/perf/tests/bp_signal.c
> +++ b/tools/perf/tests/bp_signal.c
> @@ -59,7 +59,7 @@ static void __test_function(volatile long *ptr)
> }
> #endif
>
> -static noinline int test_function(void)
> +static __noinline int test_function(void)
> {
> __test_function(&the_var);
> the_var++;
> diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c
> index 4e897c2cf26b..9436bf2973f8 100644
> --- a/tools/perf/tests/bp_signal_overflow.c
> +++ b/tools/perf/tests/bp_signal_overflow.c
> @@ -30,7 +30,7 @@
>
> static int overflows;
>
> -static noinline int test_function(void)
> +static __noinline int test_function(void)
> {
> return time(NULL);
> }
> diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
> index d01aa931fe81..a669c69a9242 100644
> --- a/tools/perf/tests/dwarf-unwind.c
> +++ b/tools/perf/tests/dwarf-unwind.c
> @@ -109,7 +109,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
> return strcmp((const char *) symbol, funcs[idx]);
> }
>
> -NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thread)
> +NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__thread(struct thread *thread)
> {
> struct perf_sample sample;
> unsigned long cnt = 0;
> @@ -140,7 +140,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thr
>
> static int global_unwind_retval = -INT_MAX;
>
> -NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__compare(void *p1, void *p2)
> +NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__compare(void *p1, void *p2)
> {
> /* Any possible value should be 'thread' */
> struct thread *thread = *(struct thread **)p1;
> @@ -159,7 +159,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__compare(void *p1, void *p
> return p1 - p2;
> }
>
> -NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_3(struct thread *thread)
> +NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__krava_3(struct thread *thread)
> {
> struct thread *array[2] = {thread, thread};
> void *fp = &bsearch;
> @@ -178,7 +178,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_3(struct thread *th
> return global_unwind_retval;
> }
>
> -NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_2(struct thread *thread)
> +NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__krava_2(struct thread *thread)
> {
> int ret;
>
> @@ -187,7 +187,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_2(struct thread *th
> return ret;
> }
>
> -NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *thread)
> +NO_TAIL_CALL_ATTRIBUTE __noinline int test_dwarf_unwind__krava_1(struct thread *thread)
> {
> int ret;
>
> @@ -196,7 +196,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *th
> return ret;
> }
>
> -noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
> +__noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
> int subtest __maybe_unused)
> {
> struct machine *machine;
> diff --git a/tools/perf/tests/workloads/leafloop.c b/tools/perf/tests/workloads/leafloop.c
> index 1bf5cc97649b..89d2cec2f461 100644
> --- a/tools/perf/tests/workloads/leafloop.c
> +++ b/tools/perf/tests/workloads/leafloop.c
> @@ -4,18 +4,18 @@
> #include "../tests.h"
>
> /* We want to check these symbols in perf script */
> -noinline void leaf(volatile int b);
> -noinline void parent(volatile int b);
> +__noinline void leaf(volatile int b);
> +__noinline void parent(volatile int b);
>
> static volatile int a;
>
> -noinline void leaf(volatile int b)
> +__noinline void leaf(volatile int b)
> {
> for (;;)
> a += b;
> }
>
> -noinline void parent(volatile int b)
> +__noinline void parent(volatile int b)
> {
> leaf(b);
> }
> diff --git a/tools/perf/tests/workloads/thloop.c b/tools/perf/tests/workloads/thloop.c
> index 457b29f91c3e..e252efb76203 100644
> --- a/tools/perf/tests/workloads/thloop.c
> +++ b/tools/perf/tests/workloads/thloop.c
> @@ -9,14 +9,14 @@
> static volatile sig_atomic_t done;
>
> /* We want to check this symbol in perf report */
> -noinline void test_loop(void);
> +__noinline void test_loop(void);
>
> static void sighandler(int sig __maybe_unused)
> {
> done = 1;
> }
>
> -noinline void test_loop(void)
> +__noinline void test_loop(void)
> {
> while (!done);
> }
> --
> 2.44.0.278.ge034bb2e1d-goog
On Mon, Mar 11, 2024 at 8:44 AM Michael S. Tsirkin <[email protected]> wrote:
>
> On Sat, Mar 09, 2024 at 06:05:08PM -0800, Ian Rogers wrote:
> > An issue was reported with clang and llvm libc where the noinline
> > attribute [1] was being expanded due to the #define in
> > linux/compiler.h (now in compiler_attributes.h). The expansion caused
> > the __attribute__ to appear twice and break the build. To avoid this
> > conflict, rename noinline to __noinline which is more consistent with
> > other compiler attributes.
> >
> > [1] https://clang.llvm.org/docs/AttributeReference.html#noinline
>
> Following this link, I don't see __noinline there - only __noinline__ and
> noinline. What's up?
__noinline (which is what this patch is changing the preprocessor
define to) will not be expanded in the presence of
__attribute__((__noinline__)), __attribute__((noinline)), or
[[gnu::inline]], unlike the previous macro definition.
--
Thanks,
~Nick Desaulniers
On 10/03/2024 02:05, Ian Rogers wrote:
> compiler.h - synced from include/linux/compiler.h, guards were
> added to definitions to avoid redefinition of macros
> in libc. ftrace, CONFIG_OBJTOOL and kentry logic was removed as
> redundant.
>
Hi Ian,
This commit breaks the Arm build (and cross compilation for Arm on x86):
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
Something like this, but I won't paste the whole output because it's huge:
tools/include/linux/ring_buffer.h: In function ‘ring_buffer_read_head’:
tools/include/asm/../../arch/arm64/include/asm/barrier.h:72:35: error:
‘__u8_alias_t’ undeclared (first use in this function)
72 | : "=r" (*(__u8_alias_t *)__u.__c)
\
| ^~~~~~~~~~~~
tools/include/linux/ring_buffer.h:59:16: note: in expansion of macro
‘smp_load_acquire’
59 | return smp_load_acquire(&base->data_head);
| ^~~~~~~~~~~~~~~~
Thanks
James
On Sat, Mar 9, 2024 at 6:05 PM Ian Rogers <[email protected]> wrote:
>
> libbpf depends upon linux/err.h which has a linux/compiler.h
> dependency. In the kernel includes, as opposed to the tools version,
> linux/compiler.h includes linux/compiler_attributes.h which defines
> __printf. As the libbpf.c __printf definition isn't guarded by an
> ifndef, this leads to a duplicate definition compilation error when
> trying to update the tools/include/linux/compiler.h. Fix this by
> adding the missing ifndef.
>
> Signed-off-by: Ian Rogers <[email protected]>
> ---
> tools/lib/bpf/libbpf.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index afd09571c482..2152360b4b18 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -66,7 +66,9 @@
> */
> #pragma GCC diagnostic ignored "-Wformat-nonliteral"
>
> -#define __printf(a, b) __attribute__((format(printf, a, b)))
> +#ifndef __printf
> +# define __printf(a, b) __attribute__((format(printf, a, b)))
styling nit: don't add spaces between # and define, please
overall LGTM
Acked-by: Andrii Nakryiko <[email protected]>
Two questions, though.
1. It seems like just dropping #define __printf in libbpf.c compiles
fine (I checked both building libbpf directly, and BPF selftest, and
perf, and bpftool directly, all of them built fine). So we can
probably just drop this. I'll need to add __printf on Github, but
that's fine.
2. Logistics. Which tree should this patch go through? Can I land it
in bpf-next or it's too much inconvenience for you?
> +#endif
>
> static struct bpf_map *bpf_object__add_map(struct bpf_object *obj);
> static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog);
> --
> 2.44.0.278.ge034bb2e1d-goog
>
On Mon, Mar 11, 2024 at 10:49 AM Andrii Nakryiko
<[email protected]> wrote:
>
> On Sat, Mar 9, 2024 at 6:05 PM Ian Rogers <[email protected]> wrote:
> >
> > libbpf depends upon linux/err.h which has a linux/compiler.h
> > dependency. In the kernel includes, as opposed to the tools version,
> > linux/compiler.h includes linux/compiler_attributes.h which defines
> > __printf. As the libbpf.c __printf definition isn't guarded by an
> > ifndef, this leads to a duplicate definition compilation error when
> > trying to update the tools/include/linux/compiler.h. Fix this by
> > adding the missing ifndef.
> >
> > Signed-off-by: Ian Rogers <[email protected]>
> > ---
> > tools/lib/bpf/libbpf.c | 4 +++-
> > 1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index afd09571c482..2152360b4b18 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -66,7 +66,9 @@
> > */
> > #pragma GCC diagnostic ignored "-Wformat-nonliteral"
> >
> > -#define __printf(a, b) __attribute__((format(printf, a, b)))
> > +#ifndef __printf
> > +# define __printf(a, b) __attribute__((format(printf, a, b)))
>
> styling nit: don't add spaces between # and define, please
>
> overall LGTM
>
> Acked-by: Andrii Nakryiko <[email protected]>
>
> Two questions, though.
>
> 1. It seems like just dropping #define __printf in libbpf.c compiles
> fine (I checked both building libbpf directly, and BPF selftest, and
> perf, and bpftool directly, all of them built fine). So we can
> probably just drop this. I'll need to add __printf on Github, but
> that's fine.
>
> 2. Logistics. Which tree should this patch go through? Can I land it
> in bpf-next or it's too much inconvenience for you?
Thanks Andrii,
dropping the #define (1) sgtm but the current compiler.h will fail to
build libbpf.c without the later compiler.h update in this series.
This causes another logistic issue for your point 2. Presumably if
this patch goes through bpf-next, the first patch "tools bpf:
Synchronize bpf.h with kernel uapi version" should also go through the
bpf-next.
Thanks,
Ian
> > +#endif
> >
> > static struct bpf_map *bpf_object__add_map(struct bpf_object *obj);
> > static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog);
> > --
> > 2.44.0.278.ge034bb2e1d-goog
> >
On Mon, Mar 11, 2024 at 9:34 AM James Clark <[email protected]> wrote:
>
>
>
> On 10/03/2024 02:05, Ian Rogers wrote:
> > compiler.h - synced from include/linux/compiler.h, guards were
> > added to definitions to avoid redefinition of macros
> > in libc. ftrace, CONFIG_OBJTOOL and kentry logic was removed as
> > redundant.
> >
>
> Hi Ian,
>
> This commit breaks the Arm build (and cross compilation for Arm on x86):
>
> $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
>
> Something like this, but I won't paste the whole output because it's huge:
>
> tools/include/linux/ring_buffer.h: In function ‘ring_buffer_read_head’:
>
> tools/include/asm/../../arch/arm64/include/asm/barrier.h:72:35: error:
> ‘__u8_alias_t’ undeclared (first use in this function)
> 72 | : "=r" (*(__u8_alias_t *)__u.__c)
> \
> | ^~~~~~~~~~~~
> tools/include/linux/ring_buffer.h:59:16: note: in expansion of macro
> ‘smp_load_acquire’
> 59 | return smp_load_acquire(&base->data_head);
> | ^~~~~~~~~~~~~~~~
Sorry for this James, I was rushing. I'll address the issues in v2 but
the one you highlight above doesn't look like a fun/simple issue to
resolve :-( Tbh, I'm not sure how much value tools/include has in its
current set up. It is weird the include order in perf prefers
tools/include/linux over tools/include/uapi. Current tools/include
seems to be trying to do a few different things:
1) provide headers like list.h so programs in tools can have linux
style lists, etc.
2) stuff that (1) drags in .. do we really want the asm barrier code
from arm? A sane user space program would be better using stdatomic.h,
plus that'd give the user space program an ability to get compiled on
to weirder targets like wasm. Plus we end up with weird type conflicts
like bool coming from linux/types.h rather than stdbool.h.
3) copies of kernel uapi headers that may be more up-to-date that
those in your system, thereby exposing constants that things like
libbpf depend upon.
4) headers with the same name as and that resemble kernel headers but
are really a reimplementation, like tools/include/linux/string.h
5) headers we have just so we can use shell scripts to scrape
constants for beautifying things in perf trace
For (1) and (2) it seems a separate library would be cleaner than
having the code in tools/include.
(3) feels like a legit use-case, so we should hold onto
tools/include/uapi, but do we want the asm directories?
(4) sounds like it should be in a library, perhaps with (1) and (2).
(5) feels like the headers should be alongside the shell scripts to
avoid polluting tools/include.
Not that I propose fixing any of this here.
Thanks,
Ian
> Thanks
> James
On Mon, Mar 11, 2024 at 12:24:24PM -0700, Ian Rogers wrote:
> 5) headers we have just so we can use shell scripts to scrape
> constants for beautifying things in perf trace
> (5) feels like the headers should be alongside the shell scripts to
> avoid polluting tools/include.
> Not that I propose fixing any of this here.
Yeah, 5 is why we have things used just for scrapping in
tools/perf/trace/beauty/include/, that now has just socket.h, used by
⬢[acme@toolbox perf-tools-next]$ tools/perf/trace/beauty/socket.sh | head
static const char *socket_ipproto[] = {
[0] = "IP",
[1] = "ICMP",
[2] = "IGMP",
[4] = "IPIP",
[6] = "TCP",
[8] = "EGP",
[12] = "PUP",
[17] = "UDP",
[22] = "IDP",
⬢[acme@toolbox perf-tools-next]$
I'll see if I get a series moving things that are just for scrapping to
that directory, then test on the container build images I have.
- Arnaldo
On Mon, Mar 11, 2024 at 11:54 AM Ian Rogers <[email protected]> wrote:
>
> On Mon, Mar 11, 2024 at 10:49 AM Andrii Nakryiko
> <[email protected]> wrote:
> >
> > On Sat, Mar 9, 2024 at 6:05 PM Ian Rogers <[email protected]> wrote:
> > >
> > > libbpf depends upon linux/err.h which has a linux/compiler.h
> > > dependency. In the kernel includes, as opposed to the tools version,
> > > linux/compiler.h includes linux/compiler_attributes.h which defines
> > > __printf. As the libbpf.c __printf definition isn't guarded by an
> > > ifndef, this leads to a duplicate definition compilation error when
> > > trying to update the tools/include/linux/compiler.h. Fix this by
> > > adding the missing ifndef.
> > >
> > > Signed-off-by: Ian Rogers <[email protected]>
> > > ---
> > > tools/lib/bpf/libbpf.c | 4 +++-
> > > 1 file changed, 3 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > index afd09571c482..2152360b4b18 100644
> > > --- a/tools/lib/bpf/libbpf.c
> > > +++ b/tools/lib/bpf/libbpf.c
> > > @@ -66,7 +66,9 @@
> > > */
> > > #pragma GCC diagnostic ignored "-Wformat-nonliteral"
> > >
> > > -#define __printf(a, b) __attribute__((format(printf, a, b)))
> > > +#ifndef __printf
> > > +# define __printf(a, b) __attribute__((format(printf, a, b)))
> >
> > styling nit: don't add spaces between # and define, please
> >
> > overall LGTM
> >
> > Acked-by: Andrii Nakryiko <[email protected]>
> >
> > Two questions, though.
> >
> > 1. It seems like just dropping #define __printf in libbpf.c compiles
> > fine (I checked both building libbpf directly, and BPF selftest, and
> > perf, and bpftool directly, all of them built fine). So we can
> > probably just drop this. I'll need to add __printf on Github, but
> > that's fine.
> >
> > 2. Logistics. Which tree should this patch go through? Can I land it
> > in bpf-next or it's too much inconvenience for you?
>
> Thanks Andrii,
>
> dropping the #define (1) sgtm but the current compiler.h will fail to
> build libbpf.c without the later compiler.h update in this series.
> This causes another logistic issue for your point 2. Presumably if
> this patch goes through bpf-next, the first patch "tools bpf:
> Synchronize bpf.h with kernel uapi version" should also go through the
> bpf-next.
>
That's what I'm saying, it seems to work without your patches already.
At least on bpf-next/master. But it's ok, let's keep it and just add
#ifndef guard, that will make my life easier when syncing to Github
later one. Then the patch can go through other trees and eventually
make it into bpf-next and then Github. So please keep my ack for
#ifndef version, thanks.
> Thanks,
> Ian
>
>
> > > +#endif
> > >
> > > static struct bpf_map *bpf_object__add_map(struct bpf_object *obj);
> > > static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog);
> > > --
> > > 2.44.0.278.ge034bb2e1d-goog
> > >