| 1061 | } |
| 1062 | |
| 1063 | static void |
| 1064 | prof_dump_prep(tsd_t *tsd, prof_tdata_t *tdata, prof_cnt_t *cnt_all, |
| 1065 | size_t *leak_ngctx, prof_gctx_tree_t *gctxs) { |
| 1066 | size_t tabind; |
| 1067 | union { |
| 1068 | prof_gctx_t *p; |
| 1069 | void *v; |
| 1070 | } gctx; |
| 1071 | |
| 1072 | prof_enter(tsd, tdata); |
| 1073 | |
| 1074 | /* |
| 1075 | * Put gctx's in limbo and clear their counters in preparation for |
| 1076 | * summing. |
| 1077 | */ |
| 1078 | gctx_tree_new(gctxs); |
| 1079 | for (tabind = 0; !ckh_iter(&bt2gctx, &tabind, NULL, &gctx.v);) { |
| 1080 | prof_dump_gctx_prep(tsd_tsdn(tsd), gctx.p, gctxs); |
| 1081 | } |
| 1082 | |
| 1083 | /* |
| 1084 | * Iterate over tdatas, and for the non-expired ones snapshot their tctx |
| 1085 | * stats and merge them into the associated gctx's. |
| 1086 | */ |
| 1087 | memset(cnt_all, 0, sizeof(prof_cnt_t)); |
| 1088 | prof_tdata_merge_iter_arg_t prof_tdata_merge_iter_arg = {tsd_tsdn(tsd), |
| 1089 | cnt_all}; |
| 1090 | malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx); |
| 1091 | tdata_tree_iter(&tdatas, NULL, prof_tdata_merge_iter, |
| 1092 | &prof_tdata_merge_iter_arg); |
| 1093 | malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx); |
| 1094 | |
| 1095 | /* Merge tctx stats into gctx's. */ |
| 1096 | *leak_ngctx = 0; |
| 1097 | prof_gctx_merge_iter_arg_t prof_gctx_merge_iter_arg = {tsd_tsdn(tsd), |
| 1098 | leak_ngctx}; |
| 1099 | gctx_tree_iter(gctxs, NULL, prof_gctx_merge_iter, |
| 1100 | &prof_gctx_merge_iter_arg); |
| 1101 | |
| 1102 | prof_leave(tsd, tdata); |
| 1103 | } |
| 1104 | |
| 1105 | void |
| 1106 | prof_dump_impl(tsd_t *tsd, write_cb_t *prof_dump_write, void *cbopaque, |
no test coverage detected