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

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. ____atomic_set_bit
  2. ____atomic_clear_bit
  3. ____atomic_change_bit
  4. ____atomic_test_and_set_bit
  5. ____atomic_test_and_clear_bit
  6. ____atomic_test_and_change_bit
  7. find_first_zero_bit_le
  8. find_next_zero_bit_le
  9. find_next_bit_le

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /*
   3  * Copyright 1995, Russell King.
   4  * Various bits and pieces copyrights include:
   5  *  Linus Torvalds (test_bit).
   6  * Big endian support: Copyright 2001, Nicolas Pitre
   7  *  reworked by rmk.
   8  *
   9  * bit 0 is the LSB of an "unsigned long" quantity.
  10  *
  11  * Please note that the code in this file should never be included
  12  * from user space.  Many of these are not implemented in assembler
  13  * since they would be too costly.  Also, they require privileged
  14  * instructions (which are not available from user mode) to ensure
  15  * that they are atomic.
  16  */
  17 
  18 #ifndef __ASM_ARM_BITOPS_H
  19 #define __ASM_ARM_BITOPS_H
  20 
  21 #ifdef __KERNEL__
  22 
  23 #ifndef _LINUX_BITOPS_H
  24 #error only <linux/bitops.h> can be included directly
  25 #endif
  26 
  27 #include <linux/compiler.h>
  28 #include <linux/irqflags.h>
  29 #include <asm/barrier.h>
  30 
  31 /*
  32  * These functions are the basis of our bit ops.
  33  *
  34  * First, the atomic bitops. These use native endian.
  35  */
  36 static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
  37 {
  38         unsigned long flags;
  39         unsigned long mask = BIT_MASK(bit);
  40 
  41         p += BIT_WORD(bit);
  42 
  43         raw_local_irq_save(flags);
  44         *p |= mask;
  45         raw_local_irq_restore(flags);
  46 }
  47 
  48 static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
  49 {
  50         unsigned long flags;
  51         unsigned long mask = BIT_MASK(bit);
  52 
  53         p += BIT_WORD(bit);
  54 
  55         raw_local_irq_save(flags);
  56         *p &= ~mask;
  57         raw_local_irq_restore(flags);
  58 }
  59 
  60 static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
  61 {
  62         unsigned long flags;
  63         unsigned long mask = BIT_MASK(bit);
  64 
  65         p += BIT_WORD(bit);
  66 
  67         raw_local_irq_save(flags);
  68         *p ^= mask;
  69         raw_local_irq_restore(flags);
  70 }
  71 
  72 static inline int
  73 ____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
  74 {
  75         unsigned long flags;
  76         unsigned int res;
  77         unsigned long mask = BIT_MASK(bit);
  78 
  79         p += BIT_WORD(bit);
  80 
  81         raw_local_irq_save(flags);
  82         res = *p;
  83         *p = res | mask;
  84         raw_local_irq_restore(flags);
  85 
  86         return (res & mask) != 0;
  87 }
  88 
  89 static inline int
  90 ____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
  91 {
  92         unsigned long flags;
  93         unsigned int res;
  94         unsigned long mask = BIT_MASK(bit);
  95 
  96         p += BIT_WORD(bit);
  97 
  98         raw_local_irq_save(flags);
  99         res = *p;
 100         *p = res & ~mask;
 101         raw_local_irq_restore(flags);
 102 
 103         return (res & mask) != 0;
 104 }
 105 
 106 static inline int
 107 ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
 108 {
 109         unsigned long flags;
 110         unsigned int res;
 111         unsigned long mask = BIT_MASK(bit);
 112 
 113         p += BIT_WORD(bit);
 114 
 115         raw_local_irq_save(flags);
 116         res = *p;
 117         *p = res ^ mask;
 118         raw_local_irq_restore(flags);
 119 
 120         return (res & mask) != 0;
 121 }
 122 
 123 #include <asm-generic/bitops/non-atomic.h>
 124 
 125 /*
 126  *  A note about Endian-ness.
 127  *  -------------------------
 128  *
 129  * When the ARM is put into big endian mode via CR15, the processor
 130  * merely swaps the order of bytes within words, thus:
 131  *
 132  *          ------------ physical data bus bits -----------
 133  *          D31 ... D24  D23 ... D16  D15 ... D8  D7 ... D0
 134  * little     byte 3       byte 2       byte 1      byte 0
 135  * big        byte 0       byte 1       byte 2      byte 3
 136  *
 137  * This means that reading a 32-bit word at address 0 returns the same
 138  * value irrespective of the endian mode bit.
 139  *
 140  * Peripheral devices should be connected with the data bus reversed in
 141  * "Big Endian" mode.  ARM Application Note 61 is applicable, and is
 142  * available from http://www.arm.com/.
 143  *
 144  * The following assumes that the data bus connectivity for big endian
 145  * mode has been followed.
 146  *
 147  * Note that bit 0 is defined to be 32-bit word bit 0, not byte 0 bit 0.
 148  */
 149 
 150 /*
 151  * Native endian assembly bitops.  nr = 0 -> word 0 bit 0.
 152  */
 153 extern void _set_bit(int nr, volatile unsigned long * p);
 154 extern void _clear_bit(int nr, volatile unsigned long * p);
 155 extern void _change_bit(int nr, volatile unsigned long * p);
 156 extern int _test_and_set_bit(int nr, volatile unsigned long * p);
 157 extern int _test_and_clear_bit(int nr, volatile unsigned long * p);
 158 extern int _test_and_change_bit(int nr, volatile unsigned long * p);
 159 
 160 /*
 161  * Little endian assembly bitops.  nr = 0 -> byte 0 bit 0.
 162  */
 163 extern int _find_first_zero_bit_le(const unsigned long *p, unsigned size);
 164 extern int _find_next_zero_bit_le(const unsigned long *p, int size, int offset);
 165 extern int _find_first_bit_le(const unsigned long *p, unsigned size);
 166 extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
 167 
 168 /*
 169  * Big endian assembly bitops.  nr = 0 -> byte 3 bit 0.
 170  */
 171 extern int _find_first_zero_bit_be(const unsigned long *p, unsigned size);
 172 extern int _find_next_zero_bit_be(const unsigned long *p, int size, int offset);
 173 extern int _find_first_bit_be(const unsigned long *p, unsigned size);
 174 extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
 175 
 176 #ifndef CONFIG_SMP
 177 /*
 178  * The __* form of bitops are non-atomic and may be reordered.
 179  */
 180 #define ATOMIC_BITOP(name,nr,p)                 \
 181         (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
 182 #else
 183 #define ATOMIC_BITOP(name,nr,p)         _##name(nr,p)
 184 #endif
 185 
 186 /*
 187  * Native endian atomic definitions.
 188  */
 189 #define set_bit(nr,p)                   ATOMIC_BITOP(set_bit,nr,p)
 190 #define clear_bit(nr,p)                 ATOMIC_BITOP(clear_bit,nr,p)
 191 #define change_bit(nr,p)                ATOMIC_BITOP(change_bit,nr,p)
 192 #define test_and_set_bit(nr,p)          ATOMIC_BITOP(test_and_set_bit,nr,p)
 193 #define test_and_clear_bit(nr,p)        ATOMIC_BITOP(test_and_clear_bit,nr,p)
 194 #define test_and_change_bit(nr,p)       ATOMIC_BITOP(test_and_change_bit,nr,p)
 195 
 196 #ifndef __ARMEB__
 197 /*
 198  * These are the little endian, atomic definitions.
 199  */
 200 #define find_first_zero_bit(p,sz)       _find_first_zero_bit_le(p,sz)
 201 #define find_next_zero_bit(p,sz,off)    _find_next_zero_bit_le(p,sz,off)
 202 #define find_first_bit(p,sz)            _find_first_bit_le(p,sz)
 203 #define find_next_bit(p,sz,off)         _find_next_bit_le(p,sz,off)
 204 
 205 #else
 206 /*
 207  * These are the big endian, atomic definitions.
 208  */
 209 #define find_first_zero_bit(p,sz)       _find_first_zero_bit_be(p,sz)
 210 #define find_next_zero_bit(p,sz,off)    _find_next_zero_bit_be(p,sz,off)
 211 #define find_first_bit(p,sz)            _find_first_bit_be(p,sz)
 212 #define find_next_bit(p,sz,off)         _find_next_bit_be(p,sz,off)
 213 
 214 #endif
 215 
 216 #if __LINUX_ARM_ARCH__ < 5
 217 
 218 #include <asm-generic/bitops/__fls.h>
 219 #include <asm-generic/bitops/__ffs.h>
 220 #include <asm-generic/bitops/fls.h>
 221 #include <asm-generic/bitops/ffs.h>
 222 
 223 #else
 224 
 225 /*
 226  * On ARMv5 and above, the gcc built-ins may rely on the clz instruction
 227  * and produce optimal inlined code in all cases. On ARMv7 it is even
 228  * better by also using the rbit instruction.
 229  */
 230 #include <asm-generic/bitops/builtin-__fls.h>
 231 #include <asm-generic/bitops/builtin-__ffs.h>
 232 #include <asm-generic/bitops/builtin-fls.h>
 233 #include <asm-generic/bitops/builtin-ffs.h>
 234 
 235 #endif
 236 
 237 #include <asm-generic/bitops/ffz.h>
 238 
 239 #include <asm-generic/bitops/fls64.h>
 240 
 241 #include <asm-generic/bitops/sched.h>
 242 #include <asm-generic/bitops/hweight.h>
 243 #include <asm-generic/bitops/lock.h>
 244 
 245 #ifdef __ARMEB__
 246 
 247 static inline int find_first_zero_bit_le(const void *p, unsigned size)
 248 {
 249         return _find_first_zero_bit_le(p, size);
 250 }
 251 #define find_first_zero_bit_le find_first_zero_bit_le
 252 
 253 static inline int find_next_zero_bit_le(const void *p, int size, int offset)
 254 {
 255         return _find_next_zero_bit_le(p, size, offset);
 256 }
 257 #define find_next_zero_bit_le find_next_zero_bit_le
 258 
 259 static inline int find_next_bit_le(const void *p, int size, int offset)
 260 {
 261         return _find_next_bit_le(p, size, offset);
 262 }
 263 #define find_next_bit_le find_next_bit_le
 264 
 265 #endif
 266 
 267 #include <asm-generic/bitops/find.h>
 268 #include <asm-generic/bitops/le.h>
 269 
 270 /*
 271  * Ext2 is defined to use little-endian byte ordering.
 272  */
 273 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 274 
 275 #endif /* __KERNEL__ */
 276 
 277 #endif /* _ARM_BITOPS_H */

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