From 2d7102a0453769fd37e9f4ce68652e104fbf5c84 Mon Sep 17 00:00:00 2001 From: Numfor Mbiziwo-Tiapo Date: Thu, 20 Jun 2019 14:54:46 -0700 Subject: [PATCH 01/43] perf tools: Fix cache.h include directive Change the include path so that progress.c can find cache.h since it was previously searching in the wrong directory. Committer notes: $ ls -la tools/perf/ui/../cache.h ls: cannot access 'tools/perf/ui/../cache.h': No such file or directory So it really should include ../../util/cache.h, or plain cache.h, since we have -Iutil in INC_FLAGS in tools/perf/Makefile.config Signed-off-by: Numfor Mbiziwo-Tiapo Cc: Jiri Olsa , Cc: Luke Mujica , Cc: Stephane Eranian To: Ian Rogers Link: https://lkml.kernel.org/n/tip-pud8usyutvd2npg2vpsygncz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/progress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c index bbfbc91a0fa4..8cd3b64c6893 100644 --- a/tools/perf/ui/progress.c +++ b/tools/perf/ui/progress.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include -#include "../cache.h" +#include "../util/cache.h" #include "progress.h" static void null_progress__update(struct ui_progress *p __maybe_unused) From 97860b483c5597663a174ff7405be957b4838391 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 19 Jun 2019 09:44:28 +0300 Subject: [PATCH 02/43] perf thread-stack: Fix thread stack return from kernel for kernel-only case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit f08046cb3082 ("perf thread-stack: Represent jmps to the start of a different symbol") had the side-effect of introducing more stack entries before return from kernel space. When user space is also traced, those entries are popped before entry to user space, but when user space is not traced, they get stuck at the bottom of the stack, making the stack grow progressively larger. Fix by detecting a return-from-kernel branch type, and popping kernel addresses from the stack then. Note, the problem and fix affect the exported Call Graph / Tree but not the callindent option used by "perf script --call-trace". Example: perf-with-kcore record example -e intel_pt//k -- ls perf-with-kcore script example --itrace=bep -s ~/libexec/perf-core/scripts/python/export-to-sqlite.py example.db branches calls ~/libexec/perf-core/scripts/python/exported-sql-viewer.py example.db Menu option: Reports -> Context-Sensitive Call Graph Before: (showing Call Path column only) Call Path ▶ perf ▼ ls ▼ 12111:12111 ▶ setup_new_exec ▶ __task_pid_nr_ns ▶ perf_event_pid_type ▶ perf_event_comm_output ▶ perf_iterate_ctx ▶ perf_iterate_sb ▶ perf_event_comm ▶ __set_task_comm ▶ load_elf_binary ▶ search_binary_handler ▶ __do_execve_file.isra.41 ▶ __x64_sys_execve ▶ do_syscall_64 ▼ entry_SYSCALL_64_after_hwframe ▼ swapgs_restore_regs_and_return_to_usermode ▼ native_iret ▶ error_entry ▶ do_page_fault ▼ error_exit ▼ retint_user ▶ prepare_exit_to_usermode ▼ native_iret ▶ error_entry ▶ do_page_fault ▼ error_exit ▼ retint_user ▶ prepare_exit_to_usermode ▼ native_iret ▶ error_entry ▶ do_page_fault ▼ error_exit ▼ retint_user ▶ prepare_exit_to_usermode ▶ native_iret After: (showing Call Path column only) Call Path ▶ perf ▼ ls ▼ 12111:12111 ▶ setup_new_exec ▶ __task_pid_nr_ns ▶ perf_event_pid_type ▶ perf_event_comm_output ▶ perf_iterate_ctx ▶ perf_iterate_sb ▶ perf_event_comm ▶ __set_task_comm ▶ load_elf_binary ▶ search_binary_handler ▶ __do_execve_file.isra.41 ▶ __x64_sys_execve ▶ do_syscall_64 ▶ entry_SYSCALL_64_after_hwframe ▶ page_fault ▼ entry_SYSCALL_64 ▼ do_syscall_64 ▶ __x64_sys_brk ▶ __x64_sys_access ▶ __x64_sys_openat ▶ __x64_sys_newfstat ▶ __x64_sys_mmap ▶ __x64_sys_close ▶ __x64_sys_read ▶ __x64_sys_mprotect ▶ __x64_sys_arch_prctl ▶ __x64_sys_munmap ▶ exit_to_usermode_loop ▶ __x64_sys_set_tid_address ▶ __x64_sys_set_robust_list ▶ __x64_sys_rt_sigaction ▶ __x64_sys_rt_sigprocmask ▶ __x64_sys_prlimit64 ▶ __x64_sys_statfs ▶ __x64_sys_ioctl ▶ __x64_sys_getdents64 ▶ __x64_sys_write ▶ __x64_sys_exit_group Committer notes: The first arg to the perf-with-kcore needs to be the same for the 'record' and 'script' lines, otherwise we'll record the perf.data file and kcore_dir/ files in one directory ('example') to then try to use it from the 'bep' directory, fix the instructions above it so that both use 'example'. Signed-off-by: Adrian Hunter Tested-by: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: stable@vger.kernel.org Fixes: f08046cb3082 ("perf thread-stack: Represent jmps to the start of a different symbol") Link: http://lkml.kernel.org/r/20190619064429.14940-2-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread-stack.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index c485186a8b6d..4c826a2e08d8 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c @@ -628,6 +628,23 @@ static int thread_stack__bottom(struct thread_stack *ts, true, false); } +static int thread_stack__pop_ks(struct thread *thread, struct thread_stack *ts, + struct perf_sample *sample, u64 ref) +{ + u64 tm = sample->time; + int err; + + /* Return to userspace, so pop all kernel addresses */ + while (thread_stack__in_kernel(ts)) { + err = thread_stack__call_return(thread, ts, --ts->cnt, + tm, ref, true); + if (err) + return err; + } + + return 0; +} + static int thread_stack__no_call_return(struct thread *thread, struct thread_stack *ts, struct perf_sample *sample, @@ -910,7 +927,18 @@ int thread_stack__process(struct thread *thread, struct comm *comm, ts->rstate = X86_RETPOLINE_DETECTED; } else if (sample->flags & PERF_IP_FLAG_RETURN) { - if (!sample->ip || !sample->addr) + if (!sample->addr) { + u32 return_from_kernel = PERF_IP_FLAG_SYSCALLRET | + PERF_IP_FLAG_INTERRUPT; + + if (!(sample->flags & return_from_kernel)) + return 0; + + /* Pop kernel stack */ + return thread_stack__pop_ks(thread, ts, sample, ref); + } + + if (!sample->ip) return 0; /* x86 retpoline 'return' doesn't match the stack */ From eb5d854456f5a4ccec6f9681b7196cf056df8cfa Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 19 Jun 2019 09:44:29 +0300 Subject: [PATCH 03/43] perf thread-stack: Eliminate code duplicating thread_stack__pop_ks() Use new function thread_stack__pop_ks() in place of equivalent code. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190619064429.14940-3-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread-stack.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index 4c826a2e08d8..6ff1ff4d4ce7 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c @@ -664,12 +664,9 @@ static int thread_stack__no_call_return(struct thread *thread, if (ip >= ks && addr < ks) { /* Return to userspace, so pop all kernel addresses */ - while (thread_stack__in_kernel(ts)) { - err = thread_stack__call_return(thread, ts, --ts->cnt, - tm, ref, true); - if (err) - return err; - } + err = thread_stack__pop_ks(thread, ts, sample, ref); + if (err) + return err; /* If the stack is empty, push the userspace address */ if (!ts->cnt) { @@ -679,12 +676,9 @@ static int thread_stack__no_call_return(struct thread *thread, } } else if (thread_stack__in_kernel(ts) && ip < ks) { /* Return to userspace, so pop all kernel addresses */ - while (thread_stack__in_kernel(ts)) { - err = thread_stack__call_return(thread, ts, --ts->cnt, - tm, ref, true); - if (err) - return err; - } + err = thread_stack__pop_ks(thread, ts, sample, ref); + if (err) + return err; } if (ts->cnt) From 9f94c7f947e919c343b30f080285af53d0fa9902 Mon Sep 17 00:00:00 2001 From: Kyle Meyer Date: Thu, 20 Jun 2019 14:36:30 -0500 Subject: [PATCH 04/43] perf tools: Increase MAX_NR_CPUS and MAX_CACHES Attempting to profile 1024 or more CPUs with perf causes two errors: perf record -a [ perf record: Woken up X times to write data ] way too many cpu caches.. [ perf record: Captured and wrote X MB perf.data (X samples) ] perf report -C 1024 Error: failed to set cpu bitmap Requested CPU 1024 too large. Consider raising MAX_NR_CPUS Increasing MAX_NR_CPUS from 1024 to 2048 and redefining MAX_CACHES as MAX_NR_CPUS * 4 returns normal functionality to perf: perf record -a [ perf record: Woken up X times to write data ] [ perf record: Captured and wrote X MB perf.data (X samples) ] perf report -C 1024 ... Signed-off-by: Kyle Meyer Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20190620193630.154025-1-meyerk@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/perf.h | 2 +- tools/perf/util/header.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 711e009381ec..74d0124d38f3 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -26,7 +26,7 @@ static inline unsigned long long rdclock(void) } #ifndef MAX_NR_CPUS -#define MAX_NR_CPUS 1024 +#define MAX_NR_CPUS 2048 #endif extern const char *input_name; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 06ddb6618ef3..abc9c2145efe 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1121,7 +1121,7 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp) return 0; } -#define MAX_CACHES 2000 +#define MAX_CACHES (MAX_NR_CPUS * 4) static int write_cache(struct feat_fd *ff, struct perf_evlist *evlist __maybe_unused) From abe5a1d3e4bee361bd3b21b8909c8421e46911d1 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 22 Jun 2019 12:32:42 +0300 Subject: [PATCH 05/43] perf intel-pt: Decoder to output CBR changes immediately The core-to-bus ratio (CBR) provides the CPU frequency. With branches enabled, the decoder was outputting CBR changes only when there was a branch. That loses the correct time of the change if the trace is not in context (e.g. not tracing kernel space). Change to output the CBR change immediately. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190622093248.581-2-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- .../util/intel-pt-decoder/intel-pt-decoder.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index f8b71bf2bb4c..3d2255f284f4 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -2015,16 +2015,8 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) case INTEL_PT_CBR: intel_pt_calc_cbr(decoder); - if (!decoder->branch_enable && - decoder->cbr != decoder->cbr_seen) { - decoder->cbr_seen = decoder->cbr; - decoder->state.type = INTEL_PT_CBR_CHG; - decoder->state.from_ip = decoder->ip; - decoder->state.to_ip = 0; - decoder->state.cbr_payload = - decoder->packet.payload; + if (decoder->cbr != decoder->cbr_seen) return 0; - } break; case INTEL_PT_MODE_EXEC: @@ -2626,8 +2618,12 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; } else { decoder->state.err = 0; - if (decoder->cbr != decoder->cbr_seen && decoder->state.type) { + if (decoder->cbr != decoder->cbr_seen) { decoder->cbr_seen = decoder->cbr; + if (!decoder->state.type) { + decoder->state.from_ip = decoder->ip; + decoder->state.to_ip = 0; + } decoder->state.type |= INTEL_PT_CBR_CHG; decoder->state.cbr_payload = decoder->cbr_payload; } From 91de8684f1cff6944634bfb9098dc3a2583f798c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 22 Jun 2019 12:32:43 +0300 Subject: [PATCH 06/43] perf intel-pt: Cater for CBR change in PSB+ PSB+ provides status information only so the core-to-bus ratio (CBR) in PSB+ will not have changed from its previous value. However, cater for the possibility of a another CBR change that gets caught up in the PSB+ anyway. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190622093248.581-3-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 3d2255f284f4..5eb792cc5d3a 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1975,6 +1975,13 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) goto next; if (err) return err; + /* + * PSB+ CBR will not have changed but cater for the + * possibility of another CBR change that gets caught up + * in the PSB+. + */ + if (decoder->cbr != decoder->cbr_seen) + return 0; break; case INTEL_PT_PIP: From 51b091861828f5801207a00211ea4e94102389c3 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 22 Jun 2019 12:32:44 +0300 Subject: [PATCH 07/43] perf intel-pt: Add CBR value to decoder state For convenience, add the core-to-bus ratio (CBR) value to the decoder state. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190622093248.581-4-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 1 + tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 5eb792cc5d3a..4d14e78c5927 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -2633,6 +2633,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) } decoder->state.type |= INTEL_PT_CBR_CHG; decoder->state.cbr_payload = decoder->cbr_payload; + decoder->state.cbr = decoder->cbr; } if (intel_pt_sample_time(decoder->pkt_state)) { intel_pt_update_sample_time(decoder); diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index 9957f2ccdca8..e289e463d635 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -213,6 +213,7 @@ struct intel_pt_state { uint64_t pwre_payload; uint64_t pwrx_payload; uint64_t cbr_payload; + uint32_t cbr; uint32_t flags; enum intel_pt_insn_op insn_op; int insn_len; From 5fe2cf7d19c48f2b53b57e6a5786972bc1b8d738 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 22 Jun 2019 12:32:45 +0300 Subject: [PATCH 08/43] perf intel-pt: Synthesize CBR events when last seen value changes The first core-to-bus ratio (CBR) event will not be shown if --itrace 's' option (skip initial number of events) is used, nor if time intervals are specified that do not include the start of tracing. Change the logic to record the last CBR value seen by the user, and synthesize CBR events whenever that changes. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190622093248.581-5-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/intel-pt.c | 65 ++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 550db6e77968..470aaae9d930 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -171,6 +171,7 @@ struct intel_pt_queue { u64 last_in_cyc_cnt; u64 last_br_insn_cnt; u64 last_br_cyc_cnt; + unsigned int cbr_seen; char insn[INTEL_PT_INSN_BUF_SZ]; }; @@ -1052,6 +1053,8 @@ static int intel_pt_setup_queue(struct intel_pt *pt, ptq->cpu = queue->cpu; ptq->tid = queue->tid; + ptq->cbr_seen = UINT_MAX; + if (pt->sampling_mode && !pt->snapshot_mode && pt->timeless_decoding) ptq->step_through_buffers = true; @@ -1184,6 +1187,17 @@ static inline bool intel_pt_skip_event(struct intel_pt *pt) pt->num_events++ < pt->synth_opts.initial_skip; } +/* + * Cannot count CBR as skipped because it won't go away until cbr == cbr_seen. + * Also ensure CBR is first non-skipped event by allowing for 4 more samples + * from this decoder state. + */ +static inline bool intel_pt_skip_cbr_event(struct intel_pt *pt) +{ + return pt->synth_opts.initial_skip && + pt->num_events + 4 < pt->synth_opts.initial_skip; +} + static void intel_pt_prep_a_sample(struct intel_pt_queue *ptq, union perf_event *event, struct perf_sample *sample) @@ -1429,9 +1443,11 @@ static int intel_pt_synth_cbr_sample(struct intel_pt_queue *ptq) struct perf_synth_intel_cbr raw; u32 flags; - if (intel_pt_skip_event(pt)) + if (intel_pt_skip_cbr_event(pt)) return 0; + ptq->cbr_seen = ptq->state->cbr; + intel_pt_prep_p_sample(pt, ptq, event, &sample); sample.id = ptq->pt->cbr_id; @@ -1868,8 +1884,7 @@ static inline bool intel_pt_is_switch_ip(struct intel_pt_queue *ptq, u64 ip) } #define INTEL_PT_PWR_EVT (INTEL_PT_MWAIT_OP | INTEL_PT_PWR_ENTRY | \ - INTEL_PT_EX_STOP | INTEL_PT_PWR_EXIT | \ - INTEL_PT_CBR_CHG) + INTEL_PT_EX_STOP | INTEL_PT_PWR_EXIT) static int intel_pt_sample(struct intel_pt_queue *ptq) { @@ -1901,31 +1916,33 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) return err; } - if (pt->sample_pwr_events && (state->type & INTEL_PT_PWR_EVT)) { - if (state->type & INTEL_PT_CBR_CHG) { + if (pt->sample_pwr_events) { + if (ptq->state->cbr != ptq->cbr_seen) { err = intel_pt_synth_cbr_sample(ptq); if (err) return err; } - if (state->type & INTEL_PT_MWAIT_OP) { - err = intel_pt_synth_mwait_sample(ptq); - if (err) - return err; - } - if (state->type & INTEL_PT_PWR_ENTRY) { - err = intel_pt_synth_pwre_sample(ptq); - if (err) - return err; - } - if (state->type & INTEL_PT_EX_STOP) { - err = intel_pt_synth_exstop_sample(ptq); - if (err) - return err; - } - if (state->type & INTEL_PT_PWR_EXIT) { - err = intel_pt_synth_pwrx_sample(ptq); - if (err) - return err; + if (state->type & INTEL_PT_PWR_EVT) { + if (state->type & INTEL_PT_MWAIT_OP) { + err = intel_pt_synth_mwait_sample(ptq); + if (err) + return err; + } + if (state->type & INTEL_PT_PWR_ENTRY) { + err = intel_pt_synth_pwre_sample(ptq); + if (err) + return err; + } + if (state->type & INTEL_PT_EX_STOP) { + err = intel_pt_synth_exstop_sample(ptq); + if (err) + return err; + } + if (state->type & INTEL_PT_PWR_EXIT) { + err = intel_pt_synth_pwrx_sample(ptq); + if (err) + return err; + } } } From b9322cab17a1092e2aa7ee2505ecceb0cd5fd685 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 22 Jun 2019 12:32:46 +0300 Subject: [PATCH 09/43] perf db-export: Export synth events Synthesized events are samples but with architecture-specific data stored in sample->raw_data. They are identified by attribute type PERF_TYPE_SYNTH. Add a function to export them. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190622093248.581-6-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- .../scripting-engines/trace-event-python.c | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 6acb379b53ec..112bed65232f 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -112,6 +112,7 @@ struct tables { PyObject *sample_handler; PyObject *call_path_handler; PyObject *call_return_handler; + PyObject *synth_handler; bool db_export_mode; }; @@ -947,6 +948,12 @@ static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s)); } +static int tuple_set_bytes(PyObject *t, unsigned int pos, void *bytes, + unsigned int sz) +{ + return PyTuple_SetItem(t, pos, _PyBytes_FromStringAndSize(bytes, sz)); +} + static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) { struct tables *tables = container_of(dbe, struct tables, dbe); @@ -1105,8 +1112,8 @@ static int python_export_branch_type(struct db_export *dbe, u32 branch_type, return 0; } -static int python_export_sample(struct db_export *dbe, - struct export_sample *es) +static void python_export_sample_table(struct db_export *dbe, + struct export_sample *es) { struct tables *tables = container_of(dbe, struct tables, dbe); PyObject *t; @@ -1141,6 +1148,33 @@ static int python_export_sample(struct db_export *dbe, call_object(tables->sample_handler, t, "sample_table"); Py_DECREF(t); +} + +static void python_export_synth(struct db_export *dbe, struct export_sample *es) +{ + struct tables *tables = container_of(dbe, struct tables, dbe); + PyObject *t; + + t = tuple_new(3); + + tuple_set_u64(t, 0, es->db_id); + tuple_set_u64(t, 1, es->evsel->attr.config); + tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size); + + call_object(tables->synth_handler, t, "synth_data"); + + Py_DECREF(t); +} + +static int python_export_sample(struct db_export *dbe, + struct export_sample *es) +{ + struct tables *tables = container_of(dbe, struct tables, dbe); + + python_export_sample_table(dbe, es); + + if (es->evsel->attr.type == PERF_TYPE_SYNTH && tables->synth_handler) + python_export_synth(dbe, es); return 0; } @@ -1477,6 +1511,14 @@ static void set_table_handlers(struct tables *tables) SET_TABLE_HANDLER(sample); SET_TABLE_HANDLER(call_path); SET_TABLE_HANDLER(call_return); + + /* + * Synthesized events are samples but with architecture-specific data + * stored in sample->raw_data. They are exported via + * python_export_sample() and consequently do not need a separate export + * callback. + */ + tables->synth_handler = get_handler("synth_data"); } #if PY_MAJOR_VERSION < 3 From 5130c6e55531b9bbcdeb8b327711ff204bc4835f Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 22 Jun 2019 12:32:47 +0300 Subject: [PATCH 10/43] perf scripts python: export-to-sqlite.py: Export Intel PT power and ptwrite events The format of synthesized events is determined by the attribute config. For the formats for Intel PT power and ptwrite events, create tables and populate them when the synth_data handler is called. If the tables remain empty, drop them at the end. The tables and views, including a combined power_events_view, will display automatically from the tables menu of the exported exported-sql-viewer.py script. Note, currently only Atoms since Gemini Lake have support for ptwrite and mwait, pwre, exstop and pwrx, but all Intel PT implementations support cbr. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190622093248.581-7-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/export-to-sqlite.py | 239 ++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py index 4542ce89034b..3222a83f4184 100644 --- a/tools/perf/scripts/python/export-to-sqlite.py +++ b/tools/perf/scripts/python/export-to-sqlite.py @@ -271,6 +271,38 @@ if perf_db_export_calls: 'insn_count bigint,' 'cyc_count bigint)') +do_query(query, 'CREATE TABLE ptwrite (' + 'id integer NOT NULL PRIMARY KEY,' + 'payload bigint,' + 'exact_ip integer)') + +do_query(query, 'CREATE TABLE cbr (' + 'id integer NOT NULL PRIMARY KEY,' + 'cbr integer,' + 'mhz integer,' + 'percent integer)') + +do_query(query, 'CREATE TABLE mwait (' + 'id integer NOT NULL PRIMARY KEY,' + 'hints integer,' + 'extensions integer)') + +do_query(query, 'CREATE TABLE pwre (' + 'id integer NOT NULL PRIMARY KEY,' + 'cstate integer,' + 'subcstate integer,' + 'hw integer)') + +do_query(query, 'CREATE TABLE exstop (' + 'id integer NOT NULL PRIMARY KEY,' + 'exact_ip integer)') + +do_query(query, 'CREATE TABLE pwrx (' + 'id integer NOT NULL PRIMARY KEY,' + 'deepest_cstate integer,' + 'last_cstate integer,' + 'wake_reason integer)') + # printf was added to sqlite in version 3.8.3 sqlite_has_printf = False try: @@ -399,6 +431,102 @@ do_query(query, 'CREATE VIEW samples_view AS ' 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC' ' FROM samples') +do_query(query, 'CREATE VIEW ptwrite_view AS ' + 'SELECT ' + 'ptwrite.id,' + 'time,' + 'cpu,' + + emit_to_hex('payload') + ' AS payload_hex,' + 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip' + ' FROM ptwrite' + ' INNER JOIN samples ON samples.id = ptwrite.id') + +do_query(query, 'CREATE VIEW cbr_view AS ' + 'SELECT ' + 'cbr.id,' + 'time,' + 'cpu,' + 'cbr,' + 'mhz,' + 'percent' + ' FROM cbr' + ' INNER JOIN samples ON samples.id = cbr.id') + +do_query(query, 'CREATE VIEW mwait_view AS ' + 'SELECT ' + 'mwait.id,' + 'time,' + 'cpu,' + + emit_to_hex('hints') + ' AS hints_hex,' + + emit_to_hex('extensions') + ' AS extensions_hex' + ' FROM mwait' + ' INNER JOIN samples ON samples.id = mwait.id') + +do_query(query, 'CREATE VIEW pwre_view AS ' + 'SELECT ' + 'pwre.id,' + 'time,' + 'cpu,' + 'cstate,' + 'subcstate,' + 'CASE WHEN hw=0 THEN \'False\' ELSE \'True\' END AS hw' + ' FROM pwre' + ' INNER JOIN samples ON samples.id = pwre.id') + +do_query(query, 'CREATE VIEW exstop_view AS ' + 'SELECT ' + 'exstop.id,' + 'time,' + 'cpu,' + 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip' + ' FROM exstop' + ' INNER JOIN samples ON samples.id = exstop.id') + +do_query(query, 'CREATE VIEW pwrx_view AS ' + 'SELECT ' + 'pwrx.id,' + 'time,' + 'cpu,' + 'deepest_cstate,' + 'last_cstate,' + 'CASE WHEN wake_reason=1 THEN \'Interrupt\'' + ' WHEN wake_reason=2 THEN \'Timer Deadline\'' + ' WHEN wake_reason=4 THEN \'Monitored Address\'' + ' WHEN wake_reason=8 THEN \'HW\'' + ' ELSE wake_reason ' + 'END AS wake_reason' + ' FROM pwrx' + ' INNER JOIN samples ON samples.id = pwrx.id') + +do_query(query, 'CREATE VIEW power_events_view AS ' + 'SELECT ' + 'samples.id,' + 'time,' + 'cpu,' + 'selected_events.name AS event,' + 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT cbr FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS cbr,' + 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT mhz FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS mhz,' + 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT percent FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS percent,' + 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('hints') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS hints_hex,' + 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('extensions') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS extensions_hex,' + 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT cstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS cstate,' + 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT subcstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS subcstate,' + 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT hw FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS hw,' + 'CASE WHEN selected_events.name=\'exstop\' THEN (SELECT exact_ip FROM exstop WHERE exstop.id = samples.id) ELSE "" END AS exact_ip,' + 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT deepest_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS deepest_cstate,' + 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT last_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS last_cstate,' + 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT ' + 'CASE WHEN wake_reason=1 THEN \'Interrupt\'' + ' WHEN wake_reason=2 THEN \'Timer Deadline\'' + ' WHEN wake_reason=4 THEN \'Monitored Address\'' + ' WHEN wake_reason=8 THEN \'HW\'' + ' ELSE wake_reason ' + 'END' + ' FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS wake_reason' + ' FROM samples' + ' INNER JOIN selected_events ON selected_events.id = evsel_id' + ' WHERE selected_events.name IN (\'cbr\',\'mwait\',\'exstop\',\'pwre\',\'pwrx\')') + do_query(query, 'END TRANSACTION') evsel_query = QSqlQuery(db) @@ -428,6 +556,18 @@ if perf_db_export_calls or perf_db_export_callchains: if perf_db_export_calls: call_query = QSqlQuery(db) call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") +ptwrite_query = QSqlQuery(db) +ptwrite_query.prepare("INSERT INTO ptwrite VALUES (?, ?, ?)") +cbr_query = QSqlQuery(db) +cbr_query.prepare("INSERT INTO cbr VALUES (?, ?, ?, ?)") +mwait_query = QSqlQuery(db) +mwait_query.prepare("INSERT INTO mwait VALUES (?, ?, ?)") +pwre_query = QSqlQuery(db) +pwre_query.prepare("INSERT INTO pwre VALUES (?, ?, ?, ?)") +exstop_query = QSqlQuery(db) +exstop_query.prepare("INSERT INTO exstop VALUES (?, ?)") +pwrx_query = QSqlQuery(db) +pwrx_query.prepare("INSERT INTO pwrx VALUES (?, ?, ?, ?)") def trace_begin(): printdate("Writing records...") @@ -446,6 +586,16 @@ def trace_begin(): unhandled_count = 0 +def is_table_empty(table_name): + do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1'); + if query.next(): + return False + return True + +def drop(table_name): + do_query(query, 'DROP VIEW ' + table_name + '_view'); + do_query(query, 'DROP TABLE ' + table_name); + def trace_end(): do_query(query, 'END TRANSACTION') @@ -454,6 +604,18 @@ def trace_end(): do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') + printdate("Dropping unused tables") + if is_table_empty("ptwrite"): + drop("ptwrite") + if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"): + drop("mwait") + drop("pwre") + drop("exstop") + drop("pwrx") + do_query(query, 'DROP VIEW power_events_view'); + if is_table_empty("cbr"): + drop("cbr") + if (unhandled_count): printdate("Warning: ", unhandled_count, " unhandled events") printdate("Done") @@ -509,3 +671,80 @@ def call_path_table(*x): def call_return_table(*x): bind_exec(call_query, 14, x) + +def ptwrite(id, raw_buf): + data = struct.unpack_from("> 32) & 0x3 + mwait_query.addBindValue(str(id)) + mwait_query.addBindValue(str(hints)) + mwait_query.addBindValue(str(extensions)) + do_query_(mwait_query) + +def pwre(id, raw_buf): + data = struct.unpack_from("> 7) & 1 + cstate = (payload >> 12) & 0xf + subcstate = (payload >> 8) & 0xf + pwre_query.addBindValue(str(id)) + pwre_query.addBindValue(str(cstate)) + pwre_query.addBindValue(str(subcstate)) + pwre_query.addBindValue(str(hw)) + do_query_(pwre_query) + +def exstop(id, raw_buf): + data = struct.unpack_from("> 4) & 0xf + wake_reason = (payload >> 8) & 0xf + pwrx_query.addBindValue(str(id)) + pwrx_query.addBindValue(str(deepest_cstate)) + pwrx_query.addBindValue(str(last_cstate)) + pwrx_query.addBindValue(str(wake_reason)) + do_query_(pwrx_query) + +def synth_data(id, config, raw_buf, *x): + if config == 0: + ptwrite(id, raw_buf) + elif config == 1: + mwait(id, raw_buf) + elif config == 2: + pwre(id, raw_buf) + elif config == 3: + exstop(id, raw_buf) + elif config == 4: + pwrx(id, raw_buf) + elif config == 5: + cbr(id, raw_buf) From aba44287a224dfcfdd99ba885ca9d9acc4de0c17 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 22 Jun 2019 12:32:48 +0300 Subject: [PATCH 11/43] perf scripts python: export-to-postgresql.py: Export Intel PT power and ptwrite events The format of synthesized events is determined by the attribute config. For the formats for Intel PT power and ptwrite events, create tables and populate them when the synth_data handler is called. If the tables remain empty, drop them at the end. The tables and views, including a combined power_events_view, will display automatically from the tables menu of the exported exported-sql-viewer.py script. Note, currently only Atoms since Gemini Lake have support for ptwrite and mwait, pwre, exstop and pwrx, but all Intel PT implementations support cbr. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190622093248.581-8-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- .../scripts/python/export-to-postgresql.py | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py index 93225c02117e..4447f0d7c754 100644 --- a/tools/perf/scripts/python/export-to-postgresql.py +++ b/tools/perf/scripts/python/export-to-postgresql.py @@ -447,6 +447,38 @@ if perf_db_export_calls: 'insn_count bigint,' 'cyc_count bigint)') +do_query(query, 'CREATE TABLE ptwrite (' + 'id bigint NOT NULL,' + 'payload bigint,' + 'exact_ip boolean)') + +do_query(query, 'CREATE TABLE cbr (' + 'id bigint NOT NULL,' + 'cbr integer,' + 'mhz integer,' + 'percent integer)') + +do_query(query, 'CREATE TABLE mwait (' + 'id bigint NOT NULL,' + 'hints integer,' + 'extensions integer)') + +do_query(query, 'CREATE TABLE pwre (' + 'id bigint NOT NULL,' + 'cstate integer,' + 'subcstate integer,' + 'hw boolean)') + +do_query(query, 'CREATE TABLE exstop (' + 'id bigint NOT NULL,' + 'exact_ip boolean)') + +do_query(query, 'CREATE TABLE pwrx (' + 'id bigint NOT NULL,' + 'deepest_cstate integer,' + 'last_cstate integer,' + 'wake_reason integer)') + do_query(query, 'CREATE VIEW machines_view AS ' 'SELECT ' 'id,' @@ -561,6 +593,104 @@ do_query(query, 'CREATE VIEW samples_view AS ' 'CASE WHEN cyc_count=0 THEN CAST(0 AS NUMERIC(20, 2)) ELSE CAST((CAST(insn_count AS FLOAT) / cyc_count) AS NUMERIC(20, 2)) END AS IPC' ' FROM samples') +do_query(query, 'CREATE VIEW ptwrite_view AS ' + 'SELECT ' + 'ptwrite.id,' + 'time,' + 'cpu,' + 'to_hex(payload) AS payload_hex,' + 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip' + ' FROM ptwrite' + ' INNER JOIN samples ON samples.id = ptwrite.id') + +do_query(query, 'CREATE VIEW cbr_view AS ' + 'SELECT ' + 'cbr.id,' + 'time,' + 'cpu,' + 'cbr,' + 'mhz,' + 'percent' + ' FROM cbr' + ' INNER JOIN samples ON samples.id = cbr.id') + +do_query(query, 'CREATE VIEW mwait_view AS ' + 'SELECT ' + 'mwait.id,' + 'time,' + 'cpu,' + 'to_hex(hints) AS hints_hex,' + 'to_hex(extensions) AS extensions_hex' + ' FROM mwait' + ' INNER JOIN samples ON samples.id = mwait.id') + +do_query(query, 'CREATE VIEW pwre_view AS ' + 'SELECT ' + 'pwre.id,' + 'time,' + 'cpu,' + 'cstate,' + 'subcstate,' + 'CASE WHEN hw=FALSE THEN \'False\' ELSE \'True\' END AS hw' + ' FROM pwre' + ' INNER JOIN samples ON samples.id = pwre.id') + +do_query(query, 'CREATE VIEW exstop_view AS ' + 'SELECT ' + 'exstop.id,' + 'time,' + 'cpu,' + 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip' + ' FROM exstop' + ' INNER JOIN samples ON samples.id = exstop.id') + +do_query(query, 'CREATE VIEW pwrx_view AS ' + 'SELECT ' + 'pwrx.id,' + 'time,' + 'cpu,' + 'deepest_cstate,' + 'last_cstate,' + 'CASE WHEN wake_reason=1 THEN \'Interrupt\'' + ' WHEN wake_reason=2 THEN \'Timer Deadline\'' + ' WHEN wake_reason=4 THEN \'Monitored Address\'' + ' WHEN wake_reason=8 THEN \'HW\'' + ' ELSE CAST ( wake_reason AS VARCHAR(2) )' + 'END AS wake_reason' + ' FROM pwrx' + ' INNER JOIN samples ON samples.id = pwrx.id') + +do_query(query, 'CREATE VIEW power_events_view AS ' + 'SELECT ' + 'samples.id,' + 'samples.time,' + 'samples.cpu,' + 'selected_events.name AS event,' + 'FORMAT(\'%6s\', cbr.cbr) AS cbr,' + 'FORMAT(\'%6s\', cbr.mhz) AS MHz,' + 'FORMAT(\'%5s\', cbr.percent) AS percent,' + 'to_hex(mwait.hints) AS hints_hex,' + 'to_hex(mwait.extensions) AS extensions_hex,' + 'FORMAT(\'%3s\', pwre.cstate) AS cstate,' + 'FORMAT(\'%3s\', pwre.subcstate) AS subcstate,' + 'CASE WHEN pwre.hw=FALSE THEN \'False\' WHEN pwre.hw=TRUE THEN \'True\' ELSE NULL END AS hw,' + 'CASE WHEN exstop.exact_ip=FALSE THEN \'False\' WHEN exstop.exact_ip=TRUE THEN \'True\' ELSE NULL END AS exact_ip,' + 'FORMAT(\'%3s\', pwrx.deepest_cstate) AS deepest_cstate,' + 'FORMAT(\'%3s\', pwrx.last_cstate) AS last_cstate,' + 'CASE WHEN pwrx.wake_reason=1 THEN \'Interrupt\'' + ' WHEN pwrx.wake_reason=2 THEN \'Timer Deadline\'' + ' WHEN pwrx.wake_reason=4 THEN \'Monitored Address\'' + ' WHEN pwrx.wake_reason=8 THEN \'HW\'' + ' ELSE FORMAT(\'%2s\', pwrx.wake_reason)' + 'END AS wake_reason' + ' FROM cbr' + ' FULL JOIN mwait ON mwait.id = cbr.id' + ' FULL JOIN pwre ON pwre.id = cbr.id' + ' FULL JOIN exstop ON exstop.id = cbr.id' + ' FULL JOIN pwrx ON pwrx.id = cbr.id' + ' INNER JOIN samples ON samples.id = coalesce(cbr.id, mwait.id, pwre.id, exstop.id, pwrx.id)' + ' INNER JOIN selected_events ON selected_events.id = samples.evsel_id' + ' ORDER BY samples.id') file_header = struct.pack("!11sii", b"PGCOPY\n\377\r\n\0", 0, 0) file_trailer = b"\377\377" @@ -620,6 +750,12 @@ if perf_db_export_calls or perf_db_export_callchains: call_path_file = open_output_file("call_path_table.bin") if perf_db_export_calls: call_file = open_output_file("call_table.bin") +ptwrite_file = open_output_file("ptwrite_table.bin") +cbr_file = open_output_file("cbr_table.bin") +mwait_file = open_output_file("mwait_table.bin") +pwre_file = open_output_file("pwre_table.bin") +exstop_file = open_output_file("exstop_table.bin") +pwrx_file = open_output_file("pwrx_table.bin") def trace_begin(): printdate("Writing to intermediate files...") @@ -637,6 +773,16 @@ def trace_begin(): unhandled_count = 0 +def is_table_empty(table_name): + do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1'); + if query.next(): + return False + return True + +def drop(table_name): + do_query(query, 'DROP VIEW ' + table_name + '_view'); + do_query(query, 'DROP TABLE ' + table_name); + def trace_end(): printdate("Copying to database...") copy_output_file(evsel_file, "selected_events") @@ -652,6 +798,12 @@ def trace_end(): copy_output_file(call_path_file, "call_paths") if perf_db_export_calls: copy_output_file(call_file, "calls") + copy_output_file(ptwrite_file, "ptwrite") + copy_output_file(cbr_file, "cbr") + copy_output_file(mwait_file, "mwait") + copy_output_file(pwre_file, "pwre") + copy_output_file(exstop_file, "exstop") + copy_output_file(pwrx_file, "pwrx") printdate("Removing intermediate files...") remove_output_file(evsel_file) @@ -667,6 +819,12 @@ def trace_end(): remove_output_file(call_path_file) if perf_db_export_calls: remove_output_file(call_file) + remove_output_file(ptwrite_file) + remove_output_file(cbr_file) + remove_output_file(mwait_file) + remove_output_file(pwre_file) + remove_output_file(exstop_file) + remove_output_file(pwrx_file) os.rmdir(output_dir_name) printdate("Adding primary keys") do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)') @@ -682,6 +840,12 @@ def trace_end(): do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)') if perf_db_export_calls: do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') + do_query(query, 'ALTER TABLE ptwrite ADD PRIMARY KEY (id)') + do_query(query, 'ALTER TABLE cbr ADD PRIMARY KEY (id)') + do_query(query, 'ALTER TABLE mwait ADD PRIMARY KEY (id)') + do_query(query, 'ALTER TABLE pwre ADD PRIMARY KEY (id)') + do_query(query, 'ALTER TABLE exstop ADD PRIMARY KEY (id)') + do_query(query, 'ALTER TABLE pwrx ADD PRIMARY KEY (id)') printdate("Adding foreign keys") do_query(query, 'ALTER TABLE threads ' @@ -717,6 +881,30 @@ def trace_end(): 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)') + do_query(query, 'ALTER TABLE ptwrite ' + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') + do_query(query, 'ALTER TABLE cbr ' + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') + do_query(query, 'ALTER TABLE mwait ' + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') + do_query(query, 'ALTER TABLE pwre ' + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') + do_query(query, 'ALTER TABLE exstop ' + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') + do_query(query, 'ALTER TABLE pwrx ' + 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)') + + printdate("Dropping unused tables") + if is_table_empty("ptwrite"): + drop("ptwrite") + if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"): + drop("mwait") + drop("pwre") + drop("exstop") + drop("pwrx") + do_query(query, 'DROP VIEW power_events_view'); + if is_table_empty("cbr"): + drop("cbr") if (unhandled_count): printdate("Warning: ", unhandled_count, " unhandled events") @@ -800,3 +988,66 @@ def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiqiqiq" value = struct.pack(fmt, 14, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id, 8, insn_cnt, 8, cyc_cnt) call_file.write(value) + +def ptwrite(id, raw_buf): + data = struct.unpack_from("> 32) & 0x3 + value = struct.pack("!hiqiiii", 3, 8, id, 4, hints, 4, extensions) + mwait_file.write(value) + +def pwre(id, raw_buf): + data = struct.unpack_from("> 7) & 1 + cstate = (payload >> 12) & 0xf + subcstate = (payload >> 8) & 0xf + value = struct.pack("!hiqiiiiiB", 4, 8, id, 4, cstate, 4, subcstate, 1, hw) + pwre_file.write(value) + +def exstop(id, raw_buf): + data = struct.unpack_from("> 4) & 0xf + wake_reason = (payload >> 8) & 0xf + value = struct.pack("!hiqiiiiii", 4, 8, id, 4, deepest_cstate, 4, last_cstate, 4, wake_reason) + pwrx_file.write(value) + +def synth_data(id, config, raw_buf, *x): + if config == 0: + ptwrite(id, raw_buf) + elif config == 1: + mwait(id, raw_buf) + elif config == 2: + pwre(id, raw_buf) + elif config == 3: + exstop(id, raw_buf) + elif config == 4: + pwrx(id, raw_buf) + elif config == 5: + cbr(id, raw_buf) From 828e27a899156047758628a97eedeb2b8df41670 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 16:04:17 -0300 Subject: [PATCH 12/43] perf ctype: Remove unused 'graph_line' variable Not being used at all anywhere. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-1e567f8tn8m4ii7dy1w9dp39@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ctype.c | 4 ---- tools/perf/util/sane_ctype.h | 1 - 2 files changed, 5 deletions(-) diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c index ee4c1e8ed54b..8d90bf8d0d70 100644 --- a/tools/perf/util/ctype.c +++ b/tools/perf/util/ctype.c @@ -31,10 +31,6 @@ unsigned char sane_ctype[256] = { /* Nothing in the 128.. range */ }; -const char *graph_line = - "_____________________________________________________________________" - "_____________________________________________________________________" - "_____________________________________________________________________"; const char *graph_dotted_line = "---------------------------------------------------------------------" "---------------------------------------------------------------------" diff --git a/tools/perf/util/sane_ctype.h b/tools/perf/util/sane_ctype.h index c2b42ff9ff32..894594fdedfb 100644 --- a/tools/perf/util/sane_ctype.h +++ b/tools/perf/util/sane_ctype.h @@ -2,7 +2,6 @@ #ifndef _PERF_SANE_CTYPE_H #define _PERF_SANE_CTYPE_H -extern const char *graph_line; extern const char *graph_dotted_line; extern const char *spaces; extern const char *dots; From b598c34ffc2b60c5c2f6450753a376a81f225652 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 16:24:20 -0300 Subject: [PATCH 13/43] perf ui stdio: No need to use 'spaces' to left align We can just use the 'field width' for the %s used to print the alignment, this way we'll get the same result without requiring having a variable with just lots of space chars. No way to do that for the dots tho, we still need that variable filled with dot chars. # perf report --stdio --hierarchy > before # perf report --stdio --hierarchy > after # diff before after # I.e. it continues as: # perf report --stdio --hierarchy | head -15 # To display the perf.data header info, please use --header/--header-only options. # # # Total Lost Samples: 0 # # Samples: 107 of event 'cycles' # Event count (approx.): 31378313 # # Overhead Command / Shared Object / Symbol # .............. ............................................ # 80.13% swapper 72.29% [kernel.vmlinux] 49.85% [k] intel_idle 9.05% [k] tick_nohz_next_event # Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-9s1dxik37waveor7c84hqti2@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/stdio/hist.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index a60f2993d390..4c97e3cdf173 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -566,10 +566,14 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, static int print_hierarchy_indent(const char *sep, int indent, const char *line, FILE *fp) { + int width; + if (sep != NULL || indent < 2) return 0; - return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line); + width = (indent - 2) * HIERARCHY_INDENT; + + return fprintf(fp, "%-*.*s", width, width, line); } static int hists__fprintf_hierarchy_headers(struct hists *hists, @@ -587,7 +591,7 @@ static int hists__fprintf_hierarchy_headers(struct hists *hists, indent = hists->nr_hpp_node; /* preserve max indent depth for column headers */ - print_hierarchy_indent(sep, indent, spaces, fp); + print_hierarchy_indent(sep, indent, " ", fp); /* the first hpp_list_node is for overhead columns */ fmt_node = list_first_entry(&hists->hpp_formats, @@ -816,7 +820,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, if (!h->leaf && !hist_entry__has_hierarchy_children(h, min_pcnt)) { int depth = hists->nr_hpp_node + h->depth + 1; - print_hierarchy_indent(sep, depth, spaces, fp); + print_hierarchy_indent(sep, depth, " ", fp); fprintf(fp, "%*sno entry >= %.2f%%\n", indent, "", min_pcnt); if (max_rows && ++nr_rows >= max_rows) From 93d50edc80abfdf9ad8064af9631a60c56bb0868 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 16:28:40 -0300 Subject: [PATCH 14/43] perf ctype: Remove now unused 'spaces' variable We can left justify just fine using the 'field width' modifier in %s printf, ditch this variable. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-2td8u86mia7143lbr5ttl0kf@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ctype.c | 4 ---- tools/perf/util/sane_ctype.h | 1 - 2 files changed, 5 deletions(-) diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c index 8d90bf8d0d70..75c0da59c230 100644 --- a/tools/perf/util/ctype.c +++ b/tools/perf/util/ctype.c @@ -35,10 +35,6 @@ const char *graph_dotted_line = "---------------------------------------------------------------------" "---------------------------------------------------------------------" "---------------------------------------------------------------------"; -const char *spaces = - " " - " " - " "; const char *dots = "....................................................................." "....................................................................." diff --git a/tools/perf/util/sane_ctype.h b/tools/perf/util/sane_ctype.h index 894594fdedfb..a2bb3890864f 100644 --- a/tools/perf/util/sane_ctype.h +++ b/tools/perf/util/sane_ctype.h @@ -3,7 +3,6 @@ #define _PERF_SANE_CTYPE_H extern const char *graph_dotted_line; -extern const char *spaces; extern const char *dots; /* Sane ctype - no locale, and works with signed chars */ From 6a9fa4e3bddedc027b691b6470c500d51d04e56c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 17:31:26 -0300 Subject: [PATCH 15/43] perf string: Move 'dots' and 'graph_dotted_line' out of sane_ctype.h Those are not in that file in the git repo, lets move it from there so that we get that sane ctype code fully isolated to allow getting it in sync either with the git sources or better with the kernel sources (include/linux/ctype.h + lib/ctype.h), that way we can use check_headers.h to get notified when changes are made in the original code so that we can cherry-pick. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-ioh5sghn3943j0rxg6lb2dgs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 1 + tools/perf/builtin-sched.c | 1 + tools/perf/builtin-top.c | 1 + tools/perf/util/ctype.c | 9 --------- tools/perf/util/evsel.c | 1 + tools/perf/util/sane_ctype.h | 3 --- tools/perf/util/string.c | 9 +++++++++ tools/perf/util/string2.h | 3 +++ 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index b80eee455111..b833b03d7195 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -21,6 +21,7 @@ #include "util/cpumap.h" #include "util/debug.h" +#include "util/string2.h" #include #include diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 275f2d92a7bf..79577b67c898 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -15,6 +15,7 @@ #include "util/thread_map.h" #include "util/color.h" #include "util/stat.h" +#include "util/string2.h" #include "util/callchain.h" #include "util/time-utils.h" diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 12b6b15a9675..4ef02e6888ff 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -40,6 +40,7 @@ #include "util/cpumap.h" #include "util/xyarray.h" #include "util/sort.h" +#include "util/string2.h" #include "util/term.h" #include "util/intlist.h" #include "util/parse-branch-options.h" diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c index 75c0da59c230..f84ecd9e5329 100644 --- a/tools/perf/util/ctype.c +++ b/tools/perf/util/ctype.c @@ -30,12 +30,3 @@ unsigned char sane_ctype[256] = { A, A, A, A, A, A, A, A, A, A, A, R, R, P, P, 0, /* 112..127 */ /* Nothing in the 128.. range */ }; - -const char *graph_dotted_line = - "---------------------------------------------------------------------" - "---------------------------------------------------------------------" - "---------------------------------------------------------------------"; -const char *dots = - "....................................................................." - "....................................................................." - "....................................................................."; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 04c4ed1573cb..4b175166d264 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -35,6 +35,7 @@ #include "debug.h" #include "trace-event.h" #include "stat.h" +#include "string2.h" #include "memswap.h" #include "util/parse-branch-options.h" diff --git a/tools/perf/util/sane_ctype.h b/tools/perf/util/sane_ctype.h index a2bb3890864f..c4dce9e3001b 100644 --- a/tools/perf/util/sane_ctype.h +++ b/tools/perf/util/sane_ctype.h @@ -2,9 +2,6 @@ #ifndef _PERF_SANE_CTYPE_H #define _PERF_SANE_CTYPE_H -extern const char *graph_dotted_line; -extern const char *dots; - /* Sane ctype - no locale, and works with signed chars */ #undef isascii #undef isspace diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index d8bfd0c4d2cb..b18884bd673b 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -6,6 +6,15 @@ #include "sane_ctype.h" +const char *graph_dotted_line = + "---------------------------------------------------------------------" + "---------------------------------------------------------------------" + "---------------------------------------------------------------------"; +const char *dots = + "....................................................................." + "....................................................................." + "....................................................................."; + #define K 1024LL /* * perf_atoll() diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h index 4c68a09b97e8..07fd37568543 100644 --- a/tools/perf/util/string2.h +++ b/tools/perf/util/string2.h @@ -6,6 +6,9 @@ #include #include +extern const char *graph_dotted_line; +extern const char *dots; + s64 perf_atoll(const char *str); char **argv_split(const char *str, int *argcp); void argv_free(char **argv); From af41949d9e022f4e37d476505e406c87479862ab Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 18:01:47 -0300 Subject: [PATCH 16/43] tools x86 machine: Add missing util.h to pick up 'page_size' We're getting it by sheer luck, add that util.h to get the 'page_size' definition. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-347078mgj3d2jfygtxs4ntti@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/machine.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/arch/x86/util/machine.c b/tools/perf/arch/x86/util/machine.c index 4520ac53caa9..0e508f26f83a 100644 --- a/tools/perf/arch/x86/util/machine.c +++ b/tools/perf/arch/x86/util/machine.c @@ -3,6 +3,7 @@ #include #include +#include "../../util/util.h" #include "../../util/machine.h" #include "../../util/map.h" #include "../../util/symbol.h" From 155681fcd7f82882a730240c2dde7eee76a46314 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 18:13:17 -0300 Subject: [PATCH 17/43] perf kallsyms: Adopt hex2u64 from tools/perf/util/util.h Just removing more stuff from tools/perf/, this is mostly used in the kallsyms parsing and in places in perf where kallsyms is involved, so we get it for free there. With this we reduce a bit more util.h. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-5mc1zg0jqdwgkn8c358kaba6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/symbol/kallsyms.c | 13 +++++++++++++ tools/lib/symbol/kallsyms.h | 2 ++ tools/perf/util/util.c | 13 ------------- tools/perf/util/util.h | 1 - 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c index 96d830545bbb..7501611abee4 100644 --- a/tools/lib/symbol/kallsyms.c +++ b/tools/lib/symbol/kallsyms.c @@ -16,6 +16,19 @@ bool kallsyms__is_function(char symbol_type) return symbol_type == 'T' || symbol_type == 'W'; } +/* + * While we find nice hex chars, build a long_val. + * Return number of chars processed. + */ +int hex2u64(const char *ptr, u64 *long_val) +{ + char *p; + + *long_val = strtoull(ptr, &p, 16); + + return p - ptr; +} + int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, char type, u64 start)) diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h index 72ab9870454b..bd988f7b18d4 100644 --- a/tools/lib/symbol/kallsyms.h +++ b/tools/lib/symbol/kallsyms.h @@ -18,6 +18,8 @@ static inline u8 kallsyms2elf_binding(char type) return isupper(type) ? STB_GLOBAL : STB_LOCAL; } +int hex2u64(const char *ptr, u64 *long_val); + u8 kallsyms2elf_type(char type); bool kallsyms__is_function(char symbol_type); diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index d388f80d8703..a61535cf1bca 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -434,19 +434,6 @@ size_t hex_width(u64 v) return n; } -/* - * While we find nice hex chars, build a long_val. - * Return number of chars processed. - */ -int hex2u64(const char *ptr, u64 *long_val) -{ - char *p; - - *long_val = strtoull(ptr, &p, 16); - - return p - ptr; -} - int perf_event_paranoid(void) { int value; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 09c1b0f91f65..125e215dd3d8 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -43,7 +43,6 @@ ssize_t readn(int fd, void *buf, size_t n); ssize_t writen(int fd, const void *buf, size_t n); size_t hex_width(u64 v); -int hex2u64(const char *ptr, u64 *val); extern unsigned int page_size; int __pure cacheline_size(void); From cf8b6970f4fc31898f3d9e25159aa57e235ca4d1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 18:15:46 -0300 Subject: [PATCH 18/43] perf symbols: We need util.h in symbol-elf.c for zfree() Continuing to untangle the headers, we're about to remove the old odd baggage that is tools/perf/util/include/linux/ctype.h. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-gapezcq3p8bzrsi96vdtq0o0@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index fdc5bd7dbb90..f04ef851ae86 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -14,6 +14,7 @@ #include "machine.h" #include "vdso.h" #include "debug.h" +#include "util.h" #include "sane_ctype.h" #include From 9f3926e08c26607a0dd5b1bc8a8aa1d03f72fcdc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 18:19:33 -0300 Subject: [PATCH 19/43] perf tools: Remove old baggage that is util/include/linux/ctype.h It was just including a ../util.h that wasn't even there: $ cat tools/perf/util/include/linux/../util.h cat: tools/perf/util/include/linux/../util.h: No such file or directory $ This would make kallsyms.h get util.h somehow and then files including it would get util.h defined stuff, a mess, fix it. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-wlzwken4psiat4zvfbvaoqiw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/symbol/kallsyms.h | 1 - tools/perf/util/include/linux/ctype.h | 1 - 2 files changed, 2 deletions(-) delete mode 100644 tools/perf/util/include/linux/ctype.h diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h index bd988f7b18d4..2b238f181d97 100644 --- a/tools/lib/symbol/kallsyms.h +++ b/tools/lib/symbol/kallsyms.h @@ -3,7 +3,6 @@ #define __TOOLS_KALLSYMS_H_ 1 #include -#include #include #ifndef KSYM_NAME_LEN diff --git a/tools/perf/util/include/linux/ctype.h b/tools/perf/util/include/linux/ctype.h deleted file mode 100644 index a53d4ee1e0b7..000000000000 --- a/tools/perf/util/include/linux/ctype.h +++ /dev/null @@ -1 +0,0 @@ -#include "../util.h" From 1b2fc358ddfb1b0915922e441182cda7043f5116 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 18:35:34 -0300 Subject: [PATCH 20/43] perf tools: Add missing util.h to pick up 'page_size' variable Not to depend of getting it indirectly. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-tirjsmvu4ektw0k7lm8k9lhu@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 1 + tools/perf/arch/x86/tests/intel-cqm.c | 1 + tools/perf/arch/x86/util/intel-pt.c | 1 + tools/perf/perf.c | 1 + tools/perf/util/machine.c | 1 + tools/perf/util/python.c | 1 + 6 files changed, 6 insertions(+) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index c6f1ab5499b5..2b83cc8e4796 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -22,6 +22,7 @@ #include "../../util/pmu.h" #include "../../util/thread_map.h" #include "../../util/cs-etm.h" +#include "../../util/util.h" #include #include diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c index 90a4a8c58a62..94aa0b673b7f 100644 --- a/tools/perf/arch/x86/tests/intel-cqm.c +++ b/tools/perf/arch/x86/tests/intel-cqm.c @@ -6,6 +6,7 @@ #include "evlist.h" #include "evsel.h" #include "arch-tests.h" +#include "util.h" #include #include diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 1869f62a10cd..9804098dcefb 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -25,6 +25,7 @@ #include "../../util/auxtrace.h" #include "../../util/tsc.h" #include "../../util/intel-pt.h" +#include "../../util/util.h" #define KiB(x) ((x) * 1024) #define MiB(x) ((x) * 1024 * 1024) diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 72df4b6fa36f..2123b3cc4dcf 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -18,6 +18,7 @@ #include "util/bpf-loader.h" #include "util/debug.h" #include "util/event.h" +#include "util/util.h" #include #include #include diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 17eec39e775e..a0bb05dd008f 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -15,6 +15,7 @@ #include "strlist.h" #include "thread.h" #include "vdso.h" +#include "util.h" #include #include #include diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 6aa7e2352e16..1e5b6718dcea 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -12,6 +12,7 @@ #include "print_binary.h" #include "thread_map.h" #include "mmap.h" +#include "util.h" #if PY_MAJOR_VERSION < 3 #define _PyUnicode_FromString(arg) \ From 3052ba56bcb589046eca6a931bd897742653d2cb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 17:27:31 -0300 Subject: [PATCH 21/43] tools perf: Move from sane_ctype.h obtained from git to the Linux's original We got the sane_ctype.h headers from git and kept using it so far, but since that code originally came from the kernel sources to the git sources, perhaps its better to just use the one in the kernel, so that we can leverage tools/perf/check_headers.sh to be notified when our copy gets out of sync, i.e. when fixes or goodies are added to the code we've copied. This will help with things like tools/lib/string.c where we want to have more things in common with the kernel, such as strim(), skip_spaces(), etc so as to go on removing the things that we have in tools/perf/util/ and instead using the code in the kernel, indirectly and removing things like EXPORT_SYMBOL(), etc, getting notified when fixes and improvements are made to the original code. Hopefully this also should help with reducing the difference of code hosted in tools/ to the one in the kernel proper. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-7k9868l713wqtgo01xxygn12@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/ctype.h | 75 +++++++++++++++++++++++++++++ tools/lib/ctype.c | 35 ++++++++++++++ tools/lib/symbol/kallsyms.c | 1 - tools/lib/symbol/kallsyms.h | 1 + tools/perf/MANIFEST | 1 + tools/perf/arch/x86/util/machine.c | 2 +- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-sched.c | 2 +- tools/perf/builtin-script.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/check-headers.sh | 2 + tools/perf/tests/code-reading.c | 2 +- tools/perf/ui/browser.c | 2 +- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/ui/browsers/map.c | 2 +- tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/Build | 4 ++ tools/perf/util/annotate.c | 2 +- tools/perf/util/auxtrace.c | 2 +- tools/perf/util/build-id.c | 2 +- tools/perf/util/config.c | 2 +- tools/perf/util/cpumap.c | 2 +- tools/perf/util/ctype.c | 32 ------------ tools/perf/util/data-convert-bt.c | 2 +- tools/perf/util/debug.c | 2 +- tools/perf/util/demangle-java.c | 2 +- tools/perf/util/env.c | 2 +- tools/perf/util/event.c | 2 +- tools/perf/util/evsel.c | 2 +- tools/perf/util/header.c | 2 +- tools/perf/util/jitdump.c | 2 +- tools/perf/util/machine.c | 2 +- tools/perf/util/print_binary.c | 2 +- tools/perf/util/probe-event.c | 2 +- tools/perf/util/probe-finder.h | 2 +- tools/perf/util/python-ext-sources | 2 +- tools/perf/util/sane_ctype.h | 47 ------------------ tools/perf/util/stat-display.c | 2 +- tools/perf/util/strfilter.c | 2 +- tools/perf/util/string.c | 2 +- tools/perf/util/symbol-elf.c | 2 +- tools/perf/util/symbol.c | 2 +- tools/perf/util/trace-event-parse.c | 2 +- 46 files changed, 155 insertions(+), 117 deletions(-) create mode 100644 tools/include/linux/ctype.h create mode 100644 tools/lib/ctype.c delete mode 100644 tools/perf/util/ctype.c delete mode 100644 tools/perf/util/sane_ctype.h diff --git a/tools/include/linux/ctype.h b/tools/include/linux/ctype.h new file mode 100644 index 000000000000..310090b4c474 --- /dev/null +++ b/tools/include/linux/ctype.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_CTYPE_H +#define _LINUX_CTYPE_H + +/* + * NOTE! This ctype does not handle EOF like the standard C + * library is required to. + */ + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + +extern const unsigned char _ctype[]; + +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) + +#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) +#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) +#define iscntrl(c) ((__ismask(c)&(_C)) != 0) +static inline int __isdigit(int c) +{ + return '0' <= c && c <= '9'; +} +#define isdigit(c) __isdigit(c) +#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) +#define islower(c) ((__ismask(c)&(_L)) != 0) +#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) +#define ispunct(c) ((__ismask(c)&(_P)) != 0) +/* Note: isspace() must return false for %NUL-terminator */ +#define isspace(c) ((__ismask(c)&(_S)) != 0) +#define isupper(c) ((__ismask(c)&(_U)) != 0) +#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + +static inline unsigned char __tolower(unsigned char c) +{ + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +static inline unsigned char __toupper(unsigned char c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} + +#define tolower(c) __tolower(c) +#define toupper(c) __toupper(c) + +/* + * Fast implementation of tolower() for internal usage. Do not use in your + * code. + */ +static inline char _tolower(const char c) +{ + return c | 0x20; +} + +/* Fast check for octal digit */ +static inline int isodigit(const char c) +{ + return c >= '0' && c <= '7'; +} + +#endif diff --git a/tools/lib/ctype.c b/tools/lib/ctype.c new file mode 100644 index 000000000000..4d2e05fd3336 --- /dev/null +++ b/tools/lib/ctype.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * linux/lib/ctype.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include +#include + +const unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c index 7501611abee4..1a7a9f877095 100644 --- a/tools/lib/symbol/kallsyms.c +++ b/tools/lib/symbol/kallsyms.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -#include #include "symbol/kallsyms.h" #include #include diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h index 2b238f181d97..bd988f7b18d4 100644 --- a/tools/lib/symbol/kallsyms.h +++ b/tools/lib/symbol/kallsyms.h @@ -3,6 +3,7 @@ #define __TOOLS_KALLSYMS_H_ 1 #include +#include #include #ifndef KSYM_NAME_LEN diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 627b7cada144..aac4c755d81b 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST @@ -7,6 +7,7 @@ tools/lib/traceevent tools/lib/api tools/lib/bpf tools/lib/subcmd +tools/lib/ctype.c tools/lib/hweight.c tools/lib/rbtree.c tools/lib/string.c diff --git a/tools/perf/arch/x86/util/machine.c b/tools/perf/arch/x86/util/machine.c index 0e508f26f83a..1e9ec783b9a1 100644 --- a/tools/perf/arch/x86/util/machine.c +++ b/tools/perf/arch/x86/util/machine.c @@ -7,7 +7,7 @@ #include "../../util/machine.h" #include "../../util/map.h" #include "../../util/symbol.h" -#include "../../util/sane_ctype.h" +#include #include diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index b833b03d7195..9bd3829de76d 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -31,7 +31,7 @@ #include #include -#include "sane_ctype.h" +#include static int kmem_slab; static int kmem_page; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 91c40808380d..91a3762b4211 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -47,7 +47,7 @@ #include #include #include -#include "sane_ctype.h" +#include #include #include #include diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 79577b67c898..1519989961ff 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -37,7 +37,7 @@ #include #include -#include "sane_ctype.h" +#include #define PR_SET_NAME 15 /* Set process name */ #define MAX_CPUS 4096 diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 61f00055476a..0131f7a0d48d 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -49,7 +49,7 @@ #include #include -#include "sane_ctype.h" +#include static char const *script_name; static char const *generate_script_lang; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8a35fc5a7281..e5e19b461061 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -82,7 +82,7 @@ #include #include -#include "sane_ctype.h" +#include #define DEFAULT_SEPARATOR " " #define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi" diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 4ef02e6888ff..6d40a4ef58c5 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -76,7 +76,7 @@ #include #include -#include "sane_ctype.h" +#include static volatile int done; static volatile int resize; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index f3532b081b31..d0eb7224dd36 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -64,7 +64,7 @@ #include #include -#include "sane_ctype.h" +#include #ifndef O_CLOEXEC # define O_CLOEXEC 02000000 diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh index c68ee06cae63..f211c015cb76 100755 --- a/tools/perf/check-headers.sh +++ b/tools/perf/check-headers.sh @@ -105,6 +105,8 @@ check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include "' check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"' check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"' +check include/linux/ctype.h '-I "isdigit("' +check lib/ctype.c '-I "^EXPORT_SYMBOL" -I "^#include " -B' # diff non-symmetric files check_2 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 4ebd2681e760..aa6df122b175 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -22,7 +22,7 @@ #include "tests.h" -#include "sane_ctype.h" +#include #define BUFSZ 1024 #define READLEN 128 diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 4ad37d8c7d6a..8812c1564995 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -16,7 +16,7 @@ #include "helpline.h" #include "keysyms.h" #include "../color.h" -#include "sane_ctype.h" +#include static int ui_browser__percent_color(struct ui_browser *browser, double percent, bool current) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 3421ecbdd3f0..59483bdb0027 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -33,7 +33,7 @@ #include "units.h" #include "time-utils.h" -#include "sane_ctype.h" +#include extern void hist_browser__init_hpp(void); diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c index c70d9337405b..5f6529c9eb8e 100644 --- a/tools/perf/ui/browsers/map.c +++ b/tools/perf/ui/browsers/map.c @@ -13,7 +13,7 @@ #include "../keysyms.h" #include "map.h" -#include "sane_ctype.h" +#include struct map_browser { struct ui_browser b; diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 4c97e3cdf173..4b1a6e921d1c 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -13,7 +13,7 @@ #include "../../util/srcline.h" #include "../../util/string2.h" #include "../../util/thread.h" -#include "../../util/sane_ctype.h" +#include static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) { diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 6d5bbc8b589b..b4dc6112138f 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -213,6 +213,10 @@ $(OUTPUT)util/bitmap.o: ../lib/bitmap.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) +$(OUTPUT)util/ctype.o: ../lib/ctype.c FORCE + $(call rule_mkdir) + $(call if_changed_dep,cc_o_c) + $(OUTPUT)util/find_bit.o: ../lib/find_bit.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index c8ce13419d9b..65005ccea232 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -49,7 +49,7 @@ #define DARROW_CHAR ((unsigned char)'.') #define UARROW_CHAR ((unsigned char)'-') -#include "sane_ctype.h" +#include struct annotation_options annotation__default_options = { .use_offset = true, diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index cfdbf65f1e02..bc215fe0b4b4 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -51,7 +51,7 @@ #include "arm-spe.h" #include "s390-cpumsf.h" -#include "sane_ctype.h" +#include #include "symbol/kallsyms.h" static bool auxtrace__dont_decode(struct perf_session *session) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 0c5517a8d0b7..89c6913dfc25 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -29,7 +29,7 @@ #include "probe-file.h" #include "strlist.h" -#include "sane_ctype.h" +#include static bool no_buildid_cache; diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index e7d2c08d263a..752cce853e51 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -24,7 +24,7 @@ #include #include -#include "sane_ctype.h" +#include #define MAXNAME (256) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index c11a459ca582..0d8fbedf7bd5 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -10,7 +10,7 @@ #include #include "asm/bug.h" -#include "sane_ctype.h" +#include static int max_cpu_num; static int max_present_cpu_num; diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c deleted file mode 100644 index f84ecd9e5329..000000000000 --- a/tools/perf/util/ctype.c +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Sane locale-independent, ASCII ctype. - * - * No surprises, and works with signed and unsigned chars. - */ -#include "sane_ctype.h" - -enum { - S = GIT_SPACE, - A = GIT_ALPHA, - D = GIT_DIGIT, - G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */ - R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */ - P = GIT_PRINT_EXTRA, /* printable - alpha - digit - glob - regex */ - - PS = GIT_SPACE | GIT_PRINT_EXTRA, -}; - -unsigned char sane_ctype[256] = { -/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - - 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */ - PS,P, P, P, R, P, P, P, R, R, G, R, P, P, R, P, /* 32.. 47 */ - D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G, /* 48.. 63 */ - P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */ - A, A, A, A, A, A, A, A, A, A, A, G, G, P, R, P, /* 80.. 95 */ - P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */ - A, A, A, A, A, A, A, A, A, A, A, R, R, P, P, 0, /* 112..127 */ - /* Nothing in the 128.. range */ -}; diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index b79e1d6839ed..7b06e7373b9e 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -29,7 +29,7 @@ #include "evsel.h" #include "machine.h" #include "config.h" -#include "sane_ctype.h" +#include #define pr_N(n, fmt, ...) \ eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 3d6459626c2a..3cc578343f48 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c @@ -21,7 +21,7 @@ #include "util.h" #include "target.h" -#include "sane_ctype.h" +#include int verbose; bool dump_trace = false, quiet = false; diff --git a/tools/perf/util/demangle-java.c b/tools/perf/util/demangle-java.c index e4c486756053..5b4900d67c80 100644 --- a/tools/perf/util/demangle-java.c +++ b/tools/perf/util/demangle-java.c @@ -8,7 +8,7 @@ #include "demangle-java.h" -#include "sane_ctype.h" +#include enum { MODE_PREFIX = 0, diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 1cc7a1837822..22eee8942527 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "cpumap.h" #include "env.h" -#include "sane_ctype.h" +#include #include "util.h" #include "bpf-event.h" #include diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index c9c6857360e4..d8f8a20543c5 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -20,7 +20,7 @@ #include "strlist.h" #include "thread.h" #include "thread_map.h" -#include "sane_ctype.h" +#include #include "map.h" #include "symbol.h" #include "symbol/kallsyms.h" diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 4b175166d264..5ab31a4a658d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -39,7 +39,7 @@ #include "memswap.h" #include "util/parse-branch-options.h" -#include "sane_ctype.h" +#include struct perf_missing_features perf_missing_features; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index abc9c2145efe..fca9dbaf61ae 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -43,7 +43,7 @@ #include "cputopo.h" #include "bpf-event.h" -#include "sane_ctype.h" +#include /* * magic2 = "PERFILE2" diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index eda28d3570bc..28908afedec4 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -28,7 +28,7 @@ #include "genelf.h" #include "../builtin.h" -#include "sane_ctype.h" +#include struct jit_buf_desc { struct perf_data *output; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index a0bb05dd008f..1b3d7265bca9 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -25,7 +25,7 @@ #include "asm/bug.h" #include "bpf-event.h" -#include "sane_ctype.h" +#include #include #include diff --git a/tools/perf/util/print_binary.c b/tools/perf/util/print_binary.c index 23e367063446..599a1543871d 100644 --- a/tools/perf/util/print_binary.c +++ b/tools/perf/util/print_binary.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "print_binary.h" #include -#include "sane_ctype.h" +#include int binary__fprintf(unsigned char *data, size_t len, size_t bytes_per_line, binary__fprintf_t printer, diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 2ebf8673f8e9..6f24eaf6e504 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -39,7 +39,7 @@ #include "session.h" #include "string2.h" -#include "sane_ctype.h" +#include #define PERFPROBE_GROUP "probe" diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 16252980ff00..670c477bf8cf 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -5,7 +5,7 @@ #include #include "intlist.h" #include "probe-event.h" -#include "sane_ctype.h" +#include #define MAX_PROBE_BUFFER 1024 #define MAX_PROBES 128 diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 7aa0ea64544e..648bcd80b475 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -6,7 +6,7 @@ # util/python.c -util/ctype.c +../lib/ctype.c util/evlist.c util/evsel.c util/cpumap.c diff --git a/tools/perf/util/sane_ctype.h b/tools/perf/util/sane_ctype.h deleted file mode 100644 index c4dce9e3001b..000000000000 --- a/tools/perf/util/sane_ctype.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _PERF_SANE_CTYPE_H -#define _PERF_SANE_CTYPE_H - -/* Sane ctype - no locale, and works with signed chars */ -#undef isascii -#undef isspace -#undef isdigit -#undef isxdigit -#undef isalpha -#undef isprint -#undef isalnum -#undef islower -#undef isupper -#undef tolower -#undef toupper - -extern unsigned char sane_ctype[256]; -#define GIT_SPACE 0x01 -#define GIT_DIGIT 0x02 -#define GIT_ALPHA 0x04 -#define GIT_GLOB_SPECIAL 0x08 -#define GIT_REGEX_SPECIAL 0x10 -#define GIT_PRINT_EXTRA 0x20 -#define GIT_PRINT 0x3E -#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) -#define isascii(x) (((x) & ~0x7f) == 0) -#define isspace(x) sane_istest(x,GIT_SPACE) -#define isdigit(x) sane_istest(x,GIT_DIGIT) -#define isxdigit(x) \ - (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G') -#define isalpha(x) sane_istest(x,GIT_ALPHA) -#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) -#define isprint(x) sane_istest(x,GIT_PRINT) -#define islower(x) (sane_istest(x,GIT_ALPHA) && (x & 0x20)) -#define isupper(x) (sane_istest(x,GIT_ALPHA) && !(x & 0x20)) -#define tolower(x) sane_case((unsigned char)(x), 0x20) -#define toupper(x) sane_case((unsigned char)(x), 0) - -static inline int sane_case(int x, int high) -{ - if (sane_istest(x, GIT_ALPHA)) - x = (x & ~0x20) | high; - return x; -} - -#endif /* _PERF_SANE_CTYPE_H */ diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index a6b9de3e83fc..992e327bce85 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -10,7 +10,7 @@ #include "thread_map.h" #include "cpumap.h" #include "string2.h" -#include "sane_ctype.h" +#include #include "cgroup.h" #include #include diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c index 7f3253d44afd..2c3a2904ebcd 100644 --- a/tools/perf/util/strfilter.c +++ b/tools/perf/util/strfilter.c @@ -4,7 +4,7 @@ #include "strfilter.h" #include -#include "sane_ctype.h" +#include /* Operators */ static const char *OP_and = "&"; /* Logical AND */ diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index b18884bd673b..084c3e4e9400 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -4,7 +4,7 @@ #include #include -#include "sane_ctype.h" +#include const char *graph_dotted_line = "---------------------------------------------------------------------" diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index f04ef851ae86..62008756d8cc 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -15,7 +15,7 @@ #include "vdso.h" #include "debug.h" #include "util.h" -#include "sane_ctype.h" +#include #include #ifndef EM_AARCH64 diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index f4540f8bbed1..46d2c03814a1 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -25,7 +25,7 @@ #include "namespaces.h" #include "header.h" #include "path.h" -#include "sane_ctype.h" +#include #include #include diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 62bc61155dd1..b3982e1bb4c5 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -11,7 +11,7 @@ #include "debug.h" #include "trace-event.h" -#include "sane_ctype.h" +#include static int get_common_field(struct scripting_context *context, int *offset, int *size, const char *type) From bd9860bf050f77c4e260a9ae10a5587009ad6e07 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:13:51 -0300 Subject: [PATCH 22/43] perf tools: Use linux/ctype.h in more places There were a few places where we still were using the libc version of ctype.h, switch to the one in tools/lib/ctype.c that the rest of perf uses. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-wa4nz4kt61eze88eprk20tfd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/util/header.c | 2 +- tools/perf/util/metricgroup.c | 2 +- tools/perf/util/time-utils.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c index 3db85cd2069e..a25896135abe 100644 --- a/tools/perf/arch/s390/util/header.c +++ b/tools/perf/arch/s390/util/header.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "../../util/header.h" #include "../../util/util.h" diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 699e020737d9..a0cf3cd95ced 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -17,7 +17,7 @@ #include "pmu-events/pmu-events.h" #include "strlist.h" #include -#include +#include struct metric_event *metricgroup__lookup(struct rblist *metric_events, struct perf_evsel *evsel, diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 2b48816a2d2e..369fa19dd596 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "perf.h" #include "debug.h" From 7bd330de43fd5693e90be13dac7fbd9af3b6335d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:23:18 -0300 Subject: [PATCH 23/43] tools lib: Adopt skip_spaces() from the kernel sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same implementation, will be used to replace ad-hoc equivalent code in tools/. Cc: Adrian Hunter Cc: André Goddard Rosa Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-dig691cg9ripvoiprpidthw7@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/string.h | 4 +++- tools/lib/string.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h index 6c3e2cc274c5..cee239350a6b 100644 --- a/tools/include/linux/string.h +++ b/tools/include/linux/string.h @@ -29,4 +29,6 @@ static inline bool strstarts(const char *str, const char *prefix) return strncmp(str, prefix, strlen(prefix)) == 0; } -#endif /* _LINUX_STRING_H_ */ +extern char * __must_check skip_spaces(const char *); + +#endif /* _TOOLS_LINUX_STRING_H_ */ diff --git a/tools/lib/string.c b/tools/lib/string.c index 93b3d4b6feac..50d400822bb3 100644 --- a/tools/lib/string.c +++ b/tools/lib/string.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /** @@ -106,3 +107,16 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size) } return ret; } + +/** + * skip_spaces - Removes leading whitespace from @str. + * @str: The string to be stripped. + * + * Returns a pointer to the first non-whitespace character in @str. + */ +char *skip_spaces(const char *str) +{ + while (isspace(*str)) + ++str; + return (char *)str; +} From 810826acd122ed859e238bf1555a09b326c8fe23 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:28:49 -0300 Subject: [PATCH 24/43] perf stat: Use recently introduced skip_spaces() No change in behaviour. Cc: Andi Kleen Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-ncpvp4eelf8fqhuy29uv56z9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-display.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 992e327bce85..ce993d29cca5 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "color.h" @@ -215,9 +216,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused, while (isdigit(*ends) || *ends == '.') ends++; *ends = 0; - while (isspace(*unit)) - unit++; - fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit); + fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, skip_spaces(unit)); } /* Filter out some columns that don't work well in metrics only mode */ From fc6a172600cd54e9b4efeb684daa8464991b6c26 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:33:14 -0300 Subject: [PATCH 25/43] perf header: Use skip_spaces() in __write_cpudesc() No change in behaviour. Cc: Stephane Eranian Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-0dbfpi70aa66s6mtd8z6p391@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index fca9dbaf61ae..1eb15f7517b0 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -416,10 +417,8 @@ static int __write_cpudesc(struct feat_fd *ff, const char *cpuinfo_proc) while (*p) { if (isspace(*p)) { char *r = p + 1; - char *q = r; + char *q = skip_spaces(r); *p = ' '; - while (*q && isspace(*q)) - q++; if (q != (p+1)) while ((*r++ = *q++)); } From 9bb5a27ac7958ce11cb02463b5a5f7f160d60916 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:39:18 -0300 Subject: [PATCH 26/43] perf time-utils: Use skip_spaces() No change in behaviour intended. Cc: Adrian Hunter Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-cpugv7qd5vzhbtvnlydo90jv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/time-utils.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 369fa19dd596..c2abc259b51d 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include @@ -141,10 +142,7 @@ static int perf_time__parse_strs(struct perf_time_interval *ptime, for (i = 0, p = str; i < num - 1; i++) { arg = p; /* Find next comma, there must be one */ - p = strchr(p, ',') + 1; - /* Skip white space */ - while (isspace(*p)) - p++; + p = skip_spaces(strchr(p, ',') + 1); /* Skip the value, must not contain space or comma */ while (*p && !isspace(*p)) { if (*p++ == ',') { From ee44b5b51f37727f57962b2cdccd548c62045252 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:46:39 -0300 Subject: [PATCH 27/43] perf probe: Use skip_spaces() for argv handling The skip_sep() routine has the same implementation as skip_spaces(), recently adopted from the kernel, sources, switch to it. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-0ix211a81z2016dl5nmtdci4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/string.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 084c3e4e9400..d28e723e2790 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -69,18 +69,6 @@ s64 perf_atoll(const char *str) return -1; } -/* - * Helper function for splitting a string into an argv-like array. - * originally copied from lib/argv_split.c - */ -static const char *skip_sep(const char *cp) -{ - while (*cp && isspace(*cp)) - cp++; - - return cp; -} - static const char *skip_arg(const char *cp) { while (*cp && !isspace(*cp)) @@ -94,7 +82,7 @@ static int count_argc(const char *str) int count = 0; while (*str) { - str = skip_sep(str); + str = skip_spaces(str); if (*str) { count++; str = skip_arg(str); @@ -148,7 +136,7 @@ char **argv_split(const char *str, int *argcp) argvp = argv; while (*str) { - str = skip_sep(str); + str = skip_spaces(str); if (*str) { const char *p = str; From c1fc14cbdcc9455507e5f54109199bfea3af185f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 11:08:10 -0300 Subject: [PATCH 28/43] perf strfilter: Use skip_spaces() No change in behaviour. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-p9rtamq7lvre9zhti70azfwe@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/strfilter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c index 2c3a2904ebcd..90ea2b209cbb 100644 --- a/tools/perf/util/strfilter.c +++ b/tools/perf/util/strfilter.c @@ -5,6 +5,7 @@ #include #include +#include /* Operators */ static const char *OP_and = "&"; /* Logical AND */ @@ -37,8 +38,7 @@ static const char *get_token(const char *s, const char **e) { const char *p; - while (isspace(*s)) /* Skip spaces */ - s++; + s = skip_spaces(s); if (*s == '\0') { p = s; From 80e9073f1f4473639d585b89ebc9130bb47920e8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 11:21:47 -0300 Subject: [PATCH 29/43] perf metricgroup: Use strsep() No change in behaviour intended, trivial optimization done by avoiding looking for spaces in 'g' right after setting it to "No_group". Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-f2siadtp3hb5o0l1w7bvd8bk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index a0cf3cd95ced..90cd84e2a503 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -308,10 +308,9 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, struct mep *me; char *s; + g = skip_spaces(g); if (*g == 0) g = "No_group"; - while (isspace(*g)) - g++; if (filter && !strstr(g, filter)) continue; if (raw) From 526bbbdd442ce143b52cd6a8b4ee424f9930be0d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 11:24:37 -0300 Subject: [PATCH 30/43] perf report: Use skip_spaces() No change in behaviour intended. Cc: Adrian Hunter Cc: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-lcywlfqbi37nhegmhl1ar6wg@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 91a3762b4211..aef59f318a67 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -941,8 +941,7 @@ parse_time_quantum(const struct option *opt, const char *arg, pr_err("time quantum cannot be 0"); return -1; } - while (isspace(*end)) - end++; + end = skip_spaces(end); if (*end == 0) return 0; if (!strcmp(end, "s")) { From 328584804edc950fb4608c9a38e396ac71ef22b6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 11:42:03 -0300 Subject: [PATCH 31/43] perf tools: Ditch rtrim(), use skip_spaces() to get closer to the kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No change in behaviour, just using the same kernel idiom for such operation. Cc: Adrian Hunter Cc: André Goddard Rosa Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-a85lkptkt0ru40irpga8yf54@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 12 ++++++------ tools/perf/ui/browser.c | 2 +- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/ui/gtk/hists.c | 4 ++-- tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/annotate.c | 10 +++++----- tools/perf/util/event.c | 4 +--- tools/perf/util/pmu.c | 3 ++- tools/perf/util/stat-display.c | 4 ++-- tools/perf/util/string.c | 14 -------------- tools/perf/util/string2.h | 4 ++-- 11 files changed, 23 insertions(+), 38 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 0131f7a0d48d..520e5b6b9ef9 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2880,7 +2880,7 @@ static int read_script_info(struct script_desc *desc, const char *filename) return -1; while (fgets(line, sizeof(line), fp)) { - p = ltrim(line); + p = skip_spaces(line); if (strlen(p) == 0) continue; if (*p != '#') @@ -2889,19 +2889,19 @@ static int read_script_info(struct script_desc *desc, const char *filename) if (strlen(p) && *p == '!') continue; - p = ltrim(p); + p = skip_spaces(p); if (strlen(p) && p[strlen(p) - 1] == '\n') p[strlen(p) - 1] = '\0'; if (!strncmp(p, "description:", strlen("description:"))) { p += strlen("description:"); - desc->half_liner = strdup(ltrim(p)); + desc->half_liner = strdup(skip_spaces(p)); continue; } if (!strncmp(p, "args:", strlen("args:"))) { p += strlen("args:"); - desc->args = strdup(ltrim(p)); + desc->args = strdup(skip_spaces(p)); continue; } } @@ -3008,7 +3008,7 @@ static int check_ev_match(char *dir_name, char *scriptname, return -1; while (fgets(line, sizeof(line), fp)) { - p = ltrim(line); + p = skip_spaces(line); if (*p == '#') continue; @@ -3018,7 +3018,7 @@ static int check_ev_match(char *dir_name, char *scriptname, break; p += 2; - p = ltrim(p); + p = skip_spaces(p); len = strcspn(p, " \t"); if (!len) break; diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 8812c1564995..55ff05a46e0b 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -594,7 +594,7 @@ static int ui_browser__color_config(const char *var, const char *value, break; *bg = '\0'; - bg = ltrim(++bg); + bg = skip_spaces(bg + 1); ui_browser__colorsets[i].bg = bg; ui_browser__colorsets[i].fg = fg; return 0; diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 59483bdb0027..04a56114df92 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1470,7 +1470,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, int i = 0; width -= fmt->entry(fmt, &hpp, entry); - ui_browser__printf(&browser->b, "%s", ltrim(s)); + ui_browser__printf(&browser->b, "%s", skip_spaces(s)); while (isspace(s[i++])) width++; diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 0c08890f006a..6341c421a8f7 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -459,7 +459,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists, advance_hpp(hpp, ret + 2); } - gtk_tree_store_set(store, &iter, col_idx, ltrim(rtrim(bf)), -1); + gtk_tree_store_set(store, &iter, col_idx, trim(bf), -1); if (!he->leaf) { hpp->buf = bf; @@ -555,7 +555,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, first_col = false; fmt->header(fmt, &hpp, hists, 0, NULL); - strcat(buf, ltrim(rtrim(hpp.buf))); + strcat(buf, trim(hpp.buf)); } } diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 4b1a6e921d1c..594e56628904 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -516,7 +516,7 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he, * dynamic entries are right-aligned but we want left-aligned * in the hierarchy mode */ - printed += fprintf(fp, "%s%s", sep ?: " ", ltrim(buf)); + printed += fprintf(fp, "%s%s", sep ?: " ", skip_spaces(buf)); } printed += putc('\n', fp); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 65005ccea232..783e2628cc8e 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -557,7 +557,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_sy if (comment == NULL) return 0; - comment = ltrim(comment); + comment = skip_spaces(comment); comment__symbol(ops->source.raw, comment + 1, &ops->source.addr, &ops->source.name); comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name); @@ -602,7 +602,7 @@ static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops if (comment == NULL) return 0; - comment = ltrim(comment); + comment = skip_spaces(comment); comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name); return 0; @@ -1098,7 +1098,7 @@ static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, str static int disasm_line__parse(char *line, const char **namep, char **rawp) { - char tmp, *name = ltrim(line); + char tmp, *name = skip_spaces(line); if (name[0] == '\0') return -1; @@ -1116,7 +1116,7 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp) goto out_free_name; (*rawp)[0] = tmp; - *rawp = ltrim(*rawp); + *rawp = skip_spaces(*rawp); return 0; @@ -1503,7 +1503,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file, return 0; } - tmp = ltrim(parsed_line); + tmp = skip_spaces(parsed_line); if (*tmp) { /* * Parse hexa addresses followed by ':' diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index d8f8a20543c5..e1d0c5ba1f92 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -158,9 +158,7 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len, if (name) { char *nl; - name += 5; /* strlen("Name:") */ - name = ltrim(name); - + name = skip_spaces(name + 5); /* strlen("Name:") */ nl = strchr(name, '\n'); if (nl) *nl = '\0'; diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index faa8eb231e1b..38dc0c6e28b8 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include @@ -1339,7 +1340,7 @@ static void wordwrap(char *s, int start, int max, int corr) break; s += wlen; column += n; - s = ltrim(s); + s = skip_spaces(s); } } diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index ce993d29cca5..90df41169113 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -212,7 +212,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused, return; } snprintf(buf, sizeof(buf), fmt, val); - ends = vals = ltrim(buf); + ends = vals = skip_spaces(buf); while (isdigit(*ends) || *ends == '.') ends++; *ends = 0; @@ -280,7 +280,7 @@ static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused return; unit = fixunit(tbuf, os->evsel, unit); snprintf(buf, sizeof buf, fmt, val); - ends = vals = ltrim(buf); + ends = vals = skip_spaces(buf); while (isdigit(*ends) || *ends == '.') ends++; *ends = 0; diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index d28e723e2790..99a555ea4a9f 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -318,20 +318,6 @@ char *strxfrchar(char *s, char from, char to) return s; } -/** - * ltrim - Removes leading whitespace from @s. - * @s: The string to be stripped. - * - * Return pointer to the first non-whitespace character in @s. - */ -char *ltrim(char *s) -{ - while (isspace(*s)) - s++; - - return s; -} - /** * rtrim - Removes trailing whitespace from @s. * @s: The string to be stripped. diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h index 07fd37568543..db02059e31c5 100644 --- a/tools/perf/util/string2.h +++ b/tools/perf/util/string2.h @@ -2,6 +2,7 @@ #ifndef PERF_STRING_H #define PERF_STRING_H +#include #include #include #include @@ -22,12 +23,11 @@ static inline bool strisglob(const char *str) int strtailcmp(const char *s1, const char *s2); char *strxfrchar(char *s, char from, char to); -char *ltrim(char *s); char *rtrim(char *s); static inline char *trim(char *s) { - return ltrim(rtrim(s)); + return skip_spaces(rtrim(s)); } char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints); From 45bfd0ac7bd2afa83600df9c1286a1642bb15c55 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 11:50:16 -0300 Subject: [PATCH 32/43] tools lib: Adopt strim() from the kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we're working on moving stuff out of tools/perf/util/ to tools/lib/, take the opportunity to adopt routines from the kernel that are equivalent, so that tools/ code look more like the kernel. Cc: Adrian Hunter Cc: André Goddard Rosa Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-zqy1zdu2ok17qvi0ytk8z13c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/string.h | 2 ++ tools/lib/string.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h index cee239350a6b..e436f8037c87 100644 --- a/tools/include/linux/string.h +++ b/tools/include/linux/string.h @@ -31,4 +31,6 @@ static inline bool strstarts(const char *str, const char *prefix) extern char * __must_check skip_spaces(const char *); +extern char *strim(char *); + #endif /* _TOOLS_LINUX_STRING_H_ */ diff --git a/tools/lib/string.c b/tools/lib/string.c index 50d400822bb3..80472e6b3829 100644 --- a/tools/lib/string.c +++ b/tools/lib/string.c @@ -120,3 +120,28 @@ char *skip_spaces(const char *str) ++str; return (char *)str; } + +/** + * strim - Removes leading and trailing whitespace from @s. + * @s: The string to be stripped. + * + * Note that the first trailing whitespace is replaced with a %NUL-terminator + * in the given string @s. Returns a pointer to the first non-whitespace + * character in @s. + */ +char *strim(char *s) +{ + size_t size; + char *end; + + size = strlen(s); + if (!size) + return s; + + end = s + size - 1; + while (end >= s && isspace(*end)) + end--; + *(end + 1) = '\0'; + + return skip_spaces(s); +} From 3ca43b6053c9a5dbbffb02aa010c1ccf8eb460a8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 12:06:20 -0300 Subject: [PATCH 33/43] perf tools: Remove trim() implementation, use tools/lib's strim() Moving more stuff out of tools/perf/util/ and using the kernel idiom. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-wpj8rktj62yse5dq6ckny6de@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 3 ++- tools/perf/ui/browsers/hists.c | 3 ++- tools/perf/ui/gtk/hists.c | 5 +++-- tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/string2.h | 5 ----- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index cd72ff0f7658..66a82badc1d1 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -22,6 +22,7 @@ #include "string2.h" #include "symbol.h" #include +#include #include static bool dont_fork; @@ -438,7 +439,7 @@ static const char *shell_test__description(char *description, size_t size, description = fgets(description, size, fp); fclose(fp); - return description ? trim(description + 1) : NULL; + return description ? strim(description + 1) : NULL; } #define for_each_shell_test(dir, base, ent) \ diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 04a56114df92..10243408f3dc 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -1686,7 +1687,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL); dummy_hpp.buf[ret] = '\0'; - start = trim(dummy_hpp.buf); + start = strim(dummy_hpp.buf); ret = strlen(start); if (start != dummy_hpp.buf) diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 6341c421a8f7..3955ed1d1bd9 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -9,6 +9,7 @@ #include "../string2.h" #include "gtk.h" #include +#include #define MAX_COLUMNS 32 @@ -459,7 +460,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists, advance_hpp(hpp, ret + 2); } - gtk_tree_store_set(store, &iter, col_idx, trim(bf), -1); + gtk_tree_store_set(store, &iter, col_idx, strim(bf), -1); if (!he->leaf) { hpp->buf = bf; @@ -555,7 +556,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, first_col = false; fmt->header(fmt, &hpp, hists, 0, NULL); - strcat(buf, trim(hpp.buf)); + strcat(buf, strim(hpp.buf)); } } diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 594e56628904..9eb0131c3ade 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -620,7 +620,7 @@ static int hists__fprintf_hierarchy_headers(struct hists *hists, fmt->header(fmt, hpp, hists, 0, NULL); - header_width += fprintf(fp, "%s", trim(hpp->buf)); + header_width += fprintf(fp, "%s", strim(hpp->buf)); } } diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h index db02059e31c5..5bc3fea52cdc 100644 --- a/tools/perf/util/string2.h +++ b/tools/perf/util/string2.h @@ -25,11 +25,6 @@ char *strxfrchar(char *s, char from, char to); char *rtrim(char *s); -static inline char *trim(char *s) -{ - return skip_spaces(rtrim(s)); -} - char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints); static inline char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints) From 13c230ab6e56c6ae3a968f01f4c6505b794cecad Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 12:13:13 -0300 Subject: [PATCH 34/43] perf tools: Ditch rtrim(), use strim() from tools/lib Cleaning up a bit more tools/perf/util/ by using things we got from the kernel and have in tools/lib/ Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-7hluuoveryoicvkclshzjf1k@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 3 ++- tools/perf/util/annotate.c | 3 ++- tools/perf/util/header.c | 6 +++--- tools/perf/util/pmu.c | 2 +- tools/perf/util/python-ext-sources | 1 + tools/perf/util/srcline.c | 3 ++- tools/perf/util/string.c | 23 ----------------------- tools/perf/util/string2.h | 2 -- tools/perf/util/thread_map.c | 3 ++- 9 files changed, 13 insertions(+), 33 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 10243408f3dc..33e67aa91347 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2071,7 +2071,8 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser, advance_hpp(&hpp, ret); } - printed += fprintf(fp, "%s\n", rtrim(s)); + strim(s); + printed += fprintf(fp, "%s\n", s); if (he->leaf && folded_sign == '-') { printed += hist_browser__fprintf_callchain(browser, he, fp, diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 783e2628cc8e..2d08c4b62c63 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -35,6 +35,7 @@ #include #include #include +#include #include /* FIXME: For the HE_COLORSET */ @@ -1495,7 +1496,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file, return -1; line_ip = -1; - parsed_line = rtrim(line); + parsed_line = strim(line); /* /filename:linenr ? Save line number and ignore. */ if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1eb15f7517b0..bf26dc85eaaa 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1048,7 +1048,7 @@ static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 lev return -1; cache->type[len] = 0; - cache->type = rtrim(cache->type); + cache->type = strim(cache->type); scnprintf(file, PATH_MAX, "%s/size", path); if (sysfs__read_str(file, &cache->size, &len)) { @@ -1057,7 +1057,7 @@ static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 lev } cache->size[len] = 0; - cache->size = rtrim(cache->size); + cache->size = strim(cache->size); scnprintf(file, PATH_MAX, "%s/shared_cpu_list", path); if (sysfs__read_str(file, &cache->map, &len)) { @@ -1067,7 +1067,7 @@ static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 lev } cache->map[len] = 0; - cache->map = rtrim(cache->map); + cache->map = strim(cache->map); return 0; } diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 38dc0c6e28b8..8139a1f3ed39 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -395,7 +395,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI buf[ret] = 0; /* Remove trailing newline from sysfs file */ - rtrim(buf); + strim(buf); return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 648bcd80b475..2237bac9fadb 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -16,6 +16,7 @@ util/namespaces.c ../lib/bitmap.c ../lib/find_bit.c ../lib/hweight.c +../lib/string.c ../lib/vsprintf.c util/thread_map.c util/util.c diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 10ca1533937e..1824cabe3512 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -5,6 +5,7 @@ #include #include +#include #include "util/dso.h" #include "util/util.h" @@ -464,7 +465,7 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr, char *srcline; struct symbol *inline_sym; - rtrim(funcname); + strim(funcname); if (getline(&filename, &filelen, fp) == -1) goto out; diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 99a555ea4a9f..93a5340424df 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -318,29 +318,6 @@ char *strxfrchar(char *s, char from, char to) return s; } -/** - * rtrim - Removes trailing whitespace from @s. - * @s: The string to be stripped. - * - * Note that the first trailing whitespace is replaced with a %NUL-terminator - * in the given string @s. Returns @s. - */ -char *rtrim(char *s) -{ - size_t size = strlen(s); - char *end; - - if (!size) - return s; - - end = s + size - 1; - while (end >= s && isspace(*end)) - end--; - *(end + 1) = '\0'; - - return s; -} - char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints) { /* diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h index 5bc3fea52cdc..6da835ad8f5b 100644 --- a/tools/perf/util/string2.h +++ b/tools/perf/util/string2.h @@ -23,8 +23,6 @@ static inline bool strisglob(const char *str) int strtailcmp(const char *s1, const char *s2); char *strxfrchar(char *s, char from, char to); -char *rtrim(char *s); - char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints); static inline char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints) diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 5d467d8ae9ab..281bf06f10f2 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -12,6 +12,7 @@ #include "strlist.h" #include #include +#include #include "asm/bug.h" #include "thread_map.h" #include "util.h" @@ -392,7 +393,7 @@ static int get_comm(char **comm, pid_t pid) * mark the end of the string. */ (*comm)[size] = 0; - rtrim(*comm); + strim(*comm); } free(path); From 2a60689a33a61f000bd90596b1289babcb861cd9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 12:24:03 -0300 Subject: [PATCH 35/43] tools lib: Adopt strreplace() from the kernel We'll use it to further reduce the size of tools/perf/util/string.c, replacing the strxfrchar() equivalent function we have there. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-x3r61ikjrso1buygxwke8id3@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/string.h | 2 ++ tools/lib/string.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h index e436f8037c87..a76d4df10435 100644 --- a/tools/include/linux/string.h +++ b/tools/include/linux/string.h @@ -19,6 +19,8 @@ extern size_t strlcpy(char *dest, const char *src, size_t size); char *str_error_r(int errnum, char *buf, size_t buflen); +char *strreplace(char *s, char old, char new); + /** * strstarts - does @str start with @prefix? * @str: string to examine diff --git a/tools/lib/string.c b/tools/lib/string.c index 80472e6b3829..f2ae1b87c719 100644 --- a/tools/lib/string.c +++ b/tools/lib/string.c @@ -145,3 +145,19 @@ char *strim(char *s) return skip_spaces(s); } + +/** + * strreplace - Replace all occurrences of character in string. + * @s: The string to operate on. + * @old: The character being replaced. + * @new: The character @old is replaced with. + * + * Returns pointer to the nul byte at the end of @s. + */ +char *strreplace(char *s, char old, char new) +{ + for (; *s; ++s) + if (*s == old) + *s = new; + return s; +} From af0de0c5f060b1d4eae6033043eb9eafd15aa738 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 12:45:09 -0300 Subject: [PATCH 36/43] perf tools: Drop strxfrchar(), use strreplace() equivalent from kernel No change in behaviour intended, just reducing the codebase and using something available in tools/lib/. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-oyi6zif3810nwi4uu85odnhv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 3 ++- tools/perf/util/string.c | 18 ------------------ tools/perf/util/string2.h | 1 - 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 1fb18292c2d3..c7fde04400f7 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include @@ -394,7 +395,7 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, return -ENOMEM; } - strxfrchar(m->name, '-', '_'); + strreplace(m->name, '-', '_'); } return 0; diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 93a5340424df..9b7fbb0cbecd 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -300,24 +300,6 @@ int strtailcmp(const char *s1, const char *s2) return 0; } -/** - * strxfrchar - Locate and replace character in @s - * @s: The string to be searched/changed. - * @from: Source character to be replaced. - * @to: Destination character. - * - * Return pointer to the changed string. - */ -char *strxfrchar(char *s, char from, char to) -{ - char *p = s; - - while ((p = strchr(p, from)) != NULL) - *p++ = to; - - return s; -} - char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints) { /* diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h index 6da835ad8f5b..2696c3fcd780 100644 --- a/tools/perf/util/string2.h +++ b/tools/perf/util/string2.h @@ -21,7 +21,6 @@ static inline bool strisglob(const char *str) return strpbrk(str, "*?[") != NULL; } int strtailcmp(const char *s1, const char *s2); -char *strxfrchar(char *s, char from, char to); char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints); From 9c10548c42219e961279826c2763a0e32dc056b9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Jun 2019 15:27:58 -0300 Subject: [PATCH 37/43] tools lib: Move argv_{split,free} from tools/perf/util/ This came from the kernel lib/argv_split.c, so move it to tools/lib/argv_split.c, to get it closer to the kernel structure. We need to audit the usage of argv_split() to figure out if it is really necessary to do have one allocation per argv[] entry, looking at one of its users I guess that is not the case and we probably are even leaking those allocations by not using argv_free() judiciously, for later. With this we further remove stuff from tools/perf/util/, reducing the perf specific codebase and encouraging other tools/ code to use these routines so as to keep the style and constructs used with the kernel. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-j479s1ive9h75w5lfg16jroz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/linux/string.h | 3 ++ tools/lib/argv_split.c | 100 +++++++++++++++++++++++++++++++++++ tools/perf/MANIFEST | 1 + tools/perf/util/Build | 5 ++ tools/perf/util/string.c | 91 ------------------------------- tools/perf/util/string2.h | 2 - 6 files changed, 109 insertions(+), 93 deletions(-) create mode 100644 tools/lib/argv_split.c diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h index a76d4df10435..980cb9266718 100644 --- a/tools/include/linux/string.h +++ b/tools/include/linux/string.h @@ -7,6 +7,9 @@ void *memdup(const void *src, size_t len); +char **argv_split(const char *str, int *argcp); +void argv_free(char **argv); + int strtobool(const char *s, bool *res); /* diff --git a/tools/lib/argv_split.c b/tools/lib/argv_split.c new file mode 100644 index 000000000000..0a58ccf3f761 --- /dev/null +++ b/tools/lib/argv_split.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Helper function for splitting a string into an argv-like array. + */ + +#include +#include +#include +#include + +static const char *skip_arg(const char *cp) +{ + while (*cp && !isspace(*cp)) + cp++; + + return cp; +} + +static int count_argc(const char *str) +{ + int count = 0; + + while (*str) { + str = skip_spaces(str); + if (*str) { + count++; + str = skip_arg(str); + } + } + + return count; +} + +/** + * argv_free - free an argv + * @argv - the argument vector to be freed + * + * Frees an argv and the strings it points to. + */ +void argv_free(char **argv) +{ + char **p; + for (p = argv; *p; p++) { + free(*p); + *p = NULL; + } + + free(argv); +} + +/** + * argv_split - split a string at whitespace, returning an argv + * @str: the string to be split + * @argcp: returned argument count + * + * Returns an array of pointers to strings which are split out from + * @str. This is performed by strictly splitting on white-space; no + * quote processing is performed. Multiple whitespace characters are + * considered to be a single argument separator. The returned array + * is always NULL-terminated. Returns NULL on memory allocation + * failure. + */ +char **argv_split(const char *str, int *argcp) +{ + int argc = count_argc(str); + char **argv = calloc(argc + 1, sizeof(*argv)); + char **argvp; + + if (argv == NULL) + goto out; + + if (argcp) + *argcp = argc; + + argvp = argv; + + while (*str) { + str = skip_spaces(str); + + if (*str) { + const char *p = str; + char *t; + + str = skip_arg(str); + + t = strndup(p, str-p); + if (t == NULL) + goto fail; + *argvp++ = t; + } + } + *argvp = NULL; + +out: + return argv; + +fail: + argv_free(argv); + return NULL; +} diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index aac4c755d81b..6a5de44b2de9 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST @@ -7,6 +7,7 @@ tools/lib/traceevent tools/lib/api tools/lib/bpf tools/lib/subcmd +tools/lib/argv_split.c tools/lib/ctype.c tools/lib/hweight.c tools/lib/rbtree.c diff --git a/tools/perf/util/Build b/tools/perf/util/Build index b4dc6112138f..d3408a463060 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -20,6 +20,7 @@ perf-y += parse-events.o perf-y += perf_regs.o perf-y += path.o perf-y += print_binary.o +perf-y += argv_split.o perf-y += rbtree.o perf-y += libstring.o perf-y += bitmap.o @@ -209,6 +210,10 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) +$(OUTPUT)util/argv_split.o: ../lib/argv_split.c FORCE + $(call rule_mkdir) + $(call if_changed_dep,cc_o_c) + $(OUTPUT)util/bitmap.o: ../lib/bitmap.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 9b7fbb0cbecd..52603876c548 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -69,97 +69,6 @@ s64 perf_atoll(const char *str) return -1; } -static const char *skip_arg(const char *cp) -{ - while (*cp && !isspace(*cp)) - cp++; - - return cp; -} - -static int count_argc(const char *str) -{ - int count = 0; - - while (*str) { - str = skip_spaces(str); - if (*str) { - count++; - str = skip_arg(str); - } - } - - return count; -} - -/** - * argv_free - free an argv - * @argv - the argument vector to be freed - * - * Frees an argv and the strings it points to. - */ -void argv_free(char **argv) -{ - char **p; - for (p = argv; *p; p++) { - free(*p); - *p = NULL; - } - - free(argv); -} - -/** - * argv_split - split a string at whitespace, returning an argv - * @str: the string to be split - * @argcp: returned argument count - * - * Returns an array of pointers to strings which are split out from - * @str. This is performed by strictly splitting on white-space; no - * quote processing is performed. Multiple whitespace characters are - * considered to be a single argument separator. The returned array - * is always NULL-terminated. Returns NULL on memory allocation - * failure. - */ -char **argv_split(const char *str, int *argcp) -{ - int argc = count_argc(str); - char **argv = calloc(argc + 1, sizeof(*argv)); - char **argvp; - - if (argv == NULL) - goto out; - - if (argcp) - *argcp = argc; - - argvp = argv; - - while (*str) { - str = skip_spaces(str); - - if (*str) { - const char *p = str; - char *t; - - str = skip_arg(str); - - t = strndup(p, str-p); - if (t == NULL) - goto fail; - *argvp++ = t; - } - } - *argvp = NULL; - -out: - return argv; - -fail: - argv_free(argv); - return NULL; -} - /* Character class matching */ static bool __match_charclass(const char *pat, char c, const char **npat) { diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h index 2696c3fcd780..708805f5573e 100644 --- a/tools/perf/util/string2.h +++ b/tools/perf/util/string2.h @@ -11,8 +11,6 @@ extern const char *graph_dotted_line; extern const char *dots; s64 perf_atoll(const char *str); -char **argv_split(const char *str, int *argcp); -void argv_free(char **argv); bool strglobmatch(const char *str, const char *pat); bool strglobmatch_nocase(const char *str, const char *pat); bool strlazymatch(const char *str, const char *pat); From 145c407c808352acd625be793396fd4f33c794f8 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 24 Jun 2019 12:37:08 -0700 Subject: [PATCH 38/43] perf stat: Make metric event lookup more robust After setting up metric groups through the event parser, the metricgroup code looks them up again in the event list. Make sure we only look up events that haven't been used by some other metric. The data structures currently cannot handle more than one metric per event. This avoids problems with multiple events partially overlapping. Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Cc: Kan Liang Link: http://lkml.kernel.org/r/20190624193711.35241-2-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 027b09aaa4cf..3f8fd127d31e 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -304,7 +304,7 @@ static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list, struct perf_evsel *c2; evlist__for_each_entry (evsel_list, c2) { - if (!strcasecmp(c2->name, name)) + if (!strcasecmp(c2->name, name) && !c2->collect_stat) return c2; } return NULL; @@ -343,7 +343,8 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) if (leader) { /* Search in group */ for_each_group_member (oc, leader) { - if (!strcasecmp(oc->name, metric_names[i])) { + if (!strcasecmp(oc->name, metric_names[i]) && + !oc->collect_stat) { found = true; break; } From 6c5f4e5cb35b4694dc035d91092d23f596ecd06a Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 24 Jun 2019 12:37:09 -0700 Subject: [PATCH 39/43] perf stat: Don't merge events in the same PMU Event merging is mainly to collapse similar events in lots of different duplicated PMUs. It can break metric displaying. It's possible for two metrics to have the same event, and when the two events happen in a row the second wouldn't be displayed. This would also not show the second metric. To avoid this don't merge events in the same PMU. This makes sense, if we have multiple events in the same PMU there is likely some reason for it (e.g. using multiple groups) and we better not merge them. While in theory it would be possible to construct metrics that have events with the same name in different PMU no current metrics have this problem. This is the fix for perf stat -M UPI,IPC (needs also another bug fix to completely work) Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Cc: Kan Liang Fixes: 430daf2dc7af ("perf stat: Collapse identically named events") Link: http://lkml.kernel.org/r/20190624193711.35241-3-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 90df41169113..58df6a0dbb9f 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -554,7 +554,8 @@ static void collect_all_aliases(struct perf_stat_config *config, struct perf_evs alias->scale != counter->scale || alias->cgrp != counter->cgrp || strcmp(alias->unit, counter->unit) || - perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter)) + perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter) || + !strcmp(alias->pmu_name, counter->pmu_name)) break; alias->merged_stat = true; cb(config, alias, data, false); From 2f87f33f4226523df9c9cc28f9874ea02fcc3d3f Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 24 Jun 2019 12:37:10 -0700 Subject: [PATCH 40/43] perf stat: Fix group lookup for metric group The metric group code tries to find a group it added earlier in the evlist. Fix the lookup to handle groups with partially overlaps correctly. When a sub string match fails and we reset the match, we have to compare the first element again. I also renamed the find_evsel function to find_evsel_group to make its purpose clearer. With the earlier changes this fixes: Before: % perf stat -M UPI,IPC sleep 1 ... 1,032,922 uops_retired.retire_slots # 1.1 UPI 1,896,096 inst_retired.any 1,896,096 inst_retired.any 1,177,254 cpu_clk_unhalted.thread After: % perf stat -M UPI,IPC sleep 1 ... 1,013,193 uops_retired.retire_slots # 1.1 UPI 932,033 inst_retired.any 932,033 inst_retired.any # 0.9 IPC 1,091,245 cpu_clk_unhalted.thread Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Cc: Kan Liang Fixes: b18f3e365019 ("perf stat: Support JSON metrics in perf stat") Link: http://lkml.kernel.org/r/20190624193711.35241-4-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 47 ++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 90cd84e2a503..bc25995255ab 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -85,26 +85,49 @@ struct egroup { const char *metric_expr; }; -static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist, - const char **ids, - int idnum, - struct perf_evsel **metric_events) +static bool record_evsel(int *ind, struct perf_evsel **start, + int idnum, + struct perf_evsel **metric_events, + struct perf_evsel *ev) +{ + metric_events[*ind] = ev; + if (*ind == 0) + *start = ev; + if (++*ind == idnum) { + metric_events[*ind] = NULL; + return true; + } + return false; +} + +static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, + const char **ids, + int idnum, + struct perf_evsel **metric_events) { struct perf_evsel *ev, *start = NULL; int ind = 0; evlist__for_each_entry (perf_evlist, ev) { + if (ev->collect_stat) + continue; if (!strcmp(ev->name, ids[ind])) { - metric_events[ind] = ev; - if (ind == 0) - start = ev; - if (++ind == idnum) { - metric_events[ind] = NULL; + if (record_evsel(&ind, &start, idnum, + metric_events, ev)) return start; - } } else { + /* + * We saw some other event that is not + * in our list of events. Discard + * the whole match and start again. + */ ind = 0; start = NULL; + if (!strcmp(ev->name, ids[ind])) { + if (record_evsel(&ind, &start, idnum, + metric_events, ev)) + return start; + } } } /* @@ -134,8 +157,8 @@ static int metricgroup__setup_events(struct list_head *groups, ret = -ENOMEM; break; } - evsel = find_evsel(perf_evlist, eg->ids, eg->idnum, - metric_events); + evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum, + metric_events); if (!evsel) { pr_debug("Cannot resolve %s: %s\n", eg->metric_name, eg->metric_expr); From e3a9427323a53ceee540276a74af7706f350d052 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 24 Jun 2019 12:37:11 -0700 Subject: [PATCH 41/43] perf stat: Fix metrics with --no-merge Since Fixes: 8c5421c016a4 ("perf pmu: Display pmu name when printing unmerged events in stat") using --no-merge adds the PMU name to the evsel name. This breaks the metric value lookup because the parser doesn't know about this. Remove the extra postfixes for the metric evaluation. Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Cc: Agustin Vega-Frias Cc: Kan Liang Fixes: 8c5421c016a4 ("perf pmu: Display pmu name when printing unmerged events in stat") Link: http://lkml.kernel.org/r/20190624193711.35241-5-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 3f8fd127d31e..cb891e5c2969 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -724,6 +724,7 @@ static void generic_metric(struct perf_stat_config *config, double ratio; int i; void *ctxp = out->ctx; + char *n, *pn; expr__ctx_init(&pctx); expr__add_id(&pctx, name, avg); @@ -743,7 +744,19 @@ static void generic_metric(struct perf_stat_config *config, stats = &v->stats; scale = 1.0; } - expr__add_id(&pctx, metric_events[i]->name, avg_stats(stats)*scale); + + n = strdup(metric_events[i]->name); + if (!n) + return; + /* + * This display code with --no-merge adds [cpu] postfixes. + * These are not supported by the parser. Remove everything + * after the space. + */ + pn = strchr(n, ' '); + if (pn) + *pn = 0; + expr__add_id(&pctx, n, avg_stats(stats)*scale); } if (!metric_events[i]) { const char *p = metric_expr; @@ -760,6 +773,9 @@ static void generic_metric(struct perf_stat_config *config, (metric_name ? metric_name : name) : "", 0); } else print_metric(config, ctxp, NULL, NULL, "", 0); + + for (i = 1; i < pctx.num_ids; i++) + free((void *)pctx.ids[i].name); } void perf_stat__print_shadow_stats(struct perf_stat_config *config, From aa23aa55166c2865ac430168c4b9d405cf8c6980 Mon Sep 17 00:00:00 2001 From: Mao Han Date: Wed, 26 Jun 2019 14:52:19 +0800 Subject: [PATCH 42/43] perf annotate: Add csky support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch add basic arch initialization and instruction associate support for the csky CPU architecture. E.g.: $ perf annotate --stdio2 Samples: 161 of event 'cpu-clock:pppH', 4000 Hz, Event count (approx.): 40250000, [percent: local period] test_4() /usr/lib/perf-test/callchain_test Percent Disassembly of section .text: 00008420 : test_4(): subi sp, sp, 4 st.w r8, (sp, 0x0) mov r8, sp subi sp, sp, 8 subi r3, r8, 4 movi r2, 0 st.w r2, (r3, 0x0) ↓ br 2e 100.00 14: subi r3, r8, 4 ld.w r2, (r3, 0x0) subi r3, r8, 8 st.w r2, (r3, 0x0) subi r3, r8, 4 ld.w r3, (r3, 0x0) addi r2, r3, 1 subi r3, r8, 4 st.w r2, (r3, 0x0) 2e: subi r3, r8, 4 ld.w r2, (r3, 0x0) lrw r3, 0x98967f // 8598 cmplt r3, r2 ↑ bf 14 mov r0, r0 mov r0, r0 mov sp, r8 ld.w r8, (sp, 0x0) addi sp, sp, 4 ← rts Signed-off-by: Mao Han Acked-by: Guo Ren Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: linux-csky@vger.kernel.org Link: http://lkml.kernel.org/r/d874d7782d9acdad5d98f2f5c4a6fb26fbe41c5d.1561531557.git.han_mao@c-sky.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/csky/annotate/instructions.c | 48 ++++++++++++++++++++ tools/perf/util/annotate.c | 5 ++ 2 files changed, 53 insertions(+) create mode 100644 tools/perf/arch/csky/annotate/instructions.c diff --git a/tools/perf/arch/csky/annotate/instructions.c b/tools/perf/arch/csky/annotate/instructions.c new file mode 100644 index 000000000000..5337bfb7d5fc --- /dev/null +++ b/tools/perf/arch/csky/annotate/instructions.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. + +#include + +static struct ins_ops *csky__associate_ins_ops(struct arch *arch, + const char *name) +{ + struct ins_ops *ops = NULL; + + /* catch all kind of jumps */ + if (!strcmp(name, "bt") || + !strcmp(name, "bf") || + !strcmp(name, "bez") || + !strcmp(name, "bnez") || + !strcmp(name, "bnezad") || + !strcmp(name, "bhsz") || + !strcmp(name, "bhz") || + !strcmp(name, "blsz") || + !strcmp(name, "blz") || + !strcmp(name, "br") || + !strcmp(name, "jmpi") || + !strcmp(name, "jmp")) + ops = &jump_ops; + + /* catch function call */ + if (!strcmp(name, "bsr") || + !strcmp(name, "jsri") || + !strcmp(name, "jsr")) + ops = &call_ops; + + /* catch function return */ + if (!strcmp(name, "rts")) + ops = &ret_ops; + + if (ops) + arch__associate_ins_ops(arch, name, ops); + return ops; +} + +static int csky__annotate_init(struct arch *arch, char *cpuid __maybe_unused) +{ + arch->initialized = true; + arch->objdump.comment_char = '/'; + arch->associate_instruction_ops = csky__associate_ins_ops; + + return 0; +} diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 2d08c4b62c63..ec7aaf31c2b2 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -145,6 +145,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i #include "arch/arc/annotate/instructions.c" #include "arch/arm/annotate/instructions.c" #include "arch/arm64/annotate/instructions.c" +#include "arch/csky/annotate/instructions.c" #include "arch/x86/annotate/instructions.c" #include "arch/powerpc/annotate/instructions.c" #include "arch/s390/annotate/instructions.c" @@ -163,6 +164,10 @@ static struct arch architectures[] = { .name = "arm64", .init = arm64__annotate_init, }, + { + .name = "csky", + .init = csky__annotate_init, + }, { .name = "x86", .init = x86__annotate_init, From 06c642c0e9fceafd16b1a4c80d44b1c09e282215 Mon Sep 17 00:00:00 2001 From: Luke Mujica Date: Tue, 25 Jun 2019 10:31:22 -0700 Subject: [PATCH 43/43] perf jevents: Use nonlocal include statements in pmu-events.c Change pmu-events.c to not use local include statements. The code that creates the include statements for pmu-events.c is in jevents.c. pmu-events.c is a generated file, and for build systems that put generated files in a separate directory, include statements with local pathing cannot find non-generated files. Signed-off-by: Luke Mujica Cc: Ian Rogers Cc: Jiri Olsa Cc: Numfor Mbiziwo-Tiapo Cc: Stephane Eranian Link: https://lkml.kernel.org/n/tip-prgnwmaoo1pv9zz4vnv1bjaj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/jevents.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c index 58f77fd0f59f..a1184ea64cc6 100644 --- a/tools/perf/pmu-events/jevents.c +++ b/tools/perf/pmu-events/jevents.c @@ -841,7 +841,7 @@ static void create_empty_mapping(const char *output_file) _Exit(1); } - fprintf(outfp, "#include \"../../pmu-events/pmu-events.h\"\n"); + fprintf(outfp, "#include \"pmu-events/pmu-events.h\"\n"); print_mapping_table_prefix(outfp); print_mapping_table_suffix(outfp); fclose(outfp); @@ -1096,7 +1096,7 @@ int main(int argc, char *argv[]) } /* Include pmu-events.h first */ - fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n"); + fprintf(eventsfp, "#include \"pmu-events/pmu-events.h\"\n"); /* * The mapfile allows multiple CPUids to point to the same JSON file,