0001
0002
0003 #include "hist.h"
0004 #include "evsel.h"
0005 #include "hists.h"
0006 #include "sort.h"
0007 #include "config.h"
0008 #include "time-utils.h"
0009 #include "../util.h"
0010 #include "../../util/util.h" // perf_exe()
0011 #include "../../perf.h"
0012 #include <stdlib.h>
0013 #include <string.h>
0014 #include <linux/time64.h>
0015 #include <linux/zalloc.h>
0016
0017 static u64 context_len = 10 * NSEC_PER_MSEC;
0018
0019 static int res_sample_config(const char *var, const char *value, void *data __maybe_unused)
0020 {
0021 if (!strcmp(var, "samples.context"))
0022 return perf_config_u64(&context_len, var, value);
0023 return 0;
0024 }
0025
0026 void res_sample_init(void)
0027 {
0028 perf_config(res_sample_config, NULL);
0029 }
0030
0031 int res_sample_browse(struct res_sample *res_samples, int num_res,
0032 struct evsel *evsel, enum rstype rstype)
0033 {
0034 char **names;
0035 int i, n;
0036 int choice;
0037 char *cmd;
0038 char pbuf[256], tidbuf[32], cpubuf[32];
0039 const char *perf = perf_exe(pbuf, sizeof pbuf);
0040 char trange[128], tsample[64];
0041 struct res_sample *r;
0042 char extra_format[256];
0043
0044 names = calloc(num_res, sizeof(char *));
0045 if (!names)
0046 return -1;
0047 for (i = 0; i < num_res; i++) {
0048 char tbuf[64];
0049
0050 timestamp__scnprintf_nsec(res_samples[i].time, tbuf, sizeof tbuf);
0051 if (asprintf(&names[i], "%s: CPU %d tid %d", tbuf,
0052 res_samples[i].cpu, res_samples[i].tid) < 0) {
0053 while (--i >= 0)
0054 zfree(&names[i]);
0055 free(names);
0056 return -1;
0057 }
0058 }
0059 choice = ui__popup_menu(num_res, names, NULL);
0060 for (i = 0; i < num_res; i++)
0061 zfree(&names[i]);
0062 free(names);
0063
0064 if (choice < 0 || choice >= num_res)
0065 return -1;
0066 r = &res_samples[choice];
0067
0068 n = timestamp__scnprintf_nsec(r->time - context_len, trange, sizeof trange);
0069 trange[n++] = ',';
0070 timestamp__scnprintf_nsec(r->time + context_len, trange + n, sizeof trange - n);
0071
0072 timestamp__scnprintf_nsec(r->time, tsample, sizeof tsample);
0073
0074 attr_to_script(extra_format, &evsel->core.attr);
0075
0076 if (asprintf(&cmd, "%s script %s%s --time %s %s%s %s%s --ns %s %s %s %s %s | less +/%s",
0077 perf,
0078 input_name ? "-i " : "",
0079 input_name ? input_name : "",
0080 trange,
0081 r->cpu >= 0 ? "--cpu " : "",
0082 r->cpu >= 0 ? (sprintf(cpubuf, "%d", r->cpu), cpubuf) : "",
0083 r->tid ? "--tid " : "",
0084 r->tid ? (sprintf(tidbuf, "%d", r->tid), tidbuf) : "",
0085 extra_format,
0086 rstype == A_ASM ? "-F +insn --xed" :
0087 rstype == A_SOURCE ? "-F +srcline,+srccode" : "",
0088 symbol_conf.inline_name ? "--inline" : "",
0089 "--show-lost-events ",
0090 r->tid ? "--show-switch-events --show-task-events " : "",
0091 tsample) < 0)
0092 return -1;
0093 run_script(cmd);
0094 free(cmd);
0095 return 0;
0096 }