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);
|
prof_tctx_t *prof_lookup(tsd_t *tsd, prof_bt_t *bt);
|
||||||
char *prof_thread_name_alloc(tsd_t *tsd, const char *thread_name);
|
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);
|
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 prof_dump_impl(tsd_t *tsd, write_cb_t *prof_dump_write, void *cbopaque,
|
||||||
void (*write_cb)(const char *), bool leakcheck);
|
prof_tdata_t *tdata, bool leakcheck);
|
||||||
prof_tdata_t * prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid,
|
prof_tdata_t * prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid,
|
||||||
uint64_t thr_discrim, char *thread_name, bool active);
|
uint64_t thr_discrim, char *thread_name, bool active);
|
||||||
void prof_tdata_detach(tsd_t *tsd, prof_tdata_t *tdata);
|
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. */
|
/* Used in unit tests. */
|
||||||
size_t prof_tdata_count(void);
|
size_t prof_tdata_count(void);
|
||||||
size_t prof_bt_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;
|
extern prof_dump_header_t *JET_MUTABLE prof_dump_header;
|
||||||
void prof_cnt_all(uint64_t *curobjs, uint64_t *curbytes, uint64_t *accumobjs,
|
void prof_cnt_all(uint64_t *curobjs, uint64_t *curbytes, uint64_t *accumobjs,
|
||||||
uint64_t *accumbytes);
|
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;
|
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. */
|
/* Red-black trees. */
|
||||||
|
|
||||||
@ -504,21 +501,24 @@ prof_thread_name_set_impl(tsd_t *tsd, const char *thread_name) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
JEMALLOC_FORMAT_PRINTF(1, 2)
|
JEMALLOC_FORMAT_PRINTF(3, 4)
|
||||||
static void
|
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;
|
va_list ap;
|
||||||
char buf[PROF_PRINTF_BUFSIZE];
|
char buf[PROF_PRINTF_BUFSIZE];
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
malloc_vsnprintf(buf, sizeof(buf), format, ap);
|
malloc_vsnprintf(buf, sizeof(buf), format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
prof_dump_write(buf);
|
prof_dump_write(cbopaque, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prof_dump_print_cnts(const prof_cnt_t *cnts) {
|
prof_dump_print_cnts(write_cb_t *prof_dump_write, void *cbopaque,
|
||||||
prof_dump_printf("%"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]",
|
const prof_cnt_t *cnts) {
|
||||||
|
prof_dump_printf(prof_dump_write, cbopaque,
|
||||||
|
"%"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]",
|
||||||
cnts->curobjs, cnts->curbytes, cnts->accumobjs, cnts->accumbytes);
|
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;
|
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 *
|
static prof_tctx_t *
|
||||||
prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) {
|
prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *opaque) {
|
||||||
tsdn_t *tsdn = (tsdn_t *)arg;
|
prof_tctx_dump_iter_arg_t *arg = (prof_tctx_dump_iter_arg_t *)opaque;
|
||||||
malloc_mutex_assert_owner(tsdn, tctx->gctx->lock);
|
malloc_mutex_assert_owner(arg->tsdn, tctx->gctx->lock);
|
||||||
|
|
||||||
switch (tctx->state) {
|
switch (tctx->state) {
|
||||||
case prof_tctx_state_initializing:
|
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;
|
break;
|
||||||
case prof_tctx_state_dumping:
|
case prof_tctx_state_dumping:
|
||||||
case prof_tctx_state_purgatory:
|
case prof_tctx_state_purgatory:
|
||||||
prof_dump_printf(" t%"FMTu64": ", tctx->thr_uid);
|
prof_dump_printf(arg->prof_dump_write, arg->cbopaque,
|
||||||
prof_dump_print_cnts(&tctx->dump_cnts);
|
" t%"FMTu64": ", tctx->thr_uid);
|
||||||
prof_dump_write("\n");
|
prof_dump_print_cnts(arg->prof_dump_write, arg->cbopaque,
|
||||||
|
&tctx->dump_cnts);
|
||||||
|
arg->prof_dump_write(arg->cbopaque, "\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
not_reached();
|
not_reached();
|
||||||
@ -761,38 +770,50 @@ prof_tdata_merge_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata,
|
|||||||
return NULL;
|
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 *
|
static prof_tdata_t *
|
||||||
prof_tdata_dump_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata,
|
prof_tdata_dump_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata,
|
||||||
void *unused) {
|
void *opaque) {
|
||||||
if (!tdata->dumping) {
|
if (!tdata->dumping) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
prof_dump_printf(" t%"FMTu64": ", tdata->thr_uid);
|
prof_tdata_dump_iter_arg_t *arg = (prof_tdata_dump_iter_arg_t *)opaque;
|
||||||
prof_dump_print_cnts(&tdata->cnt_summed);
|
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) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prof_dump_header_impl(tsdn_t *tsdn, const prof_cnt_t *cnt_all) {
|
prof_dump_header_impl(tsdn_t *tsdn, write_cb_t *prof_dump_write,
|
||||||
prof_dump_printf("heap_v2/%"FMTu64"\n t*: ",
|
void *cbopaque, const prof_cnt_t *cnt_all) {
|
||||||
((uint64_t)1U << lg_prof_sample));
|
prof_dump_printf(prof_dump_write, cbopaque,
|
||||||
prof_dump_print_cnts(cnt_all);
|
"heap_v2/%"FMTu64"\n t*: ", ((uint64_t)1U << lg_prof_sample));
|
||||||
prof_dump_write("\n");
|
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);
|
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);
|
malloc_mutex_unlock(tsdn, &tdatas_mtx);
|
||||||
}
|
}
|
||||||
prof_dump_header_t *JET_MUTABLE prof_dump_header = prof_dump_header_impl;
|
prof_dump_header_t *JET_MUTABLE prof_dump_header = prof_dump_header_impl;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prof_dump_gctx(tsdn_t *tsdn, prof_gctx_t *gctx, const prof_bt_t *bt,
|
prof_dump_gctx(tsdn_t *tsdn, write_cb_t *prof_dump_write, void *cbopaque,
|
||||||
prof_gctx_tree_t *gctxs) {
|
prof_gctx_t *gctx, const prof_bt_t *bt, prof_gctx_tree_t *gctxs) {
|
||||||
cassert(config_prof);
|
cassert(config_prof);
|
||||||
malloc_mutex_assert_owner(tsdn, gctx->lock);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prof_dump_write("@");
|
prof_dump_write(cbopaque, "@");
|
||||||
for (unsigned i = 0; i < bt->len; i++) {
|
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_write(cbopaque, "\n t*: ");
|
||||||
prof_dump_print_cnts(&gctx->cnt_summed);
|
prof_dump_print_cnts(prof_dump_write, cbopaque, &gctx->cnt_summed);
|
||||||
prof_dump_write("\n");
|
prof_dump_write(cbopaque, "\n");
|
||||||
|
|
||||||
tctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_dump_iter,
|
prof_tctx_dump_iter_arg_t arg = {tsdn, prof_dump_write, cbopaque};
|
||||||
(void *)tsdn);
|
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
|
#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 *
|
static prof_gctx_t *
|
||||||
prof_gctx_dump_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque) {
|
prof_gctx_dump_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque) {
|
||||||
tsdn_t *tsdn = (tsdn_t *)opaque;
|
prof_gctx_dump_iter_arg_t *arg = (prof_gctx_dump_iter_arg_t *)opaque;
|
||||||
malloc_mutex_lock(tsdn, gctx->lock);
|
malloc_mutex_lock(arg->tsdn, gctx->lock);
|
||||||
prof_dump_gctx(tsdn, gctx, &gctx->bt, gctxs);
|
prof_dump_gctx(arg->tsdn, arg->prof_dump_write, arg->cbopaque, gctx,
|
||||||
malloc_mutex_unlock(tsdn, gctx->lock);
|
&gctx->bt, gctxs);
|
||||||
|
malloc_mutex_unlock(arg->tsdn, gctx->lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -904,18 +934,20 @@ prof_dump_prep(tsd_t *tsd, prof_tdata_t *tdata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
prof_dump_impl(tsd_t *tsd, prof_tdata_t *tdata, void (*write_cb)(const char *),
|
prof_dump_impl(tsd_t *tsd, write_cb_t *prof_dump_write, void *cbopaque,
|
||||||
bool leakcheck) {
|
prof_tdata_t *tdata, bool leakcheck) {
|
||||||
malloc_mutex_assert_owner(tsd_tsdn(tsd), &prof_dump_mtx);
|
malloc_mutex_assert_owner(tsd_tsdn(tsd), &prof_dump_mtx);
|
||||||
prof_dump_write = write_cb;
|
|
||||||
prof_gctx_tree_t gctxs;
|
prof_gctx_tree_t gctxs;
|
||||||
prof_tdata_merge_iter_arg_t prof_tdata_merge_iter_arg;
|
prof_tdata_merge_iter_arg_t prof_tdata_merge_iter_arg;
|
||||||
prof_gctx_merge_iter_arg_t prof_gctx_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_dump_prep(tsd, tdata, &prof_tdata_merge_iter_arg,
|
||||||
&prof_gctx_merge_iter_arg, &gctxs);
|
&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,
|
gctx_tree_iter(&gctxs, NULL, prof_gctx_dump_iter,
|
||||||
(void *)tsd_tsdn(tsd));
|
&prof_gctx_dump_iter_arg);
|
||||||
prof_gctx_finish(tsd, &gctxs);
|
prof_gctx_finish(tsd, &gctxs);
|
||||||
if (leakcheck) {
|
if (leakcheck) {
|
||||||
prof_leakcheck(&prof_tdata_merge_iter_arg.cnt_all,
|
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
|
static void
|
||||||
prof_dump_close() {
|
prof_dump_close() {
|
||||||
if (prof_dump_fd != -1) {
|
if (prof_dump_fd != -1) {
|
||||||
@ -461,7 +456,7 @@ prof_dump_maps() {
|
|||||||
return;
|
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);
|
buf_writer_pipe(&prof_dump_buf_writer, prof_dump_read_maps_cb, &mfd);
|
||||||
close(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,
|
bool err = buf_writer_init(tsd_tsdn(tsd), &prof_dump_buf_writer,
|
||||||
prof_dump_flush, NULL, prof_dump_buf, PROF_DUMP_BUFSIZE);
|
prof_dump_flush, NULL, prof_dump_buf, PROF_DUMP_BUFSIZE);
|
||||||
assert(!err);
|
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();
|
prof_dump_maps();
|
||||||
buf_writer_terminate(tsd_tsdn(tsd), &prof_dump_buf_writer);
|
buf_writer_terminate(tsd_tsdn(tsd), &prof_dump_buf_writer);
|
||||||
prof_dump_close();
|
prof_dump_close();
|
||||||
|
@ -87,7 +87,8 @@ TEST_END
|
|||||||
bool prof_dump_header_intercepted = false;
|
bool prof_dump_header_intercepted = false;
|
||||||
prof_cnt_t cnt_all_copy = {0, 0, 0, 0};
|
prof_cnt_t cnt_all_copy = {0, 0, 0, 0};
|
||||||
static void
|
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;
|
prof_dump_header_intercepted = true;
|
||||||
memcpy(&cnt_all_copy, cnt_all, sizeof(prof_cnt_t));
|
memcpy(&cnt_all_copy, cnt_all, sizeof(prof_cnt_t));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user