bitops.c (3845B)
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/bits.h> 11#include <linux/irqflags.h> 12#include <linux/export.h> 13 14 15/** 16 * __mips_set_bit - Atomically set a bit in memory. This is called by 17 * set_bit() if it cannot find a faster solution. 18 * @nr: the bit to set 19 * @addr: the address to start counting from 20 */ 21void __mips_set_bit(unsigned long nr, volatile unsigned long *addr) 22{ 23 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 24 unsigned int bit = nr % BITS_PER_LONG; 25 unsigned long mask; 26 unsigned long flags; 27 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 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 45 unsigned int bit = nr % BITS_PER_LONG; 46 unsigned long mask; 47 unsigned long flags; 48 49 mask = 1UL << bit; 50 raw_local_irq_save(flags); 51 *a &= ~mask; 52 raw_local_irq_restore(flags); 53} 54EXPORT_SYMBOL(__mips_clear_bit); 55 56 57/** 58 * __mips_change_bit - Toggle a bit in memory. This is called by change_bit() 59 * if it cannot find a faster solution. 60 * @nr: Bit to change 61 * @addr: Address to start counting from 62 */ 63void __mips_change_bit(unsigned long nr, volatile unsigned long *addr) 64{ 65 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 66 unsigned int bit = nr % BITS_PER_LONG; 67 unsigned long mask; 68 unsigned long flags; 69 70 mask = 1UL << bit; 71 raw_local_irq_save(flags); 72 *a ^= mask; 73 raw_local_irq_restore(flags); 74} 75EXPORT_SYMBOL(__mips_change_bit); 76 77 78/** 79 * __mips_test_and_set_bit_lock - Set a bit and return its old value. This is 80 * called by test_and_set_bit_lock() if it cannot find a faster solution. 81 * @nr: Bit to set 82 * @addr: Address to count from 83 */ 84int __mips_test_and_set_bit_lock(unsigned long nr, 85 volatile unsigned long *addr) 86{ 87 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 88 unsigned int bit = nr % BITS_PER_LONG; 89 unsigned long mask; 90 unsigned long flags; 91 int res; 92 93 mask = 1UL << bit; 94 raw_local_irq_save(flags); 95 res = (mask & *a) != 0; 96 *a |= mask; 97 raw_local_irq_restore(flags); 98 return res; 99} 100EXPORT_SYMBOL(__mips_test_and_set_bit_lock); 101 102 103/** 104 * __mips_test_and_clear_bit - Clear a bit and return its old value. This is 105 * called by test_and_clear_bit() if it cannot find a faster solution. 106 * @nr: Bit to clear 107 * @addr: Address to count from 108 */ 109int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) 110{ 111 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 112 unsigned int bit = nr % BITS_PER_LONG; 113 unsigned long mask; 114 unsigned long flags; 115 int res; 116 117 mask = 1UL << bit; 118 raw_local_irq_save(flags); 119 res = (mask & *a) != 0; 120 *a &= ~mask; 121 raw_local_irq_restore(flags); 122 return res; 123} 124EXPORT_SYMBOL(__mips_test_and_clear_bit); 125 126 127/** 128 * __mips_test_and_change_bit - Change a bit and return its old value. This is 129 * called by test_and_change_bit() if it cannot find a faster solution. 130 * @nr: Bit to change 131 * @addr: Address to count from 132 */ 133int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr) 134{ 135 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 136 unsigned int bit = nr % BITS_PER_LONG; 137 unsigned long mask; 138 unsigned long flags; 139 int res; 140 141 mask = 1UL << bit; 142 raw_local_irq_save(flags); 143 res = (mask & *a) != 0; 144 *a ^= mask; 145 raw_local_irq_restore(flags); 146 return res; 147} 148EXPORT_SYMBOL(__mips_test_and_change_bit);