bitmap.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #include "test/jemalloc_test.h"
  2. #define NBITS_TAB \
  3. NB( 1) \
  4. NB( 2) \
  5. NB( 3) \
  6. NB( 4) \
  7. NB( 5) \
  8. NB( 6) \
  9. NB( 7) \
  10. NB( 8) \
  11. NB( 9) \
  12. NB(10) \
  13. NB(11) \
  14. NB(12) \
  15. NB(13) \
  16. NB(14) \
  17. NB(15) \
  18. NB(16) \
  19. NB(17) \
  20. NB(18) \
  21. NB(19) \
  22. NB(20) \
  23. NB(21) \
  24. NB(22) \
  25. NB(23) \
  26. NB(24) \
  27. NB(25) \
  28. NB(26) \
  29. NB(27) \
  30. NB(28) \
  31. NB(29) \
  32. NB(30) \
  33. NB(31) \
  34. NB(32) \
  35. \
  36. NB(33) \
  37. NB(34) \
  38. NB(35) \
  39. NB(36) \
  40. NB(37) \
  41. NB(38) \
  42. NB(39) \
  43. NB(40) \
  44. NB(41) \
  45. NB(42) \
  46. NB(43) \
  47. NB(44) \
  48. NB(45) \
  49. NB(46) \
  50. NB(47) \
  51. NB(48) \
  52. NB(49) \
  53. NB(50) \
  54. NB(51) \
  55. NB(52) \
  56. NB(53) \
  57. NB(54) \
  58. NB(55) \
  59. NB(56) \
  60. NB(57) \
  61. NB(58) \
  62. NB(59) \
  63. NB(60) \
  64. NB(61) \
  65. NB(62) \
  66. NB(63) \
  67. NB(64) \
  68. NB(65) \
  69. \
  70. NB(126) \
  71. NB(127) \
  72. NB(128) \
  73. NB(129) \
  74. NB(130) \
  75. \
  76. NB(254) \
  77. NB(255) \
  78. NB(256) \
  79. NB(257) \
  80. NB(258) \
  81. \
  82. NB(510) \
  83. NB(511) \
  84. NB(512) \
  85. NB(513) \
  86. NB(514) \
  87. \
  88. NB(1024) \
  89. NB(2048) \
  90. NB(4096) \
  91. NB(8192) \
  92. NB(16384) \
  93. static void
  94. test_bitmap_initializer_body(const bitmap_info_t *binfo, size_t nbits) {
  95. bitmap_info_t binfo_dyn;
  96. bitmap_info_init(&binfo_dyn, nbits);
  97. assert_zu_eq(bitmap_size(binfo), bitmap_size(&binfo_dyn),
  98. "Unexpected difference between static and dynamic initialization, "
  99. "nbits=%zu", nbits);
  100. assert_zu_eq(binfo->nbits, binfo_dyn.nbits,
  101. "Unexpected difference between static and dynamic initialization, "
  102. "nbits=%zu", nbits);
  103. #ifdef BITMAP_USE_TREE
  104. assert_u_eq(binfo->nlevels, binfo_dyn.nlevels,
  105. "Unexpected difference between static and dynamic initialization, "
  106. "nbits=%zu", nbits);
  107. {
  108. unsigned i;
  109. for (i = 0; i < binfo->nlevels; i++) {
  110. assert_zu_eq(binfo->levels[i].group_offset,
  111. binfo_dyn.levels[i].group_offset,
  112. "Unexpected difference between static and dynamic "
  113. "initialization, nbits=%zu, level=%u", nbits, i);
  114. }
  115. }
  116. #else
  117. assert_zu_eq(binfo->ngroups, binfo_dyn.ngroups,
  118. "Unexpected difference between static and dynamic initialization");
  119. #endif
  120. }
  121. TEST_BEGIN(test_bitmap_initializer) {
  122. #define NB(nbits) { \
  123. if (nbits <= BITMAP_MAXBITS) { \
  124. bitmap_info_t binfo = \
  125. BITMAP_INFO_INITIALIZER(nbits); \
  126. test_bitmap_initializer_body(&binfo, nbits); \
  127. } \
  128. }
  129. NBITS_TAB
  130. #undef NB
  131. }
  132. TEST_END
  133. static size_t
  134. test_bitmap_size_body(const bitmap_info_t *binfo, size_t nbits,
  135. size_t prev_size) {
  136. size_t size = bitmap_size(binfo);
  137. assert_zu_ge(size, (nbits >> 3),
  138. "Bitmap size is smaller than expected");
  139. assert_zu_ge(size, prev_size, "Bitmap size is smaller than expected");
  140. return size;
  141. }
  142. TEST_BEGIN(test_bitmap_size) {
  143. size_t nbits, prev_size;
  144. prev_size = 0;
  145. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  146. bitmap_info_t binfo;
  147. bitmap_info_init(&binfo, nbits);
  148. prev_size = test_bitmap_size_body(&binfo, nbits, prev_size);
  149. }
  150. #define NB(nbits) { \
  151. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  152. prev_size = test_bitmap_size_body(&binfo, nbits, \
  153. prev_size); \
  154. }
  155. prev_size = 0;
  156. NBITS_TAB
  157. #undef NB
  158. }
  159. TEST_END
  160. static void
  161. test_bitmap_init_body(const bitmap_info_t *binfo, size_t nbits) {
  162. size_t i;
  163. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  164. assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
  165. bitmap_init(bitmap, binfo, false);
  166. for (i = 0; i < nbits; i++) {
  167. assert_false(bitmap_get(bitmap, binfo, i),
  168. "Bit should be unset");
  169. }
  170. bitmap_init(bitmap, binfo, true);
  171. for (i = 0; i < nbits; i++) {
  172. assert_true(bitmap_get(bitmap, binfo, i), "Bit should be set");
  173. }
  174. free(bitmap);
  175. }
  176. TEST_BEGIN(test_bitmap_init) {
  177. size_t nbits;
  178. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  179. bitmap_info_t binfo;
  180. bitmap_info_init(&binfo, nbits);
  181. test_bitmap_init_body(&binfo, nbits);
  182. }
  183. #define NB(nbits) { \
  184. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  185. test_bitmap_init_body(&binfo, nbits); \
  186. }
  187. NBITS_TAB
  188. #undef NB
  189. }
  190. TEST_END
  191. static void
  192. test_bitmap_set_body(const bitmap_info_t *binfo, size_t nbits) {
  193. size_t i;
  194. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  195. assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
  196. bitmap_init(bitmap, binfo, false);
  197. for (i = 0; i < nbits; i++) {
  198. bitmap_set(bitmap, binfo, i);
  199. }
  200. assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
  201. free(bitmap);
  202. }
  203. TEST_BEGIN(test_bitmap_set) {
  204. size_t nbits;
  205. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  206. bitmap_info_t binfo;
  207. bitmap_info_init(&binfo, nbits);
  208. test_bitmap_set_body(&binfo, nbits);
  209. }
  210. #define NB(nbits) { \
  211. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  212. test_bitmap_set_body(&binfo, nbits); \
  213. }
  214. NBITS_TAB
  215. #undef NB
  216. }
  217. TEST_END
  218. static void
  219. test_bitmap_unset_body(const bitmap_info_t *binfo, size_t nbits) {
  220. size_t i;
  221. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  222. assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
  223. bitmap_init(bitmap, binfo, false);
  224. for (i = 0; i < nbits; i++) {
  225. bitmap_set(bitmap, binfo, i);
  226. }
  227. assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
  228. for (i = 0; i < nbits; i++) {
  229. bitmap_unset(bitmap, binfo, i);
  230. }
  231. for (i = 0; i < nbits; i++) {
  232. bitmap_set(bitmap, binfo, i);
  233. }
  234. assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
  235. free(bitmap);
  236. }
  237. TEST_BEGIN(test_bitmap_unset) {
  238. size_t nbits;
  239. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  240. bitmap_info_t binfo;
  241. bitmap_info_init(&binfo, nbits);
  242. test_bitmap_unset_body(&binfo, nbits);
  243. }
  244. #define NB(nbits) { \
  245. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  246. test_bitmap_unset_body(&binfo, nbits); \
  247. }
  248. NBITS_TAB
  249. #undef NB
  250. }
  251. TEST_END
  252. static void
  253. test_bitmap_xfu_body(const bitmap_info_t *binfo, size_t nbits) {
  254. bitmap_t *bitmap = (bitmap_t *)malloc(bitmap_size(binfo));
  255. assert_ptr_not_null(bitmap, "Unexpected malloc() failure");
  256. bitmap_init(bitmap, binfo, false);
  257. /* Iteratively set bits starting at the beginning. */
  258. for (size_t i = 0; i < nbits; i++) {
  259. assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
  260. "First unset bit should be just after previous first unset "
  261. "bit");
  262. assert_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
  263. "First unset bit should be just after previous first unset "
  264. "bit");
  265. assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  266. "First unset bit should be just after previous first unset "
  267. "bit");
  268. assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
  269. "First unset bit should be just after previous first unset "
  270. "bit");
  271. }
  272. assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
  273. /*
  274. * Iteratively unset bits starting at the end, and verify that
  275. * bitmap_sfu() reaches the unset bits.
  276. */
  277. for (size_t i = nbits - 1; i < nbits; i--) { /* (nbits..0] */
  278. bitmap_unset(bitmap, binfo, i);
  279. assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
  280. "First unset bit should the bit previously unset");
  281. assert_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
  282. "First unset bit should the bit previously unset");
  283. assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  284. "First unset bit should the bit previously unset");
  285. assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
  286. "First unset bit should the bit previously unset");
  287. bitmap_unset(bitmap, binfo, i);
  288. }
  289. assert_false(bitmap_get(bitmap, binfo, 0), "Bit should be unset");
  290. /*
  291. * Iteratively set bits starting at the beginning, and verify that
  292. * bitmap_sfu() looks past them.
  293. */
  294. for (size_t i = 1; i < nbits; i++) {
  295. bitmap_set(bitmap, binfo, i - 1);
  296. assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), i,
  297. "First unset bit should be just after the bit previously "
  298. "set");
  299. assert_zu_eq(bitmap_ffu(bitmap, binfo, (i > 0) ? i-1 : i), i,
  300. "First unset bit should be just after the bit previously "
  301. "set");
  302. assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  303. "First unset bit should be just after the bit previously "
  304. "set");
  305. assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
  306. "First unset bit should be just after the bit previously "
  307. "set");
  308. bitmap_unset(bitmap, binfo, i);
  309. }
  310. assert_zu_eq(bitmap_ffu(bitmap, binfo, 0), nbits - 1,
  311. "First unset bit should be the last bit");
  312. assert_zu_eq(bitmap_ffu(bitmap, binfo, (nbits > 1) ? nbits-2 : nbits-1),
  313. nbits - 1, "First unset bit should be the last bit");
  314. assert_zu_eq(bitmap_ffu(bitmap, binfo, nbits - 1), nbits - 1,
  315. "First unset bit should be the last bit");
  316. assert_zu_eq(bitmap_sfu(bitmap, binfo), nbits - 1,
  317. "First unset bit should be the last bit");
  318. assert_true(bitmap_full(bitmap, binfo), "All bits should be set");
  319. /*
  320. * Bubble a "usu" pattern through the bitmap and verify that
  321. * bitmap_ffu() finds the correct bit for all five min_bit cases.
  322. */
  323. if (nbits >= 3) {
  324. for (size_t i = 0; i < nbits-2; i++) {
  325. bitmap_unset(bitmap, binfo, i);
  326. bitmap_unset(bitmap, binfo, i+2);
  327. if (i > 0) {
  328. assert_zu_eq(bitmap_ffu(bitmap, binfo, i-1), i,
  329. "Unexpected first unset bit");
  330. }
  331. assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  332. "Unexpected first unset bit");
  333. assert_zu_eq(bitmap_ffu(bitmap, binfo, i+1), i+2,
  334. "Unexpected first unset bit");
  335. assert_zu_eq(bitmap_ffu(bitmap, binfo, i+2), i+2,
  336. "Unexpected first unset bit");
  337. if (i + 3 < nbits) {
  338. assert_zu_eq(bitmap_ffu(bitmap, binfo, i+3),
  339. nbits, "Unexpected first unset bit");
  340. }
  341. assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
  342. "Unexpected first unset bit");
  343. assert_zu_eq(bitmap_sfu(bitmap, binfo), i+2,
  344. "Unexpected first unset bit");
  345. }
  346. }
  347. /*
  348. * Unset the last bit, bubble another unset bit through the bitmap, and
  349. * verify that bitmap_ffu() finds the correct bit for all four min_bit
  350. * cases.
  351. */
  352. if (nbits >= 3) {
  353. bitmap_unset(bitmap, binfo, nbits-1);
  354. for (size_t i = 0; i < nbits-1; i++) {
  355. bitmap_unset(bitmap, binfo, i);
  356. if (i > 0) {
  357. assert_zu_eq(bitmap_ffu(bitmap, binfo, i-1), i,
  358. "Unexpected first unset bit");
  359. }
  360. assert_zu_eq(bitmap_ffu(bitmap, binfo, i), i,
  361. "Unexpected first unset bit");
  362. assert_zu_eq(bitmap_ffu(bitmap, binfo, i+1), nbits-1,
  363. "Unexpected first unset bit");
  364. assert_zu_eq(bitmap_ffu(bitmap, binfo, nbits-1),
  365. nbits-1, "Unexpected first unset bit");
  366. assert_zu_eq(bitmap_sfu(bitmap, binfo), i,
  367. "Unexpected first unset bit");
  368. }
  369. assert_zu_eq(bitmap_sfu(bitmap, binfo), nbits-1,
  370. "Unexpected first unset bit");
  371. }
  372. free(bitmap);
  373. }
  374. TEST_BEGIN(test_bitmap_xfu) {
  375. size_t nbits;
  376. for (nbits = 1; nbits <= BITMAP_MAXBITS; nbits++) {
  377. bitmap_info_t binfo;
  378. bitmap_info_init(&binfo, nbits);
  379. test_bitmap_xfu_body(&binfo, nbits);
  380. }
  381. #define NB(nbits) { \
  382. bitmap_info_t binfo = BITMAP_INFO_INITIALIZER(nbits); \
  383. test_bitmap_xfu_body(&binfo, nbits); \
  384. }
  385. NBITS_TAB
  386. #undef NB
  387. }
  388. TEST_END
  389. int
  390. main(void) {
  391. return test(
  392. test_bitmap_initializer,
  393. test_bitmap_size,
  394. test_bitmap_init,
  395. test_bitmap_set,
  396. test_bitmap_unset,
  397. test_bitmap_xfu);
  398. }