bitmap.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #include "test/jemalloc_test.h"
  2. #include "test/nbits.h"
  3. static void
  4. test_bitmap_initializer_body(const bitmap_info_t *binfo, size_t nbits) {
  5. bitmap_info_t binfo_dyn;
  6. bitmap_info_init(&binfo_dyn, nbits);
  7. expect_zu_eq(bitmap_size(binfo), bitmap_size(&binfo_dyn),
  8. "Unexpected difference between static and dynamic initialization, "
  9. "nbits=%zu", nbits);
  10. expect_zu_eq(binfo->nbits, binfo_dyn.nbits,
  11. "Unexpected difference between static and dynamic initialization, "
  12. "nbits=%zu", nbits);
  13. #ifdef BITMAP_USE_TREE
  14. expect_u_eq(binfo->nlevels, binfo_dyn.nlevels,
  15. "Unexpected difference between static and dynamic initialization, "
  16. "nbits=%zu", nbits);
  17. {
  18. unsigned i;
  19. for (i = 0; i < binfo->nlevels; i++) {
  20. expect_zu_eq(binfo->levels[i].group_offset,
  21. binfo_dyn.levels[i].group_offset,
  22. "Unexpected difference between static and dynamic "
  23. "initialization, nbits=%zu, level=%u", nbits, i);
  24. }
  25. }
  26. #else
  27. expect_zu_eq(binfo->ngroups, binfo_dyn.ngroups,
  28. "Unexpected difference between static and dynamic initialization");
  29. #endif
  30. }
  31. TEST_BEGIN(test_bitmap_initializer) {
  32. #define NB(nbits) { \
  33. if (nbits <= BITMAP_MAXBITS) { \
  34. bitmap_info_t binfo = \
  35. BITMAP_INFO_INITIALIZER(nbits); \
  36. test_bitmap_initializer_body(&binfo, nbits); \
  37. } \
  38. }
  39. NBITS_TAB
  40. #undef NB
  41. }
  42. TEST_END
  43. static size_t
  44. test_bitmap_size_body(const bitmap_info_t *binfo, size_t nbits,
  45. size_t prev_size) {
  46. size_t size = bitmap_size(binfo);
  47. expect_zu_ge(size, (nbits >> 3),
  48. "Bitmap size is smaller than expected");
  49. expect_zu_ge(size, prev_size, "Bitmap size is smaller than expected");
  50. return size;
  51. }
  52. TEST_BEGIN(test_bitmap_size) {
  53. size_t nbits, prev_size;
  54. prev_size = 0;
  55. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  56. bitmap_info_t binfo;
  57. bitmap_info_init(&binfo, nbits);
  58. prev_size = test_bitmap_size_body(&binfo, nbits, prev_size);
  59. }
  60. #define NB(nbits) { \
  61. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  62. prev_size = test_bitmap_size_body(&binfo, nbits, \
  63. prev_size); \
  64. }
  65. prev_size = 0;
  66. NBITS_TAB
  67. #undef NB
  68. }
  69. TEST_END
  70. static void
  71. test_bitmap_init_body(const bitmap_info_t *binfo, size_t nbits) {
  72. size_t i;
  73. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  74. expect_ptr_not_null(bitmap, "Unexpected malloc() failure");
  75. bitmap_init(bitmap, binfo, false);
  76. for (i = 0; i < nbits; i++) {
  77. expect_false(bitmap_get(bitmap, binfo, i),
  78. "Bit should be unset");
  79. }
  80. bitmap_init(bitmap, binfo, true);
  81. for (i = 0; i < nbits; i++) {
  82. expect_true(bitmap_get(bitmap, binfo, i), "Bit should be set");
  83. }
  84. free(bitmap);
  85. }
  86. TEST_BEGIN(test_bitmap_init) {
  87. size_t nbits;
  88. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  89. bitmap_info_t binfo;
  90. bitmap_info_init(&binfo, nbits);
  91. test_bitmap_init_body(&binfo, nbits);
  92. }
  93. #define NB(nbits) { \
  94. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  95. test_bitmap_init_body(&binfo, nbits); \
  96. }
  97. NBITS_TAB
  98. #undef NB
  99. }
  100. TEST_END
  101. static void
  102. test_bitmap_set_body(const bitmap_info_t *binfo, size_t nbits) {
  103. size_t i;
  104. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  105. expect_ptr_not_null(bitmap, "Unexpected malloc() failure");
  106. bitmap_init(bitmap, binfo, false);
  107. for (i = 0; i < nbits; i++) {
  108. bitmap_set(bitmap, binfo, i);
  109. }
  110. expect_true(bitmap_full(bitmap, binfo), "All bits should be set");
  111. free(bitmap);
  112. }
  113. TEST_BEGIN(test_bitmap_set) {
  114. size_t nbits;
  115. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  116. bitmap_info_t binfo;
  117. bitmap_info_init(&binfo, nbits);
  118. test_bitmap_set_body(&binfo, nbits);
  119. }
  120. #define NB(nbits) { \
  121. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  122. test_bitmap_set_body(&binfo, nbits); \
  123. }
  124. NBITS_TAB
  125. #undef NB
  126. }
  127. TEST_END
  128. static void
  129. test_bitmap_unset_body(const bitmap_info_t *binfo, size_t nbits) {
  130. size_t i;
  131. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  132. expect_ptr_not_null(bitmap, "Unexpected malloc() failure");
  133. bitmap_init(bitmap, binfo, false);
  134. for (i = 0; i < nbits; i++) {
  135. bitmap_set(bitmap, binfo, i);
  136. }
  137. expect_true(bitmap_full(bitmap, binfo), "All bits should be set");
  138. for (i = 0; i < nbits; i++) {
  139. bitmap_unset(bitmap, binfo, i);
  140. }
  141. for (i = 0; i < nbits; i++) {
  142. bitmap_set(bitmap, binfo, i);
  143. }
  144. expect_true(bitmap_full(bitmap, binfo), "All bits should be set");
  145. free(bitmap);
  146. }
  147. TEST_BEGIN(test_bitmap_unset) {
  148. size_t nbits;
  149. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  150. bitmap_info_t binfo;
  151. bitmap_info_init(&binfo, nbits);
  152. test_bitmap_unset_body(&binfo, nbits);
  153. }
  154. #define NB(nbits) { \
  155. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  156. test_bitmap_unset_body(&binfo, nbits); \
  157. }
  158. NBITS_TAB
  159. #undef NB
  160. }
  161. TEST_END
  162. static void
  163. test_bitmap_xfu_body(const bitmap_info_t *binfo, size_t nbits) {
  164. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  165. expect_ptr_not_null(bitmap, "Unexpected malloc() failure");
  166. bitmap_init(bitmap, binfo, false);
  167. /* Iteratively set bits starting at the beginning. */
  168. for (size_t i = 0; i < nbits; i++) {
  169. expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
  170. "First unset bit should be just after previous first unset "
  171. "bit");
  172. expect_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
  173. "First unset bit should be just after previous first unset "
  174. "bit");
  175. expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  176. "First unset bit should be just after previous first unset "
  177. "bit");
  178. expect_zu_eq(bitmap_sfu(bitmap, binfo), i,
  179. "First unset bit should be just after previous first unset "
  180. "bit");
  181. }
  182. expect_true(bitmap_full(bitmap, binfo), "All bits should be set");
  183. /*
  184. * Iteratively unset bits starting at the end, and verify that
  185. * bitmap_sfu() reaches the unset bits.
  186. */
  187. for (size_t i = nbits - 1; i < nbits; i--) { /* (nbits..0] */
  188. bitmap_unset(bitmap, binfo, i);
  189. expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
  190. "First unset bit should the bit previously unset");
  191. expect_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
  192. "First unset bit should the bit previously unset");
  193. expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  194. "First unset bit should the bit previously unset");
  195. expect_zu_eq(bitmap_sfu(bitmap, binfo), i,
  196. "First unset bit should the bit previously unset");
  197. bitmap_unset(bitmap, binfo, i);
  198. }
  199. expect_false(bitmap_get(bitmap, binfo, 0), "Bit should be unset");
  200. /*
  201. * Iteratively set bits starting at the beginning, and verify that
  202. * bitmap_sfu() looks past them.
  203. */
  204. for (size_t i = 1; i < nbits; i++) {
  205. bitmap_set(bitmap, binfo, i - 1);
  206. expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
  207. "First unset bit should be just after the bit previously "
  208. "set");
  209. expect_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
  210. "First unset bit should be just after the bit previously "
  211. "set");
  212. expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  213. "First unset bit should be just after the bit previously "
  214. "set");
  215. expect_zu_eq(bitmap_sfu(bitmap, binfo), i,
  216. "First unset bit should be just after the bit previously "
  217. "set");
  218. bitmap_unset(bitmap, binfo, i);
  219. }
  220. expect_zu_eq(bitmap_ffu(bitmap, binfo, 0), nbits - 1,
  221. "First unset bit should be the last bit");
  222. expect_zu_eq(bitmap_ffu(bitmap, binfo, (nbits > 1) ? nbits-2 : nbits-1),
  223. nbits - 1, "First unset bit should be the last bit");
  224. expect_zu_eq(bitmap_ffu(bitmap, binfo, nbits - 1), nbits - 1,
  225. "First unset bit should be the last bit");
  226. expect_zu_eq(bitmap_sfu(bitmap, binfo), nbits - 1,
  227. "First unset bit should be the last bit");
  228. expect_true(bitmap_full(bitmap, binfo), "All bits should be set");
  229. /*
  230. * Bubble a "usu" pattern through the bitmap and verify that
  231. * bitmap_ffu() finds the correct bit for all five min_bit cases.
  232. */
  233. if (nbits >= 3) {
  234. for (size_t i = 0; i < nbits-2; i++) {
  235. bitmap_unset(bitmap, binfo, i);
  236. bitmap_unset(bitmap, binfo, i+2);
  237. if (i > 0) {
  238. expect_zu_eq(bitmap_ffu(bitmap, binfo, i-1), i,
  239. "Unexpected first unset bit");
  240. }
  241. expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  242. "Unexpected first unset bit");
  243. expect_zu_eq(bitmap_ffu(bitmap, binfo, i+1), i+2,
  244. "Unexpected first unset bit");
  245. expect_zu_eq(bitmap_ffu(bitmap, binfo, i+2), i+2,
  246. "Unexpected first unset bit");
  247. if (i + 3 < nbits) {
  248. expect_zu_eq(bitmap_ffu(bitmap, binfo, i+3),
  249. nbits, "Unexpected first unset bit");
  250. }
  251. expect_zu_eq(bitmap_sfu(bitmap, binfo), i,
  252. "Unexpected first unset bit");
  253. expect_zu_eq(bitmap_sfu(bitmap, binfo), i+2,
  254. "Unexpected first unset bit");
  255. }
  256. }
  257. /*
  258. * Unset the last bit, bubble another unset bit through the bitmap, and
  259. * verify that bitmap_ffu() finds the correct bit for all four min_bit
  260. * cases.
  261. */
  262. if (nbits >= 3) {
  263. bitmap_unset(bitmap, binfo, nbits-1);
  264. for (size_t i = 0; i < nbits-1; i++) {
  265. bitmap_unset(bitmap, binfo, i);
  266. if (i > 0) {
  267. expect_zu_eq(bitmap_ffu(bitmap, binfo, i-1), i,
  268. "Unexpected first unset bit");
  269. }
  270. expect_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  271. "Unexpected first unset bit");
  272. expect_zu_eq(bitmap_ffu(bitmap, binfo, i+1), nbits-1,
  273. "Unexpected first unset bit");
  274. expect_zu_eq(bitmap_ffu(bitmap, binfo, nbits-1),
  275. nbits-1, "Unexpected first unset bit");
  276. expect_zu_eq(bitmap_sfu(bitmap, binfo), i,
  277. "Unexpected first unset bit");
  278. }
  279. expect_zu_eq(bitmap_sfu(bitmap, binfo), nbits-1,
  280. "Unexpected first unset bit");
  281. }
  282. free(bitmap);
  283. }
  284. TEST_BEGIN(test_bitmap_xfu) {
  285. size_t nbits, nbits_max;
  286. /* The test is O(n^2); large page sizes may slow down too much. */
  287. nbits_max = BITMAP_MAXBITS > 512 ? 512 : BITMAP_MAXBITS;
  288. for (nbits = 1; nbits <= nbits_max; nbits++) {
  289. bitmap_info_t binfo;
  290. bitmap_info_init(&binfo, nbits);
  291. test_bitmap_xfu_body(&binfo, nbits);
  292. }
  293. #define NB(nbits) { \
  294. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  295. test_bitmap_xfu_body(&binfo, nbits); \
  296. }
  297. NBITS_TAB
  298. #undef NB
  299. }
  300. TEST_END
  301. int
  302. main(void) {
  303. return test(
  304. test_bitmap_initializer,
  305. test_bitmap_size,
  306. test_bitmap_init,
  307. test_bitmap_set,
  308. test_bitmap_unset,
  309. test_bitmap_xfu);
  310. }