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