Blame jemalloc/test/unit/rtree.c

Packit Service 724aca
#include "test/jemalloc_test.h"
Packit Service 724aca
Packit Service 724aca
#include "jemalloc/internal/rtree.h"
Packit Service 724aca
Packit Service 724aca
rtree_node_alloc_t *rtree_node_alloc_orig;
Packit Service 724aca
rtree_node_dalloc_t *rtree_node_dalloc_orig;
Packit Service 724aca
rtree_leaf_alloc_t *rtree_leaf_alloc_orig;
Packit Service 724aca
rtree_leaf_dalloc_t *rtree_leaf_dalloc_orig;
Packit Service 724aca
Packit Service 724aca
/* Potentially too large to safely place on the stack. */
Packit Service 724aca
rtree_t test_rtree;
Packit Service 724aca
Packit Service 724aca
static rtree_node_elm_t *
Packit Service 724aca
rtree_node_alloc_intercept(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
Packit Service 724aca
	rtree_node_elm_t *node;
Packit Service 724aca
Packit Service 724aca
	if (rtree != &test_rtree) {
Packit Service 724aca
		return rtree_node_alloc_orig(tsdn, rtree, nelms);
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	malloc_mutex_unlock(tsdn, &rtree->init_lock);
Packit Service 724aca
	node = (rtree_node_elm_t *)calloc(nelms, sizeof(rtree_node_elm_t));
Packit Service 724aca
	assert_ptr_not_null(node, "Unexpected calloc() failure");
Packit Service 724aca
	malloc_mutex_lock(tsdn, &rtree->init_lock);
Packit Service 724aca
Packit Service 724aca
	return node;
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static void
Packit Service 724aca
rtree_node_dalloc_intercept(tsdn_t *tsdn, rtree_t *rtree,
Packit Service 724aca
    rtree_node_elm_t *node) {
Packit Service 724aca
	if (rtree != &test_rtree) {
Packit Service 724aca
		rtree_node_dalloc_orig(tsdn, rtree, node);
Packit Service 724aca
		return;
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	free(node);
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static rtree_leaf_elm_t *
Packit Service 724aca
rtree_leaf_alloc_intercept(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
Packit Service 724aca
	rtree_leaf_elm_t *leaf;
Packit Service 724aca
Packit Service 724aca
	if (rtree != &test_rtree) {
Packit Service 724aca
		return rtree_leaf_alloc_orig(tsdn, rtree, nelms);
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	malloc_mutex_unlock(tsdn, &rtree->init_lock);
Packit Service 724aca
	leaf = (rtree_leaf_elm_t *)calloc(nelms, sizeof(rtree_leaf_elm_t));
Packit Service 724aca
	assert_ptr_not_null(leaf, "Unexpected calloc() failure");
Packit Service 724aca
	malloc_mutex_lock(tsdn, &rtree->init_lock);
Packit Service 724aca
Packit Service 724aca
	return leaf;
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static void
Packit Service 724aca
rtree_leaf_dalloc_intercept(tsdn_t *tsdn, rtree_t *rtree,
Packit Service 724aca
    rtree_leaf_elm_t *leaf) {
Packit Service 724aca
	if (rtree != &test_rtree) {
Packit Service 724aca
		rtree_leaf_dalloc_orig(tsdn, rtree, leaf);
Packit Service 724aca
		return;
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	free(leaf);
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
TEST_BEGIN(test_rtree_read_empty) {
Packit Service 724aca
	tsdn_t *tsdn;
Packit Service 724aca
Packit Service 724aca
	tsdn = tsdn_fetch();
Packit Service 724aca
Packit Service 724aca
	rtree_t *rtree = &test_rtree;
Packit Service 724aca
	rtree_ctx_t rtree_ctx;
Packit Service 724aca
	rtree_ctx_data_init(&rtree_ctx);
Packit Service 724aca
	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
Packit Service 724aca
	assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx, PAGE,
Packit Service 724aca
	    false), "rtree_extent_read() should return NULL for empty tree");
Packit Service 724aca
	rtree_delete(tsdn, rtree);
Packit Service 724aca
}
Packit Service 724aca
TEST_END
Packit Service 724aca
Packit Service 724aca
#undef NTHREADS
Packit Service 724aca
#undef NITERS
Packit Service 724aca
#undef SEED
Packit Service 724aca
Packit Service 724aca
TEST_BEGIN(test_rtree_extrema) {
Packit Service 724aca
	extent_t extent_a, extent_b;
Packit Service 724aca
	extent_init(&extent_a, NULL, NULL, SC_LARGE_MINCLASS, false,
Packit Service 724aca
	    sz_size2index(SC_LARGE_MINCLASS), 0,
Packit Service 724aca
	    extent_state_active, false, false, true, EXTENT_NOT_HEAD);
Packit Service 724aca
	extent_init(&extent_b, NULL, NULL, 0, false, SC_NSIZES, 0,
Packit Service 724aca
	    extent_state_active, false, false, true, EXTENT_NOT_HEAD);
Packit Service 724aca
Packit Service 724aca
	tsdn_t *tsdn = tsdn_fetch();
Packit Service 724aca
Packit Service 724aca
	rtree_t *rtree = &test_rtree;
Packit Service 724aca
	rtree_ctx_t rtree_ctx;
Packit Service 724aca
	rtree_ctx_data_init(&rtree_ctx);
Packit Service 724aca
	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
Packit Service 724aca
Packit Service 724aca
	assert_false(rtree_write(tsdn, rtree, &rtree_ctx, PAGE, &extent_a,
Packit Service 724aca
	    extent_szind_get(&extent_a), extent_slab_get(&extent_a)),
Packit Service 724aca
	    "Unexpected rtree_write() failure");
Packit Service 724aca
	rtree_szind_slab_update(tsdn, rtree, &rtree_ctx, PAGE,
Packit Service 724aca
	    extent_szind_get(&extent_a), extent_slab_get(&extent_a));
Packit Service 724aca
	assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx, PAGE, true),
Packit Service 724aca
	    &extent_a,
Packit Service 724aca
	    "rtree_extent_read() should return previously set value");
Packit Service 724aca
Packit Service 724aca
	assert_false(rtree_write(tsdn, rtree, &rtree_ctx, ~((uintptr_t)0),
Packit Service 724aca
	    &extent_b, extent_szind_get_maybe_invalid(&extent_b),
Packit Service 724aca
	    extent_slab_get(&extent_b)), "Unexpected rtree_write() failure");
Packit Service 724aca
	assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
Packit Service 724aca
	    ~((uintptr_t)0), true), &extent_b,
Packit Service 724aca
	    "rtree_extent_read() should return previously set value");
Packit Service 724aca
Packit Service 724aca
	rtree_delete(tsdn, rtree);
Packit Service 724aca
}
Packit Service 724aca
TEST_END
Packit Service 724aca
Packit Service 724aca
TEST_BEGIN(test_rtree_bits) {
Packit Service 724aca
	tsdn_t *tsdn = tsdn_fetch();
Packit Service 724aca
Packit Service 724aca
	uintptr_t keys[] = {PAGE, PAGE + 1,
Packit Service 724aca
	    PAGE + (((uintptr_t)1) << LG_PAGE) - 1};
Packit Service 724aca
Packit Service 724aca
	extent_t extent;
Packit Service 724aca
	extent_init(&extent, NULL, NULL, 0, false, SC_NSIZES, 0,
Packit Service 724aca
	    extent_state_active, false, false, true, EXTENT_NOT_HEAD);
Packit Service 724aca
Packit Service 724aca
	rtree_t *rtree = &test_rtree;
Packit Service 724aca
	rtree_ctx_t rtree_ctx;
Packit Service 724aca
	rtree_ctx_data_init(&rtree_ctx);
Packit Service 724aca
	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
Packit Service 724aca
Packit Service 724aca
	for (unsigned i = 0; i < sizeof(keys)/sizeof(uintptr_t); i++) {
Packit Service 724aca
		assert_false(rtree_write(tsdn, rtree, &rtree_ctx, keys[i],
Packit Service 724aca
		    &extent, SC_NSIZES, false),
Packit Service 724aca
		    "Unexpected rtree_write() failure");
Packit Service 724aca
		for (unsigned j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {
Packit Service 724aca
			assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
Packit Service 724aca
			    keys[j], true), &extent,
Packit Service 724aca
			    "rtree_extent_read() should return previously set "
Packit Service 724aca
			    "value and ignore insignificant key bits; i=%u, "
Packit Service 724aca
			    "j=%u, set key=%#"FMTxPTR", get key=%#"FMTxPTR, i,
Packit Service 724aca
			    j, keys[i], keys[j]);
Packit Service 724aca
		}
Packit Service 724aca
		assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
Packit Service 724aca
		    (((uintptr_t)2) << LG_PAGE), false),
Packit Service 724aca
		    "Only leftmost rtree leaf should be set; i=%u", i);
Packit Service 724aca
		rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	rtree_delete(tsdn, rtree);
Packit Service 724aca
}
Packit Service 724aca
TEST_END
Packit Service 724aca
Packit Service 724aca
TEST_BEGIN(test_rtree_random) {
Packit Service 724aca
#define NSET 16
Packit Service 724aca
#define SEED 42
Packit Service 724aca
	sfmt_t *sfmt = init_gen_rand(SEED);
Packit Service 724aca
	tsdn_t *tsdn = tsdn_fetch();
Packit Service 724aca
	uintptr_t keys[NSET];
Packit Service 724aca
	rtree_t *rtree = &test_rtree;
Packit Service 724aca
	rtree_ctx_t rtree_ctx;
Packit Service 724aca
	rtree_ctx_data_init(&rtree_ctx);
Packit Service 724aca
Packit Service 724aca
	extent_t extent;
Packit Service 724aca
	extent_init(&extent, NULL, NULL, 0, false, SC_NSIZES, 0,
Packit Service 724aca
	    extent_state_active, false, false, true, EXTENT_NOT_HEAD);
Packit Service 724aca
Packit Service 724aca
	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
Packit Service 724aca
Packit Service 724aca
	for (unsigned i = 0; i < NSET; i++) {
Packit Service 724aca
		keys[i] = (uintptr_t)gen_rand64(sfmt);
Packit Service 724aca
		rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree,
Packit Service 724aca
		    &rtree_ctx, keys[i], false, true);
Packit Service 724aca
		assert_ptr_not_null(elm,
Packit Service 724aca
		    "Unexpected rtree_leaf_elm_lookup() failure");
Packit Service 724aca
		rtree_leaf_elm_write(tsdn, rtree, elm, &extent, SC_NSIZES,
Packit Service 724aca
		    false);
Packit Service 724aca
		assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
Packit Service 724aca
		    keys[i], true), &extent,
Packit Service 724aca
		    "rtree_extent_read() should return previously set value");
Packit Service 724aca
	}
Packit Service 724aca
	for (unsigned i = 0; i < NSET; i++) {
Packit Service 724aca
		assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
Packit Service 724aca
		    keys[i], true), &extent,
Packit Service 724aca
		    "rtree_extent_read() should return previously set value, "
Packit Service 724aca
		    "i=%u", i);
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	for (unsigned i = 0; i < NSET; i++) {
Packit Service 724aca
		rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
Packit Service 724aca
		assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
Packit Service 724aca
		    keys[i], true),
Packit Service 724aca
		   "rtree_extent_read() should return previously set value");
Packit Service 724aca
	}
Packit Service 724aca
	for (unsigned i = 0; i < NSET; i++) {
Packit Service 724aca
		assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
Packit Service 724aca
		    keys[i], true),
Packit Service 724aca
		    "rtree_extent_read() should return previously set value");
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	rtree_delete(tsdn, rtree);
Packit Service 724aca
	fini_gen_rand(sfmt);
Packit Service 724aca
#undef NSET
Packit Service 724aca
#undef SEED
Packit Service 724aca
}
Packit Service 724aca
TEST_END
Packit Service 724aca
Packit Service 724aca
int
Packit Service 724aca
main(void) {
Packit Service 724aca
	rtree_node_alloc_orig = rtree_node_alloc;
Packit Service 724aca
	rtree_node_alloc = rtree_node_alloc_intercept;
Packit Service 724aca
	rtree_node_dalloc_orig = rtree_node_dalloc;
Packit Service 724aca
	rtree_node_dalloc = rtree_node_dalloc_intercept;
Packit Service 724aca
	rtree_leaf_alloc_orig = rtree_leaf_alloc;
Packit Service 724aca
	rtree_leaf_alloc = rtree_leaf_alloc_intercept;
Packit Service 724aca
	rtree_leaf_dalloc_orig = rtree_leaf_dalloc;
Packit Service 724aca
	rtree_leaf_dalloc = rtree_leaf_dalloc_intercept;
Packit Service 724aca
Packit Service 724aca
	return test(
Packit Service 724aca
	    test_rtree_read_empty,
Packit Service 724aca
	    test_rtree_extrema,
Packit Service 724aca
	    test_rtree_bits,
Packit Service 724aca
	    test_rtree_random);
Packit Service 724aca
}