1a0698ed9Schristos #include "test/jemalloc_test.h" 2a0698ed9Schristos 3*7bdf38e5Schristos #include "jemalloc/internal/prof_data.h" 4*7bdf38e5Schristos #include "jemalloc/internal/prof_sys.h" 5*7bdf38e5Schristos 6a0698ed9Schristos #define NTHREADS 4 7a0698ed9Schristos #define NALLOCS_PER_THREAD 50 8a0698ed9Schristos #define DUMP_INTERVAL 1 9a0698ed9Schristos #define BT_COUNT_CHECK_INTERVAL 5 10a0698ed9Schristos 11a0698ed9Schristos static int 12*7bdf38e5Schristos prof_dump_open_file_intercept(const char *filename, int mode) { 13a0698ed9Schristos int fd; 14a0698ed9Schristos 15a0698ed9Schristos fd = open("/dev/null", O_WRONLY); 16a0698ed9Schristos assert_d_ne(fd, -1, "Unexpected open() failure"); 17a0698ed9Schristos 18a0698ed9Schristos return fd; 19a0698ed9Schristos } 20a0698ed9Schristos 21a0698ed9Schristos static void * 22a0698ed9Schristos alloc_from_permuted_backtrace(unsigned thd_ind, unsigned iteration) { 23a0698ed9Schristos return btalloc(1, thd_ind*NALLOCS_PER_THREAD + iteration); 24a0698ed9Schristos } 25a0698ed9Schristos 26a0698ed9Schristos static void * 27a0698ed9Schristos thd_start(void *varg) { 28a0698ed9Schristos unsigned thd_ind = *(unsigned *)varg; 29a0698ed9Schristos size_t bt_count_prev, bt_count; 30a0698ed9Schristos unsigned i_prev, i; 31a0698ed9Schristos 32a0698ed9Schristos i_prev = 0; 33a0698ed9Schristos bt_count_prev = 0; 34a0698ed9Schristos for (i = 0; i < NALLOCS_PER_THREAD; i++) { 35a0698ed9Schristos void *p = alloc_from_permuted_backtrace(thd_ind, i); 36a0698ed9Schristos dallocx(p, 0); 37a0698ed9Schristos if (i % DUMP_INTERVAL == 0) { 38*7bdf38e5Schristos expect_d_eq(mallctl("prof.dump", NULL, NULL, NULL, 0), 39a0698ed9Schristos 0, "Unexpected error while dumping heap profile"); 40a0698ed9Schristos } 41a0698ed9Schristos 42a0698ed9Schristos if (i % BT_COUNT_CHECK_INTERVAL == 0 || 43a0698ed9Schristos i+1 == NALLOCS_PER_THREAD) { 44a0698ed9Schristos bt_count = prof_bt_count(); 45*7bdf38e5Schristos expect_zu_le(bt_count_prev+(i-i_prev), bt_count, 46a0698ed9Schristos "Expected larger backtrace count increase"); 47a0698ed9Schristos i_prev = i; 48a0698ed9Schristos bt_count_prev = bt_count; 49a0698ed9Schristos } 50a0698ed9Schristos } 51a0698ed9Schristos 52a0698ed9Schristos return NULL; 53a0698ed9Schristos } 54a0698ed9Schristos 55a0698ed9Schristos TEST_BEGIN(test_idump) { 56a0698ed9Schristos bool active; 57a0698ed9Schristos thd_t thds[NTHREADS]; 58a0698ed9Schristos unsigned thd_args[NTHREADS]; 59a0698ed9Schristos unsigned i; 60a0698ed9Schristos 61a0698ed9Schristos test_skip_if(!config_prof); 62a0698ed9Schristos 63a0698ed9Schristos active = true; 64*7bdf38e5Schristos expect_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active, 65a0698ed9Schristos sizeof(active)), 0, 66a0698ed9Schristos "Unexpected mallctl failure while activating profiling"); 67a0698ed9Schristos 68*7bdf38e5Schristos prof_dump_open_file = prof_dump_open_file_intercept; 69a0698ed9Schristos 70a0698ed9Schristos for (i = 0; i < NTHREADS; i++) { 71a0698ed9Schristos thd_args[i] = i; 72a0698ed9Schristos thd_create(&thds[i], thd_start, (void *)&thd_args[i]); 73a0698ed9Schristos } 74a0698ed9Schristos for (i = 0; i < NTHREADS; i++) { 75a0698ed9Schristos thd_join(thds[i], NULL); 76a0698ed9Schristos } 77a0698ed9Schristos } 78a0698ed9Schristos TEST_END 79a0698ed9Schristos 80a0698ed9Schristos int 81a0698ed9Schristos main(void) { 82a0698ed9Schristos return test_no_reentrancy( 83a0698ed9Schristos test_idump); 84a0698ed9Schristos } 85