bitmap.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2013-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. * Copyright (C) 2013 Simon Archipoff
  5. *
  6. * StarPU is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * StarPU is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  16. */
  17. #include <starpu.h>
  18. #include <starpu_bitmap.h>
  19. #include <limits.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #ifndef LONG_BIT
  23. #define LONG_BIT (sizeof(unsigned long) * 8)
  24. #endif
  25. struct starpu_bitmap
  26. {
  27. unsigned long * bits;
  28. int size; /* the size of bits array in number of unsigned long */
  29. int cardinal;
  30. };
  31. //#define DEBUG_BITMAP
  32. #ifdef DEBUG_BITMAP
  33. static int check_bitmap(struct starpu_bitmap *b)
  34. {
  35. int card = b->cardinal;
  36. int i = starpu_bitmap_first(b);
  37. int j;
  38. for(j = 0; j < card; j++)
  39. {
  40. if(i == -1)
  41. return 0;
  42. int tmp = starpu_bitmap_next(b,i);
  43. if(tmp == i)
  44. return 0;
  45. i = tmp;
  46. }
  47. if(i != -1)
  48. return 0;
  49. return 1;
  50. }
  51. #else
  52. #define check_bitmap(b) 1
  53. #endif
  54. static int _count_bit(unsigned long e)
  55. {
  56. #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__) >= 4)
  57. return __builtin_popcountl(e);
  58. #else
  59. int c = 0;
  60. while(e)
  61. {
  62. c += e&1;
  63. e >>= 1;
  64. }
  65. return c;
  66. #endif
  67. }
  68. struct starpu_bitmap * starpu_bitmap_create(void)
  69. {
  70. struct starpu_bitmap *b;
  71. _STARPU_CALLOC(b, 1, sizeof(*b));
  72. return b;
  73. }
  74. void starpu_bitmap_destroy(struct starpu_bitmap * b)
  75. {
  76. if(b)
  77. {
  78. free(b->bits);
  79. free(b);
  80. }
  81. }
  82. void starpu_bitmap_set(struct starpu_bitmap * b, int e)
  83. {
  84. if(!starpu_bitmap_get(b, e))
  85. b->cardinal++;
  86. else
  87. return;
  88. if((e/LONG_BIT) + 1 > b->size)
  89. {
  90. _STARPU_REALLOC(b->bits, sizeof(unsigned long) * ((e/LONG_BIT) + 1));
  91. memset(b->bits + b->size, 0, sizeof(unsigned long) * ((e/LONG_BIT + 1) - b->size));
  92. b->size = (e/LONG_BIT) + 1;
  93. }
  94. b->bits[e/LONG_BIT] |= (1ul << (e%LONG_BIT));
  95. STARPU_ASSERT(check_bitmap(b));
  96. }
  97. void starpu_bitmap_unset(struct starpu_bitmap *b, int e)
  98. {
  99. if(starpu_bitmap_get(b, e))
  100. b->cardinal--;
  101. else
  102. return;
  103. if(e / LONG_BIT > b->size)
  104. return;
  105. b->bits[e/LONG_BIT] &= ~(1ul << (e%LONG_BIT));
  106. STARPU_ASSERT(check_bitmap(b));
  107. }
  108. void starpu_bitmap_unset_all(struct starpu_bitmap * b)
  109. {
  110. free(b->bits);
  111. b->bits = NULL;
  112. b->size = 0;
  113. }
  114. void starpu_bitmap_unset_and(struct starpu_bitmap * a, struct starpu_bitmap * b, struct starpu_bitmap * c)
  115. {
  116. int n = STARPU_MIN(b->size, c->size);
  117. _STARPU_REALLOC(a->bits, sizeof(unsigned long) * n);
  118. a->size = n;
  119. a->cardinal = 0;
  120. int i;
  121. for(i = 0; i < n; i++)
  122. {
  123. a->bits[i] = b->bits[i] & c->bits[i];
  124. a->cardinal += _count_bit(a->bits[i]);
  125. }
  126. }
  127. int starpu_bitmap_get(struct starpu_bitmap * b, int e)
  128. {
  129. if(e / LONG_BIT >= b->size)
  130. return 0;
  131. return (b->bits[e/LONG_BIT] & (1ul << (e%LONG_BIT))) ?
  132. 1:
  133. 0;
  134. }
  135. void starpu_bitmap_or(struct starpu_bitmap * a, struct starpu_bitmap * b)
  136. {
  137. if(a->size < b->size)
  138. {
  139. _STARPU_REALLOC(a->bits, b->size * sizeof(unsigned long));
  140. memset(a->bits + a->size, 0, (b->size - a->size) * sizeof(unsigned long));
  141. a->size = b->size;
  142. }
  143. int i;
  144. for(i = 0; i < b->size; i++)
  145. {
  146. a->bits[i] |= b->bits[i];
  147. }
  148. a->cardinal = 0;
  149. for(i = 0; i < a->size; i++)
  150. a->cardinal += _count_bit(a->bits[i]);
  151. }
  152. int starpu_bitmap_and_get(struct starpu_bitmap * b1, struct starpu_bitmap * b2, int e)
  153. {
  154. return starpu_bitmap_get(b1,e) && starpu_bitmap_get(b2,e);
  155. }
  156. int starpu_bitmap_cardinal(struct starpu_bitmap * b)
  157. {
  158. return b->cardinal;
  159. }
  160. static inline int get_first_bit_rank(unsigned long ms)
  161. {
  162. STARPU_ASSERT(ms != 0);
  163. #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
  164. return __builtin_ffsl(ms) - 1;
  165. #else
  166. unsigned long m = 1ul;
  167. int i = 0;
  168. while(!(m&ms))
  169. i++,m<<=1;
  170. return i;
  171. #endif
  172. }
  173. static inline int get_last_bit_rank(unsigned long l)
  174. {
  175. STARPU_ASSERT(l != 0);
  176. #if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
  177. return 8*sizeof(l) - __builtin_clzl(l);
  178. #else
  179. int ibit = LONG_BIT - 1;
  180. while((!(1ul << ibit)) & l)
  181. ibit--;
  182. STARPU_ASSERT(ibit >= 0);
  183. return ibit;
  184. #endif
  185. }
  186. int starpu_bitmap_first(struct starpu_bitmap * b)
  187. {
  188. int i = 0;
  189. while(i < b->size && !b->bits[i])
  190. i++;
  191. if( i == b->size)
  192. return -1;
  193. int nb_long = i;
  194. unsigned long ms = b->bits[i];
  195. return (nb_long * LONG_BIT) + get_first_bit_rank(ms);
  196. }
  197. int starpu_bitmap_has_next(struct starpu_bitmap * b, int e)
  198. {
  199. int nb_long = (e+1) / LONG_BIT;
  200. int nb_bit = (e+1) % LONG_BIT;
  201. unsigned long mask = (~0ul) << nb_bit;
  202. if(b->bits[nb_long] & mask)
  203. return 1;
  204. for(nb_long++; nb_long < b->size; nb_long++)
  205. if(b->bits[nb_long])
  206. return 1;
  207. return 0;
  208. }
  209. int starpu_bitmap_last(struct starpu_bitmap * b)
  210. {
  211. if(b->cardinal == 0)
  212. return -1;
  213. int ilong;
  214. for(ilong = b->size - 1; ilong >= 0; ilong--)
  215. {
  216. if(b->bits[ilong])
  217. break;
  218. }
  219. STARPU_ASSERT(ilong >= 0);
  220. unsigned long l = b->bits[ilong];
  221. return ilong * LONG_BIT + get_last_bit_rank(l);
  222. }
  223. int starpu_bitmap_next(struct starpu_bitmap *b, int e)
  224. {
  225. int nb_long = e / LONG_BIT;
  226. int nb_bit = e % LONG_BIT;
  227. unsigned long rest = nb_bit == LONG_BIT - 1 ? 0 : (~0ul << (nb_bit + 1)) & b->bits[nb_long];
  228. if(nb_bit != (LONG_BIT - 1) && rest)
  229. {
  230. int i = get_first_bit_rank(rest);
  231. STARPU_ASSERT(i >= 0 && i < LONG_BIT);
  232. return (nb_long * LONG_BIT) + i;
  233. }
  234. for(nb_long++;nb_long < b->size; nb_long++)
  235. if(b->bits[nb_long])
  236. return nb_long * LONG_BIT + get_first_bit_rank(b->bits[nb_long]);
  237. return -1;
  238. }