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

嵌入式Linux

开发平台:

Unix_Linux

  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, 95, 96, 97, 98, 99, 2000  Ralf Baechle
  7.  * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
  8.  */
  9. #ifndef _ASM_BITOPS_H
  10. #define _ASM_BITOPS_H
  11. #include <linux/types.h>
  12. #include <linux/byteorder/swab.h> /* sigh ... */
  13. #ifndef __KERNEL__
  14. #error "Don't do this, sucker ..."
  15. #endif
  16. #include <asm/system.h>
  17. #include <asm/sgidefs.h>
  18. #include <asm/mipsregs.h>
  19. /*
  20.  * set_bit - Atomically set a bit in memory
  21.  * @nr: the bit to set
  22.  * @addr: the address to start counting from
  23.  *
  24.  * This function is atomic and may not be reordered.  See __set_bit()
  25.  * if you do not require the atomic guarantees.
  26.  * Note that @nr may be almost arbitrarily large; this function is not
  27.  * restricted to acting on a single-word quantity.
  28.  */
  29. extern __inline__ void
  30. set_bit(unsigned long nr, volatile void *addr)
  31. {
  32. unsigned long *m = ((unsigned long *) addr) + (nr >> 6);
  33. unsigned long temp;
  34. __asm__ __volatile__(
  35. "1:tlldt%0, %1tt# set_bitnt"
  36. "ort%0, %2nt"
  37. "scdt%0, %1nt"
  38. "beqzt%0, 1b"
  39. : "=&r" (temp), "=m" (*m)
  40. : "ir" (1UL << (nr & 0x3f)), "m" (*m)
  41. : "memory");
  42. }
  43. /*
  44.  * __set_bit - Set a bit in memory
  45.  * @nr: the bit to set
  46.  * @addr: the address to start counting from
  47.  *
  48.  * Unlike set_bit(), this function is non-atomic and may be reordered.
  49.  * If it's called on the same region of memory simultaneously, the effect
  50.  * may be that only one operation succeeds.
  51.  */
  52. extern __inline__ void __set_bit(int nr, volatile void * addr)
  53. {
  54. unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  55. *m |= 1UL << (nr & 0x3f);
  56. }
  57. /*
  58.  * clear_bit - Clears a bit in memory
  59.  * @nr: Bit to clear
  60.  * @addr: Address to start counting from
  61.  *
  62.  * clear_bit() is atomic and may not be reordered.  However, it does
  63.  * not contain a memory barrier, so if it is used for locking purposes,
  64.  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  65.  * in order to ensure changes are visible on other processors.
  66.  */
  67. extern __inline__ void
  68. clear_bit(unsigned long nr, volatile void *addr)
  69. {
  70. unsigned long *m = ((unsigned long *) addr) + (nr >> 6);
  71. unsigned long temp;
  72. __asm__ __volatile__(
  73. "1:tlldt%0, %1tt# clear_bitnt"
  74. "andt%0, %2nt"
  75. "scdt%0, %1nt"
  76. "beqzt%0, 1bnt"
  77. : "=&r" (temp), "=m" (*m)
  78. : "ir" (~(1UL << (nr & 0x3f))), "m" (*m));
  79. }
  80. #define smp_mb__before_clear_bit() barrier()
  81. #define smp_mb__after_clear_bit() barrier()
  82. /*
  83.  * change_bit - Toggle a bit in memory
  84.  * @nr: Bit to clear
  85.  * @addr: Address to start counting from
  86.  *
  87.  * change_bit() is atomic and may not be reordered.
  88.  * Note that @nr may be almost arbitrarily large; this function is not
  89.  * restricted to acting on a single-word quantity.
  90.  */
  91. extern __inline__ void
  92. change_bit(unsigned long nr, volatile void *addr)
  93. {
  94. unsigned long *m = ((unsigned long *) addr) + (nr >> 6);
  95. unsigned long temp;
  96. __asm__ __volatile__(
  97. "1:tlldt%0, %1tt# change_bitnt"
  98. "xort%0, %2nt"
  99. "scdt%0, %1nt"
  100. "beqzt%0, 1b"
  101. :"=&r" (temp), "=m" (*m)
  102. :"ir" (1UL << (nr & 0x3f)), "m" (*m));
  103. }
  104. /*
  105.  * __change_bit - Toggle a bit in memory
  106.  * @nr: the bit to set
  107.  * @addr: the address to start counting from
  108.  *
  109.  * Unlike change_bit(), this function is non-atomic and may be reordered.
  110.  * If it's called on the same region of memory simultaneously, the effect
  111.  * may be that only one operation succeeds.
  112.  */
  113. extern __inline__ void __change_bit(int nr, volatile void * addr)
  114. {
  115. unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  116. *m ^= 1UL << (nr & 0x3f);
  117. }
  118. /*
  119.  * test_and_set_bit - Set a bit and return its old value
  120.  * @nr: Bit to set
  121.  * @addr: Address to count from
  122.  *
  123.  * This operation is atomic and cannot be reordered.  
  124.  * It also implies a memory barrier.
  125.  */
  126. extern __inline__ unsigned long
  127. test_and_set_bit(unsigned long nr, volatile void *addr)
  128. {
  129. unsigned long *m = ((unsigned long *) addr) + (nr >> 6);
  130. unsigned long temp, res;
  131. __asm__ __volatile__(
  132. ".settnoreordertt# test_and_set_bitn"
  133. "1:tlldt%0, %1nt"
  134. "ort%2, %0, %3nt"
  135. "scdt%2, %1nt"
  136. "beqzt%2, 1bnt"
  137. " andt%2, %0, %3nt"
  138. ".settreorder"
  139. : "=&r" (temp), "=m" (*m), "=&r" (res)
  140. : "r" (1UL << (nr & 0x3f)), "m" (*m)
  141. : "memory");
  142. return res != 0;
  143. }
  144. /*
  145.  * __test_and_set_bit - Set a bit and return its old value
  146.  * @nr: Bit to set
  147.  * @addr: Address to count from
  148.  *
  149.  * This operation is non-atomic and can be reordered.  
  150.  * If two examples of this operation race, one can appear to succeed
  151.  * but actually fail.  You must protect multiple accesses with a lock.
  152.  */
  153. extern __inline__ int
  154. __test_and_set_bit(int nr, volatile void * addr)
  155. {
  156. unsigned long mask, retval;
  157. long *a = (unsigned long *) addr;
  158. a += (nr >> 6);
  159. mask = 1UL << (nr & 0x3f);
  160. retval = ((mask & *a) != 0);
  161. *a |= mask;
  162. return retval;
  163. }
  164. /*
  165.  * test_and_clear_bit - Clear a bit and return its old value
  166.  * @nr: Bit to set
  167.  * @addr: Address to count from
  168.  *
  169.  * This operation is atomic and cannot be reordered.  
  170.  * It also implies a memory barrier.
  171.  */
  172. extern __inline__ unsigned long
  173. test_and_clear_bit(unsigned long nr, volatile void *addr)
  174. {
  175. unsigned long *m = ((unsigned long *) addr) + (nr >> 6);
  176. unsigned long temp, res;
  177. __asm__ __volatile__(
  178. ".settnoreordertt# test_and_clear_bitn"
  179. "1:tlldt%0, %1nt"
  180. "ort%2, %0, %3nt"
  181. "xort%2, %3nt"
  182. "scdt%2, %1nt"
  183. "beqzt%2, 1bnt"
  184. " andt%2, %0, %3nt"
  185. ".settreorder"
  186. : "=&r" (temp), "=m" (*m), "=&r" (res)
  187. : "r" (1UL << (nr & 0x3f)), "m" (*m)
  188. : "memory");
  189. return res != 0;
  190. }
  191. /*
  192.  * __test_and_clear_bit - Clear a bit and return its old value
  193.  * @nr: Bit to set
  194.  * @addr: Address to count from
  195.  *
  196.  * This operation is non-atomic and can be reordered.  
  197.  * If two examples of this operation race, one can appear to succeed
  198.  * but actually fail.  You must protect multiple accesses with a lock.
  199.  */
  200. extern __inline__ int
  201. __test_and_clear_bit(int nr, volatile void * addr)
  202. {
  203. unsigned long mask, retval;
  204. unsigned long *a = (unsigned long *) addr;
  205. a += (nr >> 6);
  206. mask = 1UL << (nr & 0x3f);
  207. retval = ((mask & *a) != 0);
  208. *a &= ~mask;
  209. return retval;
  210. }
  211. /*
  212.  * test_and_change_bit - Change a bit and return its new value
  213.  * @nr: Bit to set
  214.  * @addr: Address to count from
  215.  *
  216.  * This operation is atomic and cannot be reordered.  
  217.  * It also implies a memory barrier.
  218.  */
  219. extern __inline__ unsigned long
  220. test_and_change_bit(unsigned long nr, volatile void *addr)
  221. {
  222. unsigned long *m = ((unsigned long *) addr) + (nr >> 6);
  223. unsigned long temp, res;
  224. __asm__ __volatile__(
  225. ".settnoreordertt# test_and_change_bitn"
  226. "1:tlldt%0, %1nt"
  227. "xort%2, %0, %3nt"
  228. "scdt%2, %1nt"
  229. "beqzt%2, 1bnt"
  230. " andt%2, %0, %3nt"
  231. ".settreorder"
  232. : "=&r" (temp), "=m" (*m), "=&r" (res)
  233. : "r" (1UL << (nr & 0x3f)), "m" (*m)
  234. : "memory");
  235. return res != 0;
  236. }
  237. /*
  238.  * __test_and_change_bit - Change a bit and return its old value
  239.  * @nr: Bit to set
  240.  * @addr: Address to count from
  241.  *
  242.  * This operation is non-atomic and can be reordered.  
  243.  * If two examples of this operation race, one can appear to succeed
  244.  * but actually fail.  You must protect multiple accesses with a lock.
  245.  */
  246. extern __inline__ int
  247. __test_and_change_bit(int nr, volatile void * addr)
  248. {
  249. unsigned long mask, retval;
  250. unsigned long *a = (unsigned long *) addr;
  251. a += (nr >> 6);
  252. mask = 1UL << (nr & 0x3f);
  253. retval = ((mask & *a) != 0);
  254. *a ^= mask;
  255. return retval;
  256. }
  257. /*
  258.  * test_bit - Determine whether a bit is set
  259.  * @nr: bit number to test
  260.  * @addr: Address to start counting from
  261.  */
  262. extern __inline__ unsigned long
  263. test_bit(int nr, volatile void * addr)
  264. {
  265. return 1UL & (((volatile unsigned long *) addr)[nr >> 6] >> (nr & 0x3f));
  266. }
  267. #ifndef __MIPSEB__
  268. /* Little endian versions. */
  269. /*
  270.  * find_first_zero_bit - find the first zero bit in a memory region
  271.  * @addr: The address to start the search at
  272.  * @size: The maximum size to search
  273.  *
  274.  * Returns the bit-number of the first zero bit, not the number of the byte
  275.  * containing a bit.
  276.  */
  277. extern __inline__ int
  278. find_first_zero_bit (void *addr, unsigned size)
  279. {
  280. unsigned long dummy;
  281. int res;
  282. if (!size)
  283. return 0;
  284. __asm__ (".settnoreordernt"
  285. ".settnoatn"
  286. "1:tsubut$1,%6,%0nt"
  287. "blezt$1,2fnt"
  288. "lwt$1,(%5)nt"
  289. "addiut%5,4nt"
  290. #if (_MIPS_ISA == _MIPS_ISA_MIPS2 ) || (_MIPS_ISA == _MIPS_ISA_MIPS3 ) || 
  291.     (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5 ) || 
  292.     (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
  293. "beqlt%1,$1,1bnt"
  294. "addiut%0,32nt"
  295. #else
  296. "addiut%0,32nt"
  297. "beqt%1,$1,1bnt"
  298. "nopnt"
  299. "subut%0,32nt"
  300. #endif
  301. "lit%1,1n"
  302. "1:tandt%2,$1,%1nt"
  303. "beqzt%2,2fnt"
  304. "sllt%1,%1,1nt"
  305. "bnezt%1,1bnt"
  306. "addt%0,%0,1nt"
  307. ".settatnt"
  308. ".settreordern"
  309. "2:"
  310. : "=r" (res), "=r" (dummy), "=r" (addr)
  311. : "0" ((signed int) 0), "1" ((unsigned int) 0xffffffff),
  312.   "2" (addr), "r" (size)
  313. : "$1");
  314. return res;
  315. }
  316. /*
  317.  * find_next_zero_bit - find the first zero bit in a memory region
  318.  * @addr: The address to base the search on
  319.  * @offset: The bitnumber to start searching at
  320.  * @size: The maximum size to search
  321.  */
  322. extern __inline__ int
  323. find_next_zero_bit (void * addr, int size, int offset)
  324. {
  325. unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
  326. int set = 0, bit = offset & 31, res;
  327. unsigned long dummy;
  328. if (bit) {
  329. /*
  330.  * Look for zero in first byte
  331.  */
  332. __asm__(".settnoreordernt"
  333. ".settnoatn"
  334. "1:tandt$1,%4,%1nt"
  335. "beqzt$1,1fnt"
  336. "sllt%1,%1,1nt"
  337. "bnezt%1,1bnt"
  338. "addiut%0,1nt"
  339. ".settatnt"
  340. ".settreordern"
  341. "1:"
  342. : "=r" (set), "=r" (dummy)
  343. : "0" (0), "1" (1 << bit), "r" (*p)
  344. : "$1");
  345. if (set < (32 - bit))
  346. return set + offset;
  347. set = 32 - bit;
  348. p++;
  349. }
  350. /*
  351.  * No zero yet, search remaining full bytes for a zero
  352.  */
  353. res = find_first_zero_bit(p, size - 32 * (p - (unsigned int *) addr));
  354. return offset + set + res;
  355. }
  356. #endif /* !(__MIPSEB__) */
  357. /*
  358.  * ffz - find first zero in word.
  359.  * @word: The word to search
  360.  *
  361.  * Undefined if no zero exists, so code should check against ~0UL first.
  362.  */
  363. extern __inline__ unsigned long ffz(unsigned long word)
  364. {
  365. unsigned long k;
  366. word = ~word;
  367. k = 63;
  368. if (word & 0x00000000ffffffffUL) { k -= 32; word <<= 32; }
  369. if (word & 0x0000ffff00000000UL) { k -= 16; word <<= 16; }
  370. if (word & 0x00ff000000000000UL) { k -= 8;  word <<= 8;  }
  371. if (word & 0x0f00000000000000UL) { k -= 4;  word <<= 4;  }
  372. if (word & 0x3000000000000000UL) { k -= 2;  word <<= 2;  }
  373. if (word & 0x4000000000000000UL) { k -= 1; }
  374. return k;
  375. }
  376. #ifdef __KERNEL__
  377. /*
  378.  * ffs - find first bit set
  379.  * @x: the word to search
  380.  *
  381.  * This is defined the same way as
  382.  * the libc and compiler builtin ffs routines, therefore
  383.  * differs in spirit from the above ffz (man ffs).
  384.  */
  385. #define ffs(x) generic_ffs(x)
  386. /*
  387.  * hweightN - returns the hamming weight of a N-bit word
  388.  * @x: the word to weigh
  389.  *
  390.  * The Hamming Weight of a number is the total number of bits set in it.
  391.  */
  392. #define hweight32(x) generic_hweight32(x)
  393. #define hweight16(x) generic_hweight16(x)
  394. #define hweight8(x)  generic_hweight8(x)
  395. #endif /* __KERNEL__ */
  396. #ifdef __MIPSEB__
  397. /*
  398.  * find_next_zero_bit - find the first zero bit in a memory region
  399.  * @addr: The address to base the search on
  400.  * @offset: The bitnumber to start searching at
  401.  * @size: The maximum size to search
  402.  */
  403. extern __inline__ unsigned long
  404. find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
  405. {
  406. unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  407. unsigned long result = offset & ~63UL;
  408. unsigned long tmp;
  409. if (offset >= size)
  410. return size;
  411. size -= result;
  412. offset &= 63UL;
  413. if (offset) {
  414. tmp = *(p++);
  415. tmp |= ~0UL >> (64-offset);
  416. if (size < 64)
  417. goto found_first;
  418. if (~tmp)
  419. goto found_middle;
  420. size -= 64;
  421. result += 64;
  422. }
  423. while (size & ~63UL) {
  424. if (~(tmp = *(p++)))
  425. goto found_middle;
  426. result += 64;
  427. size -= 64;
  428. }
  429. if (!size)
  430. return result;
  431. tmp = *p;
  432. found_first:
  433. tmp |= ~0UL << size;
  434. found_middle:
  435. return result + ffz(tmp);
  436. }
  437. #define find_first_zero_bit(addr, size) 
  438.         find_next_zero_bit((addr), (size), 0)
  439. #endif /* (__MIPSEB__) */
  440. #ifdef __KERNEL__
  441. /* Now for the ext2 filesystem bit operations and helper routines. */
  442. #ifdef __MIPSEB__
  443. extern inline int
  444. ext2_set_bit(int nr,void * addr)
  445. {
  446. int mask, retval, flags;
  447. unsigned char *ADDR = (unsigned char *) addr;
  448. ADDR += nr >> 3;
  449. mask = 1 << (nr & 0x07);
  450. save_and_cli(flags);
  451. retval = (mask & *ADDR) != 0;
  452. *ADDR |= mask;
  453. restore_flags(flags);
  454. return retval;
  455. }
  456. extern inline int
  457. ext2_clear_bit(int nr, void * addr)
  458. {
  459. int mask, retval, flags;
  460. unsigned char *ADDR = (unsigned char *) addr;
  461. ADDR += nr >> 3;
  462. mask = 1 << (nr & 0x07);
  463. save_and_cli(flags);
  464. retval = (mask & *ADDR) != 0;
  465. *ADDR &= ~mask;
  466. restore_flags(flags);
  467. return retval;
  468. }
  469. extern inline int
  470. ext2_test_bit(int nr, const void * addr)
  471. {
  472. int mask;
  473. const unsigned char *ADDR = (const unsigned char *) addr;
  474. ADDR += nr >> 3;
  475. mask = 1 << (nr & 0x07);
  476. return ((mask & *ADDR) != 0);
  477. }
  478. #define ext2_find_first_zero_bit(addr, size) 
  479.         ext2_find_next_zero_bit((addr), (size), 0)
  480. extern inline unsigned int
  481. ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
  482. {
  483. unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
  484. unsigned int result = offset & ~31UL;
  485. unsigned int tmp;
  486. if (offset >= size)
  487. return size;
  488. size -= result;
  489. offset &= 31UL;
  490. if(offset) {
  491. /* We hold the little endian value in tmp, but then the
  492.  * shift is illegal. So we could keep a big endian value
  493.  * in tmp, like this:
  494.  *
  495.  * tmp = __swab32(*(p++));
  496.  * tmp |= ~0UL >> (32-offset);
  497.  *
  498.  * but this would decrease preformance, so we change the
  499.  * shift:
  500.  */
  501. tmp = *(p++);
  502. tmp |= __swab32(~0UL >> (32-offset));
  503. if(size < 32)
  504. goto found_first;
  505. if(~tmp)
  506. goto found_middle;
  507. size -= 32;
  508. result += 32;
  509. }
  510. while(size & ~31UL) {
  511. if(~(tmp = *(p++)))
  512. goto found_middle;
  513. result += 32;
  514. size -= 32;
  515. }
  516. if(!size)
  517. return result;
  518. tmp = *p;
  519. found_first:
  520. /* tmp is little endian, so we would have to swab the shift,
  521.  * see above. But then we have to swab tmp below for ffz, so
  522.  * we might as well do this here.
  523.  */
  524. return result + ffz(__swab32(tmp) | (~0UL << size));
  525. found_middle:
  526. return result + ffz(__swab32(tmp));
  527. }
  528. #else /* !(__MIPSEB__) */
  529. /* Native ext2 byte ordering, just collapse using defines. */
  530. #define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
  531. #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
  532. #define ext2_test_bit(nr, addr) test_bit((nr), (addr))
  533. #define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
  534. #define ext2_find_next_zero_bit(addr, size, offset) 
  535.                 find_next_zero_bit((addr), (size), (offset))
  536.  
  537. #endif /* !(__MIPSEB__) */
  538. /*
  539.  * Bitmap functions for the minix filesystem.
  540.  * FIXME: These assume that Minix uses the native byte/bitorder.
  541.  * This limits the Minix filesystem's value for data exchange very much.
  542.  */
  543. #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
  544. #define minix_set_bit(nr,addr) set_bit(nr,addr)
  545. #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
  546. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  547. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  548. #endif /* __KERNEL__ */
  549. #endif /* _ASM_BITOPS_H */