bitmap.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Copyright (c) 2013-2015 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Upstream site with license notes :
  18. * http://git.sceen.net/rbraun/librbraun.git/
  19. *
  20. *
  21. * Arbitrary-length bit arrays.
  22. *
  23. * Most functions do not check whether the given parameters are valid. This
  24. * is the responsibility of the caller.
  25. */
  26. #ifndef KERN_BITMAP_H
  27. #define KERN_BITMAP_H
  28. #include <limits.h>
  29. #include <stdbool.h>
  30. #include <string.h>
  31. #include <kern/atomic.h>
  32. #include <kern/macros.h>
  33. #define BITMAP_LONGS(nr_bits) DIV_CEIL (nr_bits, LONG_BIT)
  34. /*
  35. * Adjust the bitmap pointer and the bit index so that the latter refers
  36. * to a bit inside the word pointed by the former.
  37. *
  38. * Implemented as a macro for const-correctness.
  39. */
  40. #define bitmap_lookup(bmp, bitp) \
  41. MACRO_BEGIN \
  42. int i_ = BITMAP_LONGS (*(bitp) + 1) - 1; \
  43. *(bmp) += i_; \
  44. *(bitp) -= i_ * LONG_BIT; \
  45. MACRO_END
  46. static inline unsigned long
  47. bitmap_mask (int bit)
  48. {
  49. return (1UL << bit);
  50. }
  51. /*
  52. * Return the index of the next set bit in the bitmap, starting (and
  53. * including) the given bit index, or -1 if the bitmap is empty. If
  54. * complement is true, bits are toggled before searching so that the
  55. * result is the index of the next zero bit.
  56. */
  57. int bitmap_find_next_bit (const unsigned long *bm, int nr_bits, int bit,
  58. int complement);
  59. #define BITMAP_DECLARE(name, nr_bits) \
  60. unsigned long name[BITMAP_LONGS (nr_bits)]
  61. int bitmap_cmp (const unsigned long *a, const unsigned long *b, int nr_bits);
  62. static inline void
  63. bitmap_zero (unsigned long *bm, int nr_bits)
  64. {
  65. memset (bm, 0, BITMAP_LONGS (nr_bits) * sizeof (*bm));
  66. }
  67. static inline void
  68. bitmap_fill (unsigned long *bm, int nr_bits)
  69. {
  70. memset (bm, 0xff, BITMAP_LONGS (nr_bits) * sizeof (*bm));
  71. }
  72. static inline void
  73. bitmap_copy (unsigned long *dest, const unsigned long *src, int nr_bits)
  74. {
  75. memcpy (dest, src, BITMAP_LONGS (nr_bits) * sizeof (*dest));
  76. }
  77. static inline void
  78. bitmap_set (unsigned long *bm, int bit)
  79. {
  80. if (bit >= LONG_BIT)
  81. bitmap_lookup (&bm, &bit);
  82. *bm |= bitmap_mask (bit);
  83. }
  84. static inline void
  85. bitmap_set_atomic (unsigned long *bm, int bit)
  86. {
  87. if (bit >= LONG_BIT)
  88. bitmap_lookup (&bm, &bit);
  89. atomic_or (bm, bitmap_mask (bit), ATOMIC_RELEASE);
  90. }
  91. static inline void
  92. bitmap_clear (unsigned long *bm, int bit)
  93. {
  94. if (bit >= LONG_BIT)
  95. bitmap_lookup (&bm, &bit);
  96. *bm &= ~bitmap_mask (bit);
  97. }
  98. static inline void
  99. bitmap_clear_atomic (unsigned long *bm, int bit)
  100. {
  101. if (bit >= LONG_BIT)
  102. bitmap_lookup (&bm, &bit);
  103. atomic_and (bm, ~bitmap_mask (bit), ATOMIC_RELEASE);
  104. }
  105. static inline bool
  106. bitmap_test (const unsigned long *bm, int bit)
  107. {
  108. if (bit >= LONG_BIT)
  109. bitmap_lookup (&bm, &bit);
  110. return ((*bm & bitmap_mask (bit)) != 0);
  111. }
  112. static inline int
  113. bitmap_test_atomic (const unsigned long *bm, int bit)
  114. {
  115. if (bit >= LONG_BIT)
  116. bitmap_lookup (&bm, &bit);
  117. return ((atomic_load_acq (bm) & bitmap_mask (bit)) != 0);
  118. }
  119. static inline void
  120. bitmap_and (unsigned long *a, const unsigned long *b, int nr_bits)
  121. {
  122. int n = BITMAP_LONGS (nr_bits);
  123. for (int i = 0; i < n; i++)
  124. a[i] &= b[i];
  125. }
  126. static inline void
  127. bitmap_or (unsigned long *a, const unsigned long *b, int nr_bits)
  128. {
  129. int n = BITMAP_LONGS (nr_bits);
  130. for (int i = 0; i < n; i++)
  131. a[i] |= b[i];
  132. }
  133. static inline void
  134. bitmap_xor (unsigned long *a, const unsigned long *b, int nr_bits)
  135. {
  136. int n = BITMAP_LONGS (nr_bits);
  137. for (int i = 0; i < n; i++)
  138. a[i] ^= b[i];
  139. }
  140. static inline int
  141. bitmap_find_next (const unsigned long *bm, int nr_bits, int bit)
  142. {
  143. return (bitmap_find_next_bit (bm, nr_bits, bit, 0));
  144. }
  145. static inline int
  146. bitmap_find_first (const unsigned long *bm, int nr_bits)
  147. {
  148. return (bitmap_find_next (bm, nr_bits, 0));
  149. }
  150. static inline int
  151. bitmap_find_next_zero (const unsigned long *bm, int nr_bits, int bit)
  152. {
  153. return (bitmap_find_next_bit (bm, nr_bits, bit, 1));
  154. }
  155. static inline int
  156. bitmap_find_first_zero (const unsigned long *bm, int nr_bits)
  157. {
  158. return (bitmap_find_next_zero (bm, nr_bits, 0));
  159. }
  160. static inline bool
  161. bitmap_intersects (const unsigned long *a, const unsigned long *b, int nr_bits)
  162. {
  163. int n = BITMAP_LONGS (nr_bits);
  164. for (int i = 0; i < n; i++)
  165. if (a[i] & b[i])
  166. return (true);
  167. return (false);
  168. }
  169. static inline unsigned int
  170. bitmap_count_set (const unsigned long *bm, int nr_bits)
  171. {
  172. unsigned int ret = 0;
  173. for (int i = 0; i < BITMAP_LONGS (nr_bits); ++i)
  174. ret += __builtin_popcountl (bm[i]);
  175. return (ret);
  176. }
  177. #define bitmap_for_each(bm, nr_bits, bit) \
  178. for (int bit = 0; \
  179. bit < nr_bits && \
  180. (bit = bitmap_find_next (bm, nr_bits, bit)) != -1; \
  181. bit++)
  182. #define bitmap_for_each_zero(bm, nr_bits, bit) \
  183. for (int bit = 0; \
  184. bit < nr_bits && \
  185. (bit = bitmap_find_next_zero (bm, nr_bits, bit)) != -1; \
  186. bit++)
  187. #endif