rtree.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "test/jemalloc_test.h"
  2. #include "jemalloc/internal/rtree.h"
  3. rtree_node_alloc_t *rtree_node_alloc_orig;
  4. rtree_node_dalloc_t *rtree_node_dalloc_orig;
  5. rtree_leaf_alloc_t *rtree_leaf_alloc_orig;
  6. rtree_leaf_dalloc_t *rtree_leaf_dalloc_orig;
  7. /* Potentially too large to safely place on the stack. */
  8. rtree_t test_rtree;
  9. static rtree_node_elm_t *
  10. rtree_node_alloc_intercept(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
  11. rtree_node_elm_t *node;
  12. if (rtree != &test_rtree) {
  13. return rtree_node_alloc_orig(tsdn, rtree, nelms);
  14. }
  15. malloc_mutex_unlock(tsdn, &rtree->init_lock);
  16. node = (rtree_node_elm_t *)calloc(nelms, sizeof(rtree_node_elm_t));
  17. assert_ptr_not_null(node, "Unexpected calloc() failure");
  18. malloc_mutex_lock(tsdn, &rtree->init_lock);
  19. return node;
  20. }
  21. static void
  22. rtree_node_dalloc_intercept(tsdn_t *tsdn, rtree_t *rtree,
  23. rtree_node_elm_t *node) {
  24. if (rtree != &test_rtree) {
  25. rtree_node_dalloc_orig(tsdn, rtree, node);
  26. return;
  27. }
  28. free(node);
  29. }
  30. static rtree_leaf_elm_t *
  31. rtree_leaf_alloc_intercept(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
  32. rtree_leaf_elm_t *leaf;
  33. if (rtree != &test_rtree) {
  34. return rtree_leaf_alloc_orig(tsdn, rtree, nelms);
  35. }
  36. malloc_mutex_unlock(tsdn, &rtree->init_lock);
  37. leaf = (rtree_leaf_elm_t *)calloc(nelms, sizeof(rtree_leaf_elm_t));
  38. assert_ptr_not_null(leaf, "Unexpected calloc() failure");
  39. malloc_mutex_lock(tsdn, &rtree->init_lock);
  40. return leaf;
  41. }
  42. static void
  43. rtree_leaf_dalloc_intercept(tsdn_t *tsdn, rtree_t *rtree,
  44. rtree_leaf_elm_t *leaf) {
  45. if (rtree != &test_rtree) {
  46. rtree_leaf_dalloc_orig(tsdn, rtree, leaf);
  47. return;
  48. }
  49. free(leaf);
  50. }
  51. TEST_BEGIN(test_rtree_read_empty) {
  52. tsdn_t *tsdn;
  53. tsdn = tsdn_fetch();
  54. rtree_t *rtree = &test_rtree;
  55. rtree_ctx_t rtree_ctx;
  56. rtree_ctx_data_init(&rtree_ctx);
  57. assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
  58. assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx, PAGE,
  59. false), "rtree_extent_read() should return NULL for empty tree");
  60. rtree_delete(tsdn, rtree);
  61. }
  62. TEST_END
  63. #undef NTHREADS
  64. #undef NITERS
  65. #undef SEED
  66. TEST_BEGIN(test_rtree_extrema) {
  67. extent_t extent_a, extent_b;
  68. extent_init(&extent_a, NULL, NULL, LARGE_MINCLASS, false,
  69. sz_size2index(LARGE_MINCLASS), 0, extent_state_active, false,
  70. false, true);
  71. extent_init(&extent_b, NULL, NULL, 0, false, NSIZES, 0,
  72. extent_state_active, false, false, true);
  73. tsdn_t *tsdn = tsdn_fetch();
  74. rtree_t *rtree = &test_rtree;
  75. rtree_ctx_t rtree_ctx;
  76. rtree_ctx_data_init(&rtree_ctx);
  77. assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
  78. assert_false(rtree_write(tsdn, rtree, &rtree_ctx, PAGE, &extent_a,
  79. extent_szind_get(&extent_a), extent_slab_get(&extent_a)),
  80. "Unexpected rtree_write() failure");
  81. rtree_szind_slab_update(tsdn, rtree, &rtree_ctx, PAGE,
  82. extent_szind_get(&extent_a), extent_slab_get(&extent_a));
  83. assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx, PAGE, true),
  84. &extent_a,
  85. "rtree_extent_read() should return previously set value");
  86. assert_false(rtree_write(tsdn, rtree, &rtree_ctx, ~((uintptr_t)0),
  87. &extent_b, extent_szind_get_maybe_invalid(&extent_b),
  88. extent_slab_get(&extent_b)), "Unexpected rtree_write() failure");
  89. assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
  90. ~((uintptr_t)0), true), &extent_b,
  91. "rtree_extent_read() should return previously set value");
  92. rtree_delete(tsdn, rtree);
  93. }
  94. TEST_END
  95. TEST_BEGIN(test_rtree_bits) {
  96. tsdn_t *tsdn = tsdn_fetch();
  97. uintptr_t keys[] = {PAGE, PAGE + 1,
  98. PAGE + (((uintptr_t)1) << LG_PAGE) - 1};
  99. extent_t extent;
  100. extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
  101. extent_state_active, false, false, true);
  102. rtree_t *rtree = &test_rtree;
  103. rtree_ctx_t rtree_ctx;
  104. rtree_ctx_data_init(&rtree_ctx);
  105. assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
  106. for (unsigned i = 0; i < sizeof(keys)/sizeof(uintptr_t); i++) {
  107. assert_false(rtree_write(tsdn, rtree, &rtree_ctx, keys[i],
  108. &extent, NSIZES, false),
  109. "Unexpected rtree_write() failure");
  110. for (unsigned j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {
  111. assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
  112. keys[j], true), &extent,
  113. "rtree_extent_read() should return previously set "
  114. "value and ignore insignificant key bits; i=%u, "
  115. "j=%u, set key=%#"FMTxPTR", get key=%#"FMTxPTR, i,
  116. j, keys[i], keys[j]);
  117. }
  118. assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
  119. (((uintptr_t)2) << LG_PAGE), false),
  120. "Only leftmost rtree leaf should be set; i=%u", i);
  121. rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
  122. }
  123. rtree_delete(tsdn, rtree);
  124. }
  125. TEST_END
  126. TEST_BEGIN(test_rtree_random) {
  127. #define NSET 16
  128. #define SEED 42
  129. sfmt_t *sfmt = init_gen_rand(SEED);
  130. tsdn_t *tsdn = tsdn_fetch();
  131. uintptr_t keys[NSET];
  132. rtree_t *rtree = &test_rtree;
  133. rtree_ctx_t rtree_ctx;
  134. rtree_ctx_data_init(&rtree_ctx);
  135. extent_t extent;
  136. extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
  137. extent_state_active, false, false, true);
  138. assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
  139. for (unsigned i = 0; i < NSET; i++) {
  140. keys[i] = (uintptr_t)gen_rand64(sfmt);
  141. rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree,
  142. &rtree_ctx, keys[i], false, true);
  143. assert_ptr_not_null(elm,
  144. "Unexpected rtree_leaf_elm_lookup() failure");
  145. rtree_leaf_elm_write(tsdn, rtree, elm, &extent, NSIZES, false);
  146. assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
  147. keys[i], true), &extent,
  148. "rtree_extent_read() should return previously set value");
  149. }
  150. for (unsigned i = 0; i < NSET; i++) {
  151. assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
  152. keys[i], true), &extent,
  153. "rtree_extent_read() should return previously set value, "
  154. "i=%u", i);
  155. }
  156. for (unsigned i = 0; i < NSET; i++) {
  157. rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
  158. assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
  159. keys[i], true),
  160. "rtree_extent_read() should return previously set value");
  161. }
  162. for (unsigned i = 0; i < NSET; i++) {
  163. assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
  164. keys[i], true),
  165. "rtree_extent_read() should return previously set value");
  166. }
  167. rtree_delete(tsdn, rtree);
  168. fini_gen_rand(sfmt);
  169. #undef NSET
  170. #undef SEED
  171. }
  172. TEST_END
  173. int
  174. main(void) {
  175. rtree_node_alloc_orig = rtree_node_alloc;
  176. rtree_node_alloc = rtree_node_alloc_intercept;
  177. rtree_node_dalloc_orig = rtree_node_dalloc;
  178. rtree_node_dalloc = rtree_node_dalloc_intercept;
  179. rtree_leaf_alloc_orig = rtree_leaf_alloc;
  180. rtree_leaf_alloc = rtree_leaf_alloc_intercept;
  181. rtree_leaf_dalloc_orig = rtree_leaf_dalloc;
  182. rtree_leaf_dalloc = rtree_leaf_dalloc_intercept;
  183. return test(
  184. test_rtree_read_empty,
  185. test_rtree_extrema,
  186. test_rtree_bits,
  187. test_rtree_random);
  188. }