Blame jemalloc/test/unit/prof_reset.c

Packit 345191
#include "test/jemalloc_test.h"
Packit 345191
Packit 345191
static int
Packit 345191
prof_dump_open_intercept(bool propagate_err, const char *filename) {
Packit 345191
	int fd;
Packit 345191
Packit 345191
	fd = open("/dev/null", O_WRONLY);
Packit 345191
	assert_d_ne(fd, -1, "Unexpected open() failure");
Packit 345191
Packit 345191
	return fd;
Packit 345191
}
Packit 345191
Packit 345191
static void
Packit 345191
set_prof_active(bool active) {
Packit 345191
	assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active,
Packit 345191
	    sizeof(active)), 0, "Unexpected mallctl failure");
Packit 345191
}
Packit 345191
Packit 345191
static size_t
Packit 345191
get_lg_prof_sample(void) {
Packit 345191
	size_t lg_prof_sample;
Packit 345191
	size_t sz = sizeof(size_t);
Packit 345191
Packit 345191
	assert_d_eq(mallctl("prof.lg_sample", (void *)&lg_prof_sample, &sz,
Packit 345191
	    NULL, 0), 0,
Packit 345191
	    "Unexpected mallctl failure while reading profiling sample rate");
Packit 345191
	return lg_prof_sample;
Packit 345191
}
Packit 345191
Packit 345191
static void
Packit 345191
do_prof_reset(size_t lg_prof_sample) {
Packit 345191
	assert_d_eq(mallctl("prof.reset", NULL, NULL,
Packit 345191
	    (void *)&lg_prof_sample, sizeof(size_t)), 0,
Packit 345191
	    "Unexpected mallctl failure while resetting profile data");
Packit 345191
	assert_zu_eq(lg_prof_sample, get_lg_prof_sample(),
Packit 345191
	    "Expected profile sample rate change");
Packit 345191
}
Packit 345191
Packit 345191
TEST_BEGIN(test_prof_reset_basic) {
Packit 345191
	size_t lg_prof_sample_orig, lg_prof_sample, lg_prof_sample_next;
Packit 345191
	size_t sz;
Packit 345191
	unsigned i;
Packit 345191
Packit 345191
	test_skip_if(!config_prof);
Packit 345191
Packit 345191
	sz = sizeof(size_t);
Packit 345191
	assert_d_eq(mallctl("opt.lg_prof_sample", (void *)&lg_prof_sample_orig,
Packit 345191
	    &sz, NULL, 0), 0,
Packit 345191
	    "Unexpected mallctl failure while reading profiling sample rate");
Packit 345191
	assert_zu_eq(lg_prof_sample_orig, 0,
Packit 345191
	    "Unexpected profiling sample rate");
Packit 345191
	lg_prof_sample = get_lg_prof_sample();
Packit 345191
	assert_zu_eq(lg_prof_sample_orig, lg_prof_sample,
Packit 345191
	    "Unexpected disagreement between \"opt.lg_prof_sample\" and "
Packit 345191
	    "\"prof.lg_sample\"");
Packit 345191
Packit 345191
	/* Test simple resets. */
Packit 345191
	for (i = 0; i < 2; i++) {
Packit 345191
		assert_d_eq(mallctl("prof.reset", NULL, NULL, NULL, 0), 0,
Packit 345191
		    "Unexpected mallctl failure while resetting profile data");
Packit 345191
		lg_prof_sample = get_lg_prof_sample();
Packit 345191
		assert_zu_eq(lg_prof_sample_orig, lg_prof_sample,
Packit 345191
		    "Unexpected profile sample rate change");
Packit 345191
	}
Packit 345191
Packit 345191
	/* Test resets with prof.lg_sample changes. */
Packit 345191
	lg_prof_sample_next = 1;
Packit 345191
	for (i = 0; i < 2; i++) {
Packit 345191
		do_prof_reset(lg_prof_sample_next);
Packit 345191
		lg_prof_sample = get_lg_prof_sample();
Packit 345191
		assert_zu_eq(lg_prof_sample, lg_prof_sample_next,
Packit 345191
		    "Expected profile sample rate change");
Packit 345191
		lg_prof_sample_next = lg_prof_sample_orig;
Packit 345191
	}
Packit 345191
Packit 345191
	/* Make sure the test code restored prof.lg_sample. */
Packit 345191
	lg_prof_sample = get_lg_prof_sample();
Packit 345191
	assert_zu_eq(lg_prof_sample_orig, lg_prof_sample,
Packit 345191
	    "Unexpected disagreement between \"opt.lg_prof_sample\" and "
Packit 345191
	    "\"prof.lg_sample\"");
Packit 345191
}
Packit 345191
TEST_END
Packit 345191
Packit 345191
bool prof_dump_header_intercepted = false;
Packit 345191
prof_cnt_t cnt_all_copy = {0, 0, 0, 0};
Packit 345191
static bool
Packit 345191
prof_dump_header_intercept(tsdn_t *tsdn, bool propagate_err,
Packit 345191
    const prof_cnt_t *cnt_all) {
Packit 345191
	prof_dump_header_intercepted = true;
Packit 345191
	memcpy(&cnt_all_copy, cnt_all, sizeof(prof_cnt_t));
Packit 345191
Packit 345191
	return false;
Packit 345191
}
Packit 345191
Packit 345191
TEST_BEGIN(test_prof_reset_cleanup) {
Packit 345191
	void *p;
Packit 345191
	prof_dump_header_t *prof_dump_header_orig;
Packit 345191
Packit 345191
	test_skip_if(!config_prof);
Packit 345191
Packit 345191
	set_prof_active(true);
Packit 345191
Packit 345191
	assert_zu_eq(prof_bt_count(), 0, "Expected 0 backtraces");
Packit 345191
	p = mallocx(1, 0);
Packit 345191
	assert_ptr_not_null(p, "Unexpected mallocx() failure");
Packit 345191
	assert_zu_eq(prof_bt_count(), 1, "Expected 1 backtrace");
Packit 345191
Packit 345191
	prof_dump_header_orig = prof_dump_header;
Packit 345191
	prof_dump_header = prof_dump_header_intercept;
Packit 345191
	assert_false(prof_dump_header_intercepted, "Unexpected intercept");
Packit 345191
Packit 345191
	assert_d_eq(mallctl("prof.dump", NULL, NULL, NULL, 0),
Packit 345191
	    0, "Unexpected error while dumping heap profile");
Packit 345191
	assert_true(prof_dump_header_intercepted, "Expected intercept");
Packit 345191
	assert_u64_eq(cnt_all_copy.curobjs, 1, "Expected 1 allocation");
Packit 345191
Packit 345191
	assert_d_eq(mallctl("prof.reset", NULL, NULL, NULL, 0), 0,
Packit 345191
	    "Unexpected error while resetting heap profile data");
Packit 345191
	assert_d_eq(mallctl("prof.dump", NULL, NULL, NULL, 0),
Packit 345191
	    0, "Unexpected error while dumping heap profile");
Packit 345191
	assert_u64_eq(cnt_all_copy.curobjs, 0, "Expected 0 allocations");
Packit 345191
	assert_zu_eq(prof_bt_count(), 1, "Expected 1 backtrace");
Packit 345191
Packit 345191
	prof_dump_header = prof_dump_header_orig;
Packit 345191
Packit 345191
	dallocx(p, 0);
Packit 345191
	assert_zu_eq(prof_bt_count(), 0, "Expected 0 backtraces");
Packit 345191
Packit 345191
	set_prof_active(false);
Packit 345191
}
Packit 345191
TEST_END
Packit 345191
Packit 345191
#define NTHREADS		4
Packit 345191
#define NALLOCS_PER_THREAD	(1U << 13)
Packit 345191
#define OBJ_RING_BUF_COUNT	1531
Packit 345191
#define RESET_INTERVAL		(1U << 10)
Packit 345191
#define DUMP_INTERVAL		3677
Packit 345191
static void *
Packit 345191
thd_start(void *varg) {
Packit 345191
	unsigned thd_ind = *(unsigned *)varg;
Packit 345191
	unsigned i;
Packit 345191
	void *objs[OBJ_RING_BUF_COUNT];
Packit 345191
Packit 345191
	memset(objs, 0, sizeof(objs));
Packit 345191
Packit 345191
	for (i = 0; i < NALLOCS_PER_THREAD; i++) {
Packit 345191
		if (i % RESET_INTERVAL == 0) {
Packit 345191
			assert_d_eq(mallctl("prof.reset", NULL, NULL, NULL, 0),
Packit 345191
			    0, "Unexpected error while resetting heap profile "
Packit 345191
			    "data");
Packit 345191
		}
Packit 345191
Packit 345191
		if (i % DUMP_INTERVAL == 0) {
Packit 345191
			assert_d_eq(mallctl("prof.dump", NULL, NULL, NULL, 0),
Packit 345191
			    0, "Unexpected error while dumping heap profile");
Packit 345191
		}
Packit 345191
Packit 345191
		{
Packit 345191
			void **pp = &objs[i % OBJ_RING_BUF_COUNT];
Packit 345191
			if (*pp != NULL) {
Packit 345191
				dallocx(*pp, 0);
Packit 345191
				*pp = NULL;
Packit 345191
			}
Packit 345191
			*pp = btalloc(1, thd_ind*NALLOCS_PER_THREAD + i);
Packit 345191
			assert_ptr_not_null(*pp,
Packit 345191
			    "Unexpected btalloc() failure");
Packit 345191
		}
Packit 345191
	}
Packit 345191
Packit 345191
	/* Clean up any remaining objects. */
Packit 345191
	for (i = 0; i < OBJ_RING_BUF_COUNT; i++) {
Packit 345191
		void **pp = &objs[i % OBJ_RING_BUF_COUNT];
Packit 345191
		if (*pp != NULL) {
Packit 345191
			dallocx(*pp, 0);
Packit 345191
			*pp = NULL;
Packit 345191
		}
Packit 345191
	}
Packit 345191
Packit 345191
	return NULL;
Packit 345191
}
Packit 345191
Packit 345191
TEST_BEGIN(test_prof_reset) {
Packit 345191
	size_t lg_prof_sample_orig;
Packit 345191
	thd_t thds[NTHREADS];
Packit 345191
	unsigned thd_args[NTHREADS];
Packit 345191
	unsigned i;
Packit 345191
	size_t bt_count, tdata_count;
Packit 345191
Packit 345191
	test_skip_if(!config_prof);
Packit 345191
Packit 345191
	bt_count = prof_bt_count();
Packit 345191
	assert_zu_eq(bt_count, 0,
Packit 345191
	    "Unexpected pre-existing tdata structures");
Packit 345191
	tdata_count = prof_tdata_count();
Packit 345191
Packit 345191
	lg_prof_sample_orig = get_lg_prof_sample();
Packit 345191
	do_prof_reset(5);
Packit 345191
Packit 345191
	set_prof_active(true);
Packit 345191
Packit 345191
	for (i = 0; i < NTHREADS; i++) {
Packit 345191
		thd_args[i] = i;
Packit 345191
		thd_create(&thds[i], thd_start, (void *)&thd_args[i]);
Packit 345191
	}
Packit 345191
	for (i = 0; i < NTHREADS; i++) {
Packit 345191
		thd_join(thds[i], NULL);
Packit 345191
	}
Packit 345191
Packit 345191
	assert_zu_eq(prof_bt_count(), bt_count,
Packit 345191
	    "Unexpected bactrace count change");
Packit 345191
	assert_zu_eq(prof_tdata_count(), tdata_count,
Packit 345191
	    "Unexpected remaining tdata structures");
Packit 345191
Packit 345191
	set_prof_active(false);
Packit 345191
Packit 345191
	do_prof_reset(lg_prof_sample_orig);
Packit 345191
}
Packit 345191
TEST_END
Packit 345191
#undef NTHREADS
Packit 345191
#undef NALLOCS_PER_THREAD
Packit 345191
#undef OBJ_RING_BUF_COUNT
Packit 345191
#undef RESET_INTERVAL
Packit 345191
#undef DUMP_INTERVAL
Packit 345191
Packit 345191
/* Test sampling at the same allocation site across resets. */
Packit 345191
#define NITER 10
Packit 345191
TEST_BEGIN(test_xallocx) {
Packit 345191
	size_t lg_prof_sample_orig;
Packit 345191
	unsigned i;
Packit 345191
	void *ptrs[NITER];
Packit 345191
Packit 345191
	test_skip_if(!config_prof);
Packit 345191
Packit 345191
	lg_prof_sample_orig = get_lg_prof_sample();
Packit 345191
	set_prof_active(true);
Packit 345191
Packit 345191
	/* Reset profiling. */
Packit 345191
	do_prof_reset(0);
Packit 345191
Packit 345191
	for (i = 0; i < NITER; i++) {
Packit 345191
		void *p;
Packit 345191
		size_t sz, nsz;
Packit 345191
Packit 345191
		/* Reset profiling. */
Packit 345191
		do_prof_reset(0);
Packit 345191
Packit 345191
		/* Allocate small object (which will be promoted). */
Packit 345191
		p = ptrs[i] = mallocx(1, 0);
Packit 345191
		assert_ptr_not_null(p, "Unexpected mallocx() failure");
Packit 345191
Packit 345191
		/* Reset profiling. */
Packit 345191
		do_prof_reset(0);
Packit 345191
Packit 345191
		/* Perform successful xallocx(). */
Packit 345191
		sz = sallocx(p, 0);
Packit 345191
		assert_zu_eq(xallocx(p, sz, 0, 0), sz,
Packit 345191
		    "Unexpected xallocx() failure");
Packit 345191
Packit 345191
		/* Perform unsuccessful xallocx(). */
Packit 345191
		nsz = nallocx(sz+1, 0);
Packit 345191
		assert_zu_eq(xallocx(p, nsz, 0, 0), sz,
Packit 345191
		    "Unexpected xallocx() success");
Packit 345191
	}
Packit 345191
Packit 345191
	for (i = 0; i < NITER; i++) {
Packit 345191
		/* dallocx. */
Packit 345191
		dallocx(ptrs[i], 0);
Packit 345191
	}
Packit 345191
Packit 345191
	set_prof_active(false);
Packit 345191
	do_prof_reset(lg_prof_sample_orig);
Packit 345191
}
Packit 345191
TEST_END
Packit 345191
#undef NITER
Packit 345191
Packit 345191
int
Packit 345191
main(void) {
Packit 345191
	/* Intercept dumping prior to running any tests. */
Packit 345191
	prof_dump_open = prof_dump_open_intercept;
Packit 345191
Packit 345191
	return test_no_reentrancy(
Packit 345191
	    test_prof_reset_basic,
Packit 345191
	    test_prof_reset_cleanup,
Packit 345191
	    test_prof_reset,
Packit 345191
	    test_xallocx);
Packit 345191
}