xref: /netbsd-src/external/bsd/jemalloc/dist/test/unit/prof_log.c (revision 7bdf38e5b7a28439665f2fdeff81e36913eef7dd)
1*7bdf38e5Schristos #include "test/jemalloc_test.h"
2*7bdf38e5Schristos #include "jemalloc/internal/prof_log.h"
3*7bdf38e5Schristos 
4*7bdf38e5Schristos #define N_PARAM 100
5*7bdf38e5Schristos #define N_THREADS 10
6*7bdf38e5Schristos 
7*7bdf38e5Schristos static void expect_rep() {
8*7bdf38e5Schristos 	expect_b_eq(prof_log_rep_check(), false, "Rep check failed");
9*7bdf38e5Schristos }
10*7bdf38e5Schristos 
11*7bdf38e5Schristos static void expect_log_empty() {
12*7bdf38e5Schristos 	expect_zu_eq(prof_log_bt_count(), 0,
13*7bdf38e5Schristos 	    "The log has backtraces; it isn't empty");
14*7bdf38e5Schristos 	expect_zu_eq(prof_log_thr_count(), 0,
15*7bdf38e5Schristos 	    "The log has threads; it isn't empty");
16*7bdf38e5Schristos 	expect_zu_eq(prof_log_alloc_count(), 0,
17*7bdf38e5Schristos 	    "The log has allocations; it isn't empty");
18*7bdf38e5Schristos }
19*7bdf38e5Schristos 
20*7bdf38e5Schristos void *buf[N_PARAM];
21*7bdf38e5Schristos 
22*7bdf38e5Schristos static void f() {
23*7bdf38e5Schristos 	int i;
24*7bdf38e5Schristos 	for (i = 0; i < N_PARAM; i++) {
25*7bdf38e5Schristos 		buf[i] = malloc(100);
26*7bdf38e5Schristos 	}
27*7bdf38e5Schristos 	for (i = 0; i < N_PARAM; i++) {
28*7bdf38e5Schristos 		free(buf[i]);
29*7bdf38e5Schristos 	}
30*7bdf38e5Schristos }
31*7bdf38e5Schristos 
32*7bdf38e5Schristos TEST_BEGIN(test_prof_log_many_logs) {
33*7bdf38e5Schristos 	int i;
34*7bdf38e5Schristos 
35*7bdf38e5Schristos 	test_skip_if(!config_prof);
36*7bdf38e5Schristos 
37*7bdf38e5Schristos 	for (i = 0; i < N_PARAM; i++) {
38*7bdf38e5Schristos 		expect_b_eq(prof_log_is_logging(), false,
39*7bdf38e5Schristos 		    "Logging shouldn't have started yet");
40*7bdf38e5Schristos 		expect_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0,
41*7bdf38e5Schristos 		    "Unexpected mallctl failure when starting logging");
42*7bdf38e5Schristos 		expect_b_eq(prof_log_is_logging(), true,
43*7bdf38e5Schristos 		    "Logging should be started by now");
44*7bdf38e5Schristos 		expect_log_empty();
45*7bdf38e5Schristos 		expect_rep();
46*7bdf38e5Schristos 		f();
47*7bdf38e5Schristos 		expect_zu_eq(prof_log_thr_count(), 1, "Wrong thread count");
48*7bdf38e5Schristos 		expect_rep();
49*7bdf38e5Schristos 		expect_b_eq(prof_log_is_logging(), true,
50*7bdf38e5Schristos 		    "Logging should still be on");
51*7bdf38e5Schristos 		expect_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0,
52*7bdf38e5Schristos 		    "Unexpected mallctl failure when stopping logging");
53*7bdf38e5Schristos 		expect_b_eq(prof_log_is_logging(), false,
54*7bdf38e5Schristos 		    "Logging should have turned off");
55*7bdf38e5Schristos 	}
56*7bdf38e5Schristos }
57*7bdf38e5Schristos TEST_END
58*7bdf38e5Schristos 
59*7bdf38e5Schristos thd_t thr_buf[N_THREADS];
60*7bdf38e5Schristos 
61*7bdf38e5Schristos static void *f_thread(void *unused) {
62*7bdf38e5Schristos 	int i;
63*7bdf38e5Schristos 	for (i = 0; i < N_PARAM; i++) {
64*7bdf38e5Schristos 		void *p = malloc(100);
65*7bdf38e5Schristos 		memset(p, 100, 1);
66*7bdf38e5Schristos 		free(p);
67*7bdf38e5Schristos 	}
68*7bdf38e5Schristos 
69*7bdf38e5Schristos 	return NULL;
70*7bdf38e5Schristos }
71*7bdf38e5Schristos 
72*7bdf38e5Schristos TEST_BEGIN(test_prof_log_many_threads) {
73*7bdf38e5Schristos 
74*7bdf38e5Schristos 	test_skip_if(!config_prof);
75*7bdf38e5Schristos 
76*7bdf38e5Schristos 	int i;
77*7bdf38e5Schristos 	expect_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0,
78*7bdf38e5Schristos 	    "Unexpected mallctl failure when starting logging");
79*7bdf38e5Schristos 	for (i = 0; i < N_THREADS; i++) {
80*7bdf38e5Schristos 		thd_create(&thr_buf[i], &f_thread, NULL);
81*7bdf38e5Schristos 	}
82*7bdf38e5Schristos 
83*7bdf38e5Schristos 	for (i = 0; i < N_THREADS; i++) {
84*7bdf38e5Schristos 		thd_join(thr_buf[i], NULL);
85*7bdf38e5Schristos 	}
86*7bdf38e5Schristos 	expect_zu_eq(prof_log_thr_count(), N_THREADS,
87*7bdf38e5Schristos 	    "Wrong number of thread entries");
88*7bdf38e5Schristos 	expect_rep();
89*7bdf38e5Schristos 	expect_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0,
90*7bdf38e5Schristos 	    "Unexpected mallctl failure when stopping logging");
91*7bdf38e5Schristos }
92*7bdf38e5Schristos TEST_END
93*7bdf38e5Schristos 
94*7bdf38e5Schristos static void f3() {
95*7bdf38e5Schristos 	void *p = malloc(100);
96*7bdf38e5Schristos 	free(p);
97*7bdf38e5Schristos }
98*7bdf38e5Schristos 
99*7bdf38e5Schristos static void f1() {
100*7bdf38e5Schristos 	void *p = malloc(100);
101*7bdf38e5Schristos 	f3();
102*7bdf38e5Schristos 	free(p);
103*7bdf38e5Schristos }
104*7bdf38e5Schristos 
105*7bdf38e5Schristos static void f2() {
106*7bdf38e5Schristos 	void *p = malloc(100);
107*7bdf38e5Schristos 	free(p);
108*7bdf38e5Schristos }
109*7bdf38e5Schristos 
110*7bdf38e5Schristos TEST_BEGIN(test_prof_log_many_traces) {
111*7bdf38e5Schristos 
112*7bdf38e5Schristos 	test_skip_if(!config_prof);
113*7bdf38e5Schristos 
114*7bdf38e5Schristos 	expect_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0,
115*7bdf38e5Schristos 	    "Unexpected mallctl failure when starting logging");
116*7bdf38e5Schristos 	int i;
117*7bdf38e5Schristos 	expect_rep();
118*7bdf38e5Schristos 	expect_log_empty();
119*7bdf38e5Schristos 	for (i = 0; i < N_PARAM; i++) {
120*7bdf38e5Schristos 		expect_rep();
121*7bdf38e5Schristos 		f1();
122*7bdf38e5Schristos 		expect_rep();
123*7bdf38e5Schristos 		f2();
124*7bdf38e5Schristos 		expect_rep();
125*7bdf38e5Schristos 		f3();
126*7bdf38e5Schristos 		expect_rep();
127*7bdf38e5Schristos 	}
128*7bdf38e5Schristos 	/*
129*7bdf38e5Schristos 	 * There should be 8 total backtraces: two for malloc/free in f1(), two
130*7bdf38e5Schristos 	 * for malloc/free in f2(), two for malloc/free in f3(), and then two
131*7bdf38e5Schristos 	 * for malloc/free in f1()'s call to f3().  However compiler
132*7bdf38e5Schristos 	 * optimizations such as loop unrolling might generate more call sites.
133*7bdf38e5Schristos 	 * So >= 8 traces are expected.
134*7bdf38e5Schristos 	 */
135*7bdf38e5Schristos 	expect_zu_ge(prof_log_bt_count(), 8,
136*7bdf38e5Schristos 	    "Expect at least 8 backtraces given sample workload");
137*7bdf38e5Schristos 	expect_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0,
138*7bdf38e5Schristos 	    "Unexpected mallctl failure when stopping logging");
139*7bdf38e5Schristos }
140*7bdf38e5Schristos TEST_END
141*7bdf38e5Schristos 
142*7bdf38e5Schristos int
143*7bdf38e5Schristos main(void) {
144*7bdf38e5Schristos 	if (config_prof) {
145*7bdf38e5Schristos 		prof_log_dummy_set(true);
146*7bdf38e5Schristos 	}
147*7bdf38e5Schristos 	return test_no_reentrancy(
148*7bdf38e5Schristos 	    test_prof_log_many_logs,
149*7bdf38e5Schristos 	    test_prof_log_many_traces,
150*7bdf38e5Schristos 	    test_prof_log_many_threads);
151*7bdf38e5Schristos }
152