linux/arch/arc/include/asm/atomic-llsc.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2
   3#ifndef _ASM_ARC_ATOMIC_LLSC_H
   4#define _ASM_ARC_ATOMIC_LLSC_H
   5
   6#define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
   7
   8#define ATOMIC_OP(op, c_op, asm_op)                                     \
   9static inline void arch_atomic_##op(int i, atomic_t *v)                 \
  10{                                                                       \
  11        unsigned int val;                                               \
  12                                                                        \
  13        __asm__ __volatile__(                                           \
  14        "1:     llock   %[val], [%[ctr]]                \n"             \
  15        "       " #asm_op " %[val], %[val], %[i]        \n"             \
  16        "       scond   %[val], [%[ctr]]                \n"             \
  17        "       bnz     1b                              \n"             \
  18        : [val] "=&r"   (val) /* Early clobber to prevent reg reuse */  \
  19        : [ctr] "r"     (&v->counter), /* Not "m": llock only supports reg direct addr mode */  \
  20          [i]   "ir"    (i)                                             \
  21        : "cc");                                                        \
  22}                                                                       \
  23
  24#define ATOMIC_OP_RETURN(op, c_op, asm_op)                              \
  25static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \
  26{                                                                       \
  27        unsigned int val;                                               \
  28                                                                        \
  29        __asm__ __volatile__(                                           \
  30        "1:     llock   %[val], [%[ctr]]                \n"             \
  31        "       " #asm_op " %[val], %[val], %[i]        \n"             \
  32        "       scond   %[val], [%[ctr]]                \n"             \
  33        "       bnz     1b                              \n"             \
  34        : [val] "=&r"   (val)                                           \
  35        : [ctr] "r"     (&v->counter),                                  \
  36          [i]   "ir"    (i)                                             \
  37        : "cc");                                                        \
  38                                                                        \
  39        return val;                                                     \
  40}
  41
  42#define arch_atomic_add_return_relaxed          arch_atomic_add_return_relaxed
  43#define arch_atomic_sub_return_relaxed          arch_atomic_sub_return_relaxed
  44
  45#define ATOMIC_FETCH_OP(op, c_op, asm_op)                               \
  46static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v)  \
  47{                                                                       \
  48        unsigned int val, orig;                                         \
  49                                                                        \
  50        __asm__ __volatile__(                                           \
  51        "1:     llock   %[orig], [%[ctr]]               \n"             \
  52        "       " #asm_op " %[val], %[orig], %[i]       \n"             \
  53        "       scond   %[val], [%[ctr]]                \n"             \
  54        "       bnz     1b                              \n"             \
  55        : [val] "=&r"   (val),                                          \
  56          [orig] "=&r" (orig)                                           \
  57        : [ctr] "r"     (&v->counter),                                  \
  58          [i]   "ir"    (i)                                             \
  59        : "cc");                                                        \
  60                                                                        \
  61        return orig;                                                    \
  62}
  63
  64#define arch_atomic_fetch_add_relaxed           arch_atomic_fetch_add_relaxed
  65#define arch_atomic_fetch_sub_relaxed           arch_atomic_fetch_sub_relaxed
  66
  67#define arch_atomic_fetch_and_relaxed           arch_atomic_fetch_and_relaxed
  68#define arch_atomic_fetch_andnot_relaxed        arch_atomic_fetch_andnot_relaxed
  69#define arch_atomic_fetch_or_relaxed            arch_atomic_fetch_or_relaxed
  70#define arch_atomic_fetch_xor_relaxed           arch_atomic_fetch_xor_relaxed
  71
  72#define ATOMIC_OPS(op, c_op, asm_op)                                    \
  73        ATOMIC_OP(op, c_op, asm_op)                                     \
  74        ATOMIC_OP_RETURN(op, c_op, asm_op)                              \
  75        ATOMIC_FETCH_OP(op, c_op, asm_op)
  76
  77ATOMIC_OPS(add, +=, add)
  78ATOMIC_OPS(sub, -=, sub)
  79
  80#undef ATOMIC_OPS
  81#define ATOMIC_OPS(op, c_op, asm_op)                                    \
  82        ATOMIC_OP(op, c_op, asm_op)                                     \
  83        ATOMIC_FETCH_OP(op, c_op, asm_op)
  84
  85ATOMIC_OPS(and, &=, and)
  86ATOMIC_OPS(andnot, &= ~, bic)
  87ATOMIC_OPS(or, |=, or)
  88ATOMIC_OPS(xor, ^=, xor)
  89
  90#define arch_atomic_andnot              arch_atomic_andnot
  91
  92#undef ATOMIC_OPS
  93#undef ATOMIC_FETCH_OP
  94#undef ATOMIC_OP_RETURN
  95#undef ATOMIC_OP
  96
  97#endif
  98