xref: /netbsd-src/external/bsd/jemalloc.old/dist/test/unit/prof_accum.c (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
1*8e33eff8Schristos #include "test/jemalloc_test.h"
2*8e33eff8Schristos 
3*8e33eff8Schristos #define NTHREADS		4
4*8e33eff8Schristos #define NALLOCS_PER_THREAD	50
5*8e33eff8Schristos #define DUMP_INTERVAL		1
6*8e33eff8Schristos #define BT_COUNT_CHECK_INTERVAL	5
7*8e33eff8Schristos 
8*8e33eff8Schristos static int
9*8e33eff8Schristos prof_dump_open_intercept(bool propagate_err, const char *filename) {
10*8e33eff8Schristos 	int fd;
11*8e33eff8Schristos 
12*8e33eff8Schristos 	fd = open("/dev/null", O_WRONLY);
13*8e33eff8Schristos 	assert_d_ne(fd, -1, "Unexpected open() failure");
14*8e33eff8Schristos 
15*8e33eff8Schristos 	return fd;
16*8e33eff8Schristos }
17*8e33eff8Schristos 
18*8e33eff8Schristos static void *
19*8e33eff8Schristos alloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration) {
20*8e33eff8Schristos 	return btalloc(1, thd_ind*NALLOCS_PER_THREAD + iteration);
21*8e33eff8Schristos }
22*8e33eff8Schristos 
23*8e33eff8Schristos static void *
24*8e33eff8Schristos thd_start(void *varg) {
25*8e33eff8Schristos 	unsigned thd_ind = *(unsigned *)varg;
26*8e33eff8Schristos 	size_t bt_count_prev, bt_count;
27*8e33eff8Schristos 	unsigned i_prev, i;
28*8e33eff8Schristos 
29*8e33eff8Schristos 	i_prev = 0;
30*8e33eff8Schristos 	bt_count_prev = 0;
31*8e33eff8Schristos 	for (i = 0; i < NALLOCS_PER_THREAD; i++) {
32*8e33eff8Schristos 		void *p = alloc_from_permuted_backtrace(thd_ind, i);
33*8e33eff8Schristos 		dallocx(p, 0);
34*8e33eff8Schristos 		if (i % DUMP_INTERVAL == 0) {
35*8e33eff8Schristos 			assert_d_eq(mallctl("prof.dump", NULL, NULL, NULL, 0),
36*8e33eff8Schristos 			    0, "Unexpected error while dumping heap profile");
37*8e33eff8Schristos 		}
38*8e33eff8Schristos 
39*8e33eff8Schristos 		if (i % BT_COUNT_CHECK_INTERVAL == 0 ||
40*8e33eff8Schristos 		    i+1 == NALLOCS_PER_THREAD) {
41*8e33eff8Schristos 			bt_count = prof_bt_count();
42*8e33eff8Schristos 			assert_zu_le(bt_count_prev+(i-i_prev), bt_count,
43*8e33eff8Schristos 			    "Expected larger backtrace count increase");
44*8e33eff8Schristos 			i_prev = i;
45*8e33eff8Schristos 			bt_count_prev = bt_count;
46*8e33eff8Schristos 		}
47*8e33eff8Schristos 	}
48*8e33eff8Schristos 
49*8e33eff8Schristos 	return NULL;
50*8e33eff8Schristos }
51*8e33eff8Schristos 
52*8e33eff8Schristos TEST_BEGIN(test_idump) {
53*8e33eff8Schristos 	bool active;
54*8e33eff8Schristos 	thd_t thds[NTHREADS];
55*8e33eff8Schristos 	unsigned thd_args[NTHREADS];
56*8e33eff8Schristos 	unsigned i;
57*8e33eff8Schristos 
58*8e33eff8Schristos 	test_skip_if(!config_prof);
59*8e33eff8Schristos 
60*8e33eff8Schristos 	active = true;
61*8e33eff8Schristos 	assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active,
62*8e33eff8Schristos 	    sizeof(active)), 0,
63*8e33eff8Schristos 	    "Unexpected mallctl failure while activating profiling");
64*8e33eff8Schristos 
65*8e33eff8Schristos 	prof_dump_open = prof_dump_open_intercept;
66*8e33eff8Schristos 
67*8e33eff8Schristos 	for (i = 0; i < NTHREADS; i++) {
68*8e33eff8Schristos 		thd_args[i] = i;
69*8e33eff8Schristos 		thd_create(&thds[i], thd_start, (void *)&thd_args[i]);
70*8e33eff8Schristos 	}
71*8e33eff8Schristos 	for (i = 0; i < NTHREADS; i++) {
72*8e33eff8Schristos 		thd_join(thds[i], NULL);
73*8e33eff8Schristos 	}
74*8e33eff8Schristos }
75*8e33eff8Schristos TEST_END
76*8e33eff8Schristos 
77*8e33eff8Schristos int
78*8e33eff8Schristos main(void) {
79*8e33eff8Schristos 	return test_no_reentrancy(
80*8e33eff8Schristos 	    test_idump);
81*8e33eff8Schristos }
82