linux/arch/mips/lib/bitops.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (c) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org)
   7 * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
   8 */
   9#include <linux/bitops.h>
  10#include <linux/irqflags.h>
  11#include <linux/export.h>
  12
  13
  14/**
  15 * __mips_set_bit - Atomically set a bit in memory.  This is called by
  16 * set_bit() if it cannot find a faster solution.
  17 * @nr: the bit to set
  18 * @addr: the address to start counting from
  19 */
  20void __mips_set_bit(unsigned long nr, volatile unsigned long *addr)
  21{
  22        unsigned long *a = (unsigned long *)addr;
  23        unsigned bit = nr & SZLONG_MASK;
  24        unsigned long mask;
  25        unsigned long flags;
  26
  27        a += nr >> SZLONG_LOG;
  28        mask = 1UL << bit;
  29        raw_local_irq_save(flags);
  30        *a |= mask;
  31        raw_local_irq_restore(flags);
  32}
  33EXPORT_SYMBOL(__mips_set_bit);
  34
  35
  36/**
  37 * __mips_clear_bit - Clears a bit in memory.  This is called by clear_bit() if
  38 * it cannot find a faster solution.
  39 * @nr: Bit to clear
  40 * @addr: Address to start counting from
  41 */
  42void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr)
  43{
  44        unsigned long *a = (unsigned long *)addr;
  45        unsigned bit = nr & SZLONG_MASK;
  46        unsigned long mask;
  47        unsigned long flags;
  48
  49        a += nr >> SZLONG_LOG;
  50        mask = 1UL << bit;
  51        raw_local_irq_save(flags);
  52        *a &= ~mask;
  53        raw_local_irq_restore(flags);
  54}
  55EXPORT_SYMBOL(__mips_clear_bit);
  56
  57
  58/**
  59 * __mips_change_bit - Toggle a bit in memory.  This is called by change_bit()
  60 * if it cannot find a faster solution.
  61 * @nr: Bit to change
  62 * @addr: Address to start counting from
  63 */
  64void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
  65{
  66        unsigned long *a = (unsigned long *)addr;
  67        unsigned bit = nr & SZLONG_MASK;
  68        unsigned long mask;
  69        unsigned long flags;
  70
  71        a += nr >> SZLONG_LOG;
  72        mask = 1UL << bit;
  73        raw_local_irq_save(flags);
  74        *a ^= mask;
  75        raw_local_irq_restore(flags);
  76}
  77EXPORT_SYMBOL(__mips_change_bit);
  78
  79
  80/**
  81 * __mips_test_and_set_bit - Set a bit and return its old value.  This is
  82 * called by test_and_set_bit() if it cannot find a faster solution.
  83 * @nr: Bit to set
  84 * @addr: Address to count from
  85 */
  86int __mips_test_and_set_bit(unsigned long nr,
  87                            volatile unsigned long *addr)
  88{
  89        unsigned long *a = (unsigned long *)addr;
  90        unsigned bit = nr & SZLONG_MASK;
  91        unsigned long mask;
  92        unsigned long flags;
  93        int res;
  94
  95        a += nr >> SZLONG_LOG;
  96        mask = 1UL << bit;
  97        raw_local_irq_save(flags);
  98        res = (mask & *a) != 0;
  99        *a |= mask;
 100        raw_local_irq_restore(flags);
 101        return res;
 102}
 103EXPORT_SYMBOL(__mips_test_and_set_bit);
 104
 105
 106/**
 107 * __mips_test_and_set_bit_lock - Set a bit and return its old value.  This is
 108 * called by test_and_set_bit_lock() if it cannot find a faster solution.
 109 * @nr: Bit to set
 110 * @addr: Address to count from
 111 */
 112int __mips_test_and_set_bit_lock(unsigned long nr,
 113                                 volatile unsigned long *addr)
 114{
 115        unsigned long *a = (unsigned long *)addr;
 116        unsigned bit = nr & SZLONG_MASK;
 117        unsigned long mask;
 118        unsigned long flags;
 119        int res;
 120
 121        a += nr >> SZLONG_LOG;
 122        mask = 1UL << bit;
 123        raw_local_irq_save(flags);
 124        res = (mask & *a) != 0;
 125        *a |= mask;
 126        raw_local_irq_restore(flags);
 127        return res;
 128}
 129EXPORT_SYMBOL(__mips_test_and_set_bit_lock);
 130
 131
 132/**
 133 * __mips_test_and_clear_bit - Clear a bit and return its old value.  This is
 134 * called by test_and_clear_bit() if it cannot find a faster solution.
 135 * @nr: Bit to clear
 136 * @addr: Address to count from
 137 */
 138int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
 139{
 140        unsigned long *a = (unsigned long *)addr;
 141        unsigned bit = nr & SZLONG_MASK;
 142        unsigned long mask;
 143        unsigned long flags;
 144        int res;
 145
 146        a += nr >> SZLONG_LOG;
 147        mask = 1UL << bit;
 148        raw_local_irq_save(flags);
 149        res = (mask & *a) != 0;
 150        *a &= ~mask;
 151        raw_local_irq_restore(flags);
 152        return res;
 153}
 154EXPORT_SYMBOL(__mips_test_and_clear_bit);
 155
 156
 157/**
 158 * __mips_test_and_change_bit - Change a bit and return its old value.  This is
 159 * called by test_and_change_bit() if it cannot find a faster solution.
 160 * @nr: Bit to change
 161 * @addr: Address to count from
 162 */
 163int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
 164{
 165        unsigned long *a = (unsigned long *)addr;
 166        unsigned bit = nr & SZLONG_MASK;
 167        unsigned long mask;
 168        unsigned long flags;
 169        int res;
 170
 171        a += nr >> SZLONG_LOG;
 172        mask = 1UL << bit;
 173        raw_local_irq_save(flags);
 174        res = (mask & *a) != 0;
 175        *a ^= mask;
 176        raw_local_irq_restore(flags);
 177        return res;
 178}
 179EXPORT_SYMBOL(__mips_test_and_change_bit);
 180