- return cpu_usage;
-}
-
-static uint32_t
-hash_trace(struct trace *trace)
-{
- return hash_bytes(trace->backtrace,
- trace->n_frames * sizeof *trace->backtrace, 0);
-}
-
-static struct trace *
-trace_map_lookup(struct hmap *trace_map, struct trace *key)
-{
- struct trace *value;
-
- HMAP_FOR_EACH_WITH_HASH (value, node, hash_trace(key), trace_map) {
- if (key->n_frames == value->n_frames
- && !memcmp(key->backtrace, value->backtrace,
- key->n_frames * sizeof *key->backtrace)) {
- return value;
- }
- }
- return NULL;
-}
-
-/* Appends a string to 'ds' representing backtraces recorded at regular
- * intervals in the recent past. This information can be used to get a sense
- * of what the process has been spending the majority of time doing. Will
- * ommit any backtraces which have not occurred at least 'min_count' times. */
-void
-format_backtraces(struct ds *ds, size_t min_count)
-{
- time_init();
-
- if (HAVE_EXECINFO_H && CACHE_TIME) {
- struct hmap trace_map = HMAP_INITIALIZER(&trace_map);
- struct trace *trace, *next;
- sigset_t oldsigs;
- size_t i;
-
- block_sigalrm(&oldsigs);
-
- for (i = 0; i < MAX_TRACES; i++) {
- struct trace *trace = &traces[i];
- struct trace *map_trace;
-
- if (!trace->n_frames) {
- continue;
- }
-
- map_trace = trace_map_lookup(&trace_map, trace);
- if (map_trace) {
- map_trace->count++;
- } else {
- hmap_insert(&trace_map, &trace->node, hash_trace(trace));
- trace->count = 1;
- }
- }
-
- HMAP_FOR_EACH_SAFE (trace, next, node, &trace_map) {
- char **frame_strs;
- size_t j;
-
- hmap_remove(&trace_map, &trace->node);
-
- if (trace->count < min_count) {
- continue;
- }
-
- frame_strs = backtrace_symbols(trace->backtrace, trace->n_frames);
-
- ds_put_format(ds, "Count %zu\n", trace->count);
- for (j = 0; j < trace->n_frames; j++) {
- ds_put_format(ds, "%s\n", frame_strs[j]);
- }
- ds_put_cstr(ds, "\n");
-
- free(frame_strs);
- }
- hmap_destroy(&trace_map);
-
- ds_chomp(ds, '\n');
- unblock_sigalrm(&oldsigs);
- }