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