bit_test.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright (C) 2010 iptelorg GmbH
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. *
  16. */
  17. /** Kamailio core :: Bit test functions
  18. * @ingroup core
  19. * Module: core
  20. *
  21. * Bit test functions:
  22. * - int bit_test(int offset, unsigned int *addr)
  23. * Returns the bit found at offset position
  24. * in a bitstring pointed by addr.
  25. *
  26. * - int bit_test_and_set(int offset, unsigned int *addr)
  27. * Returns the bit found at offset position
  28. * in a bitstring pointed by addr, and sets
  29. * the bit at the given offset.
  30. *
  31. * - int bit_test_and_reset(int offset, unsigned int *addr)
  32. * Returns the bit found at offset position
  33. * in a bitstring pointed by addr, and resets
  34. * the bit at the given offset.
  35. *
  36. * Note that 0 <= offset <= 128, Make sure that addr points to
  37. * a large enough memory area.
  38. */
  39. #ifndef _BIT_TEST_H
  40. #define _BIT_TEST_H
  41. /* fix __CPU_i386 -> __CPU_x86 */
  42. #if defined __CPU_i386 && ! defined __CPU_x86
  43. #define __CPU_x86
  44. #endif
  45. #ifdef CC_GCC_LIKE_ASM
  46. #if defined __CPU_x86 || defined __CPU_x86_64
  47. #define BIT_TEST_ASM
  48. #endif
  49. #endif
  50. #ifdef BIT_TEST_ASM
  51. /* Returns the bit found at offset position in the bitstring
  52. * pointed by addr.
  53. * Note that the CPU can access 4 bytes starting from addr,
  54. * hence 0 <= offset < 128 holds. Make sure that addr points
  55. * to a memory area that is large enough.
  56. */
  57. static inline int bit_test(int offset, unsigned int *addr)
  58. {
  59. unsigned char v;
  60. asm volatile(
  61. " bt %2, %1 \n\t"
  62. " setc %0 \n\t"
  63. : "=qm" (v) : "m" (*addr), "r" (offset)
  64. );
  65. return (int)v;
  66. }
  67. /* Returns the bit found at offset position in the bitstring
  68. * pointed by addr and sets it to 1.
  69. * Note that the CPU can access 4 bytes starting from addr,
  70. * hence 0 <= offset < 128 holds. Make sure that addr points
  71. * to a memory area that is large enough.
  72. */
  73. static inline int bit_test_and_set(int offset, unsigned int *addr)
  74. {
  75. unsigned char v;
  76. asm volatile(
  77. " bts %2, %1 \n\t"
  78. " setc %0 \n\t"
  79. : "=qm" (v) : "m" (*addr), "r" (offset)
  80. );
  81. return (int)v;
  82. }
  83. /* Returns the bit found at offset position in the bitstring
  84. * pointed by addr and resets it to 0.
  85. * Note that the CPU can access 4 bytes starting from addr,
  86. * hence 0 <= offset < 128 holds. Make sure that addr points
  87. * to a memory area that is large enough.
  88. */
  89. static inline int bit_test_and_reset(int offset, unsigned int *addr)
  90. {
  91. unsigned char v;
  92. asm volatile(
  93. " btr %2, %1 \n\t"
  94. " setc %0 \n\t"
  95. : "=qm" (v) : "m" (*addr), "r" (offset)
  96. );
  97. return (int)v;
  98. }
  99. #else /* BIT_TEST_ASM */
  100. /* Returns the bit found at offset position in the bitstring
  101. * pointed by addr.
  102. * Note that offset can be grater than 32, make sure that addr points
  103. * to a memory area that is large enough.
  104. */
  105. static inline int bit_test(int offset, unsigned int *addr)
  106. {
  107. return ((*(addr + offset/32)) & (1U << (offset % 32))) ? 1 : 0;
  108. }
  109. /* Returns the bit found at offset position in the bitstring
  110. * pointed by addr and sets it to 1.
  111. * Note that offset can be grater than 32, make sure that addr points
  112. * to a memory area that is large enough.
  113. */
  114. static inline int bit_test_and_set(int offset, unsigned int *addr)
  115. {
  116. unsigned int *i;
  117. int mask, res;
  118. i = addr + offset/32;
  119. mask = 1U << (offset % 32);
  120. res = ((*i) & mask) ? 1 : 0;
  121. (*i) |= mask;
  122. return res;
  123. }
  124. /* Returns the bit found at offset position in the bitstring
  125. * pointed by addr and resets it to 0.
  126. * Note that offset can be grater than 32, make sure that addr points
  127. * to a memory area that is large enough.
  128. */
  129. static inline int bit_test_and_reset(int offset, unsigned int *addr)
  130. {
  131. unsigned int *i;
  132. int mask, res;
  133. i = addr + offset/32;
  134. mask = 1U << (offset % 32);
  135. res = ((*i) & mask) ? 1 : 0;
  136. (*i) &= ~mask;
  137. return res;
  138. }
  139. #endif /* BIT_TEST_ASM */
  140. #endif /* #ifndef _BIT_TEST_H */