Pass write callback explicitly in prof_data

This commit is contained in:
Yinan Zhang 2020-04-20 14:09:08 -07:00
parent 4556d3c0c8
commit 1f5fe3a3e3
4 changed files with 84 additions and 54 deletions

View File

@ -17,8 +17,8 @@ bool prof_data_init(tsd_t *tsd);
prof_tctx_t *prof_lookup(tsd_t *tsd, prof_bt_t *bt);
char *prof_thread_name_alloc(tsd_t *tsd, const char *thread_name);
int prof_thread_name_set_impl(tsd_t *tsd, const char *thread_name);
void prof_dump_impl(tsd_t *tsd, prof_tdata_t *tdata,
void (*write_cb)(const char *), bool leakcheck);
void prof_dump_impl(tsd_t *tsd, write_cb_t *prof_dump_write, void *cbopaque,
prof_tdata_t *tdata, bool leakcheck);
prof_tdata_t * prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid,
uint64_t thr_discrim, char *thread_name, bool active);
void prof_tdata_detach(tsd_t *tsd, prof_tdata_t *tdata);
@ -28,7 +28,8 @@ void prof_tctx_try_destroy(tsd_t *tsd, prof_tctx_t *tctx);
/* Used in unit tests. */
size_t prof_tdata_count(void);
size_t prof_bt_count(void);
typedef void (prof_dump_header_t)(tsdn_t *, const prof_cnt_t *);
typedef void (prof_dump_header_t)(tsdn_t *, write_cb_t *, void *,
const prof_cnt_t *);
extern prof_dump_header_t *JET_MUTABLE prof_dump_header;
void prof_cnt_all(uint64_t *curobjs, uint64_t *curbytes, uint64_t *accumobjs,
uint64_t *accumbytes);

View File

@ -59,9 +59,6 @@ static ckh_t bt2gctx;
*/
static prof_tdata_tree_t tdatas;
/* Dump write callback; stored global to simplify function interfaces. */
static void (*prof_dump_write)(const char *);
/******************************************************************************/
/* Red-black trees. */
@ -504,21 +501,24 @@ prof_thread_name_set_impl(tsd_t *tsd, const char *thread_name) {
return 0;
}
JEMALLOC_FORMAT_PRINTF(1, 2)
JEMALLOC_FORMAT_PRINTF(3, 4)
static void
prof_dump_printf(const char *format, ...) {
prof_dump_printf(write_cb_t *prof_dump_write, void *cbopaque,
const char *format, ...) {
va_list ap;
char buf[PROF_PRINTF_BUFSIZE];
va_start(ap, format);
malloc_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
prof_dump_write(buf);
prof_dump_write(cbopaque, buf);
}
static void
prof_dump_print_cnts(const prof_cnt_t *cnts) {
prof_dump_printf("%"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]",
prof_dump_print_cnts(write_cb_t *prof_dump_write, void *cbopaque,
const prof_cnt_t *cnts) {
prof_dump_printf(prof_dump_write, cbopaque,
"%"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]",
cnts->curobjs, cnts->curbytes, cnts->accumobjs, cnts->accumbytes);
}
@ -586,10 +586,17 @@ prof_tctx_merge_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) {
return NULL;
}
typedef struct prof_tctx_dump_iter_arg_s prof_tctx_dump_iter_arg_t;
struct prof_tctx_dump_iter_arg_s {
tsdn_t *tsdn;
write_cb_t *prof_dump_write;
void *cbopaque;
};
static prof_tctx_t *
prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) {
tsdn_t *tsdn = (tsdn_t *)arg;
malloc_mutex_assert_owner(tsdn, tctx->gctx->lock);
prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *opaque) {
prof_tctx_dump_iter_arg_t *arg = (prof_tctx_dump_iter_arg_t *)opaque;
malloc_mutex_assert_owner(arg->tsdn, tctx->gctx->lock);
switch (tctx->state) {
case prof_tctx_state_initializing:
@ -598,9 +605,11 @@ prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) {
break;
case prof_tctx_state_dumping:
case prof_tctx_state_purgatory:
prof_dump_printf(" t%"FMTu64": ", tctx->thr_uid);
prof_dump_print_cnts(&tctx->dump_cnts);
prof_dump_write("\n");
prof_dump_printf(arg->prof_dump_write, arg->cbopaque,
" t%"FMTu64": ", tctx->thr_uid);
prof_dump_print_cnts(arg->prof_dump_write, arg->cbopaque,
&tctx->dump_cnts);
arg->prof_dump_write(arg->cbopaque, "\n");
break;
default:
not_reached();
@ -761,38 +770,50 @@ prof_tdata_merge_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata,
return NULL;
}
typedef struct prof_tdata_dump_iter_arg_s prof_tdata_dump_iter_arg_t;
struct prof_tdata_dump_iter_arg_s {
write_cb_t *prof_dump_write;
void *cbopaque;
};
static prof_tdata_t *
prof_tdata_dump_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata,
void *unused) {
void *opaque) {
if (!tdata->dumping) {
return NULL;
}
prof_dump_printf(" t%"FMTu64": ", tdata->thr_uid);
prof_dump_print_cnts(&tdata->cnt_summed);
prof_tdata_dump_iter_arg_t *arg = (prof_tdata_dump_iter_arg_t *)opaque;
prof_dump_printf(arg->prof_dump_write, arg->cbopaque, " t%"FMTu64": ",
tdata->thr_uid);
prof_dump_print_cnts(arg->prof_dump_write, arg->cbopaque,
&tdata->cnt_summed);
if (tdata->thread_name != NULL) {
prof_dump_printf(" %s", tdata->thread_name);
arg->prof_dump_write(arg->cbopaque, " ");
arg->prof_dump_write(arg->cbopaque, tdata->thread_name);
}
prof_dump_write("\n");
arg->prof_dump_write(arg->cbopaque, "\n");
return NULL;
}
static void
prof_dump_header_impl(tsdn_t *tsdn, const prof_cnt_t *cnt_all) {
prof_dump_printf("heap_v2/%"FMTu64"\n t*: ",
((uint64_t)1U << lg_prof_sample));
prof_dump_print_cnts(cnt_all);
prof_dump_write("\n");
prof_dump_header_impl(tsdn_t *tsdn, write_cb_t *prof_dump_write,
void *cbopaque, const prof_cnt_t *cnt_all) {
prof_dump_printf(prof_dump_write, cbopaque,
"heap_v2/%"FMTu64"\n t*: ", ((uint64_t)1U << lg_prof_sample));
prof_dump_print_cnts(prof_dump_write, cbopaque, cnt_all);
prof_dump_write(cbopaque, "\n");
prof_tdata_dump_iter_arg_t arg = {prof_dump_write, cbopaque};
malloc_mutex_lock(tsdn, &tdatas_mtx);
tdata_tree_iter(&tdatas, NULL, prof_tdata_dump_iter, NULL);
tdata_tree_iter(&tdatas, NULL, prof_tdata_dump_iter, &arg);
malloc_mutex_unlock(tsdn, &tdatas_mtx);
}
prof_dump_header_t *JET_MUTABLE prof_dump_header = prof_dump_header_impl;
static void
prof_dump_gctx(tsdn_t *tsdn, prof_gctx_t *gctx, const prof_bt_t *bt,
prof_gctx_tree_t *gctxs) {
prof_dump_gctx(tsdn_t *tsdn, write_cb_t *prof_dump_write, void *cbopaque,
prof_gctx_t *gctx, const prof_bt_t *bt, prof_gctx_tree_t *gctxs) {
cassert(config_prof);
malloc_mutex_assert_owner(tsdn, gctx->lock);
@ -806,17 +827,18 @@ prof_dump_gctx(tsdn_t *tsdn, prof_gctx_t *gctx, const prof_bt_t *bt,
return;
}
prof_dump_write("@");
prof_dump_write(cbopaque, "@");
for (unsigned i = 0; i < bt->len; i++) {
prof_dump_printf(" %#"FMTxPTR, (uintptr_t)bt->vec[i]);
prof_dump_printf(prof_dump_write, cbopaque, " %#"FMTxPTR,
(uintptr_t)bt->vec[i]);
}
prof_dump_write("\n t*: ");
prof_dump_print_cnts(&gctx->cnt_summed);
prof_dump_write("\n");
prof_dump_write(cbopaque, "\n t*: ");
prof_dump_print_cnts(prof_dump_write, cbopaque, &gctx->cnt_summed);
prof_dump_write(cbopaque, "\n");
tctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_dump_iter,
(void *)tsdn);
prof_tctx_dump_iter_arg_t arg = {tsdn, prof_dump_write, cbopaque};
tctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_dump_iter, &arg);
}
/*
@ -852,12 +874,20 @@ prof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_ngctx) {
#endif
}
typedef struct prof_gctx_dump_iter_arg_s prof_gctx_dump_iter_arg_t;
struct prof_gctx_dump_iter_arg_s {
tsdn_t *tsdn;
write_cb_t *prof_dump_write;
void *cbopaque;
};
static prof_gctx_t *
prof_gctx_dump_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque) {
tsdn_t *tsdn = (tsdn_t *)opaque;
malloc_mutex_lock(tsdn, gctx->lock);
prof_dump_gctx(tsdn, gctx, &gctx->bt, gctxs);
malloc_mutex_unlock(tsdn, gctx->lock);
prof_gctx_dump_iter_arg_t *arg = (prof_gctx_dump_iter_arg_t *)opaque;
malloc_mutex_lock(arg->tsdn, gctx->lock);
prof_dump_gctx(arg->tsdn, arg->prof_dump_write, arg->cbopaque, gctx,
&gctx->bt, gctxs);
malloc_mutex_unlock(arg->tsdn, gctx->lock);
return NULL;
}
@ -904,18 +934,20 @@ prof_dump_prep(tsd_t *tsd, prof_tdata_t *tdata,
}
void
prof_dump_impl(tsd_t *tsd, prof_tdata_t *tdata, void (*write_cb)(const char *),
bool leakcheck) {
prof_dump_impl(tsd_t *tsd, write_cb_t *prof_dump_write, void *cbopaque,
prof_tdata_t *tdata, bool leakcheck) {
malloc_mutex_assert_owner(tsd_tsdn(tsd), &prof_dump_mtx);
prof_dump_write = write_cb;
prof_gctx_tree_t gctxs;
prof_tdata_merge_iter_arg_t prof_tdata_merge_iter_arg;
prof_gctx_merge_iter_arg_t prof_gctx_merge_iter_arg;
prof_dump_prep(tsd, tdata, &prof_tdata_merge_iter_arg,
&prof_gctx_merge_iter_arg, &gctxs);
prof_dump_header(tsd_tsdn(tsd), &prof_tdata_merge_iter_arg.cnt_all);
prof_dump_header(tsd_tsdn(tsd), prof_dump_write, cbopaque,
&prof_tdata_merge_iter_arg.cnt_all);
prof_gctx_dump_iter_arg_t prof_gctx_dump_iter_arg = {tsd_tsdn(tsd),
prof_dump_write, cbopaque};
gctx_tree_iter(&gctxs, NULL, prof_gctx_dump_iter,
(void *)tsd_tsdn(tsd));
&prof_gctx_dump_iter_arg);
prof_gctx_finish(tsd, &gctxs);
if (leakcheck) {
prof_leakcheck(&prof_tdata_merge_iter_arg.cnt_all,

View File

@ -388,11 +388,6 @@ prof_dump_flush(void *cbopaque, const char *s) {
}
}
static void
prof_dump_write(const char *s) {
buf_writer_cb(&prof_dump_buf_writer, s);
}
static void
prof_dump_close() {
if (prof_dump_fd != -1) {
@ -461,7 +456,7 @@ prof_dump_maps() {
return;
}
prof_dump_write("\nMAPPED_LIBRARIES:\n");
buf_writer_cb(&prof_dump_buf_writer, "\nMAPPED_LIBRARIES:\n");
buf_writer_pipe(&prof_dump_buf_writer, prof_dump_read_maps_cb, &mfd);
close(mfd);
}
@ -487,7 +482,8 @@ prof_dump(tsd_t *tsd, bool propagate_err, const char *filename,
bool err = buf_writer_init(tsd_tsdn(tsd), &prof_dump_buf_writer,
prof_dump_flush, NULL, prof_dump_buf, PROF_DUMP_BUFSIZE);
assert(!err);
prof_dump_impl(tsd, tdata, prof_dump_write, leakcheck);
prof_dump_impl(tsd, buf_writer_cb, &prof_dump_buf_writer, tdata,
leakcheck);
prof_dump_maps();
buf_writer_terminate(tsd_tsdn(tsd), &prof_dump_buf_writer);
prof_dump_close();

View File

@ -87,7 +87,8 @@ TEST_END
bool prof_dump_header_intercepted = false;
prof_cnt_t cnt_all_copy = {0, 0, 0, 0};
static void
prof_dump_header_intercept(tsdn_t *tsdn, const prof_cnt_t *cnt_all) {
prof_dump_header_intercept(tsdn_t *tsdn, write_cb_t *cb, void *cbopaque,
const prof_cnt_t *cnt_all) {
prof_dump_header_intercepted = true;
memcpy(&cnt_all_copy, cnt_all, sizeof(prof_cnt_t));
}