builtin-ftrace.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * builtin-ftrace.c
  4. *
  5. * Copyright (c) 2013 LG Electronics, Namhyung Kim <[email protected]>
  6. * Copyright (c) 2020 Changbin Du <[email protected]>, significant enhancement.
  7. */
  8. #include "builtin.h"
  9. #include <errno.h>
  10. #include <unistd.h>
  11. #include <signal.h>
  12. #include <stdlib.h>
  13. #include <fcntl.h>
  14. #include <math.h>
  15. #include <poll.h>
  16. #include <ctype.h>
  17. #include <linux/capability.h>
  18. #include <linux/string.h>
  19. #include "debug.h"
  20. #include <subcmd/pager.h>
  21. #include <subcmd/parse-options.h>
  22. #include <api/fs/tracing_path.h>
  23. #include "evlist.h"
  24. #include "target.h"
  25. #include "cpumap.h"
  26. #include "thread_map.h"
  27. #include "strfilter.h"
  28. #include "util/cap.h"
  29. #include "util/config.h"
  30. #include "util/ftrace.h"
  31. #include "util/units.h"
  32. #include "util/parse-sublevel-options.h"
  33. #define DEFAULT_TRACER "function_graph"
  34. static volatile int workload_exec_errno;
  35. static bool done;
  36. static void sig_handler(int sig __maybe_unused)
  37. {
  38. done = true;
  39. }
  40. /*
  41. * evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
  42. * we asked by setting its exec_error to the function below,
  43. * ftrace__workload_exec_failed_signal.
  44. *
  45. * XXX We need to handle this more appropriately, emitting an error, etc.
  46. */
  47. static void ftrace__workload_exec_failed_signal(int signo __maybe_unused,
  48. siginfo_t *info __maybe_unused,
  49. void *ucontext __maybe_unused)
  50. {
  51. workload_exec_errno = info->si_value.sival_int;
  52. done = true;
  53. }
  54. static int __write_tracing_file(const char *name, const char *val, bool append)
  55. {
  56. char *file;
  57. int fd, ret = -1;
  58. ssize_t size = strlen(val);
  59. int flags = O_WRONLY;
  60. char errbuf[512];
  61. char *val_copy;
  62. file = get_tracing_file(name);
  63. if (!file) {
  64. pr_debug("cannot get tracing file: %s\n", name);
  65. return -1;
  66. }
  67. if (append)
  68. flags |= O_APPEND;
  69. else
  70. flags |= O_TRUNC;
  71. fd = open(file, flags);
  72. if (fd < 0) {
  73. pr_debug("cannot open tracing file: %s: %s\n",
  74. name, str_error_r(errno, errbuf, sizeof(errbuf)));
  75. goto out;
  76. }
  77. /*
  78. * Copy the original value and append a '\n'. Without this,
  79. * the kernel can hide possible errors.
  80. */
  81. val_copy = strdup(val);
  82. if (!val_copy)
  83. goto out_close;
  84. val_copy[size] = '\n';
  85. if (write(fd, val_copy, size + 1) == size + 1)
  86. ret = 0;
  87. else
  88. pr_debug("write '%s' to tracing/%s failed: %s\n",
  89. val, name, str_error_r(errno, errbuf, sizeof(errbuf)));
  90. free(val_copy);
  91. out_close:
  92. close(fd);
  93. out:
  94. put_tracing_file(file);
  95. return ret;
  96. }
  97. static int write_tracing_file(const char *name, const char *val)
  98. {
  99. return __write_tracing_file(name, val, false);
  100. }
  101. static int append_tracing_file(const char *name, const char *val)
  102. {
  103. return __write_tracing_file(name, val, true);
  104. }
  105. static int read_tracing_file_to_stdout(const char *name)
  106. {
  107. char buf[4096];
  108. char *file;
  109. int fd;
  110. int ret = -1;
  111. file = get_tracing_file(name);
  112. if (!file) {
  113. pr_debug("cannot get tracing file: %s\n", name);
  114. return -1;
  115. }
  116. fd = open(file, O_RDONLY);
  117. if (fd < 0) {
  118. pr_debug("cannot open tracing file: %s: %s\n",
  119. name, str_error_r(errno, buf, sizeof(buf)));
  120. goto out;
  121. }
  122. /* read contents to stdout */
  123. while (true) {
  124. int n = read(fd, buf, sizeof(buf));
  125. if (n == 0)
  126. break;
  127. else if (n < 0)
  128. goto out_close;
  129. if (fwrite(buf, n, 1, stdout) != 1)
  130. goto out_close;
  131. }
  132. ret = 0;
  133. out_close:
  134. close(fd);
  135. out:
  136. put_tracing_file(file);
  137. return ret;
  138. }
  139. static int read_tracing_file_by_line(const char *name,
  140. void (*cb)(char *str, void *arg),
  141. void *cb_arg)
  142. {
  143. char *line = NULL;
  144. size_t len = 0;
  145. char *file;
  146. FILE *fp;
  147. file = get_tracing_file(name);
  148. if (!file) {
  149. pr_debug("cannot get tracing file: %s\n", name);
  150. return -1;
  151. }
  152. fp = fopen(file, "r");
  153. if (fp == NULL) {
  154. pr_debug("cannot open tracing file: %s\n", name);
  155. put_tracing_file(file);
  156. return -1;
  157. }
  158. while (getline(&line, &len, fp) != -1) {
  159. cb(line, cb_arg);
  160. }
  161. if (line)
  162. free(line);
  163. fclose(fp);
  164. put_tracing_file(file);
  165. return 0;
  166. }
  167. static int write_tracing_file_int(const char *name, int value)
  168. {
  169. char buf[16];
  170. snprintf(buf, sizeof(buf), "%d", value);
  171. if (write_tracing_file(name, buf) < 0)
  172. return -1;
  173. return 0;
  174. }
  175. static int write_tracing_option_file(const char *name, const char *val)
  176. {
  177. char *file;
  178. int ret;
  179. if (asprintf(&file, "options/%s", name) < 0)
  180. return -1;
  181. ret = __write_tracing_file(file, val, false);
  182. free(file);
  183. return ret;
  184. }
  185. static int reset_tracing_cpu(void);
  186. static void reset_tracing_filters(void);
  187. static void reset_tracing_options(struct perf_ftrace *ftrace __maybe_unused)
  188. {
  189. write_tracing_option_file("function-fork", "0");
  190. write_tracing_option_file("func_stack_trace", "0");
  191. write_tracing_option_file("sleep-time", "1");
  192. write_tracing_option_file("funcgraph-irqs", "1");
  193. write_tracing_option_file("funcgraph-proc", "0");
  194. write_tracing_option_file("funcgraph-abstime", "0");
  195. write_tracing_option_file("latency-format", "0");
  196. write_tracing_option_file("irq-info", "0");
  197. }
  198. static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
  199. {
  200. if (write_tracing_file("tracing_on", "0") < 0)
  201. return -1;
  202. if (write_tracing_file("current_tracer", "nop") < 0)
  203. return -1;
  204. if (write_tracing_file("set_ftrace_pid", " ") < 0)
  205. return -1;
  206. if (reset_tracing_cpu() < 0)
  207. return -1;
  208. if (write_tracing_file("max_graph_depth", "0") < 0)
  209. return -1;
  210. if (write_tracing_file("tracing_thresh", "0") < 0)
  211. return -1;
  212. reset_tracing_filters();
  213. reset_tracing_options(ftrace);
  214. return 0;
  215. }
  216. static int set_tracing_pid(struct perf_ftrace *ftrace)
  217. {
  218. int i;
  219. char buf[16];
  220. if (target__has_cpu(&ftrace->target))
  221. return 0;
  222. for (i = 0; i < perf_thread_map__nr(ftrace->evlist->core.threads); i++) {
  223. scnprintf(buf, sizeof(buf), "%d",
  224. perf_thread_map__pid(ftrace->evlist->core.threads, i));
  225. if (append_tracing_file("set_ftrace_pid", buf) < 0)
  226. return -1;
  227. }
  228. return 0;
  229. }
  230. static int set_tracing_cpumask(struct perf_cpu_map *cpumap)
  231. {
  232. char *cpumask;
  233. size_t mask_size;
  234. int ret;
  235. int last_cpu;
  236. last_cpu = perf_cpu_map__cpu(cpumap, perf_cpu_map__nr(cpumap) - 1).cpu;
  237. mask_size = last_cpu / 4 + 2; /* one more byte for EOS */
  238. mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */
  239. cpumask = malloc(mask_size);
  240. if (cpumask == NULL) {
  241. pr_debug("failed to allocate cpu mask\n");
  242. return -1;
  243. }
  244. cpu_map__snprint_mask(cpumap, cpumask, mask_size);
  245. ret = write_tracing_file("tracing_cpumask", cpumask);
  246. free(cpumask);
  247. return ret;
  248. }
  249. static int set_tracing_cpu(struct perf_ftrace *ftrace)
  250. {
  251. struct perf_cpu_map *cpumap = ftrace->evlist->core.user_requested_cpus;
  252. if (!target__has_cpu(&ftrace->target))
  253. return 0;
  254. return set_tracing_cpumask(cpumap);
  255. }
  256. static int set_tracing_func_stack_trace(struct perf_ftrace *ftrace)
  257. {
  258. if (!ftrace->func_stack_trace)
  259. return 0;
  260. if (write_tracing_option_file("func_stack_trace", "1") < 0)
  261. return -1;
  262. return 0;
  263. }
  264. static int set_tracing_func_irqinfo(struct perf_ftrace *ftrace)
  265. {
  266. if (!ftrace->func_irq_info)
  267. return 0;
  268. if (write_tracing_option_file("irq-info", "1") < 0)
  269. return -1;
  270. return 0;
  271. }
  272. static int reset_tracing_cpu(void)
  273. {
  274. struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
  275. int ret;
  276. ret = set_tracing_cpumask(cpumap);
  277. perf_cpu_map__put(cpumap);
  278. return ret;
  279. }
  280. static int __set_tracing_filter(const char *filter_file, struct list_head *funcs)
  281. {
  282. struct filter_entry *pos;
  283. list_for_each_entry(pos, funcs, list) {
  284. if (append_tracing_file(filter_file, pos->name) < 0)
  285. return -1;
  286. }
  287. return 0;
  288. }
  289. static int set_tracing_filters(struct perf_ftrace *ftrace)
  290. {
  291. int ret;
  292. ret = __set_tracing_filter("set_ftrace_filter", &ftrace->filters);
  293. if (ret < 0)
  294. return ret;
  295. ret = __set_tracing_filter("set_ftrace_notrace", &ftrace->notrace);
  296. if (ret < 0)
  297. return ret;
  298. ret = __set_tracing_filter("set_graph_function", &ftrace->graph_funcs);
  299. if (ret < 0)
  300. return ret;
  301. /* old kernels do not have this filter */
  302. __set_tracing_filter("set_graph_notrace", &ftrace->nograph_funcs);
  303. return ret;
  304. }
  305. static void reset_tracing_filters(void)
  306. {
  307. write_tracing_file("set_ftrace_filter", " ");
  308. write_tracing_file("set_ftrace_notrace", " ");
  309. write_tracing_file("set_graph_function", " ");
  310. write_tracing_file("set_graph_notrace", " ");
  311. }
  312. static int set_tracing_depth(struct perf_ftrace *ftrace)
  313. {
  314. if (ftrace->graph_depth == 0)
  315. return 0;
  316. if (ftrace->graph_depth < 0) {
  317. pr_err("invalid graph depth: %d\n", ftrace->graph_depth);
  318. return -1;
  319. }
  320. if (write_tracing_file_int("max_graph_depth", ftrace->graph_depth) < 0)
  321. return -1;
  322. return 0;
  323. }
  324. static int set_tracing_percpu_buffer_size(struct perf_ftrace *ftrace)
  325. {
  326. int ret;
  327. if (ftrace->percpu_buffer_size == 0)
  328. return 0;
  329. ret = write_tracing_file_int("buffer_size_kb",
  330. ftrace->percpu_buffer_size / 1024);
  331. if (ret < 0)
  332. return ret;
  333. return 0;
  334. }
  335. static int set_tracing_trace_inherit(struct perf_ftrace *ftrace)
  336. {
  337. if (!ftrace->inherit)
  338. return 0;
  339. if (write_tracing_option_file("function-fork", "1") < 0)
  340. return -1;
  341. return 0;
  342. }
  343. static int set_tracing_sleep_time(struct perf_ftrace *ftrace)
  344. {
  345. if (!ftrace->graph_nosleep_time)
  346. return 0;
  347. if (write_tracing_option_file("sleep-time", "0") < 0)
  348. return -1;
  349. return 0;
  350. }
  351. static int set_tracing_funcgraph_irqs(struct perf_ftrace *ftrace)
  352. {
  353. if (!ftrace->graph_noirqs)
  354. return 0;
  355. if (write_tracing_option_file("funcgraph-irqs", "0") < 0)
  356. return -1;
  357. return 0;
  358. }
  359. static int set_tracing_funcgraph_verbose(struct perf_ftrace *ftrace)
  360. {
  361. if (!ftrace->graph_verbose)
  362. return 0;
  363. if (write_tracing_option_file("funcgraph-proc", "1") < 0)
  364. return -1;
  365. if (write_tracing_option_file("funcgraph-abstime", "1") < 0)
  366. return -1;
  367. if (write_tracing_option_file("latency-format", "1") < 0)
  368. return -1;
  369. return 0;
  370. }
  371. static int set_tracing_thresh(struct perf_ftrace *ftrace)
  372. {
  373. int ret;
  374. if (ftrace->graph_thresh == 0)
  375. return 0;
  376. ret = write_tracing_file_int("tracing_thresh", ftrace->graph_thresh);
  377. if (ret < 0)
  378. return ret;
  379. return 0;
  380. }
  381. static int set_tracing_options(struct perf_ftrace *ftrace)
  382. {
  383. if (set_tracing_pid(ftrace) < 0) {
  384. pr_err("failed to set ftrace pid\n");
  385. return -1;
  386. }
  387. if (set_tracing_cpu(ftrace) < 0) {
  388. pr_err("failed to set tracing cpumask\n");
  389. return -1;
  390. }
  391. if (set_tracing_func_stack_trace(ftrace) < 0) {
  392. pr_err("failed to set tracing option func_stack_trace\n");
  393. return -1;
  394. }
  395. if (set_tracing_func_irqinfo(ftrace) < 0) {
  396. pr_err("failed to set tracing option irq-info\n");
  397. return -1;
  398. }
  399. if (set_tracing_filters(ftrace) < 0) {
  400. pr_err("failed to set tracing filters\n");
  401. return -1;
  402. }
  403. if (set_tracing_depth(ftrace) < 0) {
  404. pr_err("failed to set graph depth\n");
  405. return -1;
  406. }
  407. if (set_tracing_percpu_buffer_size(ftrace) < 0) {
  408. pr_err("failed to set tracing per-cpu buffer size\n");
  409. return -1;
  410. }
  411. if (set_tracing_trace_inherit(ftrace) < 0) {
  412. pr_err("failed to set tracing option function-fork\n");
  413. return -1;
  414. }
  415. if (set_tracing_sleep_time(ftrace) < 0) {
  416. pr_err("failed to set tracing option sleep-time\n");
  417. return -1;
  418. }
  419. if (set_tracing_funcgraph_irqs(ftrace) < 0) {
  420. pr_err("failed to set tracing option funcgraph-irqs\n");
  421. return -1;
  422. }
  423. if (set_tracing_funcgraph_verbose(ftrace) < 0) {
  424. pr_err("failed to set tracing option funcgraph-proc/funcgraph-abstime\n");
  425. return -1;
  426. }
  427. if (set_tracing_thresh(ftrace) < 0) {
  428. pr_err("failed to set tracing thresh\n");
  429. return -1;
  430. }
  431. return 0;
  432. }
  433. static void select_tracer(struct perf_ftrace *ftrace)
  434. {
  435. bool graph = !list_empty(&ftrace->graph_funcs) ||
  436. !list_empty(&ftrace->nograph_funcs);
  437. bool func = !list_empty(&ftrace->filters) ||
  438. !list_empty(&ftrace->notrace);
  439. /* The function_graph has priority over function tracer. */
  440. if (graph)
  441. ftrace->tracer = "function_graph";
  442. else if (func)
  443. ftrace->tracer = "function";
  444. /* Otherwise, the default tracer is used. */
  445. pr_debug("%s tracer is used\n", ftrace->tracer);
  446. }
  447. static int __cmd_ftrace(struct perf_ftrace *ftrace)
  448. {
  449. char *trace_file;
  450. int trace_fd;
  451. char buf[4096];
  452. struct pollfd pollfd = {
  453. .events = POLLIN,
  454. };
  455. if (!(perf_cap__capable(CAP_PERFMON) ||
  456. perf_cap__capable(CAP_SYS_ADMIN))) {
  457. pr_err("ftrace only works for %s!\n",
  458. #ifdef HAVE_LIBCAP_SUPPORT
  459. "users with the CAP_PERFMON or CAP_SYS_ADMIN capability"
  460. #else
  461. "root"
  462. #endif
  463. );
  464. return -1;
  465. }
  466. select_tracer(ftrace);
  467. if (reset_tracing_files(ftrace) < 0) {
  468. pr_err("failed to reset ftrace\n");
  469. goto out;
  470. }
  471. /* reset ftrace buffer */
  472. if (write_tracing_file("trace", "0") < 0)
  473. goto out;
  474. if (set_tracing_options(ftrace) < 0)
  475. goto out_reset;
  476. if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
  477. pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
  478. goto out_reset;
  479. }
  480. setup_pager();
  481. trace_file = get_tracing_file("trace_pipe");
  482. if (!trace_file) {
  483. pr_err("failed to open trace_pipe\n");
  484. goto out_reset;
  485. }
  486. trace_fd = open(trace_file, O_RDONLY);
  487. put_tracing_file(trace_file);
  488. if (trace_fd < 0) {
  489. pr_err("failed to open trace_pipe\n");
  490. goto out_reset;
  491. }
  492. fcntl(trace_fd, F_SETFL, O_NONBLOCK);
  493. pollfd.fd = trace_fd;
  494. /* display column headers */
  495. read_tracing_file_to_stdout("trace");
  496. if (!ftrace->initial_delay) {
  497. if (write_tracing_file("tracing_on", "1") < 0) {
  498. pr_err("can't enable tracing\n");
  499. goto out_close_fd;
  500. }
  501. }
  502. evlist__start_workload(ftrace->evlist);
  503. if (ftrace->initial_delay) {
  504. usleep(ftrace->initial_delay * 1000);
  505. if (write_tracing_file("tracing_on", "1") < 0) {
  506. pr_err("can't enable tracing\n");
  507. goto out_close_fd;
  508. }
  509. }
  510. while (!done) {
  511. if (poll(&pollfd, 1, -1) < 0)
  512. break;
  513. if (pollfd.revents & POLLIN) {
  514. int n = read(trace_fd, buf, sizeof(buf));
  515. if (n < 0)
  516. break;
  517. if (fwrite(buf, n, 1, stdout) != 1)
  518. break;
  519. }
  520. }
  521. write_tracing_file("tracing_on", "0");
  522. if (workload_exec_errno) {
  523. const char *emsg = str_error_r(workload_exec_errno, buf, sizeof(buf));
  524. /* flush stdout first so below error msg appears at the end. */
  525. fflush(stdout);
  526. pr_err("workload failed: %s\n", emsg);
  527. goto out_close_fd;
  528. }
  529. /* read remaining buffer contents */
  530. while (true) {
  531. int n = read(trace_fd, buf, sizeof(buf));
  532. if (n <= 0)
  533. break;
  534. if (fwrite(buf, n, 1, stdout) != 1)
  535. break;
  536. }
  537. out_close_fd:
  538. close(trace_fd);
  539. out_reset:
  540. reset_tracing_files(ftrace);
  541. out:
  542. return (done && !workload_exec_errno) ? 0 : -1;
  543. }
  544. static void make_histogram(int buckets[], char *buf, size_t len, char *linebuf,
  545. bool use_nsec)
  546. {
  547. char *p, *q;
  548. char *unit;
  549. double num;
  550. int i;
  551. /* ensure NUL termination */
  552. buf[len] = '\0';
  553. /* handle data line by line */
  554. for (p = buf; (q = strchr(p, '\n')) != NULL; p = q + 1) {
  555. *q = '\0';
  556. /* move it to the line buffer */
  557. strcat(linebuf, p);
  558. /*
  559. * parse trace output to get function duration like in
  560. *
  561. * # tracer: function_graph
  562. * #
  563. * # CPU DURATION FUNCTION CALLS
  564. * # | | | | | | |
  565. * 1) + 10.291 us | do_filp_open();
  566. * 1) 4.889 us | do_filp_open();
  567. * 1) 6.086 us | do_filp_open();
  568. *
  569. */
  570. if (linebuf[0] == '#')
  571. goto next;
  572. /* ignore CPU */
  573. p = strchr(linebuf, ')');
  574. if (p == NULL)
  575. p = linebuf;
  576. while (*p && !isdigit(*p) && (*p != '|'))
  577. p++;
  578. /* no duration */
  579. if (*p == '\0' || *p == '|')
  580. goto next;
  581. num = strtod(p, &unit);
  582. if (!unit || strncmp(unit, " us", 3))
  583. goto next;
  584. if (use_nsec)
  585. num *= 1000;
  586. i = log2(num);
  587. if (i < 0)
  588. i = 0;
  589. if (i >= NUM_BUCKET)
  590. i = NUM_BUCKET - 1;
  591. buckets[i]++;
  592. next:
  593. /* empty the line buffer for the next output */
  594. linebuf[0] = '\0';
  595. }
  596. /* preserve any remaining output (before newline) */
  597. strcat(linebuf, p);
  598. }
  599. static void display_histogram(int buckets[], bool use_nsec)
  600. {
  601. int i;
  602. int total = 0;
  603. int bar_total = 46; /* to fit in 80 column */
  604. char bar[] = "###############################################";
  605. int bar_len;
  606. for (i = 0; i < NUM_BUCKET; i++)
  607. total += buckets[i];
  608. if (total == 0) {
  609. printf("No data found\n");
  610. return;
  611. }
  612. printf("# %14s | %10s | %-*s |\n",
  613. " DURATION ", "COUNT", bar_total, "GRAPH");
  614. bar_len = buckets[0] * bar_total / total;
  615. printf(" %4d - %-4d %s | %10d | %.*s%*s |\n",
  616. 0, 1, "us", buckets[0], bar_len, bar, bar_total - bar_len, "");
  617. for (i = 1; i < NUM_BUCKET - 1; i++) {
  618. int start = (1 << (i - 1));
  619. int stop = 1 << i;
  620. const char *unit = use_nsec ? "ns" : "us";
  621. if (start >= 1024) {
  622. start >>= 10;
  623. stop >>= 10;
  624. unit = use_nsec ? "us" : "ms";
  625. }
  626. bar_len = buckets[i] * bar_total / total;
  627. printf(" %4d - %-4d %s | %10d | %.*s%*s |\n",
  628. start, stop, unit, buckets[i], bar_len, bar,
  629. bar_total - bar_len, "");
  630. }
  631. bar_len = buckets[NUM_BUCKET - 1] * bar_total / total;
  632. printf(" %4d - %-4s %s | %10d | %.*s%*s |\n",
  633. 1, "...", use_nsec ? "ms" : " s", buckets[NUM_BUCKET - 1],
  634. bar_len, bar, bar_total - bar_len, "");
  635. }
  636. static int prepare_func_latency(struct perf_ftrace *ftrace)
  637. {
  638. char *trace_file;
  639. int fd;
  640. if (ftrace->target.use_bpf)
  641. return perf_ftrace__latency_prepare_bpf(ftrace);
  642. if (reset_tracing_files(ftrace) < 0) {
  643. pr_err("failed to reset ftrace\n");
  644. return -1;
  645. }
  646. /* reset ftrace buffer */
  647. if (write_tracing_file("trace", "0") < 0)
  648. return -1;
  649. if (set_tracing_options(ftrace) < 0)
  650. return -1;
  651. /* force to use the function_graph tracer to track duration */
  652. if (write_tracing_file("current_tracer", "function_graph") < 0) {
  653. pr_err("failed to set current_tracer to function_graph\n");
  654. return -1;
  655. }
  656. trace_file = get_tracing_file("trace_pipe");
  657. if (!trace_file) {
  658. pr_err("failed to open trace_pipe\n");
  659. return -1;
  660. }
  661. fd = open(trace_file, O_RDONLY);
  662. if (fd < 0)
  663. pr_err("failed to open trace_pipe\n");
  664. put_tracing_file(trace_file);
  665. return fd;
  666. }
  667. static int start_func_latency(struct perf_ftrace *ftrace)
  668. {
  669. if (ftrace->target.use_bpf)
  670. return perf_ftrace__latency_start_bpf(ftrace);
  671. if (write_tracing_file("tracing_on", "1") < 0) {
  672. pr_err("can't enable tracing\n");
  673. return -1;
  674. }
  675. return 0;
  676. }
  677. static int stop_func_latency(struct perf_ftrace *ftrace)
  678. {
  679. if (ftrace->target.use_bpf)
  680. return perf_ftrace__latency_stop_bpf(ftrace);
  681. write_tracing_file("tracing_on", "0");
  682. return 0;
  683. }
  684. static int read_func_latency(struct perf_ftrace *ftrace, int buckets[])
  685. {
  686. if (ftrace->target.use_bpf)
  687. return perf_ftrace__latency_read_bpf(ftrace, buckets);
  688. return 0;
  689. }
  690. static int cleanup_func_latency(struct perf_ftrace *ftrace)
  691. {
  692. if (ftrace->target.use_bpf)
  693. return perf_ftrace__latency_cleanup_bpf(ftrace);
  694. reset_tracing_files(ftrace);
  695. return 0;
  696. }
  697. static int __cmd_latency(struct perf_ftrace *ftrace)
  698. {
  699. int trace_fd;
  700. char buf[4096];
  701. char line[256];
  702. struct pollfd pollfd = {
  703. .events = POLLIN,
  704. };
  705. int buckets[NUM_BUCKET] = { };
  706. if (!(perf_cap__capable(CAP_PERFMON) ||
  707. perf_cap__capable(CAP_SYS_ADMIN))) {
  708. pr_err("ftrace only works for %s!\n",
  709. #ifdef HAVE_LIBCAP_SUPPORT
  710. "users with the CAP_PERFMON or CAP_SYS_ADMIN capability"
  711. #else
  712. "root"
  713. #endif
  714. );
  715. return -1;
  716. }
  717. trace_fd = prepare_func_latency(ftrace);
  718. if (trace_fd < 0)
  719. goto out;
  720. fcntl(trace_fd, F_SETFL, O_NONBLOCK);
  721. pollfd.fd = trace_fd;
  722. if (start_func_latency(ftrace) < 0)
  723. goto out;
  724. evlist__start_workload(ftrace->evlist);
  725. line[0] = '\0';
  726. while (!done) {
  727. if (poll(&pollfd, 1, -1) < 0)
  728. break;
  729. if (pollfd.revents & POLLIN) {
  730. int n = read(trace_fd, buf, sizeof(buf) - 1);
  731. if (n < 0)
  732. break;
  733. make_histogram(buckets, buf, n, line, ftrace->use_nsec);
  734. }
  735. }
  736. stop_func_latency(ftrace);
  737. if (workload_exec_errno) {
  738. const char *emsg = str_error_r(workload_exec_errno, buf, sizeof(buf));
  739. pr_err("workload failed: %s\n", emsg);
  740. goto out;
  741. }
  742. /* read remaining buffer contents */
  743. while (!ftrace->target.use_bpf) {
  744. int n = read(trace_fd, buf, sizeof(buf) - 1);
  745. if (n <= 0)
  746. break;
  747. make_histogram(buckets, buf, n, line, ftrace->use_nsec);
  748. }
  749. read_func_latency(ftrace, buckets);
  750. display_histogram(buckets, ftrace->use_nsec);
  751. out:
  752. close(trace_fd);
  753. cleanup_func_latency(ftrace);
  754. return (done && !workload_exec_errno) ? 0 : -1;
  755. }
  756. static int perf_ftrace_config(const char *var, const char *value, void *cb)
  757. {
  758. struct perf_ftrace *ftrace = cb;
  759. if (!strstarts(var, "ftrace."))
  760. return 0;
  761. if (strcmp(var, "ftrace.tracer"))
  762. return -1;
  763. if (!strcmp(value, "function_graph") ||
  764. !strcmp(value, "function")) {
  765. ftrace->tracer = value;
  766. return 0;
  767. }
  768. pr_err("Please select \"function_graph\" (default) or \"function\"\n");
  769. return -1;
  770. }
  771. static void list_function_cb(char *str, void *arg)
  772. {
  773. struct strfilter *filter = (struct strfilter *)arg;
  774. if (strfilter__compare(filter, str))
  775. printf("%s", str);
  776. }
  777. static int opt_list_avail_functions(const struct option *opt __maybe_unused,
  778. const char *str, int unset)
  779. {
  780. struct strfilter *filter;
  781. const char *err = NULL;
  782. int ret;
  783. if (unset || !str)
  784. return -1;
  785. filter = strfilter__new(str, &err);
  786. if (!filter)
  787. return err ? -EINVAL : -ENOMEM;
  788. ret = strfilter__or(filter, str, &err);
  789. if (ret == -EINVAL) {
  790. pr_err("Filter parse error at %td.\n", err - str + 1);
  791. pr_err("Source: \"%s\"\n", str);
  792. pr_err(" %*c\n", (int)(err - str + 1), '^');
  793. strfilter__delete(filter);
  794. return ret;
  795. }
  796. ret = read_tracing_file_by_line("available_filter_functions",
  797. list_function_cb, filter);
  798. strfilter__delete(filter);
  799. if (ret < 0)
  800. return ret;
  801. exit(0);
  802. }
  803. static int parse_filter_func(const struct option *opt, const char *str,
  804. int unset __maybe_unused)
  805. {
  806. struct list_head *head = opt->value;
  807. struct filter_entry *entry;
  808. entry = malloc(sizeof(*entry) + strlen(str) + 1);
  809. if (entry == NULL)
  810. return -ENOMEM;
  811. strcpy(entry->name, str);
  812. list_add_tail(&entry->list, head);
  813. return 0;
  814. }
  815. static void delete_filter_func(struct list_head *head)
  816. {
  817. struct filter_entry *pos, *tmp;
  818. list_for_each_entry_safe(pos, tmp, head, list) {
  819. list_del_init(&pos->list);
  820. free(pos);
  821. }
  822. }
  823. static int parse_buffer_size(const struct option *opt,
  824. const char *str, int unset)
  825. {
  826. unsigned long *s = (unsigned long *)opt->value;
  827. static struct parse_tag tags_size[] = {
  828. { .tag = 'B', .mult = 1 },
  829. { .tag = 'K', .mult = 1 << 10 },
  830. { .tag = 'M', .mult = 1 << 20 },
  831. { .tag = 'G', .mult = 1 << 30 },
  832. { .tag = 0 },
  833. };
  834. unsigned long val;
  835. if (unset) {
  836. *s = 0;
  837. return 0;
  838. }
  839. val = parse_tag_value(str, tags_size);
  840. if (val != (unsigned long) -1) {
  841. if (val < 1024) {
  842. pr_err("buffer size too small, must larger than 1KB.");
  843. return -1;
  844. }
  845. *s = val;
  846. return 0;
  847. }
  848. return -1;
  849. }
  850. static int parse_func_tracer_opts(const struct option *opt,
  851. const char *str, int unset)
  852. {
  853. int ret;
  854. struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
  855. struct sublevel_option func_tracer_opts[] = {
  856. { .name = "call-graph", .value_ptr = &ftrace->func_stack_trace },
  857. { .name = "irq-info", .value_ptr = &ftrace->func_irq_info },
  858. { .name = NULL, }
  859. };
  860. if (unset)
  861. return 0;
  862. ret = perf_parse_sublevel_options(str, func_tracer_opts);
  863. if (ret)
  864. return ret;
  865. return 0;
  866. }
  867. static int parse_graph_tracer_opts(const struct option *opt,
  868. const char *str, int unset)
  869. {
  870. int ret;
  871. struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
  872. struct sublevel_option graph_tracer_opts[] = {
  873. { .name = "nosleep-time", .value_ptr = &ftrace->graph_nosleep_time },
  874. { .name = "noirqs", .value_ptr = &ftrace->graph_noirqs },
  875. { .name = "verbose", .value_ptr = &ftrace->graph_verbose },
  876. { .name = "thresh", .value_ptr = &ftrace->graph_thresh },
  877. { .name = "depth", .value_ptr = &ftrace->graph_depth },
  878. { .name = NULL, }
  879. };
  880. if (unset)
  881. return 0;
  882. ret = perf_parse_sublevel_options(str, graph_tracer_opts);
  883. if (ret)
  884. return ret;
  885. return 0;
  886. }
  887. enum perf_ftrace_subcommand {
  888. PERF_FTRACE_NONE,
  889. PERF_FTRACE_TRACE,
  890. PERF_FTRACE_LATENCY,
  891. };
  892. int cmd_ftrace(int argc, const char **argv)
  893. {
  894. int ret;
  895. int (*cmd_func)(struct perf_ftrace *) = NULL;
  896. struct perf_ftrace ftrace = {
  897. .tracer = DEFAULT_TRACER,
  898. .target = { .uid = UINT_MAX, },
  899. };
  900. const struct option common_options[] = {
  901. OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
  902. "Trace on existing process id"),
  903. /* TODO: Add short option -t after -t/--tracer can be removed. */
  904. OPT_STRING(0, "tid", &ftrace.target.tid, "tid",
  905. "Trace on existing thread id (exclusive to --pid)"),
  906. OPT_INCR('v', "verbose", &verbose,
  907. "Be more verbose"),
  908. OPT_BOOLEAN('a', "all-cpus", &ftrace.target.system_wide,
  909. "System-wide collection from all CPUs"),
  910. OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
  911. "List of cpus to monitor"),
  912. OPT_END()
  913. };
  914. const struct option ftrace_options[] = {
  915. OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
  916. "Tracer to use: function_graph(default) or function"),
  917. OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
  918. "Show available functions to filter",
  919. opt_list_avail_functions, "*"),
  920. OPT_CALLBACK('T', "trace-funcs", &ftrace.filters, "func",
  921. "Trace given functions using function tracer",
  922. parse_filter_func),
  923. OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
  924. "Do not trace given functions", parse_filter_func),
  925. OPT_CALLBACK(0, "func-opts", &ftrace, "options",
  926. "Function tracer options, available options: call-graph,irq-info",
  927. parse_func_tracer_opts),
  928. OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
  929. "Trace given functions using function_graph tracer",
  930. parse_filter_func),
  931. OPT_CALLBACK('g', "nograph-funcs", &ftrace.nograph_funcs, "func",
  932. "Set nograph filter on given functions", parse_filter_func),
  933. OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
  934. "Graph tracer options, available options: nosleep-time,noirqs,verbose,thresh=<n>,depth=<n>",
  935. parse_graph_tracer_opts),
  936. OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
  937. "Size of per cpu buffer, needs to use a B, K, M or G suffix.", parse_buffer_size),
  938. OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
  939. "Trace children processes"),
  940. OPT_UINTEGER('D', "delay", &ftrace.initial_delay,
  941. "Number of milliseconds to wait before starting tracing after program start"),
  942. OPT_PARENT(common_options),
  943. };
  944. const struct option latency_options[] = {
  945. OPT_CALLBACK('T', "trace-funcs", &ftrace.filters, "func",
  946. "Show latency of given function", parse_filter_func),
  947. #ifdef HAVE_BPF_SKEL
  948. OPT_BOOLEAN('b', "use-bpf", &ftrace.target.use_bpf,
  949. "Use BPF to measure function latency"),
  950. #endif
  951. OPT_BOOLEAN('n', "use-nsec", &ftrace.use_nsec,
  952. "Use nano-second histogram"),
  953. OPT_PARENT(common_options),
  954. };
  955. const struct option *options = ftrace_options;
  956. const char * const ftrace_usage[] = {
  957. "perf ftrace [<options>] [<command>]",
  958. "perf ftrace [<options>] -- [<command>] [<options>]",
  959. "perf ftrace {trace|latency} [<options>] [<command>]",
  960. "perf ftrace {trace|latency} [<options>] -- [<command>] [<options>]",
  961. NULL
  962. };
  963. enum perf_ftrace_subcommand subcmd = PERF_FTRACE_NONE;
  964. INIT_LIST_HEAD(&ftrace.filters);
  965. INIT_LIST_HEAD(&ftrace.notrace);
  966. INIT_LIST_HEAD(&ftrace.graph_funcs);
  967. INIT_LIST_HEAD(&ftrace.nograph_funcs);
  968. signal(SIGINT, sig_handler);
  969. signal(SIGUSR1, sig_handler);
  970. signal(SIGCHLD, sig_handler);
  971. signal(SIGPIPE, sig_handler);
  972. ret = perf_config(perf_ftrace_config, &ftrace);
  973. if (ret < 0)
  974. return -1;
  975. if (argc > 1) {
  976. if (!strcmp(argv[1], "trace")) {
  977. subcmd = PERF_FTRACE_TRACE;
  978. } else if (!strcmp(argv[1], "latency")) {
  979. subcmd = PERF_FTRACE_LATENCY;
  980. options = latency_options;
  981. }
  982. if (subcmd != PERF_FTRACE_NONE) {
  983. argc--;
  984. argv++;
  985. }
  986. }
  987. /* for backward compatibility */
  988. if (subcmd == PERF_FTRACE_NONE)
  989. subcmd = PERF_FTRACE_TRACE;
  990. argc = parse_options(argc, argv, options, ftrace_usage,
  991. PARSE_OPT_STOP_AT_NON_OPTION);
  992. if (argc < 0) {
  993. ret = -EINVAL;
  994. goto out_delete_filters;
  995. }
  996. /* Make system wide (-a) the default target. */
  997. if (!argc && target__none(&ftrace.target))
  998. ftrace.target.system_wide = true;
  999. switch (subcmd) {
  1000. case PERF_FTRACE_TRACE:
  1001. cmd_func = __cmd_ftrace;
  1002. break;
  1003. case PERF_FTRACE_LATENCY:
  1004. if (list_empty(&ftrace.filters)) {
  1005. pr_err("Should provide a function to measure\n");
  1006. parse_options_usage(ftrace_usage, options, "T", 1);
  1007. ret = -EINVAL;
  1008. goto out_delete_filters;
  1009. }
  1010. cmd_func = __cmd_latency;
  1011. break;
  1012. case PERF_FTRACE_NONE:
  1013. default:
  1014. pr_err("Invalid subcommand\n");
  1015. ret = -EINVAL;
  1016. goto out_delete_filters;
  1017. }
  1018. ret = target__validate(&ftrace.target);
  1019. if (ret) {
  1020. char errbuf[512];
  1021. target__strerror(&ftrace.target, ret, errbuf, 512);
  1022. pr_err("%s\n", errbuf);
  1023. goto out_delete_filters;
  1024. }
  1025. ftrace.evlist = evlist__new();
  1026. if (ftrace.evlist == NULL) {
  1027. ret = -ENOMEM;
  1028. goto out_delete_filters;
  1029. }
  1030. ret = evlist__create_maps(ftrace.evlist, &ftrace.target);
  1031. if (ret < 0)
  1032. goto out_delete_evlist;
  1033. if (argc) {
  1034. ret = evlist__prepare_workload(ftrace.evlist, &ftrace.target,
  1035. argv, false,
  1036. ftrace__workload_exec_failed_signal);
  1037. if (ret < 0)
  1038. goto out_delete_evlist;
  1039. }
  1040. ret = cmd_func(&ftrace);
  1041. out_delete_evlist:
  1042. evlist__delete(ftrace.evlist);
  1043. out_delete_filters:
  1044. delete_filter_func(&ftrace.filters);
  1045. delete_filter_func(&ftrace.notrace);
  1046. delete_filter_func(&ftrace.graph_funcs);
  1047. delete_filter_func(&ftrace.nograph_funcs);
  1048. return ret;
  1049. }