root/arch/riscv/include/asm/bitops.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. test_and_set_bit
  2. test_and_clear_bit
  3. test_and_change_bit
  4. set_bit
  5. clear_bit
  6. change_bit
  7. test_and_set_bit_lock
  8. clear_bit_unlock
  9. __clear_bit_unlock

   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * Copyright (C) 2012 Regents of the University of California
   4  */
   5 
   6 #ifndef _ASM_RISCV_BITOPS_H
   7 #define _ASM_RISCV_BITOPS_H
   8 
   9 #ifndef _LINUX_BITOPS_H
  10 #error "Only <linux/bitops.h> can be included directly"
  11 #endif /* _LINUX_BITOPS_H */
  12 
  13 #include <linux/compiler.h>
  14 #include <linux/irqflags.h>
  15 #include <asm/barrier.h>
  16 #include <asm/bitsperlong.h>
  17 
  18 #include <asm-generic/bitops/__ffs.h>
  19 #include <asm-generic/bitops/ffz.h>
  20 #include <asm-generic/bitops/fls.h>
  21 #include <asm-generic/bitops/__fls.h>
  22 #include <asm-generic/bitops/fls64.h>
  23 #include <asm-generic/bitops/find.h>
  24 #include <asm-generic/bitops/sched.h>
  25 #include <asm-generic/bitops/ffs.h>
  26 
  27 #include <asm-generic/bitops/hweight.h>
  28 
  29 #if (BITS_PER_LONG == 64)
  30 #define __AMO(op)       "amo" #op ".d"
  31 #elif (BITS_PER_LONG == 32)
  32 #define __AMO(op)       "amo" #op ".w"
  33 #else
  34 #error "Unexpected BITS_PER_LONG"
  35 #endif
  36 
  37 #define __test_and_op_bit_ord(op, mod, nr, addr, ord)           \
  38 ({                                                              \
  39         unsigned long __res, __mask;                            \
  40         __mask = BIT_MASK(nr);                                  \
  41         __asm__ __volatile__ (                                  \
  42                 __AMO(op) #ord " %0, %2, %1"                    \
  43                 : "=r" (__res), "+A" (addr[BIT_WORD(nr)])       \
  44                 : "r" (mod(__mask))                             \
  45                 : "memory");                                    \
  46         ((__res & __mask) != 0);                                \
  47 })
  48 
  49 #define __op_bit_ord(op, mod, nr, addr, ord)                    \
  50         __asm__ __volatile__ (                                  \
  51                 __AMO(op) #ord " zero, %1, %0"                  \
  52                 : "+A" (addr[BIT_WORD(nr)])                     \
  53                 : "r" (mod(BIT_MASK(nr)))                       \
  54                 : "memory");
  55 
  56 #define __test_and_op_bit(op, mod, nr, addr)                    \
  57         __test_and_op_bit_ord(op, mod, nr, addr, .aqrl)
  58 #define __op_bit(op, mod, nr, addr)                             \
  59         __op_bit_ord(op, mod, nr, addr, )
  60 
  61 /* Bitmask modifiers */
  62 #define __NOP(x)        (x)
  63 #define __NOT(x)        (~(x))
  64 
  65 /**
  66  * test_and_set_bit - Set a bit and return its old value
  67  * @nr: Bit to set
  68  * @addr: Address to count from
  69  *
  70  * This operation may be reordered on other architectures than x86.
  71  */
  72 static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
  73 {
  74         return __test_and_op_bit(or, __NOP, nr, addr);
  75 }
  76 
  77 /**
  78  * test_and_clear_bit - Clear a bit and return its old value
  79  * @nr: Bit to clear
  80  * @addr: Address to count from
  81  *
  82  * This operation can be reordered on other architectures other than x86.
  83  */
  84 static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
  85 {
  86         return __test_and_op_bit(and, __NOT, nr, addr);
  87 }
  88 
  89 /**
  90  * test_and_change_bit - Change a bit and return its old value
  91  * @nr: Bit to change
  92  * @addr: Address to count from
  93  *
  94  * This operation is atomic and cannot be reordered.
  95  * It also implies a memory barrier.
  96  */
  97 static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
  98 {
  99         return __test_and_op_bit(xor, __NOP, nr, addr);
 100 }
 101 
 102 /**
 103  * set_bit - Atomically set a bit in memory
 104  * @nr: the bit to set
 105  * @addr: the address to start counting from
 106  *
 107  * Note: there are no guarantees that this function will not be reordered
 108  * on non x86 architectures, so if you are writing portable code,
 109  * make sure not to rely on its reordering guarantees.
 110  *
 111  * Note that @nr may be almost arbitrarily large; this function is not
 112  * restricted to acting on a single-word quantity.
 113  */
 114 static inline void set_bit(int nr, volatile unsigned long *addr)
 115 {
 116         __op_bit(or, __NOP, nr, addr);
 117 }
 118 
 119 /**
 120  * clear_bit - Clears a bit in memory
 121  * @nr: Bit to clear
 122  * @addr: Address to start counting from
 123  *
 124  * Note: there are no guarantees that this function will not be reordered
 125  * on non x86 architectures, so if you are writing portable code,
 126  * make sure not to rely on its reordering guarantees.
 127  */
 128 static inline void clear_bit(int nr, volatile unsigned long *addr)
 129 {
 130         __op_bit(and, __NOT, nr, addr);
 131 }
 132 
 133 /**
 134  * change_bit - Toggle a bit in memory
 135  * @nr: Bit to change
 136  * @addr: Address to start counting from
 137  *
 138  * change_bit()  may be reordered on other architectures than x86.
 139  * Note that @nr may be almost arbitrarily large; this function is not
 140  * restricted to acting on a single-word quantity.
 141  */
 142 static inline void change_bit(int nr, volatile unsigned long *addr)
 143 {
 144         __op_bit(xor, __NOP, nr, addr);
 145 }
 146 
 147 /**
 148  * test_and_set_bit_lock - Set a bit and return its old value, for lock
 149  * @nr: Bit to set
 150  * @addr: Address to count from
 151  *
 152  * This operation is atomic and provides acquire barrier semantics.
 153  * It can be used to implement bit locks.
 154  */
 155 static inline int test_and_set_bit_lock(
 156         unsigned long nr, volatile unsigned long *addr)
 157 {
 158         return __test_and_op_bit_ord(or, __NOP, nr, addr, .aq);
 159 }
 160 
 161 /**
 162  * clear_bit_unlock - Clear a bit in memory, for unlock
 163  * @nr: the bit to set
 164  * @addr: the address to start counting from
 165  *
 166  * This operation is atomic and provides release barrier semantics.
 167  */
 168 static inline void clear_bit_unlock(
 169         unsigned long nr, volatile unsigned long *addr)
 170 {
 171         __op_bit_ord(and, __NOT, nr, addr, .rl);
 172 }
 173 
 174 /**
 175  * __clear_bit_unlock - Clear a bit in memory, for unlock
 176  * @nr: the bit to set
 177  * @addr: the address to start counting from
 178  *
 179  * This operation is like clear_bit_unlock, however it is not atomic.
 180  * It does provide release barrier semantics so it can be used to unlock
 181  * a bit lock, however it would only be used if no other CPU can modify
 182  * any bits in the memory until the lock is released (a good example is
 183  * if the bit lock itself protects access to the other bits in the word).
 184  *
 185  * On RISC-V systems there seems to be no benefit to taking advantage of the
 186  * non-atomic property here: it's a lot more instructions and we still have to
 187  * provide release semantics anyway.
 188  */
 189 static inline void __clear_bit_unlock(
 190         unsigned long nr, volatile unsigned long *addr)
 191 {
 192         clear_bit_unlock(nr, addr);
 193 }
 194 
 195 #undef __test_and_op_bit
 196 #undef __op_bit
 197 #undef __NOP
 198 #undef __NOT
 199 #undef __AMO
 200 
 201 #include <asm-generic/bitops/non-atomic.h>
 202 #include <asm-generic/bitops/le.h>
 203 #include <asm-generic/bitops/ext2-atomic.h>
 204 
 205 #endif /* _ASM_RISCV_BITOPS_H */

/* [<][>][^][v][top][bottom][index][help] */