Pass write callback explicitly in prof_data
This commit is contained in:
parent
4556d3c0c8
commit
1f5fe3a3e3
@ -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);
|
||||
|
118
src/prof_data.c
118
src/prof_data.c
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user