Fix supported autotools versions in README.md
[librseq.git] / include / rseq / rseq-arm64.h
index fce89788adf75bf64c0f38fb1acf92513965f848..69702cf02278923c098f08afd4aba33477612a49 100644 (file)
-/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/* SPDX-License-Identifier: MIT */
+/* SPDX-FileCopyrightText: 2016-2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> */
+/* SPDX-FileCopyrightText: 2018 Will Deacon <will.deacon@arm.com> */
+
 /*
  * rseq-arm64.h
- *
- * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * (C) Copyright 2018 - Will Deacon <will.deacon@arm.com>
  */
 
-#define RSEQ_SIG       0xd428bc00      /* BRK #0x45E0 */
+/*
+ * RSEQ_ASM_*() macro helpers are internal to the librseq headers. Those
+ * are not part of the public API.
+ */
+
+/*
+ * aarch64 -mbig-endian generates mixed endianness code vs data:
+ * little-endian code and big-endian data. Ensure the RSEQ_SIG signature
+ * matches code endianness.
+ */
+#define RSEQ_SIG_CODE  0xd428bc00      /* BRK #0x45E0.  */
+
+#ifdef __AARCH64EB__
+#define RSEQ_SIG_DATA  0x00bc28d4      /* BRK #0x45E0.  */
+#else
+#define RSEQ_SIG_DATA  RSEQ_SIG_CODE
+#endif
+
+#define RSEQ_SIG       RSEQ_SIG_DATA
 
+/*
+ * Refer to the Linux kernel memory model (LKMM) for documentation of
+ * the memory barriers.
+ */
+
+/* CPU memory barrier. */
 #define rseq_smp_mb()  __asm__ __volatile__ ("dmb ish" ::: "memory")
+/* CPU read memory barrier */
 #define rseq_smp_rmb() __asm__ __volatile__ ("dmb ishld" ::: "memory")
+/* CPU write memory barrier */
 #define rseq_smp_wmb() __asm__ __volatile__ ("dmb ishst" ::: "memory")
 
+/* Acquire: One-way permeable barrier. */
 #define rseq_smp_load_acquire(p)                                               \
 __extension__ ({                                                               \
-       __typeof(*p) ____p1;                                                    \
-       switch (sizeof(*p)) {                                                   \
+       union { rseq_unqual_scalar_typeof(*(p)) __val; char __c[sizeof(*(p))]; } __u; \
+       switch (sizeof(*(p))) {                                                 \
        case 1:                                                                 \
-               asm volatile ("ldarb %w0, %1"                                   \
-                       : "=r" (*(__u8 *)p)                                     \
-                       : "Q" (*p) : "memory");                                 \
+               __asm__ __volatile__ ("ldarb %w0, %1"                           \
+                       : "=r" (*(__u8 *)__u.__c)                               \
+                       : "Q" (*(p)) : "memory");                               \
                break;                                                          \
        case 2:                                                                 \
-               asm volatile ("ldarh %w0, %1"                                   \
-                       : "=r" (*(__u16 *)p)                                    \
-                       : "Q" (*p) : "memory");                                 \
+               __asm__ __volatile__ ("ldarh %w0, %1"                           \
+                       : "=r" (*(__u16 *)__u.__c)                              \
+                       : "Q" (*(p)) : "memory");                               \
                break;                                                          \
        case 4:                                                                 \
-               asm volatile ("ldar %w0, %1"                                    \
-                       : "=r" (*(__u32 *)p)                                    \
-                       : "Q" (*p) : "memory");                                 \
+               __asm__ __volatile__ ("ldar %w0, %1"                            \
+                       : "=r" (*(__u32 *)__u.__c)                              \
+                       : "Q" (*(p)) : "memory");                               \
                break;                                                          \
        case 8:                                                                 \
-               asm volatile ("ldar %0, %1"                                     \
-                       : "=r" (*(__u64 *)p)                                    \
-                       : "Q" (*p) : "memory");                                 \
+               __asm__ __volatile__ ("ldar %0, %1"                             \
+                       : "=r" (*(__u64 *)__u.__c)                              \
+                       : "Q" (*(p)) : "memory");                               \
                break;                                                          \
        }                                                                       \
-       ____p1;                                                                 \
+       (rseq_unqual_scalar_typeof(*(p)))__u.__val;                             \
 })
 
+/* Acquire barrier after control dependency. */
 #define rseq_smp_acquire__after_ctrl_dep()     rseq_smp_rmb()
 
+/* Release: One-way permeable barrier. */
 #define rseq_smp_store_release(p, v)                                           \
 do {                                                                           \
-       switch (sizeof(*p)) {                                                   \
+       union { rseq_unqual_scalar_typeof(*(p)) __val; char __c[sizeof(*(p))]; } __u = \
+               { .__val = (rseq_unqual_scalar_typeof(*(p))) (v) };             \
+       switch (sizeof(*(p))) {                                                 \
        case 1:                                                                 \
-               asm volatile ("stlrb %w1, %0"                                   \
-                               : "=Q" (*p)                                     \
-                               : "r" ((__u8)v)                                 \
+               __asm__ __volatile__ ("stlrb %w1, %0"                           \
+                               : "=Q" (*(p))                                   \
+                               : "r" (*(__u8 *)__u.__c)                        \
                                : "memory");                                    \
                break;                                                          \
        case 2:                                                                 \
-               asm volatile ("stlrh %w1, %0"                                   \
-                               : "=Q" (*p)                                     \
-                               : "r" ((__u16)v)                                \
+               __asm__ __volatile__ ("stlrh %w1, %0"                           \
+                               : "=Q" (*(p))                                   \
+                               : "r" (*(__u16 *)__u.__c)                       \
                                : "memory");                                    \
                break;                                                          \
        case 4:                                                                 \
-               asm volatile ("stlr %w1, %0"                                    \
-                               : "=Q" (*p)                                     \
-                               : "r" ((__u32)v)                                \
+               __asm__ __volatile__ ("stlr %w1, %0"                            \
+                               : "=Q" (*(p))                                   \
+                               : "r" (*(__u32 *)__u.__c)                       \
                                : "memory");                                    \
                break;                                                          \
        case 8:                                                                 \
-               asm volatile ("stlr %1, %0"                                     \
-                               : "=Q" (*p)                                     \
-                               : "r" ((__u64)v)                                \
+               __asm__ __volatile__ ("stlr %1, %0"                             \
+                               : "=Q" (*(p))                                   \
+                               : "r" (*(__u64 *)__u.__c)                       \
                                : "memory");                                    \
                break;                                                          \
        }                                                                       \
 } while (0)
 
-#ifdef RSEQ_SKIP_FASTPATH
-#include "rseq-skip.h"
-#else /* !RSEQ_SKIP_FASTPATH */
-
+/* Temporary scratch registers. */
 #define RSEQ_ASM_TMP_REG32     "w15"
 #define RSEQ_ASM_TMP_REG       "x15"
 #define RSEQ_ASM_TMP_REG_2     "x14"
 
+/* Only used in RSEQ_ASM_DEFINE_TABLE. */
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip,               \
                                post_commit_offset, abort_ip)                   \
        "       .pushsection    __rseq_cs, \"aw\"\n"                            \
@@ -90,26 +119,71 @@ do {                                                                               \
                          __rseq_str(post_commit_offset) ", "                   \
                          __rseq_str(abort_ip) "\n"                             \
        "       .popsection\n\t"                                                \
-       "       .pushsection __rseq_cs_ptr_array, \"aw\"\n"                             \
+       "       .pushsection __rseq_cs_ptr_array, \"aw\"\n"                     \
        "       .quad " __rseq_str(label) "b\n"                                 \
        "       .popsection\n"
 
+/*
+ * Define an rseq critical section structure of version 0 with no flags.
+ *
+ *  @label:
+ *    Local label for the beginning of the critical section descriptor
+ *    structure.
+ *  @start_ip:
+ *    Pointer to the first instruction of the sequence of consecutive assembly
+ *    instructions.
+ *  @post_commit_ip:
+ *    Pointer to the instruction after the last instruction of the sequence of
+ *    consecutive assembly instructions.
+ *  @abort_ip:
+ *    Pointer to the instruction where to move the execution flow in case of
+ *    abort of the sequence of consecutive assembly instructions.
+ */
 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip)       \
        __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,                      \
-                               (post_commit_ip - start_ip), abort_ip)
+                               (post_commit_ip) - (start_ip), abort_ip)
 
 /*
+ * Define the @exit_ip pointer as an exit point for the sequence of consecutive
+ * assembly instructions at @start_ip.
+ *
+ *  @start_ip:
+ *    Pointer to the first instruction of the sequence of consecutive assembly
+ *    instructions.
+ *  @exit_ip:
+ *    Pointer to an exit point instruction.
+ *
  * Exit points of a rseq critical section consist of all instructions outside
- * of the critical section where a critical section can branch to. The abort IP
- * is already part of the __rseq_cs section and should not be explicitly
- * defined as an additional exit point. Knowing all exit points is useful to
- * assist debuggers stepping over the critical section.
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
  */
 #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                          \
        "       .pushsection __rseq_exit_point_array, \"aw\"\n"                 \
        "       .quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n"      \
        "       .popsection\n"
 
+/*
+ * Define a critical section abort handler.
+ *
+ *  @label:
+ *    Local label to the abort handler.
+ *  @teardown:
+ *    Sequence of instructions to run on abort.
+ *  @abort_label:
+ *    C label to jump to at the end of the sequence.
+ */
+#define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)                    \
+       "       b       222f\n"                                                 \
+       "       .inst   "       __rseq_str(RSEQ_SIG_CODE) "\n"                  \
+       __rseq_str(label) ":\n"                                                 \
+       teardown                                                                \
+       "       b       %l[" __rseq_str(abort_label) "]\n"                      \
+       "222:\n"
+
+/* Jump to local label @label when @cpu_id != @current_cpu_id. */
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)                       \
        RSEQ_INJECT_ASM(1)                                                      \
        "       adrp    " RSEQ_ASM_TMP_REG ", " __rseq_str(cs_label) "\n"       \
@@ -118,68 +192,90 @@ do {                                                                              \
        "       str     " RSEQ_ASM_TMP_REG ", %[" __rseq_str(rseq_cs) "]\n"     \
        __rseq_str(label) ":\n"
 
-#define RSEQ_ASM_DEFINE_ABORT(label, abort_label)                              \
-       "       b       222f\n"                                                 \
-       "       .inst   "       __rseq_str(RSEQ_SIG) "\n"                       \
-       __rseq_str(label) ":\n"                                                 \
-       "       b       %l[" __rseq_str(abort_label) "]\n"                      \
-       "222:\n"
-
+/* Store @value to address @var. */
 #define RSEQ_ASM_OP_STORE(value, var)                                          \
        "       str     %[" __rseq_str(value) "], %[" __rseq_str(var) "]\n"
 
+/* Store-release @value to address @var. */
 #define RSEQ_ASM_OP_STORE_RELEASE(value, var)                                  \
        "       stlr    %[" __rseq_str(value) "], %[" __rseq_str(var) "]\n"
 
+/*
+ * End-of-sequence store of @value to address @var. Emit
+ * @post_commit_label label after the store instruction.
+ */
 #define RSEQ_ASM_OP_FINAL_STORE(value, var, post_commit_label)                 \
        RSEQ_ASM_OP_STORE(value, var)                                           \
        __rseq_str(post_commit_label) ":\n"
 
+/*
+ * End-of-sequence store-release of @value to address @var. Emit
+ * @post_commit_label label after the store instruction.
+ */
 #define RSEQ_ASM_OP_FINAL_STORE_RELEASE(value, var, post_commit_label)         \
        RSEQ_ASM_OP_STORE_RELEASE(value, var)                                   \
        __rseq_str(post_commit_label) ":\n"
 
-#define RSEQ_ASM_OP_CMPEQ(var, expect, label)                                  \
+/* Jump to local label @label when @var != @expect. */
+#define RSEQ_ASM_OP_CBNE(var, expect, label)                                   \
        "       ldr     " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n"         \
        "       sub     " RSEQ_ASM_TMP_REG ", " RSEQ_ASM_TMP_REG                \
                        ", %[" __rseq_str(expect) "]\n"                         \
        "       cbnz    " RSEQ_ASM_TMP_REG ", " __rseq_str(label) "\n"
 
-#define RSEQ_ASM_OP_CMPEQ32(var, expect, label)                                        \
+/*
+ * Jump to local label @label when @var != @expect (32-bit register
+ * comparison).
+ */
+#define RSEQ_ASM_OP_CBNE32(var, expect, label)                                 \
        "       ldr     " RSEQ_ASM_TMP_REG32 ", %[" __rseq_str(var) "]\n"       \
        "       sub     " RSEQ_ASM_TMP_REG32 ", " RSEQ_ASM_TMP_REG32            \
                        ", %w[" __rseq_str(expect) "]\n"                        \
        "       cbnz    " RSEQ_ASM_TMP_REG32 ", " __rseq_str(label) "\n"
 
-#define RSEQ_ASM_OP_CMPNE(var, expect, label)                                  \
+/* Jump to local label @label when @var == @expect. */
+#define RSEQ_ASM_OP_CBEQ(var, expect, label)                                   \
        "       ldr     " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n"         \
        "       sub     " RSEQ_ASM_TMP_REG ", " RSEQ_ASM_TMP_REG                \
                        ", %[" __rseq_str(expect) "]\n"                         \
        "       cbz     " RSEQ_ASM_TMP_REG ", " __rseq_str(label) "\n"
 
-#define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)                     \
+/* Jump to local label @label when @cpu_id != @current_cpu_id. */
+#define RSEQ_ASM_CBNE_CPU_ID(cpu_id, current_cpu_id, label)                    \
        RSEQ_INJECT_ASM(2)                                                      \
-       RSEQ_ASM_OP_CMPEQ32(current_cpu_id, cpu_id, label)
+       RSEQ_ASM_OP_CBNE32(current_cpu_id, cpu_id, label)
 
+/* Load @var into temporary register. */
 #define RSEQ_ASM_OP_R_LOAD(var)                                                        \
        "       ldr     " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n"
 
+/* Store from temporary register into @var. */
 #define RSEQ_ASM_OP_R_STORE(var)                                               \
        "       str     " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n"
 
+/* Load from address in temporary register+@offset into temporary register. */
 #define RSEQ_ASM_OP_R_LOAD_OFF(offset)                                         \
        "       ldr     " RSEQ_ASM_TMP_REG ", [" RSEQ_ASM_TMP_REG               \
                        ", %[" __rseq_str(offset) "]]\n"
 
+/* Add @count to temporary register. */
 #define RSEQ_ASM_OP_R_ADD(count)                                               \
        "       add     " RSEQ_ASM_TMP_REG ", " RSEQ_ASM_TMP_REG                \
                        ", %[" __rseq_str(count) "]\n"
 
+/*
+ * End-of-sequence store of temporary register to address @var. Emit
+ * @post_commit_label label after the store instruction.
+ */
 #define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label)                      \
        "       str     " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n"         \
        __rseq_str(post_commit_label) ":\n"
 
-#define RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)                                        \
+/*
+ * Copy @len bytes from @src to @dst. This is an inefficient bytewise
+ * copy and could be improved in the future.
+ */
+#define RSEQ_ASM_OP_R_BYTEWISE_MEMCPY(dst, src, len)                           \
        "       cbz     %[" __rseq_str(len) "], 333f\n"                         \
        "       mov     " RSEQ_ASM_TMP_REG_2 ", %[" __rseq_str(len) "]\n"       \
        "222:   sub     " RSEQ_ASM_TMP_REG_2 ", " RSEQ_ASM_TMP_REG_2 ", #1\n"   \
@@ -190,459 +286,34 @@ do {                                                                             \
        "       cbnz    " RSEQ_ASM_TMP_REG_2 ", 222b\n"                         \
        "333:\n"
 
-static inline __attribute__((always_inline))
-int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
-{
-       RSEQ_INJECT_C(9)
-
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
-               RSEQ_INJECT_ASM(4)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
-#endif
-               RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
-               RSEQ_INJECT_ASM(5)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [v]                   "Qo" (*v),
-                 [expect]              "r" (expect),
-                 [newv]                "r" (newv)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG
-               : abort, cmpfail
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1, error2
-#endif
-       );
-
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-cmpfail:
-       return 1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-error2:
-       rseq_bug("expected value comparison failed");
-#endif
-}
-
-static inline __attribute__((always_inline))
-int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
-                              off_t voffp, intptr_t *load, int cpu)
-{
-       RSEQ_INJECT_C(9)
-
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-               RSEQ_ASM_OP_CMPNE(v, expectnot, %l[cmpfail])
-               RSEQ_INJECT_ASM(4)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-               RSEQ_ASM_OP_CMPNE(v, expectnot, %l[error2])
-#endif
-               RSEQ_ASM_OP_R_LOAD(v)
-               RSEQ_ASM_OP_R_STORE(load)
-               RSEQ_ASM_OP_R_LOAD_OFF(voffp)
-               RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
-               RSEQ_INJECT_ASM(5)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [v]                   "Qo" (*v),
-                 [expectnot]           "r" (expectnot),
-                 [load]                "Qo" (*load),
-                 [voffp]               "r" (voffp)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG
-               : abort, cmpfail
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1, error2
-#endif
-       );
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-cmpfail:
-       return 1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-error2:
-       rseq_bug("expected value comparison failed");
-#endif
-}
+/* Per-cpu-id indexing. */
 
-static inline __attribute__((always_inline))
-int rseq_addv(intptr_t *v, intptr_t count, int cpu)
-{
-       RSEQ_INJECT_C(9)
+#define RSEQ_TEMPLATE_INDEX_CPU_ID
+#define RSEQ_TEMPLATE_MO_RELAXED
+#include "rseq-arm64-bits.h"
+#undef RSEQ_TEMPLATE_MO_RELAXED
 
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-#endif
-               RSEQ_ASM_OP_R_LOAD(v)
-               RSEQ_ASM_OP_R_ADD(count)
-               RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
-               RSEQ_INJECT_ASM(4)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [v]                   "Qo" (*v),
-                 [count]               "r" (count)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG
-               : abort
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1
-#endif
-       );
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-#endif
-}
-
-static inline __attribute__((always_inline))
-int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
-                                intptr_t *v2, intptr_t newv2,
-                                intptr_t newv, int cpu)
-{
-       RSEQ_INJECT_C(9)
-
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
-               RSEQ_INJECT_ASM(4)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
-#endif
-               RSEQ_ASM_OP_STORE(newv2, v2)
-               RSEQ_INJECT_ASM(5)
-               RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
-               RSEQ_INJECT_ASM(6)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [expect]              "r" (expect),
-                 [v]                   "Qo" (*v),
-                 [newv]                "r" (newv),
-                 [v2]                  "Qo" (*v2),
-                 [newv2]               "r" (newv2)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG
-               : abort, cmpfail
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1, error2
-#endif
-       );
-
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-cmpfail:
-       return 1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-error2:
-       rseq_bug("expected value comparison failed");
-#endif
-}
-
-static inline __attribute__((always_inline))
-int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
-                                        intptr_t *v2, intptr_t newv2,
-                                        intptr_t newv, int cpu)
-{
-       RSEQ_INJECT_C(9)
-
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
-               RSEQ_INJECT_ASM(4)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
-#endif
-               RSEQ_ASM_OP_STORE(newv2, v2)
-               RSEQ_INJECT_ASM(5)
-               RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
-               RSEQ_INJECT_ASM(6)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [expect]              "r" (expect),
-                 [v]                   "Qo" (*v),
-                 [newv]                "r" (newv),
-                 [v2]                  "Qo" (*v2),
-                 [newv2]               "r" (newv2)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG
-               : abort, cmpfail
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1, error2
-#endif
-       );
-
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-cmpfail:
-       return 1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-error2:
-       rseq_bug("expected value comparison failed");
-#endif
-}
-
-static inline __attribute__((always_inline))
-int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
-                             intptr_t *v2, intptr_t expect2,
-                             intptr_t newv, int cpu)
-{
-       RSEQ_INJECT_C(9)
-
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error3])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
-               RSEQ_INJECT_ASM(4)
-               RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[cmpfail])
-               RSEQ_INJECT_ASM(5)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
-               RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[error3])
-#endif
-               RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
-               RSEQ_INJECT_ASM(6)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [v]                   "Qo" (*v),
-                 [expect]              "r" (expect),
-                 [v2]                  "Qo" (*v2),
-                 [expect2]             "r" (expect2),
-                 [newv]                "r" (newv)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG
-               : abort, cmpfail
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1, error2, error3
-#endif
-       );
-
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-cmpfail:
-       return 1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-error2:
-       rseq_bug("expected value comparison failed");
-error3:
-       rseq_bug("2nd expected value comparison failed");
-#endif
-}
-
-static inline __attribute__((always_inline))
-int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
-                                void *dst, void *src, size_t len,
-                                intptr_t newv, int cpu)
-{
-       RSEQ_INJECT_C(9)
-
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
-               RSEQ_INJECT_ASM(4)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
-#endif
-               RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
-               RSEQ_INJECT_ASM(5)
-               RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
-               RSEQ_INJECT_ASM(6)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [expect]              "r" (expect),
-                 [v]                   "Qo" (*v),
-                 [newv]                "r" (newv),
-                 [dst]                 "r" (dst),
-                 [src]                 "r" (src),
-                 [len]                 "r" (len)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG, RSEQ_ASM_TMP_REG_2
-               : abort, cmpfail
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1, error2
-#endif
-       );
-
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-cmpfail:
-       return 1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-error2:
-       rseq_bug("expected value comparison failed");
-#endif
-}
-
-static inline __attribute__((always_inline))
-int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
-                                        void *dst, void *src, size_t len,
-                                        intptr_t newv, int cpu)
-{
-       RSEQ_INJECT_C(9)
-
-       __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
-               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
-#endif
-               RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
-               RSEQ_INJECT_ASM(3)
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
-               RSEQ_INJECT_ASM(4)
-#ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
-               RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
-#endif
-               RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
-               RSEQ_INJECT_ASM(5)
-               RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
-               RSEQ_INJECT_ASM(6)
-               RSEQ_ASM_DEFINE_ABORT(4, abort)
-               : /* gcc asm goto does not allow outputs */
-               : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "Qo" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
-                 [expect]              "r" (expect),
-                 [v]                   "Qo" (*v),
-                 [newv]                "r" (newv),
-                 [dst]                 "r" (dst),
-                 [src]                 "r" (src),
-                 [len]                 "r" (len)
-                 RSEQ_INJECT_INPUT
-               : "memory", RSEQ_ASM_TMP_REG, RSEQ_ASM_TMP_REG_2
-               : abort, cmpfail
-#ifdef RSEQ_COMPARE_TWICE
-                 , error1, error2
-#endif
-       );
-
-       return 0;
-abort:
-       RSEQ_INJECT_FAILED
-       return -1;
-cmpfail:
-       return 1;
-#ifdef RSEQ_COMPARE_TWICE
-error1:
-       rseq_bug("cpu_id comparison failed");
-error2:
-       rseq_bug("expected value comparison failed");
-#endif
-}
+#define RSEQ_TEMPLATE_MO_RELEASE
+#include "rseq-arm64-bits.h"
+#undef RSEQ_TEMPLATE_MO_RELEASE
+#undef RSEQ_TEMPLATE_INDEX_CPU_ID
+
+/* Per-mm-cid indexing. */
+
+#define RSEQ_TEMPLATE_INDEX_MM_CID
+#define RSEQ_TEMPLATE_MO_RELAXED
+#include "rseq-arm64-bits.h"
+#undef RSEQ_TEMPLATE_MO_RELAXED
+
+#define RSEQ_TEMPLATE_MO_RELEASE
+#include "rseq-arm64-bits.h"
+#undef RSEQ_TEMPLATE_MO_RELEASE
+#undef RSEQ_TEMPLATE_INDEX_MM_CID
+
+/* APIs which are not indexed. */
 
-#endif /* !RSEQ_SKIP_FASTPATH */
+#define RSEQ_TEMPLATE_INDEX_NONE
+#define RSEQ_TEMPLATE_MO_RELAXED
+#include "rseq-arm64-bits.h"
+#undef RSEQ_TEMPLATE_MO_RELAXED
+#undef RSEQ_TEMPLATE_INDEX_NONE
This page took 0.038747 seconds and 4 git commands to generate.