summaryrefslogtreecommitdiffstats
path: root/deps/jemalloc/test/unit/prof_log.c
blob: 5ff208e2d33476714188582f00432fbbda78df23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "test/jemalloc_test.h"
#include "jemalloc/internal/prof_log.h"

#define N_PARAM 100
#define N_THREADS 10

static void expect_rep() {
	expect_b_eq(prof_log_rep_check(), false, "Rep check failed");
}

static void expect_log_empty() {
	expect_zu_eq(prof_log_bt_count(), 0,
	    "The log has backtraces; it isn't empty");
	expect_zu_eq(prof_log_thr_count(), 0,
	    "The log has threads; it isn't empty");
	expect_zu_eq(prof_log_alloc_count(), 0,
	    "The log has allocations; it isn't empty");
}

void *buf[N_PARAM];

static void f() {
	int i;
	for (i = 0; i < N_PARAM; i++) {
		buf[i] = malloc(100);
	}
	for (i = 0; i < N_PARAM; i++) {
		free(buf[i]);
	}
}

TEST_BEGIN(test_prof_log_many_logs) {
	int i;

	test_skip_if(!config_prof);

	for (i = 0; i < N_PARAM; i++) {
		expect_b_eq(prof_log_is_logging(), false,
		    "Logging shouldn't have started yet");
		expect_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0,
		    "Unexpected mallctl failure when starting logging");
		expect_b_eq(prof_log_is_logging(), true,
		    "Logging should be started by now");
		expect_log_empty();
		expect_rep();
		f();
		expect_zu_eq(prof_log_thr_count(), 1, "Wrong thread count");
		expect_rep();
		expect_b_eq(prof_log_is_logging(), true,
		    "Logging should still be on");
		expect_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0,
		    "Unexpected mallctl failure when stopping logging");
		expect_b_eq(prof_log_is_logging(), false,
		    "Logging should have turned off");
	}
}
TEST_END

thd_t thr_buf[N_THREADS];

static void *f_thread(void *unused) {
	int i;
	for (i = 0; i < N_PARAM; i++) {
		void *p = malloc(100);
		memset(p, 100, 1);
		free(p);
	}

	return NULL;
}

TEST_BEGIN(test_prof_log_many_threads) {

	test_skip_if(!config_prof);

	int i;
	expect_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0,
	    "Unexpected mallctl failure when starting logging");
	for (i = 0; i < N_THREADS; i++) {
		thd_create(&thr_buf[i], &f_thread, NULL);
	}

	for (i = 0; i < N_THREADS; i++) {
		thd_join(thr_buf[i], NULL);
	}
	expect_zu_eq(prof_log_thr_count(), N_THREADS,
	    "Wrong number of thread entries");
	expect_rep();
	expect_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0,
	    "Unexpected mallctl failure when stopping logging");
}
TEST_END

static void f3() {
	void *p = malloc(100);
	free(p);
}

static void f1() {
	void *p = malloc(100);
	f3();
	free(p);
}

static void f2() {
	void *p = malloc(100);
	free(p);
}

TEST_BEGIN(test_prof_log_many_traces) {

	test_skip_if(!config_prof);

	expect_d_eq(mallctl("prof.log_start", NULL, NULL, NULL, 0), 0,
	    "Unexpected mallctl failure when starting logging");
	int i;
	expect_rep();
	expect_log_empty();
	for (i = 0; i < N_PARAM; i++) {
		expect_rep();
		f1();
		expect_rep();
		f2();
		expect_rep();
		f3();
		expect_rep();
	}
	/*
	 * There should be 8 total backtraces: two for malloc/free in f1(), two
	 * for malloc/free in f2(), two for malloc/free in f3(), and then two
	 * for malloc/free in f1()'s call to f3().  However compiler
	 * optimizations such as loop unrolling might generate more call sites.
	 * So >= 8 traces are expected.
	 */
	expect_zu_ge(prof_log_bt_count(), 8,
	    "Expect at least 8 backtraces given sample workload");
	expect_d_eq(mallctl("prof.log_stop", NULL, NULL, NULL, 0), 0,
	    "Unexpected mallctl failure when stopping logging");
}
TEST_END

int
main(void) {
	if (config_prof) {
		prof_log_dummy_set(true);
	}
	return test_no_reentrancy(
	    test_prof_log_many_logs,
	    test_prof_log_many_traces,
	    test_prof_log_many_threads);
}