bitops.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #ifndef _PARISC_BITOPS_H
  2. #define _PARISC_BITOPS_H
  3. #include <linux/spinlock.h>
  4. #include <asm/system.h>
  5. #include <asm/byteorder.h>
  6. #include <asm/atomic.h>
  7. #ifdef __LP64__
  8. #   define SHIFT_PER_LONG 6
  9. #ifndef BITS_PER_LONG
  10. #   define BITS_PER_LONG 64
  11. #endif
  12. #else
  13. #   define SHIFT_PER_LONG 5
  14. #ifndef BITS_PER_LONG
  15. #   define BITS_PER_LONG 32
  16. #endif
  17. #endif
  18. #define CHOP_SHIFTCOUNT(x) ((x) & (BITS_PER_LONG - 1))
  19. static __inline__ int test_and_set_bit(int nr, void * address)
  20. {
  21. unsigned long mask;
  22. unsigned long *addr = (unsigned long *) address;
  23. int oldbit;
  24. unsigned long flags;
  25. addr += (nr >> SHIFT_PER_LONG);
  26. SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
  27. mask = 1L << CHOP_SHIFTCOUNT(nr);
  28. oldbit = (*addr & mask) ? 1 : 0;
  29. *addr |= mask;
  30. SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
  31. return oldbit;
  32. }
  33. static __inline__ int test_and_clear_bit(int nr, void * address)
  34. {
  35. unsigned long mask;
  36. unsigned long *addr = (unsigned long *) address;
  37. int oldbit;
  38. unsigned long flags;
  39. addr += (nr >> SHIFT_PER_LONG);
  40. SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
  41. mask = 1L << CHOP_SHIFTCOUNT(nr);
  42. oldbit = (*addr & mask) ? 1 : 0;
  43. *addr &= ~mask;
  44. SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
  45. return oldbit;
  46. }
  47. static __inline__ int test_and_change_bit(int nr, void * address)
  48. {
  49. unsigned long mask;
  50. unsigned long *addr = (unsigned long *) address;
  51. int oldbit;
  52. unsigned long flags;
  53. addr += (nr >> SHIFT_PER_LONG);
  54. SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
  55. mask = 1L << CHOP_SHIFTCOUNT(nr);
  56. oldbit = (*addr & mask) ? 1 : 0;
  57. *addr ^= mask;
  58. SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
  59. return oldbit;
  60. }
  61. /* again, the read-only case doesn't have to do any locking */
  62. static __inline__ int test_bit(int nr, const volatile void *address)
  63. {
  64. unsigned long mask;
  65. unsigned long *addr = (unsigned long *) address;
  66. addr += (nr >> SHIFT_PER_LONG);
  67. mask = 1L << CHOP_SHIFTCOUNT(nr);
  68. return !!(*addr & mask);
  69. }
  70. /* sparc does this, other arch's don't -- what's the right answer? XXX */
  71. #define smp_mb__before_clear_bit() do { } while(0)
  72. #define smp_mb__after_clear_bit() do { } while(0)
  73. #define set_bit(nr,addr) ((void)test_and_set_bit(nr,addr))
  74. #define clear_bit(nr,addr) ((void)test_and_clear_bit(nr,addr))
  75. #define change_bit(nr,addr) ((void)test_and_change_bit(nr,addr))
  76. /* XXX We'd need some binary search here */
  77. extern __inline__ unsigned long ffz(unsigned long word)
  78. {
  79. unsigned long result;
  80. result = 0;
  81. while(word & 1) {
  82. result++;
  83. word >>= 1;
  84. }
  85. return result;
  86. }
  87. #ifdef __KERNEL__
  88. /*
  89.  * ffs: find first bit set. This is defined the same way as
  90.  * the libc and compiler builtin ffs routines, therefore
  91.  * differs in spirit from the above ffz (man ffs).
  92.  */
  93. #define ffs(x) generic_ffs(x)
  94. /*
  95.  * hweightN: returns the hamming weight (i.e. the number
  96.  * of bits set) of a N-bit word
  97.  */
  98. #define hweight32(x) generic_hweight32(x)
  99. #define hweight16(x) generic_hweight16(x)
  100. #define hweight8(x) generic_hweight8(x)
  101. #endif /* __KERNEL__ */
  102. /*
  103.  * This implementation of find_{first,next}_zero_bit was stolen from
  104.  * Linus' asm-alpha/bitops.h.
  105.  */
  106. #define find_first_zero_bit(addr, size) 
  107. find_next_zero_bit((addr), (size), 0)
  108. static __inline__ unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
  109. {
  110. unsigned long * p = ((unsigned long *) addr) + (offset >> SHIFT_PER_LONG);
  111. unsigned long result = offset & ~(BITS_PER_LONG-1);
  112. unsigned long tmp;
  113. if (offset >= size)
  114. return size;
  115. size -= result;
  116. offset &= (BITS_PER_LONG-1);
  117. if (offset) {
  118. tmp = *(p++);
  119. tmp |= ~0UL >> (BITS_PER_LONG-offset);
  120. if (size < BITS_PER_LONG)
  121. goto found_first;
  122. if (~tmp)
  123. goto found_middle;
  124. size -= BITS_PER_LONG;
  125. result += BITS_PER_LONG;
  126. }
  127. while (size & ~(BITS_PER_LONG -1)) {
  128. if (~(tmp = *(p++)))
  129. goto found_middle;
  130. result += BITS_PER_LONG;
  131. size -= BITS_PER_LONG;
  132. }
  133. if (!size)
  134. return result;
  135. tmp = *p;
  136. found_first:
  137. tmp |= ~0UL << size;
  138. found_middle:
  139. return result + ffz(tmp);
  140. }
  141. #define _EXT2_HAVE_ASM_BITOPS_
  142. #ifdef __KERNEL__
  143. /*
  144.  * test_and_{set,clear}_bit guarantee atomicity without
  145.  * disabling interrupts.
  146.  */
  147. #define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr)
  148. #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr)
  149. #endif /* __KERNEL__ */
  150. static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
  151. {
  152. __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
  153. return (ADDR[nr >> 3] >> (nr & 7)) & 1;
  154. }
  155. /*
  156.  * This implementation of ext2_find_{first,next}_zero_bit was stolen from
  157.  * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
  158.  */
  159. #define ext2_find_first_zero_bit(addr, size) 
  160.         ext2_find_next_zero_bit((addr), (size), 0)
  161. extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
  162. unsigned long size, unsigned long offset)
  163. {
  164. unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
  165. unsigned int result = offset & ~31UL;
  166. unsigned int tmp;
  167. if (offset >= size)
  168. return size;
  169. size -= result;
  170. offset &= 31UL;
  171. if (offset) {
  172. tmp = cpu_to_le32p(p++);
  173. tmp |= ~0UL >> (32-offset);
  174. if (size < 32)
  175. goto found_first;
  176. if (tmp != ~0U)
  177. goto found_middle;
  178. size -= 32;
  179. result += 32;
  180. }
  181. while (size >= 32) {
  182. if ((tmp = cpu_to_le32p(p++)) != ~0U)
  183. goto found_middle;
  184. result += 32;
  185. size -= 32;
  186. }
  187. if (!size)
  188. return result;
  189. tmp = cpu_to_le32p(p);
  190. found_first:
  191. tmp |= ~0U << size;
  192. found_middle:
  193. return result + ffz(tmp);
  194. }
  195. /* Bitmap functions for the minix filesystem.  */
  196. #define minix_set_bit(nr,addr) ext2_set_bit(nr,addr)
  197. #define minix_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
  198. #define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
  199. #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
  200. #endif /* _PARISC_BITOPS_H */