bitmap.c 5.7 KB

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