res_sample.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Display a menu with individual samples to browse with perf script */
  3. #include "hist.h"
  4. #include "evsel.h"
  5. #include "hists.h"
  6. #include "sort.h"
  7. #include "config.h"
  8. #include "time-utils.h"
  9. #include "../util.h"
  10. #include "../../util/util.h" // perf_exe()
  11. #include "../../perf.h"
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <linux/time64.h>
  15. #include <linux/zalloc.h>
  16. static u64 context_len = 10 * NSEC_PER_MSEC;
  17. static int res_sample_config(const char *var, const char *value, void *data __maybe_unused)
  18. {
  19. if (!strcmp(var, "samples.context"))
  20. return perf_config_u64(&context_len, var, value);
  21. return 0;
  22. }
  23. void res_sample_init(void)
  24. {
  25. perf_config(res_sample_config, NULL);
  26. }
  27. int res_sample_browse(struct res_sample *res_samples, int num_res,
  28. struct evsel *evsel, enum rstype rstype)
  29. {
  30. char **names;
  31. int i, n;
  32. int choice;
  33. char *cmd;
  34. char pbuf[256], tidbuf[32], cpubuf[32];
  35. const char *perf = perf_exe(pbuf, sizeof pbuf);
  36. char trange[128], tsample[64];
  37. struct res_sample *r;
  38. char extra_format[256];
  39. names = calloc(num_res, sizeof(char *));
  40. if (!names)
  41. return -1;
  42. for (i = 0; i < num_res; i++) {
  43. char tbuf[64];
  44. timestamp__scnprintf_nsec(res_samples[i].time, tbuf, sizeof tbuf);
  45. if (asprintf(&names[i], "%s: CPU %d tid %d", tbuf,
  46. res_samples[i].cpu, res_samples[i].tid) < 0) {
  47. while (--i >= 0)
  48. zfree(&names[i]);
  49. free(names);
  50. return -1;
  51. }
  52. }
  53. choice = ui__popup_menu(num_res, names, NULL);
  54. for (i = 0; i < num_res; i++)
  55. zfree(&names[i]);
  56. free(names);
  57. if (choice < 0 || choice >= num_res)
  58. return -1;
  59. r = &res_samples[choice];
  60. n = timestamp__scnprintf_nsec(r->time - context_len, trange, sizeof trange);
  61. trange[n++] = ',';
  62. timestamp__scnprintf_nsec(r->time + context_len, trange + n, sizeof trange - n);
  63. timestamp__scnprintf_nsec(r->time, tsample, sizeof tsample);
  64. attr_to_script(extra_format, &evsel->core.attr);
  65. if (asprintf(&cmd, "%s script %s%s --time %s %s%s %s%s --ns %s %s %s %s %s | less +/%s",
  66. perf,
  67. input_name ? "-i " : "",
  68. input_name ? input_name : "",
  69. trange,
  70. r->cpu >= 0 ? "--cpu " : "",
  71. r->cpu >= 0 ? (sprintf(cpubuf, "%d", r->cpu), cpubuf) : "",
  72. r->tid ? "--tid " : "",
  73. r->tid ? (sprintf(tidbuf, "%d", r->tid), tidbuf) : "",
  74. extra_format,
  75. rstype == A_ASM ? "-F +disasm" :
  76. rstype == A_SOURCE ? "-F +srcline,+srccode" : "",
  77. symbol_conf.inline_name ? "--inline" : "",
  78. "--show-lost-events ",
  79. r->tid ? "--show-switch-events --show-task-events " : "",
  80. tsample) < 0)
  81. return -1;
  82. run_script(cmd);
  83. free(cmd);
  84. return 0;
  85. }