bitops.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 ([email protected])
  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. * __mips_set_bit - Atomically set a bit in memory. This is called by
  15. * set_bit() if it cannot find a faster solution.
  16. * @nr: the bit to set
  17. * @addr: the address to start counting from
  18. */
  19. void __mips_set_bit(unsigned long nr, volatile unsigned long *addr)
  20. {
  21. volatile unsigned long *a = &addr[BIT_WORD(nr)];
  22. unsigned int bit = nr % BITS_PER_LONG;
  23. unsigned long mask;
  24. unsigned long flags;
  25. mask = 1UL << bit;
  26. raw_local_irq_save(flags);
  27. *a |= mask;
  28. raw_local_irq_restore(flags);
  29. }
  30. EXPORT_SYMBOL(__mips_set_bit);
  31. /**
  32. * __mips_clear_bit - Clears a bit in memory. This is called by clear_bit() if
  33. * it cannot find a faster solution.
  34. * @nr: Bit to clear
  35. * @addr: Address to start counting from
  36. */
  37. void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr)
  38. {
  39. volatile unsigned long *a = &addr[BIT_WORD(nr)];
  40. unsigned int bit = nr % BITS_PER_LONG;
  41. unsigned long mask;
  42. unsigned long flags;
  43. mask = 1UL << bit;
  44. raw_local_irq_save(flags);
  45. *a &= ~mask;
  46. raw_local_irq_restore(flags);
  47. }
  48. EXPORT_SYMBOL(__mips_clear_bit);
  49. /**
  50. * __mips_change_bit - Toggle a bit in memory. This is called by change_bit()
  51. * if it cannot find a faster solution.
  52. * @nr: Bit to change
  53. * @addr: Address to start counting from
  54. */
  55. void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
  56. {
  57. volatile unsigned long *a = &addr[BIT_WORD(nr)];
  58. unsigned int bit = nr % BITS_PER_LONG;
  59. unsigned long mask;
  60. unsigned long flags;
  61. mask = 1UL << bit;
  62. raw_local_irq_save(flags);
  63. *a ^= mask;
  64. raw_local_irq_restore(flags);
  65. }
  66. EXPORT_SYMBOL(__mips_change_bit);
  67. /**
  68. * __mips_test_and_set_bit_lock - Set a bit and return its old value. This is
  69. * called by test_and_set_bit_lock() if it cannot find a faster solution.
  70. * @nr: Bit to set
  71. * @addr: Address to count from
  72. */
  73. int __mips_test_and_set_bit_lock(unsigned long nr,
  74. volatile unsigned long *addr)
  75. {
  76. volatile unsigned long *a = &addr[BIT_WORD(nr)];
  77. unsigned int bit = nr % BITS_PER_LONG;
  78. unsigned long mask;
  79. unsigned long flags;
  80. int res;
  81. mask = 1UL << bit;
  82. raw_local_irq_save(flags);
  83. res = (mask & *a) != 0;
  84. *a |= mask;
  85. raw_local_irq_restore(flags);
  86. return res;
  87. }
  88. EXPORT_SYMBOL(__mips_test_and_set_bit_lock);
  89. /**
  90. * __mips_test_and_clear_bit - Clear a bit and return its old value. This is
  91. * called by test_and_clear_bit() if it cannot find a faster solution.
  92. * @nr: Bit to clear
  93. * @addr: Address to count from
  94. */
  95. int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
  96. {
  97. volatile unsigned long *a = &addr[BIT_WORD(nr)];
  98. unsigned int bit = nr % BITS_PER_LONG;
  99. unsigned long mask;
  100. unsigned long flags;
  101. int res;
  102. mask = 1UL << bit;
  103. raw_local_irq_save(flags);
  104. res = (mask & *a) != 0;
  105. *a &= ~mask;
  106. raw_local_irq_restore(flags);
  107. return res;
  108. }
  109. EXPORT_SYMBOL(__mips_test_and_clear_bit);
  110. /**
  111. * __mips_test_and_change_bit - Change a bit and return its old value. This is
  112. * called by test_and_change_bit() if it cannot find a faster solution.
  113. * @nr: Bit to change
  114. * @addr: Address to count from
  115. */
  116. int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
  117. {
  118. volatile unsigned long *a = &addr[BIT_WORD(nr)];
  119. unsigned int bit = nr % BITS_PER_LONG;
  120. unsigned long mask;
  121. unsigned long flags;
  122. int res;
  123. mask = 1UL << bit;
  124. raw_local_irq_save(flags);
  125. res = (mask & *a) != 0;
  126. *a ^= mask;
  127. raw_local_irq_restore(flags);
  128. return res;
  129. }
  130. EXPORT_SYMBOL(__mips_test_and_change_bit);