linux/include/asm-cris/bitops.h
<<
>>
Prefs
   1/* asm/bitops.h for Linux/CRIS
   2 *
   3 * TODO: asm versions if speed is needed
   4 *
   5 * All bit operations return 0 if the bit was cleared before the
   6 * operation and != 0 if it was not.
   7 *
   8 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
   9 */
  10
  11#ifndef _CRIS_BITOPS_H
  12#define _CRIS_BITOPS_H
  13
  14/* Currently this is unsuitable for consumption outside the kernel.  */
  15#ifdef __KERNEL__ 
  16
  17#ifndef _LINUX_BITOPS_H
  18#error only <linux/bitops.h> can be included directly
  19#endif
  20
  21#include <asm/arch/bitops.h>
  22#include <asm/system.h>
  23#include <asm/atomic.h>
  24#include <linux/compiler.h>
  25
  26/*
  27 * Some hacks to defeat gcc over-optimizations..
  28 */
  29struct __dummy { unsigned long a[100]; };
  30#define ADDR (*(struct __dummy *) addr)
  31#define CONST_ADDR (*(const struct __dummy *) addr)
  32
  33/*
  34 * set_bit - Atomically set a bit in memory
  35 * @nr: the bit to set
  36 * @addr: the address to start counting from
  37 *
  38 * This function is atomic and may not be reordered.  See __set_bit()
  39 * if you do not require the atomic guarantees.
  40 * Note that @nr may be almost arbitrarily large; this function is not
  41 * restricted to acting on a single-word quantity.
  42 */
  43
  44#define set_bit(nr, addr)    (void)test_and_set_bit(nr, addr)
  45
  46/*
  47 * clear_bit - Clears a bit in memory
  48 * @nr: Bit to clear
  49 * @addr: Address to start counting from
  50 *
  51 * clear_bit() is atomic and may not be reordered.  However, it does
  52 * not contain a memory barrier, so if it is used for locking purposes,
  53 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  54 * in order to ensure changes are visible on other processors.
  55 */
  56
  57#define clear_bit(nr, addr)  (void)test_and_clear_bit(nr, addr)
  58
  59/*
  60 * change_bit - Toggle a bit in memory
  61 * @nr: Bit to change
  62 * @addr: Address to start counting from
  63 *
  64 * change_bit() is atomic and may not be reordered.
  65 * Note that @nr may be almost arbitrarily large; this function is not
  66 * restricted to acting on a single-word quantity.
  67 */
  68
  69#define change_bit(nr, addr) (void)test_and_change_bit(nr, addr)
  70
  71/**
  72 * test_and_set_bit - Set a bit and return its old value
  73 * @nr: Bit to set
  74 * @addr: Address to count from
  75 *
  76 * This operation is atomic and cannot be reordered.  
  77 * It also implies a memory barrier.
  78 */
  79
  80static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
  81{
  82        unsigned int mask, retval;
  83        unsigned long flags;
  84        unsigned int *adr = (unsigned int *)addr;
  85        
  86        adr += nr >> 5;
  87        mask = 1 << (nr & 0x1f);
  88        cris_atomic_save(addr, flags);
  89        retval = (mask & *adr) != 0;
  90        *adr |= mask;
  91        cris_atomic_restore(addr, flags);
  92        return retval;
  93}
  94
  95/*
  96 * clear_bit() doesn't provide any barrier for the compiler.
  97 */
  98#define smp_mb__before_clear_bit()      barrier()
  99#define smp_mb__after_clear_bit()       barrier()
 100
 101/**
 102 * test_and_clear_bit - Clear a bit and return its old value
 103 * @nr: Bit to clear
 104 * @addr: Address to count from
 105 *
 106 * This operation is atomic and cannot be reordered.  
 107 * It also implies a memory barrier.
 108 */
 109
 110static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
 111{
 112        unsigned int mask, retval;
 113        unsigned long flags;
 114        unsigned int *adr = (unsigned int *)addr;
 115        
 116        adr += nr >> 5;
 117        mask = 1 << (nr & 0x1f);
 118        cris_atomic_save(addr, flags);
 119        retval = (mask & *adr) != 0;
 120        *adr &= ~mask;
 121        cris_atomic_restore(addr, flags);
 122        return retval;
 123}
 124
 125/**
 126 * test_and_change_bit - Change a bit and return its old value
 127 * @nr: Bit to change
 128 * @addr: Address to count from
 129 *
 130 * This operation is atomic and cannot be reordered.  
 131 * It also implies a memory barrier.
 132 */
 133
 134static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 135{
 136        unsigned int mask, retval;
 137        unsigned long flags;
 138        unsigned int *adr = (unsigned int *)addr;
 139        adr += nr >> 5;
 140        mask = 1 << (nr & 0x1f);
 141        cris_atomic_save(addr, flags);
 142        retval = (mask & *adr) != 0;
 143        *adr ^= mask;
 144        cris_atomic_restore(addr, flags);
 145        return retval;
 146}
 147
 148#include <asm-generic/bitops/non-atomic.h>
 149
 150/*
 151 * Since we define it "external", it collides with the built-in
 152 * definition, which doesn't have the same semantics.  We don't want to
 153 * use -fno-builtin, so just hide the name ffs.
 154 */
 155#define ffs kernel_ffs
 156
 157#include <asm-generic/bitops/fls.h>
 158#include <asm-generic/bitops/fls64.h>
 159#include <asm-generic/bitops/hweight.h>
 160#include <asm-generic/bitops/find.h>
 161#include <asm-generic/bitops/lock.h>
 162
 163#include <asm-generic/bitops/ext2-non-atomic.h>
 164
 165#define ext2_set_bit_atomic(l,n,a)   test_and_set_bit(n,a)
 166#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
 167
 168#include <asm-generic/bitops/minix.h>
 169#include <asm-generic/bitops/sched.h>
 170
 171#endif /* __KERNEL__ */
 172
 173#endif /* _CRIS_BITOPS_H */
 174