Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'perf-core-for-mingo-20160429' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

- Allow generate timestamped suffixed multiple perf.data files upon receiving
SIGUSR2 in 'perf record', to slice a long running monitoring session, allowing
to dump uninteresting sessions (Wang Nan)

- Handle ENOMEM for perf_event_max_stack + PERF_SAMPLE_CALLCHAIN
in perf_evsel__open_strerror(), showing a more informative
message when the request call stack depth can't be allocated by
the kernel (Arnaldo Carvalho de Melo)

Infrastructure changes:

- Use strbuf for making strings in 'perf probe' (Masami Hiramatsu)

- Do not use sizeof on pointer type, not a problem since its a pointer to
pointer, fix none the less. Found by Coccinelle (Vaishali Thakkar)

Cleanups:

- Fix for Coverity found issues in the bpf feature build test (Florian Fainelli)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

+392 -289
+1 -2
tools/build/feature/test-bpf.c
··· 27 27 attr.log_level = 0; 28 28 attr.kern_version = 0; 29 29 30 - attr = attr; 31 30 /* 32 31 * Test existence of __NR_bpf and BPF_PROG_LOAD. 33 32 * This call should fail if we run the testcase. 34 33 */ 35 - return syscall(__NR_bpf, BPF_PROG_LOAD, attr, sizeof(attr)); 34 + return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); 36 35 }
+13
tools/perf/Documentation/perf-record.txt
··· 347 347 --all-user:: 348 348 Configure all used events to run in user space. 349 349 350 + --timestamp-filename 351 + Append timestamp to output file name. 352 + 353 + --switch-output:: 354 + Generate multiple perf.data files, timestamp prefixed, switching to a new one 355 + when receiving a SIGUSR2. 356 + 357 + A possible use case is to, given an external event, slice the perf.data file 358 + that gets then processed, possibly via a perf script, to decide if that 359 + particular perf.data snapshot should be kept or not. 360 + 361 + Implies --timestamp-filename, --no-buildid and --no-buildid-cache. 362 + 350 363 SEE ALSO 351 364 -------- 352 365 linkperf:perf-stat[1], linkperf:perf-list[1]
+118 -55
tools/perf/builtin-record.c
··· 34 34 #include "util/parse-regs-options.h" 35 35 #include "util/llvm-utils.h" 36 36 #include "util/bpf-loader.h" 37 + #include "util/trigger.h" 37 38 #include "asm/bug.h" 38 39 39 40 #include <unistd.h> ··· 58 57 bool no_buildid_cache_set; 59 58 bool buildid_all; 60 59 bool timestamp_filename; 60 + bool switch_output; 61 61 unsigned long long samples; 62 62 }; 63 63 ··· 129 127 static volatile int signr = -1; 130 128 static volatile int child_finished; 131 129 132 - static volatile enum { 133 - AUXTRACE_SNAPSHOT_OFF = -1, 134 - AUXTRACE_SNAPSHOT_DISABLED = 0, 135 - AUXTRACE_SNAPSHOT_ENABLED = 1, 136 - } auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_OFF; 137 - 138 - static inline void 139 - auxtrace_snapshot_on(void) 140 - { 141 - auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED; 142 - } 143 - 144 - static inline void 145 - auxtrace_snapshot_enable(void) 146 - { 147 - if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) 148 - return; 149 - auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_ENABLED; 150 - } 151 - 152 - static inline void 153 - auxtrace_snapshot_disable(void) 154 - { 155 - if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) 156 - return; 157 - auxtrace_snapshot_state = AUXTRACE_SNAPSHOT_DISABLED; 158 - } 159 - 160 - static inline bool 161 - auxtrace_snapshot_is_enabled(void) 162 - { 163 - if (auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_OFF) 164 - return false; 165 - return auxtrace_snapshot_state == AUXTRACE_SNAPSHOT_ENABLED; 166 - } 167 - 168 - static volatile int auxtrace_snapshot_err; 169 130 static volatile int auxtrace_record__snapshot_started; 131 + static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 132 + static DEFINE_TRIGGER(switch_output_trigger); 170 133 171 134 static void sig_handler(int sig) 172 135 { ··· 249 282 { 250 283 pr_debug("Recording AUX area tracing snapshot\n"); 251 284 if (record__auxtrace_read_snapshot_all(rec) < 0) { 252 - auxtrace_snapshot_err = -1; 285 + trigger_error(&auxtrace_snapshot_trigger); 253 286 } else { 254 - auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 255 - if (!auxtrace_snapshot_err) 256 - auxtrace_snapshot_enable(); 287 + if (auxtrace_record__snapshot_finish(rec->itr)) 288 + trigger_error(&auxtrace_snapshot_trigger); 289 + else 290 + trigger_ready(&auxtrace_snapshot_trigger); 257 291 } 258 292 } 259 293 ··· 500 532 return; 501 533 } 502 534 535 + static int record__synthesize_workload(struct record *rec) 536 + { 537 + struct { 538 + struct thread_map map; 539 + struct thread_map_data map_data; 540 + } thread_map; 541 + 542 + thread_map.map.nr = 1; 543 + thread_map.map.map[0].pid = rec->evlist->workload.pid; 544 + thread_map.map.map[0].comm = NULL; 545 + return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map, 546 + process_synthesized_event, 547 + &rec->session->machines.host, 548 + rec->opts.sample_address, 549 + rec->opts.proc_map_timeout); 550 + } 551 + 552 + static int record__synthesize(struct record *rec); 553 + 503 554 static int 504 555 record__switch_output(struct record *rec, bool at_exit) 505 556 { ··· 547 560 if (!quiet) 548 561 fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 549 562 file->path, timestamp); 563 + 564 + /* Output tracking events */ 565 + if (!at_exit) { 566 + record__synthesize(rec); 567 + 568 + /* 569 + * In 'perf record --switch-output' without -a, 570 + * record__synthesize() in record__switch_output() won't 571 + * generate tracking events because there's no thread_map 572 + * in evlist. Which causes newly created perf.data doesn't 573 + * contain map and comm information. 574 + * Create a fake thread_map and directly call 575 + * perf_event__synthesize_thread_map() for those events. 576 + */ 577 + if (target__none(&rec->opts.target)) 578 + record__synthesize_workload(rec); 579 + } 550 580 return fd; 551 581 } 552 582 ··· 688 684 signal(SIGINT, sig_handler); 689 685 signal(SIGTERM, sig_handler); 690 686 691 - if (rec->opts.auxtrace_snapshot_mode) { 687 + if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) { 692 688 signal(SIGUSR2, snapshot_sig_handler); 693 - auxtrace_snapshot_on(); 689 + if (rec->opts.auxtrace_snapshot_mode) 690 + trigger_on(&auxtrace_snapshot_trigger); 691 + if (rec->switch_output) 692 + trigger_on(&switch_output_trigger); 694 693 } else { 695 694 signal(SIGUSR2, SIG_IGN); 696 695 } ··· 822 815 perf_evlist__enable(rec->evlist); 823 816 } 824 817 825 - auxtrace_snapshot_enable(); 818 + trigger_ready(&auxtrace_snapshot_trigger); 819 + trigger_ready(&switch_output_trigger); 826 820 for (;;) { 827 821 unsigned long long hits = rec->samples; 828 822 829 823 if (record__mmap_read_all(rec) < 0) { 830 - auxtrace_snapshot_disable(); 824 + trigger_error(&auxtrace_snapshot_trigger); 825 + trigger_error(&switch_output_trigger); 831 826 err = -1; 832 827 goto out_child; 833 828 } 834 829 835 830 if (auxtrace_record__snapshot_started) { 836 831 auxtrace_record__snapshot_started = 0; 837 - if (!auxtrace_snapshot_err) 832 + if (!trigger_is_error(&auxtrace_snapshot_trigger)) 838 833 record__read_auxtrace_snapshot(rec); 839 - if (auxtrace_snapshot_err) { 834 + if (trigger_is_error(&auxtrace_snapshot_trigger)) { 840 835 pr_err("AUX area tracing snapshot failed\n"); 841 836 err = -1; 837 + goto out_child; 838 + } 839 + } 840 + 841 + if (trigger_is_hit(&switch_output_trigger)) { 842 + trigger_ready(&switch_output_trigger); 843 + 844 + if (!quiet) 845 + fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 846 + waking); 847 + waking = 0; 848 + fd = record__switch_output(rec, false); 849 + if (fd < 0) { 850 + pr_err("Failed to switch to new file\n"); 851 + trigger_error(&switch_output_trigger); 852 + err = fd; 842 853 goto out_child; 843 854 } 844 855 } ··· 883 858 * disable events in this case. 884 859 */ 885 860 if (done && !disabled && !target__none(&opts->target)) { 886 - auxtrace_snapshot_disable(); 861 + trigger_off(&auxtrace_snapshot_trigger); 887 862 perf_evlist__disable(rec->evlist); 888 863 disabled = true; 889 864 } 890 865 } 891 - auxtrace_snapshot_disable(); 866 + trigger_off(&auxtrace_snapshot_trigger); 867 + trigger_off(&switch_output_trigger); 892 868 893 869 if (forks && workload_exec_errno) { 894 870 char msg[STRERR_BUFSIZE]; ··· 1323 1297 "Record build-id of all DSOs regardless of hits"), 1324 1298 OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1325 1299 "append timestamp to output filename"), 1300 + OPT_BOOLEAN(0, "switch-output", &record.switch_output, 1301 + "Switch output when receive SIGUSR2"), 1326 1302 OPT_END() 1327 1303 }; 1328 1304 ··· 1380 1352 return -EINVAL; 1381 1353 } 1382 1354 1355 + if (rec->switch_output) 1356 + rec->timestamp_filename = true; 1357 + 1383 1358 if (!rec->itr) { 1384 1359 rec->itr = auxtrace_record__init(rec->evlist, &err); 1385 1360 if (err) ··· 1416 1385 "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1417 1386 "even with a suitable vmlinux or kallsyms file.\n\n"); 1418 1387 1419 - if (rec->no_buildid_cache || rec->no_buildid) 1388 + if (rec->no_buildid_cache || rec->no_buildid) { 1420 1389 disable_buildid_cache(); 1390 + } else if (rec->switch_output) { 1391 + /* 1392 + * In 'perf record --switch-output', disable buildid 1393 + * generation by default to reduce data file switching 1394 + * overhead. Still generate buildid if they are required 1395 + * explicitly using 1396 + * 1397 + * perf record --signal-trigger --no-no-buildid \ 1398 + * --no-no-buildid-cache 1399 + * 1400 + * Following code equals to: 1401 + * 1402 + * if ((rec->no_buildid || !rec->no_buildid_set) && 1403 + * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 1404 + * disable_buildid_cache(); 1405 + */ 1406 + bool disable = true; 1407 + 1408 + if (rec->no_buildid_set && !rec->no_buildid) 1409 + disable = false; 1410 + if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 1411 + disable = false; 1412 + if (disable) { 1413 + rec->no_buildid = true; 1414 + rec->no_buildid_cache = true; 1415 + disable_buildid_cache(); 1416 + } 1417 + } 1421 1418 1422 1419 if (rec->evlist->nr_entries == 0 && 1423 1420 perf_evlist__add_default(rec->evlist) < 0) { ··· 1504 1445 1505 1446 static void snapshot_sig_handler(int sig __maybe_unused) 1506 1447 { 1507 - if (!auxtrace_snapshot_is_enabled()) 1508 - return; 1509 - auxtrace_snapshot_disable(); 1510 - auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 1511 - auxtrace_record__snapshot_started = 1; 1448 + if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 1449 + trigger_hit(&auxtrace_snapshot_trigger); 1450 + auxtrace_record__snapshot_started = 1; 1451 + if (auxtrace_record__snapshot_start(record.itr)) 1452 + trigger_error(&auxtrace_snapshot_trigger); 1453 + } 1454 + 1455 + if (trigger_is_ready(&switch_output_trigger)) 1456 + trigger_hit(&switch_output_trigger); 1512 1457 }
+1 -61
tools/perf/builtin-trace.c
··· 52 52 # define O_CLOEXEC 02000000 53 53 #endif 54 54 55 - #ifndef MSG_CMSG_CLOEXEC 56 - # define MSG_CMSG_CLOEXEC 0x40000000 57 - #endif 58 - 59 55 struct trace { 60 56 struct perf_tool tool; 61 57 struct syscalltbl *sctbl; ··· 509 513 }; 510 514 static DEFINE_STRARRAY(socket_families); 511 515 512 - #ifndef MSG_PROBE 513 - #define MSG_PROBE 0x10 514 - #endif 515 - #ifndef MSG_WAITFORONE 516 - #define MSG_WAITFORONE 0x10000 517 - #endif 518 - #ifndef MSG_SENDPAGE_NOTLAST 519 - #define MSG_SENDPAGE_NOTLAST 0x20000 520 - #endif 521 - #ifndef MSG_FASTOPEN 522 - #define MSG_FASTOPEN 0x20000000 523 - #endif 524 - 525 - static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, 526 - struct syscall_arg *arg) 527 - { 528 - int printed = 0, flags = arg->val; 529 - 530 - if (flags == 0) 531 - return scnprintf(bf, size, "NONE"); 532 - #define P_MSG_FLAG(n) \ 533 - if (flags & MSG_##n) { \ 534 - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ 535 - flags &= ~MSG_##n; \ 536 - } 537 - 538 - P_MSG_FLAG(OOB); 539 - P_MSG_FLAG(PEEK); 540 - P_MSG_FLAG(DONTROUTE); 541 - P_MSG_FLAG(TRYHARD); 542 - P_MSG_FLAG(CTRUNC); 543 - P_MSG_FLAG(PROBE); 544 - P_MSG_FLAG(TRUNC); 545 - P_MSG_FLAG(DONTWAIT); 546 - P_MSG_FLAG(EOR); 547 - P_MSG_FLAG(WAITALL); 548 - P_MSG_FLAG(FIN); 549 - P_MSG_FLAG(SYN); 550 - P_MSG_FLAG(CONFIRM); 551 - P_MSG_FLAG(RST); 552 - P_MSG_FLAG(ERRQUEUE); 553 - P_MSG_FLAG(NOSIGNAL); 554 - P_MSG_FLAG(MORE); 555 - P_MSG_FLAG(WAITFORONE); 556 - P_MSG_FLAG(SENDPAGE_NOTLAST); 557 - P_MSG_FLAG(FASTOPEN); 558 - P_MSG_FLAG(CMSG_CLOEXEC); 559 - #undef P_MSG_FLAG 560 - 561 - if (flags) 562 - printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); 563 - 564 - return printed; 565 - } 566 - 567 - #define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags 568 - 569 516 static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size, 570 517 struct syscall_arg *arg) 571 518 { ··· 789 850 #include "trace/beauty/pid.c" 790 851 #include "trace/beauty/mmap.c" 791 852 #include "trace/beauty/mode_t.c" 853 + #include "trace/beauty/msg_flags.c" 792 854 #include "trace/beauty/perf_event_open.c" 793 855 #include "trace/beauty/sched_policy.c" 794 856 #include "trace/beauty/socket_type.c"
+1 -1
tools/perf/tests/dso-data.c
··· 202 202 { 203 203 int i; 204 204 205 - dsos = malloc(sizeof(dsos) * cnt); 205 + dsos = malloc(sizeof(*dsos) * cnt); 206 206 TEST_ASSERT_VAL("failed to alloc dsos array", dsos); 207 207 208 208 for (i = 0; i < cnt; i++) {
+62
tools/perf/trace/beauty/msg_flags.c
··· 1 + #include <sys/types.h> 2 + #include <sys/socket.h> 3 + 4 + #ifndef MSG_PROBE 5 + #define MSG_PROBE 0x10 6 + #endif 7 + #ifndef MSG_WAITFORONE 8 + #define MSG_WAITFORONE 0x10000 9 + #endif 10 + #ifndef MSG_SENDPAGE_NOTLAST 11 + #define MSG_SENDPAGE_NOTLAST 0x20000 12 + #endif 13 + #ifndef MSG_FASTOPEN 14 + #define MSG_FASTOPEN 0x20000000 15 + #endif 16 + #ifndef MSG_CMSG_CLOEXEC 17 + # define MSG_CMSG_CLOEXEC 0x40000000 18 + #endif 19 + 20 + static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, 21 + struct syscall_arg *arg) 22 + { 23 + int printed = 0, flags = arg->val; 24 + 25 + if (flags == 0) 26 + return scnprintf(bf, size, "NONE"); 27 + #define P_MSG_FLAG(n) \ 28 + if (flags & MSG_##n) { \ 29 + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ 30 + flags &= ~MSG_##n; \ 31 + } 32 + 33 + P_MSG_FLAG(OOB); 34 + P_MSG_FLAG(PEEK); 35 + P_MSG_FLAG(DONTROUTE); 36 + P_MSG_FLAG(TRYHARD); 37 + P_MSG_FLAG(CTRUNC); 38 + P_MSG_FLAG(PROBE); 39 + P_MSG_FLAG(TRUNC); 40 + P_MSG_FLAG(DONTWAIT); 41 + P_MSG_FLAG(EOR); 42 + P_MSG_FLAG(WAITALL); 43 + P_MSG_FLAG(FIN); 44 + P_MSG_FLAG(SYN); 45 + P_MSG_FLAG(CONFIRM); 46 + P_MSG_FLAG(RST); 47 + P_MSG_FLAG(ERRQUEUE); 48 + P_MSG_FLAG(NOSIGNAL); 49 + P_MSG_FLAG(MORE); 50 + P_MSG_FLAG(WAITFORONE); 51 + P_MSG_FLAG(SENDPAGE_NOTLAST); 52 + P_MSG_FLAG(FASTOPEN); 53 + P_MSG_FLAG(CMSG_CLOEXEC); 54 + #undef P_MSG_FLAG 55 + 56 + if (flags) 57 + printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); 58 + 59 + return printed; 60 + } 61 + 62 + #define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
+10 -2
tools/perf/util/evsel.c
··· 2325 2325 "Probably the maximum number of open file descriptors has been reached.\n" 2326 2326 "Hint: Try again after reducing the number of events.\n" 2327 2327 "Hint: Try increasing the limit with 'ulimit -n <limit>'"); 2328 + case ENOMEM: 2329 + if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 && 2330 + access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0) 2331 + return scnprintf(msg, size, 2332 + "Not enough memory to setup event with callchain.\n" 2333 + "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n" 2334 + "Hint: Current value: %d", sysctl_perf_event_max_stack); 2335 + break; 2328 2336 case ENODEV: 2329 2337 if (target->cpu_list) 2330 2338 return scnprintf(msg, size, "%s", 2331 - "No such device - did you specify an out-of-range profile CPU?\n"); 2339 + "No such device - did you specify an out-of-range profile CPU?"); 2332 2340 break; 2333 2341 case EOPNOTSUPP: 2334 2342 if (evsel->attr.precise_ip) ··· 2368 2360 return scnprintf(msg, size, 2369 2361 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" 2370 2362 "/bin/dmesg may provide additional information.\n" 2371 - "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2363 + "No CONFIG_PERF_EVENTS=y kernel support configured?", 2372 2364 err, strerror_r(err, sbuf, sizeof(sbuf)), 2373 2365 perf_evsel__name(evsel)); 2374 2366 }
+84 -160
tools/perf/util/probe-event.c
··· 1673 1673 } 1674 1674 1675 1675 /* Compose only probe arg */ 1676 - int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 1676 + char *synthesize_perf_probe_arg(struct perf_probe_arg *pa) 1677 1677 { 1678 1678 struct perf_probe_arg_field *field = pa->field; 1679 - int ret; 1680 - char *tmp = buf; 1679 + struct strbuf buf; 1680 + char *ret; 1681 1681 1682 + strbuf_init(&buf, 64); 1682 1683 if (pa->name && pa->var) 1683 - ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 1684 + strbuf_addf(&buf, "%s=%s", pa->name, pa->var); 1684 1685 else 1685 - ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 1686 - if (ret <= 0) 1687 - goto error; 1688 - tmp += ret; 1689 - len -= ret; 1686 + strbuf_addstr(&buf, pa->name ?: pa->var); 1690 1687 1691 1688 while (field) { 1692 1689 if (field->name[0] == '[') 1693 - ret = e_snprintf(tmp, len, "%s", field->name); 1690 + strbuf_addstr(&buf, field->name); 1694 1691 else 1695 - ret = e_snprintf(tmp, len, "%s%s", 1696 - field->ref ? "->" : ".", field->name); 1697 - if (ret <= 0) 1698 - goto error; 1699 - tmp += ret; 1700 - len -= ret; 1692 + strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".", 1693 + field->name); 1701 1694 field = field->next; 1702 1695 } 1703 1696 1704 - if (pa->type) { 1705 - ret = e_snprintf(tmp, len, ":%s", pa->type); 1706 - if (ret <= 0) 1707 - goto error; 1708 - tmp += ret; 1709 - len -= ret; 1710 - } 1697 + if (pa->type) 1698 + strbuf_addf(&buf, ":%s", pa->type); 1711 1699 1712 - return tmp - buf; 1713 - error: 1714 - pr_debug("Failed to synthesize perf probe argument: %d\n", ret); 1700 + ret = strbuf_detach(&buf, NULL); 1701 + 1715 1702 return ret; 1716 1703 } 1717 1704 1718 1705 /* Compose only probe point (not argument) */ 1719 1706 static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 1720 1707 { 1721 - char *buf, *tmp; 1722 - char offs[32] = "", line[32] = "", file[32] = ""; 1723 - int ret, len; 1708 + struct strbuf buf; 1709 + char *tmp; 1710 + int len; 1724 1711 1725 - buf = zalloc(MAX_CMDLEN); 1726 - if (buf == NULL) { 1727 - ret = -ENOMEM; 1728 - goto error; 1729 - } 1730 - if (pp->offset) { 1731 - ret = e_snprintf(offs, 32, "+%lu", pp->offset); 1732 - if (ret <= 0) 1733 - goto error; 1734 - } 1735 - if (pp->line) { 1736 - ret = e_snprintf(line, 32, ":%d", pp->line); 1737 - if (ret <= 0) 1738 - goto error; 1712 + strbuf_init(&buf, 64); 1713 + if (pp->function) { 1714 + strbuf_addstr(&buf, pp->function); 1715 + if (pp->offset) 1716 + strbuf_addf(&buf, "+%lu", pp->offset); 1717 + else if (pp->line) 1718 + strbuf_addf(&buf, ":%d", pp->line); 1719 + else if (pp->retprobe) 1720 + strbuf_addstr(&buf, "%return"); 1739 1721 } 1740 1722 if (pp->file) { 1741 1723 tmp = pp->file; ··· 1726 1744 tmp = strchr(pp->file + len - 30, '/'); 1727 1745 tmp = tmp ? tmp + 1 : pp->file + len - 30; 1728 1746 } 1729 - ret = e_snprintf(file, 32, "@%s", tmp); 1730 - if (ret <= 0) 1731 - goto error; 1747 + strbuf_addf(&buf, "@%s", tmp); 1748 + if (!pp->function && pp->line) 1749 + strbuf_addf(&buf, ":%d", pp->line); 1732 1750 } 1733 1751 1734 - if (pp->function) 1735 - ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1736 - offs, pp->retprobe ? "%return" : "", line, 1737 - file); 1738 - else 1739 - ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); 1740 - if (ret <= 0) 1741 - goto error; 1742 - 1743 - return buf; 1744 - error: 1745 - pr_debug("Failed to synthesize perf probe point: %d\n", ret); 1746 - free(buf); 1747 - return NULL; 1752 + return strbuf_detach(&buf, NULL); 1748 1753 } 1749 1754 1750 1755 #if 0 ··· 1760 1791 #endif 1761 1792 1762 1793 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 1763 - char **buf, size_t *buflen, 1764 - int depth) 1794 + struct strbuf *buf, int depth) 1765 1795 { 1766 - int ret; 1767 1796 if (ref->next) { 1768 1797 depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 1769 - buflen, depth + 1); 1798 + depth + 1); 1770 1799 if (depth < 0) 1771 1800 goto out; 1772 1801 } 1773 - 1774 - ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 1775 - if (ret < 0) 1776 - depth = ret; 1777 - else { 1778 - *buf += ret; 1779 - *buflen -= ret; 1780 - } 1802 + strbuf_addf(buf, "%+ld(", ref->offset); 1781 1803 out: 1782 1804 return depth; 1783 - 1784 1805 } 1785 1806 1786 1807 static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 1787 - char *buf, size_t buflen) 1808 + struct strbuf *buf) 1788 1809 { 1789 1810 struct probe_trace_arg_ref *ref = arg->ref; 1790 - int ret, depth = 0; 1791 - char *tmp = buf; 1811 + int depth = 0; 1792 1812 1793 1813 /* Argument name or separator */ 1794 1814 if (arg->name) 1795 - ret = e_snprintf(buf, buflen, " %s=", arg->name); 1815 + strbuf_addf(buf, " %s=", arg->name); 1796 1816 else 1797 - ret = e_snprintf(buf, buflen, " "); 1798 - if (ret < 0) 1799 - return ret; 1800 - buf += ret; 1801 - buflen -= ret; 1817 + strbuf_addch(buf, ' '); 1802 1818 1803 1819 /* Special case: @XXX */ 1804 1820 if (arg->value[0] == '@' && arg->ref) ··· 1791 1837 1792 1838 /* Dereferencing arguments */ 1793 1839 if (ref) { 1794 - depth = __synthesize_probe_trace_arg_ref(ref, &buf, 1795 - &buflen, 1); 1840 + depth = __synthesize_probe_trace_arg_ref(ref, buf, 1); 1796 1841 if (depth < 0) 1797 1842 return depth; 1798 1843 } 1799 1844 1800 1845 /* Print argument value */ 1801 1846 if (arg->value[0] == '@' && arg->ref) 1802 - ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1803 - arg->ref->offset); 1847 + strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset); 1804 1848 else 1805 - ret = e_snprintf(buf, buflen, "%s", arg->value); 1806 - if (ret < 0) 1807 - return ret; 1808 - buf += ret; 1809 - buflen -= ret; 1849 + strbuf_addstr(buf, arg->value); 1810 1850 1811 1851 /* Closing */ 1812 - while (depth--) { 1813 - ret = e_snprintf(buf, buflen, ")"); 1814 - if (ret < 0) 1815 - return ret; 1816 - buf += ret; 1817 - buflen -= ret; 1818 - } 1852 + while (depth--) 1853 + strbuf_addch(buf, ')'); 1819 1854 /* Print argument type */ 1820 - if (arg->type) { 1821 - ret = e_snprintf(buf, buflen, ":%s", arg->type); 1822 - if (ret <= 0) 1823 - return ret; 1824 - buf += ret; 1825 - } 1855 + if (arg->type) 1856 + strbuf_addf(buf, ":%s", arg->type); 1826 1857 1827 - return buf - tmp; 1858 + return 0; 1828 1859 } 1829 1860 1830 1861 char *synthesize_probe_trace_command(struct probe_trace_event *tev) 1831 1862 { 1832 1863 struct probe_trace_point *tp = &tev->point; 1833 - char *buf; 1834 - int i, len, ret; 1835 - 1836 - buf = zalloc(MAX_CMDLEN); 1837 - if (buf == NULL) 1838 - return NULL; 1839 - 1840 - len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p', 1841 - tev->group, tev->event); 1842 - if (len <= 0) 1843 - goto error; 1864 + struct strbuf buf; 1865 + char *ret = NULL; 1866 + int i; 1844 1867 1845 1868 /* Uprobes must have tp->module */ 1846 1869 if (tev->uprobes && !tp->module) 1847 - goto error; 1870 + return NULL; 1871 + 1872 + strbuf_init(&buf, 32); 1873 + strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p', 1874 + tev->group, tev->event); 1848 1875 /* 1849 1876 * If tp->address == 0, then this point must be a 1850 1877 * absolute address uprobe. ··· 1839 1904 1840 1905 /* Use the tp->address for uprobes */ 1841 1906 if (tev->uprobes) 1842 - ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", 1843 - tp->module, tp->address); 1907 + strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address); 1844 1908 else if (!strncmp(tp->symbol, "0x", 2)) 1845 1909 /* Absolute address. See try_to_find_absolute_address() */ 1846 - ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx", 1847 - tp->module ?: "", tp->module ? ":" : "", 1848 - tp->address); 1910 + strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "", 1911 + tp->module ? ":" : "", tp->address); 1849 1912 else 1850 - ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", 1851 - tp->module ?: "", tp->module ? ":" : "", 1852 - tp->symbol, tp->offset); 1913 + strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "", 1914 + tp->module ? ":" : "", tp->symbol, tp->offset); 1853 1915 1854 - if (ret <= 0) 1855 - goto error; 1856 - len += ret; 1857 - 1858 - for (i = 0; i < tev->nargs; i++) { 1859 - ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 1860 - MAX_CMDLEN - len); 1861 - if (ret <= 0) 1916 + for (i = 0; i < tev->nargs; i++) 1917 + if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0) 1862 1918 goto error; 1863 - len += ret; 1864 - } 1865 1919 1866 - return buf; 1920 + ret = strbuf_detach(&buf, NULL); 1867 1921 error: 1868 - free(buf); 1869 - return NULL; 1922 + strbuf_release(&buf); 1923 + return ret; 1870 1924 } 1871 1925 1872 1926 static int find_perf_probe_point_from_map(struct probe_trace_point *tp, ··· 1937 2013 static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1938 2014 struct perf_probe_event *pev, bool is_kprobe) 1939 2015 { 1940 - char buf[64] = ""; 2016 + struct strbuf buf = STRBUF_INIT; 1941 2017 int i, ret; 1942 2018 1943 2019 /* Convert event/group name */ ··· 1960 2036 if (tev->args[i].name) 1961 2037 pev->args[i].name = strdup(tev->args[i].name); 1962 2038 else { 1963 - ret = synthesize_probe_trace_arg(&tev->args[i], 1964 - buf, 64); 1965 - pev->args[i].name = strdup(buf); 2039 + strbuf_init(&buf, 32); 2040 + ret = synthesize_probe_trace_arg(&tev->args[i], &buf); 2041 + pev->args[i].name = strbuf_detach(&buf, NULL); 1966 2042 } 1967 2043 if (pev->args[i].name == NULL && ret >= 0) 1968 2044 ret = -ENOMEM; ··· 2140 2216 const char *module, 2141 2217 struct strbuf *result) 2142 2218 { 2143 - int i, ret; 2144 - char buf[128]; 2145 - char *place; 2219 + int i; 2220 + char *buf; 2221 + 2222 + if (asprintf(&buf, "%s:%s", group, event) < 0) 2223 + return -errno; 2224 + strbuf_addf(result, " %-20s (on ", buf); 2225 + free(buf); 2146 2226 2147 2227 /* Synthesize only event probe point */ 2148 - place = synthesize_perf_probe_point(&pev->point); 2149 - if (!place) 2150 - return -EINVAL; 2228 + buf = synthesize_perf_probe_point(&pev->point); 2229 + if (!buf) 2230 + return -ENOMEM; 2231 + strbuf_addstr(result, buf); 2232 + free(buf); 2151 2233 2152 - ret = e_snprintf(buf, 128, "%s:%s", group, event); 2153 - if (ret < 0) 2154 - goto out; 2155 - 2156 - strbuf_addf(result, " %-20s (on %s", buf, place); 2157 2234 if (module) 2158 2235 strbuf_addf(result, " in %s", module); 2159 2236 2160 2237 if (pev->nargs > 0) { 2161 2238 strbuf_add(result, " with", 5); 2162 2239 for (i = 0; i < pev->nargs; i++) { 2163 - ret = synthesize_perf_probe_arg(&pev->args[i], 2164 - buf, 128); 2165 - if (ret < 0) 2166 - goto out; 2240 + buf = synthesize_perf_probe_arg(&pev->args[i]); 2241 + if (!buf) 2242 + return -ENOMEM; 2167 2243 strbuf_addf(result, " %s", buf); 2244 + free(buf); 2168 2245 } 2169 2246 } 2170 2247 strbuf_addch(result, ')'); 2171 - out: 2172 - free(place); 2173 - return ret; 2248 + 2249 + return 0; 2174 2250 } 2175 2251 2176 2252 /* Show an event */
+1 -1
tools/perf/util/probe-event.h
··· 120 120 /* Events to command string */ 121 121 char *synthesize_perf_probe_command(struct perf_probe_event *pev); 122 122 char *synthesize_probe_trace_command(struct probe_trace_event *tev); 123 - int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len); 123 + char *synthesize_perf_probe_arg(struct perf_probe_arg *pa); 124 124 125 125 /* Check the perf_probe_event needs debuginfo */ 126 126 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
+7 -7
tools/perf/util/probe-finder.c
··· 553 553 static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) 554 554 { 555 555 Dwarf_Die vr_die; 556 - char buf[32], *ptr; 556 + char *buf, *ptr; 557 557 int ret = 0; 558 558 559 559 /* Copy raw parameters */ ··· 563 563 if (pf->pvar->name) 564 564 pf->tvar->name = strdup(pf->pvar->name); 565 565 else { 566 - ret = synthesize_perf_probe_arg(pf->pvar, buf, 32); 567 - if (ret < 0) 568 - return ret; 566 + buf = synthesize_perf_probe_arg(pf->pvar); 567 + if (!buf) 568 + return -ENOMEM; 569 569 ptr = strchr(buf, ':'); /* Change type separator to _ */ 570 570 if (ptr) 571 571 *ptr = '_'; 572 - pf->tvar->name = strdup(buf); 572 + pf->tvar->name = buf; 573 573 } 574 574 if (pf->tvar->name == NULL) 575 575 return -ENOMEM; ··· 1334 1334 if (ret2 == 0) { 1335 1335 strlist__add(vl->vars, 1336 1336 strbuf_detach(&buf, NULL)); 1337 - } 1338 - strbuf_release(&buf); 1337 + } else 1338 + strbuf_release(&buf); 1339 1339 } 1340 1340 } 1341 1341
+94
tools/perf/util/trigger.h
··· 1 + #ifndef __TRIGGER_H_ 2 + #define __TRIGGER_H_ 1 3 + 4 + #include "util/debug.h" 5 + #include "asm/bug.h" 6 + 7 + /* 8 + * Use trigger to model operations which need to be executed when 9 + * an event (a signal, for example) is observed. 10 + * 11 + * States and transits: 12 + * 13 + * 14 + * OFF--(on)--> READY --(hit)--> HIT 15 + * ^ | 16 + * | (ready) 17 + * | | 18 + * \_____________/ 19 + * 20 + * is_hit and is_ready are two key functions to query the state of 21 + * a trigger. is_hit means the event already happen; is_ready means the 22 + * trigger is waiting for the event. 23 + */ 24 + 25 + struct trigger { 26 + volatile enum { 27 + TRIGGER_ERROR = -2, 28 + TRIGGER_OFF = -1, 29 + TRIGGER_READY = 0, 30 + TRIGGER_HIT = 1, 31 + } state; 32 + const char *name; 33 + }; 34 + 35 + #define TRIGGER_WARN_ONCE(t, exp) \ 36 + WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \ 37 + t->name, t->state, __func__) 38 + 39 + static inline bool trigger_is_available(struct trigger *t) 40 + { 41 + return t->state >= 0; 42 + } 43 + 44 + static inline bool trigger_is_error(struct trigger *t) 45 + { 46 + return t->state <= TRIGGER_ERROR; 47 + } 48 + 49 + static inline void trigger_on(struct trigger *t) 50 + { 51 + TRIGGER_WARN_ONCE(t, TRIGGER_OFF); 52 + t->state = TRIGGER_READY; 53 + } 54 + 55 + static inline void trigger_ready(struct trigger *t) 56 + { 57 + if (!trigger_is_available(t)) 58 + return; 59 + t->state = TRIGGER_READY; 60 + } 61 + 62 + static inline void trigger_hit(struct trigger *t) 63 + { 64 + if (!trigger_is_available(t)) 65 + return; 66 + TRIGGER_WARN_ONCE(t, TRIGGER_READY); 67 + t->state = TRIGGER_HIT; 68 + } 69 + 70 + static inline void trigger_off(struct trigger *t) 71 + { 72 + if (!trigger_is_available(t)) 73 + return; 74 + t->state = TRIGGER_OFF; 75 + } 76 + 77 + static inline void trigger_error(struct trigger *t) 78 + { 79 + t->state = TRIGGER_ERROR; 80 + } 81 + 82 + static inline bool trigger_is_ready(struct trigger *t) 83 + { 84 + return t->state == TRIGGER_READY; 85 + } 86 + 87 + static inline bool trigger_is_hit(struct trigger *t) 88 + { 89 + return t->state == TRIGGER_HIT; 90 + } 91 + 92 + #define DEFINE_TRIGGER(n) \ 93 + struct trigger n = {.state = TRIGGER_OFF, .name = #n} 94 + #endif