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);
}
|