From 3d8906034eed1e3c8ce283a8a0209d7dc32d460a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 17 Aug 2009 14:36:32 +1000 Subject: [PATCH] --- yaml --- r: 158266 b: refs/heads/master c: 1660e9d3d04b6c636b7171bf6c08ac7b82a7de79 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/powerpc/include/asm/pgtable.h | 6 +- trunk/arch/x86/include/asm/perf_counter.h | 10 - trunk/arch/x86/kernel/cpu/perf_counter.c | 325 +-------- .../tools/perf/Documentation/perf-report.txt | 3 - trunk/tools/perf/Makefile | 12 +- trunk/tools/perf/builtin-annotate.c | 457 ++++++++++-- trunk/tools/perf/builtin-help.c | 1 - trunk/tools/perf/builtin-record.c | 23 +- trunk/tools/perf/builtin-report.c | 670 +++++++++++++++--- trunk/tools/perf/builtin-stat.c | 3 +- trunk/tools/perf/builtin-top.c | 49 +- trunk/tools/perf/builtin.h | 1 - trunk/tools/perf/util/abspath.c | 3 +- trunk/tools/perf/util/cache.h | 1 + trunk/tools/perf/util/callchain.c | 2 - trunk/tools/perf/util/callchain.h | 1 - trunk/tools/perf/util/color.c | 16 +- trunk/tools/perf/util/color.h | 3 +- trunk/tools/perf/util/config.c | 22 +- trunk/tools/perf/util/debug.c | 95 --- trunk/tools/perf/util/debug.h | 8 - trunk/tools/perf/util/event.h | 96 --- trunk/tools/perf/util/exec_cmd.c | 1 + trunk/tools/perf/util/header.c | 35 - trunk/tools/perf/util/header.h | 4 - trunk/tools/perf/util/map.c | 97 --- trunk/tools/perf/util/module.c | 4 +- trunk/tools/perf/util/parse-events.c | 26 +- trunk/tools/perf/util/parse-events.h | 4 +- trunk/tools/perf/util/parse-options.c | 22 - trunk/tools/perf/util/path.c | 25 +- trunk/tools/perf/util/run-command.c | 6 +- trunk/tools/perf/util/symbol.c | 199 ++---- trunk/tools/perf/util/symbol.h | 14 +- trunk/tools/perf/util/thread.c | 143 ---- trunk/tools/perf/util/thread.h | 19 - trunk/tools/perf/util/util.h | 1 - trunk/tools/perf/util/values.c | 230 ------ trunk/tools/perf/util/values.h | 27 - 40 files changed, 1136 insertions(+), 1530 deletions(-) delete mode 100644 trunk/tools/perf/util/debug.c delete mode 100644 trunk/tools/perf/util/debug.h delete mode 100644 trunk/tools/perf/util/event.h delete mode 100644 trunk/tools/perf/util/map.c delete mode 100644 trunk/tools/perf/util/thread.c delete mode 100644 trunk/tools/perf/util/thread.h delete mode 100644 trunk/tools/perf/util/values.c delete mode 100644 trunk/tools/perf/util/values.h diff --git a/[refs] b/[refs] index e40505d7239c..6d6ae0529034 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8f28827a162fd1e8da4e96bed69b06d2606e8322 +refs/heads/master: 1660e9d3d04b6c636b7171bf6c08ac7b82a7de79 diff --git a/trunk/arch/powerpc/include/asm/pgtable.h b/trunk/arch/powerpc/include/asm/pgtable.h index eb17da781128..2a5da069714e 100644 --- a/trunk/arch/powerpc/include/asm/pgtable.h +++ b/trunk/arch/powerpc/include/asm/pgtable.h @@ -104,8 +104,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, else pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte)); -#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP) - /* Second case is 32-bit with 64-bit PTE in SMP mode. In this case, we +#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) + /* Second case is 32-bit with 64-bit PTE. In this case, we * can just store as long as we do the two halves in the right order * with a barrier in between. This is possible because we take care, * in the hash code, to pre-invalidate if the PTE was already hashed, @@ -140,7 +140,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, #else /* Anything else just stores the PTE normally. That covers all 64-bit - * cases, and 32-bit non-hash with 64-bit PTEs in UP mode + * cases, and 32-bit non-hash with 32-bit PTEs. */ *ptep = pte; #endif diff --git a/trunk/arch/x86/include/asm/perf_counter.h b/trunk/arch/x86/include/asm/perf_counter.h index e7b7c938ae27..fa64e401589d 100644 --- a/trunk/arch/x86/include/asm/perf_counter.h +++ b/trunk/arch/x86/include/asm/perf_counter.h @@ -84,16 +84,6 @@ union cpuid10_edx { #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) -/* - * We model BTS tracing as another fixed-mode PMC. - * - * We choose a value in the middle of the fixed counter range, since lower - * values are used by actual fixed counters and higher values are used - * to indicate other overflow conditions in the PERF_GLOBAL_STATUS msr. - */ -#define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16) - - #ifdef CONFIG_PERF_COUNTERS extern void init_hw_perf_counters(void); extern void perf_counters_lapic_init(void); diff --git a/trunk/arch/x86/kernel/cpu/perf_counter.c b/trunk/arch/x86/kernel/cpu/perf_counter.c index 396e35db7058..900332b800f8 100644 --- a/trunk/arch/x86/kernel/cpu/perf_counter.c +++ b/trunk/arch/x86/kernel/cpu/perf_counter.c @@ -6,7 +6,6 @@ * Copyright (C) 2009 Jaswinder Singh Rajput * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra - * Copyright (C) 2009 Intel Corporation, * * For licencing details see kernel-base/COPYING */ @@ -21,7 +20,6 @@ #include #include #include -#include #include #include @@ -29,52 +27,12 @@ static u64 perf_counter_mask __read_mostly; -/* The maximal number of PEBS counters: */ -#define MAX_PEBS_COUNTERS 4 - -/* The size of a BTS record in bytes: */ -#define BTS_RECORD_SIZE 24 - -/* The size of a per-cpu BTS buffer in bytes: */ -#define BTS_BUFFER_SIZE (BTS_RECORD_SIZE * 1024) - -/* The BTS overflow threshold in bytes from the end of the buffer: */ -#define BTS_OVFL_TH (BTS_RECORD_SIZE * 64) - - -/* - * Bits in the debugctlmsr controlling branch tracing. - */ -#define X86_DEBUGCTL_TR (1 << 6) -#define X86_DEBUGCTL_BTS (1 << 7) -#define X86_DEBUGCTL_BTINT (1 << 8) -#define X86_DEBUGCTL_BTS_OFF_OS (1 << 9) -#define X86_DEBUGCTL_BTS_OFF_USR (1 << 10) - -/* - * A debug store configuration. - * - * We only support architectures that use 64bit fields. - */ -struct debug_store { - u64 bts_buffer_base; - u64 bts_index; - u64 bts_absolute_maximum; - u64 bts_interrupt_threshold; - u64 pebs_buffer_base; - u64 pebs_index; - u64 pebs_absolute_maximum; - u64 pebs_interrupt_threshold; - u64 pebs_counter_reset[MAX_PEBS_COUNTERS]; -}; - struct cpu_hw_counters { struct perf_counter *counters[X86_PMC_IDX_MAX]; unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; unsigned long interrupts; int enabled; - struct debug_store *ds; }; /* @@ -100,8 +58,6 @@ struct x86_pmu { int apic; u64 max_period; u64 intel_ctrl; - void (*enable_bts)(u64 config); - void (*disable_bts)(void); }; static struct x86_pmu x86_pmu __read_mostly; @@ -621,9 +577,6 @@ x86_perf_counter_update(struct perf_counter *counter, u64 prev_raw_count, new_raw_count; s64 delta; - if (idx == X86_PMC_IDX_FIXED_BTS) - return 0; - /* * Careful: an NMI might modify the previous counter value. * @@ -713,109 +666,10 @@ static void release_pmc_hardware(void) #endif } -static inline bool bts_available(void) -{ - return x86_pmu.enable_bts != NULL; -} - -static inline void init_debug_store_on_cpu(int cpu) -{ - struct debug_store *ds = per_cpu(cpu_hw_counters, cpu).ds; - - if (!ds) - return; - - wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, - (u32)((u64)(long)ds), (u32)((u64)(long)ds >> 32)); -} - -static inline void fini_debug_store_on_cpu(int cpu) -{ - if (!per_cpu(cpu_hw_counters, cpu).ds) - return; - - wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); -} - -static void release_bts_hardware(void) -{ - int cpu; - - if (!bts_available()) - return; - - get_online_cpus(); - - for_each_online_cpu(cpu) - fini_debug_store_on_cpu(cpu); - - for_each_possible_cpu(cpu) { - struct debug_store *ds = per_cpu(cpu_hw_counters, cpu).ds; - - if (!ds) - continue; - - per_cpu(cpu_hw_counters, cpu).ds = NULL; - - kfree((void *)(long)ds->bts_buffer_base); - kfree(ds); - } - - put_online_cpus(); -} - -static int reserve_bts_hardware(void) -{ - int cpu, err = 0; - - if (!bts_available()) - return -EOPNOTSUPP; - - get_online_cpus(); - - for_each_possible_cpu(cpu) { - struct debug_store *ds; - void *buffer; - - err = -ENOMEM; - buffer = kzalloc(BTS_BUFFER_SIZE, GFP_KERNEL); - if (unlikely(!buffer)) - break; - - ds = kzalloc(sizeof(*ds), GFP_KERNEL); - if (unlikely(!ds)) { - kfree(buffer); - break; - } - - ds->bts_buffer_base = (u64)(long)buffer; - ds->bts_index = ds->bts_buffer_base; - ds->bts_absolute_maximum = - ds->bts_buffer_base + BTS_BUFFER_SIZE; - ds->bts_interrupt_threshold = - ds->bts_absolute_maximum - BTS_OVFL_TH; - - per_cpu(cpu_hw_counters, cpu).ds = ds; - err = 0; - } - - if (err) - release_bts_hardware(); - else { - for_each_online_cpu(cpu) - init_debug_store_on_cpu(cpu); - } - - put_online_cpus(); - - return err; -} - static void hw_perf_counter_destroy(struct perf_counter *counter) { if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) { release_pmc_hardware(); - release_bts_hardware(); mutex_unlock(&pmc_reserve_mutex); } } @@ -858,42 +712,6 @@ set_ext_hw_attr(struct hw_perf_counter *hwc, struct perf_counter_attr *attr) return 0; } -static void intel_pmu_enable_bts(u64 config) -{ - unsigned long debugctlmsr; - - debugctlmsr = get_debugctlmsr(); - - debugctlmsr |= X86_DEBUGCTL_TR; - debugctlmsr |= X86_DEBUGCTL_BTS; - debugctlmsr |= X86_DEBUGCTL_BTINT; - - if (!(config & ARCH_PERFMON_EVENTSEL_OS)) - debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; - - if (!(config & ARCH_PERFMON_EVENTSEL_USR)) - debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; - - update_debugctlmsr(debugctlmsr); -} - -static void intel_pmu_disable_bts(void) -{ - struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); - unsigned long debugctlmsr; - - if (!cpuc->ds) - return; - - debugctlmsr = get_debugctlmsr(); - - debugctlmsr &= - ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | - X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); - - update_debugctlmsr(debugctlmsr); -} - /* * Setup the hardware configuration for a given attr_type */ @@ -910,13 +728,9 @@ static int __hw_perf_counter_init(struct perf_counter *counter) err = 0; if (!atomic_inc_not_zero(&active_counters)) { mutex_lock(&pmc_reserve_mutex); - if (atomic_read(&active_counters) == 0) { - if (!reserve_pmc_hardware()) - err = -EBUSY; - else - reserve_bts_hardware(); - } - if (!err) + if (atomic_read(&active_counters) == 0 && !reserve_pmc_hardware()) + err = -EBUSY; + else atomic_inc(&active_counters); mutex_unlock(&pmc_reserve_mutex); } @@ -1003,18 +817,7 @@ static void p6_pmu_disable_all(void) static void intel_pmu_disable_all(void) { - struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); - - if (!cpuc->enabled) - return; - - cpuc->enabled = 0; - barrier(); - wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); - - if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) - intel_pmu_disable_bts(); } static void amd_pmu_disable_all(void) @@ -1072,25 +875,7 @@ static void p6_pmu_enable_all(void) static void intel_pmu_enable_all(void) { - struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); - - if (cpuc->enabled) - return; - - cpuc->enabled = 1; - barrier(); - wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); - - if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { - struct perf_counter *counter = - cpuc->counters[X86_PMC_IDX_FIXED_BTS]; - - if (WARN_ON_ONCE(!counter)) - return; - - intel_pmu_enable_bts(counter->hw.config); - } } static void amd_pmu_enable_all(void) @@ -1177,11 +962,6 @@ p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) static inline void intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) { - if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { - intel_pmu_disable_bts(); - return; - } - if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { intel_pmu_disable_fixed(hwc, idx); return; @@ -1210,9 +990,6 @@ x86_perf_counter_set_period(struct perf_counter *counter, s64 period = hwc->sample_period; int err, ret = 0; - if (idx == X86_PMC_IDX_FIXED_BTS) - return 0; - /* * If we are way outside a reasoable range then just skip forward: */ @@ -1295,14 +1072,6 @@ static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) { - if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { - if (!__get_cpu_var(cpu_hw_counters).enabled) - return; - - intel_pmu_enable_bts(hwc->config); - return; - } - if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { intel_pmu_enable_fixed(hwc, idx); return; @@ -1324,16 +1093,11 @@ fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc) { unsigned int event; - event = hwc->config & ARCH_PERFMON_EVENT_MASK; - - if (unlikely((event == - x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && - (hwc->sample_period == 1))) - return X86_PMC_IDX_FIXED_BTS; - if (!x86_pmu.num_counters_fixed) return -1; + event = hwc->config & ARCH_PERFMON_EVENT_MASK; + if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) return X86_PMC_IDX_FIXED_INSTRUCTIONS; if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) @@ -1354,25 +1118,7 @@ static int x86_pmu_enable(struct perf_counter *counter) int idx; idx = fixed_mode_idx(counter, hwc); - if (idx == X86_PMC_IDX_FIXED_BTS) { - /* - * Try to use BTS for branch tracing. If that is not - * available, try to get a generic counter. - */ - if (unlikely(!cpuc->ds)) - goto try_generic; - - /* - * Try to get the fixed counter, if that is already taken - * then try to get a generic counter: - */ - if (test_and_set_bit(idx, cpuc->used_mask)) - goto try_generic; - - hwc->config_base = 0; - hwc->counter_base = 0; - hwc->idx = idx; - } else if (idx >= 0) { + if (idx >= 0) { /* * Try to get the fixed counter, if that is already taken * then try to get a generic counter: @@ -1483,45 +1229,6 @@ void perf_counter_print_debug(void) local_irq_restore(flags); } -static void intel_pmu_drain_bts_buffer(struct cpu_hw_counters *cpuc, - struct perf_sample_data *data) -{ - struct debug_store *ds = cpuc->ds; - struct bts_record { - u64 from; - u64 to; - u64 flags; - }; - struct perf_counter *counter = cpuc->counters[X86_PMC_IDX_FIXED_BTS]; - unsigned long orig_ip = data->regs->ip; - u64 at; - - if (!counter) - return; - - if (!ds) - return; - - for (at = ds->bts_buffer_base; - at < ds->bts_index; - at += sizeof(struct bts_record)) { - struct bts_record *rec = (struct bts_record *)(long)at; - - data->regs->ip = rec->from; - data->addr = rec->to; - - perf_counter_output(counter, 1, data); - } - - ds->bts_index = ds->bts_buffer_base; - - data->regs->ip = orig_ip; - data->addr = 0; - - /* There's new data available. */ - counter->pending_kill = POLL_IN; -} - static void x86_pmu_disable(struct perf_counter *counter) { struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); @@ -1546,15 +1253,6 @@ static void x86_pmu_disable(struct perf_counter *counter) * that we are disabling: */ x86_perf_counter_update(counter, hwc, idx); - - /* Drain the remaining BTS records. */ - if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { - struct perf_sample_data data; - struct pt_regs regs; - - data.regs = ®s; - intel_pmu_drain_bts_buffer(cpuc, &data); - } cpuc->counters[idx] = NULL; clear_bit(idx, cpuc->used_mask); @@ -1582,7 +1280,6 @@ static int intel_pmu_save_and_restart(struct perf_counter *counter) static void intel_pmu_reset(void) { - struct debug_store *ds = __get_cpu_var(cpu_hw_counters).ds; unsigned long flags; int idx; @@ -1600,8 +1297,6 @@ static void intel_pmu_reset(void) for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) { checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); } - if (ds) - ds->bts_index = ds->bts_buffer_base; local_irq_restore(flags); } @@ -1667,7 +1362,6 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_counters); perf_disable(); - intel_pmu_drain_bts_buffer(cpuc, &data); status = intel_pmu_get_status(); if (!status) { perf_enable(); @@ -1877,8 +1571,6 @@ static struct x86_pmu intel_pmu = { * the generic counter period: */ .max_period = (1ULL << 31) - 1, - .enable_bts = intel_pmu_enable_bts, - .disable_bts = intel_pmu_disable_bts, }; static struct x86_pmu amd_pmu = { @@ -2270,8 +1962,3 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) return entry; } - -void hw_perf_counter_setup_online(int cpu) -{ - init_debug_store_on_cpu(cpu); -} diff --git a/trunk/tools/perf/Documentation/perf-report.txt b/trunk/tools/perf/Documentation/perf-report.txt index 370344afb5b2..e72e93110782 100644 --- a/trunk/tools/perf/Documentation/perf-report.txt +++ b/trunk/tools/perf/Documentation/perf-report.txt @@ -27,9 +27,6 @@ OPTIONS -n --show-nr-samples Show the number of samples for each symbol --T ---threads - Show per-thread event counters -C:: --comms=:: Only consider symbols in these comms. CSV that understands diff --git a/trunk/tools/perf/Makefile b/trunk/tools/perf/Makefile index 5d54ddb83ab1..c045b4271e57 100644 --- a/trunk/tools/perf/Makefile +++ b/trunk/tools/perf/Makefile @@ -166,12 +166,7 @@ endif # CFLAGS and LDFLAGS are for the users to override from the command line. -# -# Include saner warnings here, which can catch bugs: -# -EXTRA_WARNINGS = -Wcast-align -Wformat -Wformat-security -Wformat-y2k -Wshadow -Winit-self -Wpacked -Wredundant-decls -Wstack-protector -Wstrict-aliasing=3 -Wswitch-default -Wswitch-enum -Wno-system-headers -Wundef -Wvolatile-register-var -Wwrite-strings -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wdeclaration-after-statement - -CFLAGS = $(M64) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) +CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 LDFLAGS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) ALL_LDFLAGS = $(LDFLAGS) @@ -315,7 +310,6 @@ LIB_H += util/sigchain.h LIB_H += util/symbol.h LIB_H += util/module.h LIB_H += util/color.h -LIB_H += util/values.h LIB_OBJS += util/abspath.o LIB_OBJS += util/alias.o @@ -343,10 +337,6 @@ LIB_OBJS += util/color.o LIB_OBJS += util/pager.o LIB_OBJS += util/header.o LIB_OBJS += util/callchain.o -LIB_OBJS += util/values.o -LIB_OBJS += util/debug.o -LIB_OBJS += util/map.o -LIB_OBJS += util/thread.o BUILTIN_OBJS += builtin-annotate.o BUILTIN_OBJS += builtin-help.o diff --git a/trunk/tools/perf/builtin-annotate.c b/trunk/tools/perf/builtin-annotate.c index 96d421f7161d..1dba568e1941 100644 --- a/trunk/tools/perf/builtin-annotate.c +++ b/trunk/tools/perf/builtin-annotate.c @@ -17,13 +17,16 @@ #include "util/string.h" #include "perf.h" -#include "util/debug.h" #include "util/parse-options.h" #include "util/parse-events.h" -#include "util/thread.h" + +#define SHOW_KERNEL 1 +#define SHOW_USER 2 +#define SHOW_HV 4 static char const *input_name = "perf.data"; +static char *vmlinux = "vmlinux"; static char default_sort_order[] = "comm,symbol"; static char *sort_order = default_sort_order; @@ -31,6 +34,13 @@ static char *sort_order = default_sort_order; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; +static int dump_trace = 0; +#define dprintf(x...) do { if (dump_trace) printf(x); } while (0) + +static int verbose; + +static int modules; + static int full_paths; static int print_line; @@ -38,8 +48,39 @@ static int print_line; static unsigned long page_size; static unsigned long mmap_window = 32; -static struct rb_root threads; -static struct thread *last_match; +struct ip_event { + struct perf_event_header header; + u64 ip; + u32 pid, tid; +}; + +struct mmap_event { + struct perf_event_header header; + u32 pid, tid; + u64 start; + u64 len; + u64 pgoff; + char filename[PATH_MAX]; +}; + +struct comm_event { + struct perf_event_header header; + u32 pid, tid; + char comm[16]; +}; + +struct fork_event { + struct perf_event_header header; + u32 pid, ppid; +}; + +typedef union event_union { + struct perf_event_header header; + struct ip_event ip; + struct mmap_event mmap; + struct comm_event comm; + struct fork_event fork; +} event_t; struct sym_ext { @@ -48,6 +89,323 @@ struct sym_ext { char *path; }; +static LIST_HEAD(dsos); +static struct dso *kernel_dso; +static struct dso *vdso; + + +static void dsos__add(struct dso *dso) +{ + list_add_tail(&dso->node, &dsos); +} + +static struct dso *dsos__find(const char *name) +{ + struct dso *pos; + + list_for_each_entry(pos, &dsos, node) + if (strcmp(pos->name, name) == 0) + return pos; + return NULL; +} + +static struct dso *dsos__findnew(const char *name) +{ + struct dso *dso = dsos__find(name); + int nr; + + if (dso) + return dso; + + dso = dso__new(name, 0); + if (!dso) + goto out_delete_dso; + + nr = dso__load(dso, NULL, verbose); + if (nr < 0) { + if (verbose) + fprintf(stderr, "Failed to open: %s\n", name); + goto out_delete_dso; + } + if (!nr && verbose) { + fprintf(stderr, + "No symbols found in: %s, maybe install a debug package?\n", + name); + } + + dsos__add(dso); + + return dso; + +out_delete_dso: + dso__delete(dso); + return NULL; +} + +static void dsos__fprintf(FILE *fp) +{ + struct dso *pos; + + list_for_each_entry(pos, &dsos, node) + dso__fprintf(pos, fp); +} + +static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) +{ + return dso__find_symbol(dso, ip); +} + +static int load_kernel(void) +{ + int err; + + kernel_dso = dso__new("[kernel]", 0); + if (!kernel_dso) + return -1; + + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); + if (err <= 0) { + dso__delete(kernel_dso); + kernel_dso = NULL; + } else + dsos__add(kernel_dso); + + vdso = dso__new("[vdso]", 0); + if (!vdso) + return -1; + + vdso->find_symbol = vdso__find_symbol; + + dsos__add(vdso); + + return err; +} + +struct map { + struct list_head node; + u64 start; + u64 end; + u64 pgoff; + u64 (*map_ip)(struct map *, u64); + struct dso *dso; +}; + +static u64 map__map_ip(struct map *map, u64 ip) +{ + return ip - map->start + map->pgoff; +} + +static u64 vdso__map_ip(struct map *map __used, u64 ip) +{ + return ip; +} + +static struct map *map__new(struct mmap_event *event) +{ + struct map *self = malloc(sizeof(*self)); + + if (self != NULL) { + const char *filename = event->filename; + + self->start = event->start; + self->end = event->start + event->len; + self->pgoff = event->pgoff; + + self->dso = dsos__findnew(filename); + if (self->dso == NULL) + goto out_delete; + + if (self->dso == vdso) + self->map_ip = vdso__map_ip; + else + self->map_ip = map__map_ip; + } + return self; +out_delete: + free(self); + return NULL; +} + +static struct map *map__clone(struct map *self) +{ + struct map *map = malloc(sizeof(*self)); + + if (!map) + return NULL; + + memcpy(map, self, sizeof(*self)); + + return map; +} + +static int map__overlap(struct map *l, struct map *r) +{ + if (l->start > r->start) { + struct map *t = l; + l = r; + r = t; + } + + if (l->end > r->start) + return 1; + + return 0; +} + +static size_t map__fprintf(struct map *self, FILE *fp) +{ + return fprintf(fp, " %Lx-%Lx %Lx %s\n", + self->start, self->end, self->pgoff, self->dso->name); +} + + +struct thread { + struct rb_node rb_node; + struct list_head maps; + pid_t pid; + char *comm; +}; + +static struct thread *thread__new(pid_t pid) +{ + struct thread *self = malloc(sizeof(*self)); + + if (self != NULL) { + self->pid = pid; + self->comm = malloc(32); + if (self->comm) + snprintf(self->comm, 32, ":%d", self->pid); + INIT_LIST_HEAD(&self->maps); + } + + return self; +} + +static int thread__set_comm(struct thread *self, const char *comm) +{ + if (self->comm) + free(self->comm); + self->comm = strdup(comm); + return self->comm ? 0 : -ENOMEM; +} + +static size_t thread__fprintf(struct thread *self, FILE *fp) +{ + struct map *pos; + size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); + + list_for_each_entry(pos, &self->maps, node) + ret += map__fprintf(pos, fp); + + return ret; +} + + +static struct rb_root threads; +static struct thread *last_match; + +static struct thread *threads__findnew(pid_t pid) +{ + struct rb_node **p = &threads.rb_node; + struct rb_node *parent = NULL; + struct thread *th; + + /* + * Font-end cache - PID lookups come in blocks, + * so most of the time we dont have to look up + * the full rbtree: + */ + if (last_match && last_match->pid == pid) + return last_match; + + while (*p != NULL) { + parent = *p; + th = rb_entry(parent, struct thread, rb_node); + + if (th->pid == pid) { + last_match = th; + return th; + } + + if (pid < th->pid) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + th = thread__new(pid); + if (th != NULL) { + rb_link_node(&th->rb_node, parent, p); + rb_insert_color(&th->rb_node, &threads); + last_match = th; + } + + return th; +} + +static void thread__insert_map(struct thread *self, struct map *map) +{ + struct map *pos, *tmp; + + list_for_each_entry_safe(pos, tmp, &self->maps, node) { + if (map__overlap(pos, map)) { + list_del_init(&pos->node); + /* XXX leaks dsos */ + free(pos); + } + } + + list_add_tail(&map->node, &self->maps); +} + +static int thread__fork(struct thread *self, struct thread *parent) +{ + struct map *map; + + if (self->comm) + free(self->comm); + self->comm = strdup(parent->comm); + if (!self->comm) + return -ENOMEM; + + list_for_each_entry(map, &parent->maps, node) { + struct map *new = map__clone(map); + if (!new) + return -ENOMEM; + thread__insert_map(self, new); + } + + return 0; +} + +static struct map *thread__find_map(struct thread *self, u64 ip) +{ + struct map *pos; + + if (self == NULL) + return NULL; + + list_for_each_entry(pos, &self->maps, node) + if (ip >= pos->start && ip <= pos->end) + return pos; + + return NULL; +} + +static size_t threads__fprintf(FILE *fp) +{ + size_t ret = 0; + struct rb_node *nd; + + for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { + struct thread *pos = rb_entry(nd, struct thread, rb_node); + + ret += thread__fprintf(pos, fp); + } + + return ret; +} + /* * histogram, sorted on item, collects counts */ @@ -74,7 +432,7 @@ struct hist_entry { struct sort_entry { struct list_head list; - const char *header; + char *header; int64_t (*cmp)(struct hist_entry *, struct hist_entry *); int64_t (*collapse)(struct hist_entry *, struct hist_entry *); @@ -218,7 +576,7 @@ static struct sort_entry sort_sym = { static int sort__need_collapse = 0; struct sort_dimension { - const char *name; + char *name; struct sort_entry *entry; int taken; }; @@ -473,7 +831,7 @@ static void output__resort(void) static void register_idle_thread(void) { - struct thread *thread = threads__findnew(0, &threads, &last_match); + struct thread *thread = threads__findnew(0); if (thread == NULL || thread__set_comm(thread, "[idle]")) { @@ -494,20 +852,18 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) char level; int show = 0; struct dso *dso = NULL; - struct thread *thread; + struct thread *thread = threads__findnew(event->ip.pid); u64 ip = event->ip.ip; struct map *map = NULL; - thread = threads__findnew(event->ip.pid, &threads, &last_match); - - dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", + dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", (void *)(offset + head), (void *)(long)(event->header.size), event->header.misc, event->ip.pid, (void *)(long)ip); - dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); + dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); if (thread == NULL) { fprintf(stderr, "problem processing %d event, skipping it.\n", @@ -521,7 +877,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) dso = kernel_dso; - dump_printf(" ...... dso: %s\n", dso->name); + dprintf(" ...... dso: %s\n", dso->name); } else if (event->header.misc & PERF_EVENT_MISC_USER) { @@ -542,12 +898,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) if ((long long)ip < 0) dso = kernel_dso; } - dump_printf(" ...... dso: %s\n", dso ? dso->name : ""); + dprintf(" ...... dso: %s\n", dso ? dso->name : ""); } else { show = SHOW_HV; level = 'H'; - dump_printf(" ...... dso: [hypervisor]\n"); + dprintf(" ...... dso: [hypervisor]\n"); } if (show & show_mask) { @@ -570,12 +926,10 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) static int process_mmap_event(event_t *event, unsigned long offset, unsigned long head) { - struct thread *thread; - struct map *map = map__new(&event->mmap, NULL, 0); - - thread = threads__findnew(event->mmap.pid, &threads, &last_match); + struct thread *thread = threads__findnew(event->mmap.pid); + struct map *map = map__new(&event->mmap); - dump_printf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", + dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", (void *)(offset + head), (void *)(long)(event->header.size), event->mmap.pid, @@ -585,7 +939,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head) event->mmap.filename); if (thread == NULL || map == NULL) { - dump_printf("problem processing PERF_EVENT_MMAP, skipping event.\n"); + dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); return 0; } @@ -598,17 +952,16 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head) static int process_comm_event(event_t *event, unsigned long offset, unsigned long head) { - struct thread *thread; + struct thread *thread = threads__findnew(event->comm.pid); - thread = threads__findnew(event->comm.pid, &threads, &last_match); - dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", + dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", (void *)(offset + head), (void *)(long)(event->header.size), event->comm.comm, event->comm.pid); if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { - dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n"); + dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); return -1; } total_comm++; @@ -619,18 +972,16 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head) static int process_fork_event(event_t *event, unsigned long offset, unsigned long head) { - struct thread *thread; - struct thread *parent; + struct thread *thread = threads__findnew(event->fork.pid); + struct thread *parent = threads__findnew(event->fork.ppid); - thread = threads__findnew(event->fork.pid, &threads, &last_match); - parent = threads__findnew(event->fork.ppid, &threads, &last_match); - dump_printf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", + dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", (void *)(offset + head), (void *)(long)(event->header.size), event->fork.pid, event->fork.ppid); if (!thread || !parent || thread__fork(thread, parent)) { - dump_printf("problem processing PERF_EVENT_FORK, skipping event.\n"); + dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); return -1; } total_fork++; @@ -716,7 +1067,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) const char *path = NULL; unsigned int hits = 0; double percent = 0.0; - const char *color; + char *color; struct sym_ext *sym_ext = sym->priv; offset = line_ip - start; @@ -798,7 +1149,7 @@ static void free_source_line(struct symbol *sym, int len) /* Get the filename:line for the colored entries */ static void -get_source_line(struct symbol *sym, u64 start, int len, const char *filename) +get_source_line(struct symbol *sym, u64 start, int len, char *filename) { int i; char cmd[PATH_MAX * 2]; @@ -844,7 +1195,7 @@ get_source_line(struct symbol *sym, u64 start, int len, const char *filename) } } -static void print_summary(const char *filename) +static void print_summary(char *filename) { struct sym_ext *sym_ext; struct rb_node *node; @@ -860,7 +1211,7 @@ static void print_summary(const char *filename) node = rb_first(&root_sym_ext); while (node) { double percent; - const char *color; + char *color; char *path; sym_ext = rb_entry(node, struct sym_ext, node); @@ -875,7 +1226,7 @@ static void print_summary(const char *filename) static void annotate_sym(struct dso *dso, struct symbol *sym) { - const char *filename = dso->name, *d_filename; + char *filename = dso->name, *d_filename; u64 start, end, len; char command[PATH_MAX*2]; FILE *file; @@ -885,7 +1236,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) if (sym->module) filename = sym->module->path; else if (dso == kernel_dso) - filename = vmlinux_name; + filename = vmlinux; start = sym->obj_start; if (!start) @@ -957,7 +1308,7 @@ static int __cmd_annotate(void) int ret, rc = EXIT_FAILURE; unsigned long offset = 0; unsigned long head = 0; - struct stat input_stat; + struct stat stat; event_t *event; uint32_t size; char *buf; @@ -970,13 +1321,13 @@ static int __cmd_annotate(void) exit(-1); } - ret = fstat(input, &input_stat); + ret = fstat(input, &stat); if (ret < 0) { perror("failed to stat file"); exit(-1); } - if (!input_stat.st_size) { + if (!stat.st_size) { fprintf(stderr, "zero-sized file, nothing to do!\n"); exit(0); } @@ -1003,10 +1354,10 @@ static int __cmd_annotate(void) if (head + event->header.size >= page_size * mmap_window) { unsigned long shift = page_size * (head / page_size); - int munmap_ret; + int ret; - munmap_ret = munmap(buf, page_size * mmap_window); - assert(munmap_ret == 0); + ret = munmap(buf, page_size * mmap_window); + assert(ret == 0); offset += shift; head -= shift; @@ -1015,14 +1366,14 @@ static int __cmd_annotate(void) size = event->header.size; - dump_printf("%p [%p]: event: %d\n", + dprintf("%p [%p]: event: %d\n", (void *)(offset + head), (void *)(long)event->header.size, event->header.type); if (!size || process_event(event, offset, head) < 0) { - dump_printf("%p [%p]: skipping unknown header type: %d\n", + dprintf("%p [%p]: skipping unknown header type: %d\n", (void *)(offset + head), (void *)(long)(event->header.size), event->header.type); @@ -1042,23 +1393,23 @@ static int __cmd_annotate(void) head += size; - if (offset + head < (unsigned long)input_stat.st_size) + if (offset + head < (unsigned long)stat.st_size) goto more; rc = EXIT_SUCCESS; close(input); - dump_printf(" IP events: %10ld\n", total); - dump_printf(" mmap events: %10ld\n", total_mmap); - dump_printf(" comm events: %10ld\n", total_comm); - dump_printf(" fork events: %10ld\n", total_fork); - dump_printf(" unknown events: %10ld\n", total_unknown); + dprintf(" IP events: %10ld\n", total); + dprintf(" mmap events: %10ld\n", total_mmap); + dprintf(" comm events: %10ld\n", total_comm); + dprintf(" fork events: %10ld\n", total_fork); + dprintf(" unknown events: %10ld\n", total_unknown); if (dump_trace) return 0; if (verbose >= 3) - threads__fprintf(stdout, &threads); + threads__fprintf(stdout); if (verbose >= 2) dsos__fprintf(stdout); @@ -1085,7 +1436,7 @@ static const struct option options[] = { "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), - OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), + OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), OPT_BOOLEAN('m', "modules", &modules, "load module symbols - WARNING: use only with -k and LIVE kernel"), OPT_BOOLEAN('l', "print-line", &print_line, diff --git a/trunk/tools/perf/builtin-help.c b/trunk/tools/perf/builtin-help.c index 4fb8734a796e..2599d86a733b 100644 --- a/trunk/tools/perf/builtin-help.c +++ b/trunk/tools/perf/builtin-help.c @@ -456,7 +456,6 @@ int cmd_help(int argc, const char **argv, const char *prefix __used) break; case HELP_FORMAT_WEB: show_html_page(argv[0]); - default: break; } diff --git a/trunk/tools/perf/builtin-record.c b/trunk/tools/perf/builtin-record.c index 6a5db675ee4f..3d051b9cf25f 100644 --- a/trunk/tools/perf/builtin-record.c +++ b/trunk/tools/perf/builtin-record.c @@ -15,8 +15,6 @@ #include "util/string.h" #include "util/header.h" -#include "util/event.h" -#include "util/debug.h" #include #include @@ -44,6 +42,7 @@ static int inherit = 1; static int force = 0; static int append_file = 0; static int call_graph = 0; +static int verbose = 0; static int inherit_stat = 0; static int no_samples = 0; static int sample_address = 0; @@ -63,6 +62,24 @@ static int file_new = 1; struct perf_header *header; +struct mmap_event { + struct perf_event_header header; + u32 pid; + u32 tid; + u64 start; + u64 len; + u64 pgoff; + char filename[PATH_MAX]; +}; + +struct comm_event { + struct perf_event_header header; + u32 pid; + u32 tid; + char comm[16]; +}; + + struct mmap_data { int counter; void *base; @@ -202,7 +219,7 @@ static pid_t pid_synthesize_comm_event(pid_t pid, int full) snprintf(filename, sizeof(filename), "/proc/%d/status", pid); fp = fopen(filename, "r"); - if (fp == NULL) { + if (fd == NULL) { /* * We raced with a task exiting - just return: */ diff --git a/trunk/tools/perf/builtin-report.c b/trunk/tools/perf/builtin-report.c index 1e3ad22d53dc..b53a60fc12de 100644 --- a/trunk/tools/perf/builtin-report.c +++ b/trunk/tools/perf/builtin-report.c @@ -17,18 +17,19 @@ #include "util/string.h" #include "util/callchain.h" #include "util/strlist.h" -#include "util/values.h" #include "perf.h" -#include "util/debug.h" #include "util/header.h" #include "util/parse-options.h" #include "util/parse-events.h" -#include "util/thread.h" +#define SHOW_KERNEL 1 +#define SHOW_USER 2 +#define SHOW_HV 4 static char const *input_name = "perf.data"; +static char *vmlinux = NULL; static char default_sort_order[] = "comm,dso,symbol"; static char *sort_order = default_sort_order; @@ -40,14 +41,17 @@ static char *field_sep; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; -static int full_paths; -static int show_nr_samples; +static int dump_trace = 0; +#define dprintf(x...) do { if (dump_trace) printf(x); } while (0) +#define cdprintf(x...) do { if (dump_trace) color_fprintf(stdout, color, x); } while (0) -static int show_threads; -static struct perf_read_values show_threads_values; +static int verbose; +#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) -static char default_pretty_printing_style[] = "normal"; -static char *pretty_printing_style = default_pretty_printing_style; +static int modules; + +static int full_paths; +static int show_nr_samples; static unsigned long page_size; static unsigned long mmap_window = 32; @@ -62,15 +66,6 @@ static char callchain_default_opt[] = "fractal,0.5"; static int callchain; -static char __cwd[PATH_MAX]; -static char *cwd = __cwd; -static int cwdlen; - -static struct rb_root threads; -static struct thread *last_match; - -static struct perf_header *header; - static struct callchain_param callchain_param = { .mode = CHAIN_GRAPH_REL, @@ -79,6 +74,59 @@ struct callchain_param callchain_param = { static u64 sample_type; +struct ip_event { + struct perf_event_header header; + u64 ip; + u32 pid, tid; + unsigned char __more_data[]; +}; + +struct mmap_event { + struct perf_event_header header; + u32 pid, tid; + u64 start; + u64 len; + u64 pgoff; + char filename[PATH_MAX]; +}; + +struct comm_event { + struct perf_event_header header; + u32 pid, tid; + char comm[16]; +}; + +struct fork_event { + struct perf_event_header header; + u32 pid, ppid; + u32 tid, ptid; +}; + +struct lost_event { + struct perf_event_header header; + u64 id; + u64 lost; +}; + +struct read_event { + struct perf_event_header header; + u32 pid,tid; + u64 value; + u64 time_enabled; + u64 time_running; + u64 id; +}; + +typedef union event_union { + struct perf_event_header header; + struct ip_event ip; + struct mmap_event mmap; + struct comm_event comm; + struct fork_event fork; + struct lost_event lost; + struct read_event read; +} event_t; + static int repsep_fprintf(FILE *fp, const char *fmt, ...) { int n; @@ -92,7 +140,6 @@ static int repsep_fprintf(FILE *fp, const char *fmt, ...) n = vasprintf(&bf, fmt, ap); if (n > 0) { char *sep = bf; - while (1) { sep = strchr(sep, *field_sep); if (sep == NULL) @@ -107,10 +154,396 @@ static int repsep_fprintf(FILE *fp, const char *fmt, ...) return n; } +static LIST_HEAD(dsos); +static struct dso *kernel_dso; +static struct dso *vdso; +static struct dso *hypervisor_dso; + +static void dsos__add(struct dso *dso) +{ + list_add_tail(&dso->node, &dsos); +} + +static struct dso *dsos__find(const char *name) +{ + struct dso *pos; + + list_for_each_entry(pos, &dsos, node) + if (strcmp(pos->name, name) == 0) + return pos; + return NULL; +} + +static struct dso *dsos__findnew(const char *name) +{ + struct dso *dso = dsos__find(name); + int nr; + + if (dso) + return dso; + + dso = dso__new(name, 0); + if (!dso) + goto out_delete_dso; + + nr = dso__load(dso, NULL, verbose); + if (nr < 0) { + eprintf("Failed to open: %s\n", name); + goto out_delete_dso; + } + if (!nr) + eprintf("No symbols found in: %s, maybe install a debug package?\n", name); + + dsos__add(dso); + + return dso; + +out_delete_dso: + dso__delete(dso); + return NULL; +} + +static void dsos__fprintf(FILE *fp) +{ + struct dso *pos; + + list_for_each_entry(pos, &dsos, node) + dso__fprintf(pos, fp); +} + +static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) +{ + return dso__find_symbol(dso, ip); +} + +static int load_kernel(void) +{ + int err; + + kernel_dso = dso__new("[kernel]", 0); + if (!kernel_dso) + return -1; + + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); + if (err <= 0) { + dso__delete(kernel_dso); + kernel_dso = NULL; + } else + dsos__add(kernel_dso); + + vdso = dso__new("[vdso]", 0); + if (!vdso) + return -1; + + vdso->find_symbol = vdso__find_symbol; + + dsos__add(vdso); + + hypervisor_dso = dso__new("[hypervisor]", 0); + if (!hypervisor_dso) + return -1; + dsos__add(hypervisor_dso); + + return err; +} + +static char __cwd[PATH_MAX]; +static char *cwd = __cwd; +static int cwdlen; + +static int strcommon(const char *pathname) +{ + int n = 0; + + while (n < cwdlen && pathname[n] == cwd[n]) + ++n; + + return n; +} + +struct map { + struct list_head node; + u64 start; + u64 end; + u64 pgoff; + u64 (*map_ip)(struct map *, u64); + struct dso *dso; +}; + +static u64 map__map_ip(struct map *map, u64 ip) +{ + return ip - map->start + map->pgoff; +} + +static u64 vdso__map_ip(struct map *map __used, u64 ip) +{ + return ip; +} + +static inline int is_anon_memory(const char *filename) +{ + return strcmp(filename, "//anon") == 0; +} + +static struct map *map__new(struct mmap_event *event) +{ + struct map *self = malloc(sizeof(*self)); + + if (self != NULL) { + const char *filename = event->filename; + char newfilename[PATH_MAX]; + int anon; + + if (cwd) { + int n = strcommon(filename); + + if (n == cwdlen) { + snprintf(newfilename, sizeof(newfilename), + ".%s", filename + n); + filename = newfilename; + } + } + + anon = is_anon_memory(filename); + + if (anon) { + snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); + filename = newfilename; + } + + self->start = event->start; + self->end = event->start + event->len; + self->pgoff = event->pgoff; + + self->dso = dsos__findnew(filename); + if (self->dso == NULL) + goto out_delete; + + if (self->dso == vdso || anon) + self->map_ip = vdso__map_ip; + else + self->map_ip = map__map_ip; + } + return self; +out_delete: + free(self); + return NULL; +} + +static struct map *map__clone(struct map *self) +{ + struct map *map = malloc(sizeof(*self)); + + if (!map) + return NULL; + + memcpy(map, self, sizeof(*self)); + + return map; +} + +static int map__overlap(struct map *l, struct map *r) +{ + if (l->start > r->start) { + struct map *t = l; + l = r; + r = t; + } + + if (l->end > r->start) + return 1; + + return 0; +} + +static size_t map__fprintf(struct map *self, FILE *fp) +{ + return fprintf(fp, " %Lx-%Lx %Lx %s\n", + self->start, self->end, self->pgoff, self->dso->name); +} + + +struct thread { + struct rb_node rb_node; + struct list_head maps; + pid_t pid; + char *comm; +}; + +static struct thread *thread__new(pid_t pid) +{ + struct thread *self = malloc(sizeof(*self)); + + if (self != NULL) { + self->pid = pid; + self->comm = malloc(32); + if (self->comm) + snprintf(self->comm, 32, ":%d", self->pid); + INIT_LIST_HEAD(&self->maps); + } + + return self; +} + static unsigned int dsos__col_width, comms__col_width, threads__col_width; +static int thread__set_comm(struct thread *self, const char *comm) +{ + if (self->comm) + free(self->comm); + self->comm = strdup(comm); + if (!self->comm) + return -ENOMEM; + + if (!col_width_list_str && !field_sep && + (!comm_list || strlist__has_entry(comm_list, comm))) { + unsigned int slen = strlen(comm); + if (slen > comms__col_width) { + comms__col_width = slen; + threads__col_width = slen + 6; + } + } + + return 0; +} + +static size_t thread__fprintf(struct thread *self, FILE *fp) +{ + struct map *pos; + size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); + + list_for_each_entry(pos, &self->maps, node) + ret += map__fprintf(pos, fp); + + return ret; +} + + +static struct rb_root threads; +static struct thread *last_match; + +static struct thread *threads__findnew(pid_t pid) +{ + struct rb_node **p = &threads.rb_node; + struct rb_node *parent = NULL; + struct thread *th; + + /* + * Font-end cache - PID lookups come in blocks, + * so most of the time we dont have to look up + * the full rbtree: + */ + if (last_match && last_match->pid == pid) + return last_match; + + while (*p != NULL) { + parent = *p; + th = rb_entry(parent, struct thread, rb_node); + + if (th->pid == pid) { + last_match = th; + return th; + } + + if (pid < th->pid) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + th = thread__new(pid); + if (th != NULL) { + rb_link_node(&th->rb_node, parent, p); + rb_insert_color(&th->rb_node, &threads); + last_match = th; + } + + return th; +} + +static void thread__insert_map(struct thread *self, struct map *map) +{ + struct map *pos, *tmp; + + list_for_each_entry_safe(pos, tmp, &self->maps, node) { + if (map__overlap(pos, map)) { + if (verbose >= 2) { + printf("overlapping maps:\n"); + map__fprintf(map, stdout); + map__fprintf(pos, stdout); + } + + if (map->start <= pos->start && map->end > pos->start) + pos->start = map->end; + + if (map->end >= pos->end && map->start < pos->end) + pos->end = map->start; + + if (verbose >= 2) { + printf("after collision:\n"); + map__fprintf(pos, stdout); + } + + if (pos->start >= pos->end) { + list_del_init(&pos->node); + free(pos); + } + } + } + + list_add_tail(&map->node, &self->maps); +} + +static int thread__fork(struct thread *self, struct thread *parent) +{ + struct map *map; + + if (self->comm) + free(self->comm); + self->comm = strdup(parent->comm); + if (!self->comm) + return -ENOMEM; + + list_for_each_entry(map, &parent->maps, node) { + struct map *new = map__clone(map); + if (!new) + return -ENOMEM; + thread__insert_map(self, new); + } + + return 0; +} + +static struct map *thread__find_map(struct thread *self, u64 ip) +{ + struct map *pos; + + if (self == NULL) + return NULL; + + list_for_each_entry(pos, &self->maps, node) + if (ip >= pos->start && ip <= pos->end) + return pos; + + return NULL; +} + +static size_t threads__fprintf(FILE *fp) +{ + size_t ret = 0; + struct rb_node *nd; + + for (nd = rb_first(&threads); nd; nd = rb_next(nd)) { + struct thread *pos = rb_entry(nd, struct thread, rb_node); + + ret += thread__fprintf(pos, fp); + } + + return ret; +} + /* * histogram, sorted on item, collects counts */ @@ -140,7 +573,7 @@ struct hist_entry { struct sort_entry { struct list_head list; - const char *header; + char *header; int64_t (*cmp)(struct hist_entry *, struct hist_entry *); int64_t (*collapse)(struct hist_entry *, struct hist_entry *); @@ -324,7 +757,7 @@ static int sort__need_collapse = 0; static int sort__has_parent = 0; struct sort_dimension { - const char *name; + char *name; struct sort_entry *entry; int taken; }; @@ -339,7 +772,7 @@ static struct sort_dimension sort_dimensions[] = { static LIST_HEAD(hist_entry__sort_list); -static int sort_dimension__add(const char *tok) +static int sort_dimension__add(char *tok) { unsigned int i; @@ -598,7 +1031,6 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, case CHAIN_GRAPH_REL: ret += callchain__fprintf_graph(fp, chain, total_samples, 1, 1); - case CHAIN_NONE: default: break; } @@ -708,8 +1140,8 @@ resolve_symbol(struct thread *thread, struct map **mapp, if ((long long)ip < 0) dso = kernel_dso; } - dump_printf(" ...... dso: %s\n", dso ? dso->name : ""); - dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); + dprintf(" ...... dso: %s\n", dso ? dso->name : ""); + dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip); *ipp = ip; if (dsop) @@ -965,9 +1397,6 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) size_t ret = 0; unsigned int width; char *col_width = col_width_list_str; - int raw_printing_style; - - raw_printing_style = !strcmp(pretty_printing_style, "raw"); init_rem_hits(); @@ -1044,16 +1473,12 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) free(rem_sq_bracket); - if (show_threads) - perf_read_values_display(fp, &show_threads_values, - raw_printing_style); - return ret; } static void register_idle_thread(void) { - struct thread *thread = threads__findnew(0, &threads, &last_match); + struct thread *thread = threads__findnew(0); if (thread == NULL || thread__set_comm(thread, "[idle]")) { @@ -1088,7 +1513,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) char level; int show = 0; struct dso *dso = NULL; - struct thread *thread; + struct thread *thread = threads__findnew(event->ip.pid); u64 ip = event->ip.ip; u64 period = 1; struct map *map = NULL; @@ -1096,14 +1521,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) struct ip_callchain *chain = NULL; int cpumode; - thread = threads__findnew(event->ip.pid, &threads, &last_match); - if (sample_type & PERF_SAMPLE_PERIOD) { period = *(u64 *)more_data; more_data += sizeof(u64); } - dump_printf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", + dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", (void *)(offset + head), (void *)(long)(event->header.size), event->header.misc, @@ -1116,7 +1539,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) chain = (void *)more_data; - dump_printf("... chain: nr:%Lu\n", chain->nr); + dprintf("... chain: nr:%Lu\n", chain->nr); if (validate_chain(chain, event) < 0) { eprintf("call-chain problem with event, skipping it.\n"); @@ -1125,11 +1548,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) if (dump_trace) { for (i = 0; i < chain->nr; i++) - dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]); + dprintf("..... %2d: %016Lx\n", i, chain->ips[i]); } } - dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); + dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); if (thread == NULL) { eprintf("problem processing %d event, skipping it.\n", @@ -1148,7 +1571,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) dso = kernel_dso; - dump_printf(" ...... dso: %s\n", dso->name); + dprintf(" ...... dso: %s\n", dso->name); } else if (cpumode == PERF_EVENT_MISC_USER) { @@ -1161,7 +1584,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) dso = hypervisor_dso; - dump_printf(" ...... dso: [hypervisor]\n"); + dprintf(" ...... dso: [hypervisor]\n"); } if (show & show_mask) { @@ -1187,12 +1610,10 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) static int process_mmap_event(event_t *event, unsigned long offset, unsigned long head) { - struct thread *thread; - struct map *map = map__new(&event->mmap, cwd, cwdlen); + struct thread *thread = threads__findnew(event->mmap.pid); + struct map *map = map__new(&event->mmap); - thread = threads__findnew(event->mmap.pid, &threads, &last_match); - - dump_printf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n", + dprintf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n", (void *)(offset + head), (void *)(long)(event->header.size), event->mmap.pid, @@ -1203,7 +1624,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head) event->mmap.filename); if (thread == NULL || map == NULL) { - dump_printf("problem processing PERF_EVENT_MMAP, skipping event.\n"); + dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); return 0; } @@ -1216,18 +1637,16 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head) static int process_comm_event(event_t *event, unsigned long offset, unsigned long head) { - struct thread *thread; - - thread = threads__findnew(event->comm.pid, &threads, &last_match); + struct thread *thread = threads__findnew(event->comm.pid); - dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", + dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", (void *)(offset + head), (void *)(long)(event->header.size), event->comm.comm, event->comm.pid); if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { - dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n"); + dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); return -1; } total_comm++; @@ -1238,13 +1657,10 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head) static int process_task_event(event_t *event, unsigned long offset, unsigned long head) { - struct thread *thread; - struct thread *parent; + struct thread *thread = threads__findnew(event->fork.pid); + struct thread *parent = threads__findnew(event->fork.ppid); - thread = threads__findnew(event->fork.pid, &threads, &last_match); - parent = threads__findnew(event->fork.ppid, &threads, &last_match); - - dump_printf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n", + dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n", (void *)(offset + head), (void *)(long)(event->header.size), event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT", @@ -1262,7 +1678,7 @@ process_task_event(event_t *event, unsigned long offset, unsigned long head) return 0; if (!thread || !parent || thread__fork(thread, parent)) { - dump_printf("problem processing PERF_EVENT_FORK, skipping event.\n"); + dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); return -1; } total_fork++; @@ -1273,7 +1689,7 @@ process_task_event(event_t *event, unsigned long offset, unsigned long head) static int process_lost_event(event_t *event, unsigned long offset, unsigned long head) { - dump_printf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", + dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", (void *)(offset + head), (void *)(long)(event->header.size), event->lost.id, @@ -1284,24 +1700,67 @@ process_lost_event(event_t *event, unsigned long offset, unsigned long head) return 0; } -static int -process_read_event(event_t *event, unsigned long offset, unsigned long head) +static void trace_event(event_t *event) { - struct perf_counter_attr *attr; + unsigned char *raw_event = (void *)event; + char *color = PERF_COLOR_BLUE; + int i, j; + + if (!dump_trace) + return; - attr = perf_header__find_attr(event->read.id, header); + dprintf("."); + cdprintf("\n. ... raw event: size %d bytes\n", event->header.size); - if (show_threads) { - const char *name = attr ? __event_name(attr->type, attr->config) - : "unknown"; - perf_read_values_add_value(&show_threads_values, - event->read.pid, event->read.tid, - event->read.id, - name, - event->read.value); + for (i = 0; i < event->header.size; i++) { + if ((i & 15) == 0) { + dprintf("."); + cdprintf(" %04x: ", i); + } + + cdprintf(" %02x", raw_event[i]); + + if (((i & 15) == 15) || i == event->header.size-1) { + cdprintf(" "); + for (j = 0; j < 15-(i & 15); j++) + cdprintf(" "); + for (j = 0; j < (i & 15); j++) { + if (isprint(raw_event[i-15+j])) + cdprintf("%c", raw_event[i-15+j]); + else + cdprintf("."); + } + cdprintf("\n"); + } } + dprintf(".\n"); +} + +static struct perf_header *header; + +static struct perf_counter_attr *perf_header__find_attr(u64 id) +{ + int i; + + for (i = 0; i < header->attrs; i++) { + struct perf_header_attr *attr = header->attr[i]; + int j; + + for (j = 0; j < attr->ids; j++) { + if (attr->id[j] == id) + return &attr->attr; + } + } + + return NULL; +} - dump_printf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n", +static int +process_read_event(event_t *event, unsigned long offset, unsigned long head) +{ + struct perf_counter_attr *attr = perf_header__find_attr(event->read.id); + + dprintf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n", (void *)(offset + head), (void *)(long)(event->header.size), event->read.pid, @@ -1353,21 +1812,35 @@ process_event(event_t *event, unsigned long offset, unsigned long head) return 0; } +static u64 perf_header__sample_type(void) +{ + u64 sample_type = 0; + int i; + + for (i = 0; i < header->attrs; i++) { + struct perf_header_attr *attr = header->attr[i]; + + if (!sample_type) + sample_type = attr->attr.sample_type; + else if (sample_type != attr->attr.sample_type) + die("non matching sample_type"); + } + + return sample_type; +} + static int __cmd_report(void) { int ret, rc = EXIT_FAILURE; unsigned long offset = 0; unsigned long head, shift; - struct stat input_stat; + struct stat stat; event_t *event; uint32_t size; char *buf; register_idle_thread(); - if (show_threads) - perf_read_values_init(&show_threads_values); - input = open(input_name, O_RDONLY); if (input < 0) { fprintf(stderr, " failed to open file: %s", input_name); @@ -1377,13 +1850,13 @@ static int __cmd_report(void) exit(-1); } - ret = fstat(input, &input_stat); + ret = fstat(input, &stat); if (ret < 0) { perror("failed to stat file"); exit(-1); } - if (!input_stat.st_size) { + if (!stat.st_size) { fprintf(stderr, "zero-sized file, nothing to do!\n"); exit(0); } @@ -1391,7 +1864,7 @@ static int __cmd_report(void) header = perf_header__read(input); head = header->data_offset; - sample_type = perf_header__sample_type(header); + sample_type = perf_header__sample_type(); if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { if (sort__has_parent) { @@ -1451,12 +1924,12 @@ static int __cmd_report(void) size = 8; if (head + event->header.size >= page_size * mmap_window) { - int munmap_ret; + int ret; shift = page_size * (head / page_size); - munmap_ret = munmap(buf, page_size * mmap_window); - assert(munmap_ret == 0); + ret = munmap(buf, page_size * mmap_window); + assert(ret == 0); offset += shift; head -= shift; @@ -1465,14 +1938,14 @@ static int __cmd_report(void) size = event->header.size; - dump_printf("\n%p [%p]: event: %d\n", + dprintf("\n%p [%p]: event: %d\n", (void *)(offset + head), (void *)(long)event->header.size, event->header.type); if (!size || process_event(event, offset, head) < 0) { - dump_printf("%p [%p]: skipping unknown header type: %d\n", + dprintf("%p [%p]: skipping unknown header type: %d\n", (void *)(offset + head), (void *)(long)(event->header.size), event->header.type); @@ -1495,25 +1968,25 @@ static int __cmd_report(void) if (offset + head >= header->data_offset + header->data_size) goto done; - if (offset + head < (unsigned long)input_stat.st_size) + if (offset + head < (unsigned long)stat.st_size) goto more; done: rc = EXIT_SUCCESS; close(input); - dump_printf(" IP events: %10ld\n", total); - dump_printf(" mmap events: %10ld\n", total_mmap); - dump_printf(" comm events: %10ld\n", total_comm); - dump_printf(" fork events: %10ld\n", total_fork); - dump_printf(" lost events: %10ld\n", total_lost); - dump_printf(" unknown events: %10ld\n", total_unknown); + dprintf(" IP events: %10ld\n", total); + dprintf(" mmap events: %10ld\n", total_mmap); + dprintf(" comm events: %10ld\n", total_comm); + dprintf(" fork events: %10ld\n", total_fork); + dprintf(" lost events: %10ld\n", total_lost); + dprintf(" unknown events: %10ld\n", total_unknown); if (dump_trace) return 0; if (verbose >= 3) - threads__fprintf(stdout, &threads); + threads__fprintf(stdout); if (verbose >= 2) dsos__fprintf(stdout); @@ -1522,9 +1995,6 @@ static int __cmd_report(void) output__resort(total); output__fprintf(stdout, total); - if (show_threads) - perf_read_values_destroy(&show_threads_values); - return rc; } @@ -1593,15 +2063,11 @@ static const struct option options[] = { "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), - OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), + OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), OPT_BOOLEAN('m', "modules", &modules, "load module symbols - WARNING: use only with -k and LIVE kernel"), OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples, "Show a column with the number of samples"), - OPT_BOOLEAN('T', "threads", &show_threads, - "Show per-thread event counters"), - OPT_STRING(0, "pretty", &pretty_printing_style, "key", - "pretty printing style key: normal raw"), OPT_STRING('s', "sort", &sort_order, "key[,key2...]", "sort by key(s): pid, comm, dso, symbol, parent"), OPT_BOOLEAN('P', "full-paths", &full_paths, diff --git a/trunk/tools/perf/builtin-stat.c b/trunk/tools/perf/builtin-stat.c index 1a2626230660..b4b06c7903e1 100644 --- a/trunk/tools/perf/builtin-stat.c +++ b/trunk/tools/perf/builtin-stat.c @@ -42,8 +42,6 @@ #include "util/util.h" #include "util/parse-options.h" #include "util/parse-events.h" -#include "util/event.h" -#include "util/debug.h" #include #include @@ -65,6 +63,7 @@ static struct perf_counter_attr default_attrs[] = { #define MAX_RUN 100 static int system_wide = 0; +static int verbose = 0; static unsigned int nr_cpus = 0; static int run_idx = 0; diff --git a/trunk/tools/perf/builtin-top.c b/trunk/tools/perf/builtin-top.c index 62b55ecab2c6..7de28ce9ca26 100644 --- a/trunk/tools/perf/builtin-top.c +++ b/trunk/tools/perf/builtin-top.c @@ -27,8 +27,6 @@ #include "util/parse-options.h" #include "util/parse-events.h" -#include "util/debug.h" - #include #include @@ -70,6 +68,8 @@ static int group = 0; static unsigned int page_size; static unsigned int mmap_pages = 16; static int freq = 0; +static int verbose = 0; +static char *vmlinux = NULL; static int delay_secs = 2; static int zero; @@ -122,8 +122,7 @@ static void parse_source(struct sym_entry *syme) struct module *module; struct section *section = NULL; FILE *file; - char command[PATH_MAX*2]; - const char *path = vmlinux_name; + char command[PATH_MAX*2], *path = vmlinux; u64 start, end, len; if (!syme) @@ -339,6 +338,8 @@ static void show_details(struct sym_entry *syme) printf("%d lines not displayed, maybe increase display entries [e]\n", more); } +struct dso *kernel_dso; + /* * Symbols will be added here in record_ip and will get out * after decayed. @@ -490,12 +491,10 @@ static void print_sym_table(void) ); for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { - struct symbol *sym; + struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); + struct symbol *sym = (struct symbol *)(syme + 1); double pcnt; - syme = rb_entry(nd, struct sym_entry, rb_node); - sym = (struct symbol *)(syme + 1); - if (++printed > print_entries || (int)syme->snap_count < count_filter) continue; @@ -614,7 +613,7 @@ static void print_mapped_keys(void) fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); - if (vmlinux_name) { + if (vmlinux) { fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); fprintf(stdout, "\t[S] stop annotation.\n"); @@ -643,9 +642,7 @@ static int key_mapped(int c) case 'F': case 's': case 'S': - return vmlinux_name ? 1 : 0; - default: - break; + return vmlinux ? 1 : 0; } return 0; @@ -731,8 +728,6 @@ static void handle_keypress(int c) case 'z': zero = ~zero; break; - default: - break; } } @@ -821,13 +816,13 @@ static int parse_symbols(void) { struct rb_node *node; struct symbol *sym; - int use_modules = vmlinux_name ? 1 : 0; + int modules = vmlinux ? 1 : 0; kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); if (kernel_dso == NULL) return -1; - if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0) + if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0) goto out_delete_dso; node = rb_first(&kernel_dso->syms); @@ -942,6 +937,26 @@ static void mmap_read_counter(struct mmap_data *md) last_read = this_read; for (; old != head;) { + struct ip_event { + struct perf_event_header header; + u64 ip; + u32 pid, target_pid; + }; + struct mmap_event { + struct perf_event_header header; + u32 pid, target_pid; + u64 start; + u64 len; + u64 pgoff; + char filename[PATH_MAX]; + }; + + typedef union event_union { + struct perf_event_header header; + struct ip_event ip; + struct mmap_event mmap; + } event_t; + event_t *event = (event_t *)&data[old & md->mask]; event_t event_copy; @@ -1123,7 +1138,7 @@ static const struct option options[] = { "system-wide collection from all CPUs"), OPT_INTEGER('C', "CPU", &profile_cpu, "CPU to profile on"), - OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), + OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), OPT_INTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_INTEGER('r', "realtime", &realtime_prio, diff --git a/trunk/tools/perf/builtin.h b/trunk/tools/perf/builtin.h index 3a63e41fb44e..51d168230ee7 100644 --- a/trunk/tools/perf/builtin.h +++ b/trunk/tools/perf/builtin.h @@ -22,6 +22,5 @@ extern int cmd_stat(int argc, const char **argv, const char *prefix); extern int cmd_top(int argc, const char **argv, const char *prefix); extern int cmd_version(int argc, const char **argv, const char *prefix); extern int cmd_list(int argc, const char **argv, const char *prefix); -extern int cmd_trace(int argc, const char **argv, const char *prefix); #endif diff --git a/trunk/tools/perf/util/abspath.c b/trunk/tools/perf/util/abspath.c index a791dd467261..61d33b81fc97 100644 --- a/trunk/tools/perf/util/abspath.c +++ b/trunk/tools/perf/util/abspath.c @@ -50,8 +50,7 @@ const char *make_absolute_path(const char *path) die ("Could not get current working directory"); if (last_elem) { - len = strlen(buf); - + int len = strlen(buf); if (len + strlen(last_elem) + 2 > PATH_MAX) die ("Too long path name: '%s/%s'", buf, last_elem); diff --git a/trunk/tools/perf/util/cache.h b/trunk/tools/perf/util/cache.h index 6f8ea9d210b6..4b50c412b9c5 100644 --- a/trunk/tools/perf/util/cache.h +++ b/trunk/tools/perf/util/cache.h @@ -52,6 +52,7 @@ extern const char *perf_mailmap_file; extern void maybe_flush_or_die(FILE *, const char *); extern int copy_fd(int ifd, int ofd); extern int copy_file(const char *dst, const char *src, int mode); +extern ssize_t read_in_full(int fd, void *buf, size_t count); extern ssize_t write_in_full(int fd, const void *buf, size_t count); extern void write_or_die(int fd, const void *buf, size_t count); extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg); diff --git a/trunk/tools/perf/util/callchain.c b/trunk/tools/perf/util/callchain.c index 3b8380f1b478..011473411642 100644 --- a/trunk/tools/perf/util/callchain.c +++ b/trunk/tools/perf/util/callchain.c @@ -50,7 +50,6 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, else p = &(*p)->rb_right; break; - case CHAIN_NONE: default: break; } @@ -144,7 +143,6 @@ int register_callchain_param(struct callchain_param *param) case CHAIN_FLAT: param->sort = sort_chain_flat; break; - case CHAIN_NONE: default: return -1; } diff --git a/trunk/tools/perf/util/callchain.h b/trunk/tools/perf/util/callchain.h index 43cf3ea9e088..a926ae4f5a16 100644 --- a/trunk/tools/perf/util/callchain.h +++ b/trunk/tools/perf/util/callchain.h @@ -4,7 +4,6 @@ #include "../perf.h" #include #include -#include "util.h" #include "symbol.h" enum chain_mode { diff --git a/trunk/tools/perf/util/color.c b/trunk/tools/perf/util/color.c index e88bca55a599..90a044d1fe7d 100644 --- a/trunk/tools/perf/util/color.c +++ b/trunk/tools/perf/util/color.c @@ -166,7 +166,7 @@ int perf_color_default_config(const char *var, const char *value, void *cb) return perf_default_config(var, value, cb); } -static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, +static int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args, const char *trail) { int r = 0; @@ -191,10 +191,6 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, return r; } -int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) -{ - return __color_vfprintf(fp, color, fmt, args, NULL); -} int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) @@ -203,7 +199,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) int r; va_start(args, fmt); - r = color_vfprintf(fp, color, fmt, args); + r = color_vfprintf(fp, color, fmt, args, NULL); va_end(args); return r; } @@ -213,7 +209,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) va_list args; int r; va_start(args, fmt); - r = __color_vfprintf(fp, color, fmt, args, "\n"); + r = color_vfprintf(fp, color, fmt, args, "\n"); va_end(args); return r; } @@ -246,9 +242,9 @@ int color_fwrite_lines(FILE *fp, const char *color, return 0; } -const char *get_percent_color(double percent) +char *get_percent_color(double percent) { - const char *color = PERF_COLOR_NORMAL; + char *color = PERF_COLOR_NORMAL; /* * We color high-overhead entries in red, mid-overhead @@ -267,7 +263,7 @@ const char *get_percent_color(double percent) int percent_color_fprintf(FILE *fp, const char *fmt, double percent) { int r; - const char *color; + char *color; color = get_percent_color(percent); r = color_fprintf(fp, color, fmt, percent); diff --git a/trunk/tools/perf/util/color.h b/trunk/tools/perf/util/color.h index 58d597564b99..706cec50bd25 100644 --- a/trunk/tools/perf/util/color.h +++ b/trunk/tools/perf/util/color.h @@ -32,11 +32,10 @@ int perf_color_default_config(const char *var, const char *value, void *cb); int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty); void color_parse(const char *value, const char *var, char *dst); void color_parse_mem(const char *value, int len, const char *var, char *dst); -int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); int percent_color_fprintf(FILE *fp, const char *fmt, double percent); -const char *get_percent_color(double percent); +char *get_percent_color(double percent); #endif /* COLOR_H */ diff --git a/trunk/tools/perf/util/config.c b/trunk/tools/perf/util/config.c index 8784649109ce..780df541006d 100644 --- a/trunk/tools/perf/util/config.c +++ b/trunk/tools/perf/util/config.c @@ -160,18 +160,17 @@ static int get_extended_base_var(char *name, int baselen, int c) name[baselen++] = '.'; for (;;) { - int ch = get_next_char(); - - if (ch == '\n') + int c = get_next_char(); + if (c == '\n') return -1; - if (ch == '"') + if (c == '"') break; - if (ch == '\\') { - ch = get_next_char(); - if (ch == '\n') + if (c == '\\') { + c = get_next_char(); + if (c == '\n') return -1; } - name[baselen++] = ch; + name[baselen++] = c; if (baselen > MAXNAME / 2) return -1; } @@ -531,8 +530,6 @@ static int store_aux(const char* key, const char* value, void *cb __used) store.offset[store.seen] = ftell(config_file); } } - default: - break; } return 0; } @@ -622,7 +619,6 @@ static ssize_t find_beginning_of_line(const char* contents, size_t size, switch (contents[offset]) { case '=': equal_offset = offset; break; case ']': bracket_offset = offset; break; - default: break; } if (offset > 0 && contents[offset-1] == '\\') { offset_ = offset; @@ -746,9 +742,9 @@ int perf_config_set_multivar(const char* key, const char* value, goto write_err_out; } else { struct stat st; - char *contents; + char* contents; ssize_t contents_sz, copy_begin, copy_end; - int new_line = 0; + int i, new_line = 0; if (value_regex == NULL) store.value_regex = NULL; diff --git a/trunk/tools/perf/util/debug.c b/trunk/tools/perf/util/debug.c deleted file mode 100644 index e8ca98fe0bd4..000000000000 --- a/trunk/tools/perf/util/debug.c +++ /dev/null @@ -1,95 +0,0 @@ -/* For general debugging purposes */ - -#include "../perf.h" - -#include -#include -#include - -#include "color.h" -#include "event.h" -#include "debug.h" - -int verbose = 0; -int dump_trace = 0; - -int eprintf(const char *fmt, ...) -{ - va_list args; - int ret = 0; - - if (verbose) { - va_start(args, fmt); - ret = vfprintf(stderr, fmt, args); - va_end(args); - } - - return ret; -} - -int dump_printf(const char *fmt, ...) -{ - va_list args; - int ret = 0; - - if (dump_trace) { - va_start(args, fmt); - ret = vprintf(fmt, args); - va_end(args); - } - - return ret; -} - -static int dump_printf_color(const char *fmt, const char *color, ...) -{ - va_list args; - int ret = 0; - - if (dump_trace) { - va_start(args, color); - ret = color_vfprintf(stdout, color, fmt, args); - va_end(args); - } - - return ret; -} - - -void trace_event(event_t *event) -{ - unsigned char *raw_event = (void *)event; - const char *color = PERF_COLOR_BLUE; - int i, j; - - if (!dump_trace) - return; - - dump_printf("."); - dump_printf_color("\n. ... raw event: size %d bytes\n", color, - event->header.size); - - for (i = 0; i < event->header.size; i++) { - if ((i & 15) == 0) { - dump_printf("."); - dump_printf_color(" %04x: ", color, i); - } - - dump_printf_color(" %02x", color, raw_event[i]); - - if (((i & 15) == 15) || i == event->header.size-1) { - dump_printf_color(" ", color); - for (j = 0; j < 15-(i & 15); j++) - dump_printf_color(" ", color); - for (j = 0; j < (i & 15); j++) { - if (isprint(raw_event[i-15+j])) - dump_printf_color("%c", color, - raw_event[i-15+j]); - else - dump_printf_color(".", color); - } - dump_printf_color("\n", color); - } - } - dump_printf(".\n"); -} diff --git a/trunk/tools/perf/util/debug.h b/trunk/tools/perf/util/debug.h deleted file mode 100644 index 437eea58ce40..000000000000 --- a/trunk/tools/perf/util/debug.h +++ /dev/null @@ -1,8 +0,0 @@ -/* For debugging general purposes */ - -extern int verbose; -extern int dump_trace; - -int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -void trace_event(event_t *event); diff --git a/trunk/tools/perf/util/event.h b/trunk/tools/perf/util/event.h deleted file mode 100644 index fa2d4e91d329..000000000000 --- a/trunk/tools/perf/util/event.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef __PERF_EVENT_H -#define __PERF_EVENT_H -#include "../perf.h" -#include "util.h" -#include - -enum { - SHOW_KERNEL = 1, - SHOW_USER = 2, - SHOW_HV = 4, -}; - -/* - * PERF_SAMPLE_IP | PERF_SAMPLE_TID | * - */ -struct ip_event { - struct perf_event_header header; - u64 ip; - u32 pid, tid; - unsigned char __more_data[]; -}; - -struct mmap_event { - struct perf_event_header header; - u32 pid, tid; - u64 start; - u64 len; - u64 pgoff; - char filename[PATH_MAX]; -}; - -struct comm_event { - struct perf_event_header header; - u32 pid, tid; - char comm[16]; -}; - -struct fork_event { - struct perf_event_header header; - u32 pid, ppid; - u32 tid, ptid; -}; - -struct lost_event { - struct perf_event_header header; - u64 id; - u64 lost; -}; - -/* - * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID - */ -struct read_event { - struct perf_event_header header; - u32 pid,tid; - u64 value; - u64 time_enabled; - u64 time_running; - u64 id; -}; - -typedef union event_union { - struct perf_event_header header; - struct ip_event ip; - struct mmap_event mmap; - struct comm_event comm; - struct fork_event fork; - struct lost_event lost; - struct read_event read; -} event_t; - -struct map { - struct list_head node; - u64 start; - u64 end; - u64 pgoff; - u64 (*map_ip)(struct map *, u64); - struct dso *dso; -}; - -static inline u64 map__map_ip(struct map *map, u64 ip) -{ - return ip - map->start + map->pgoff; -} - -static inline u64 vdso__map_ip(struct map *map __used, u64 ip) -{ - return ip; -} - -struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen); -struct map *map__clone(struct map *self); -int map__overlap(struct map *l, struct map *r); -size_t map__fprintf(struct map *self, FILE *fp); - -#endif diff --git a/trunk/tools/perf/util/exec_cmd.c b/trunk/tools/perf/util/exec_cmd.c index 2745605dba11..34a352867382 100644 --- a/trunk/tools/perf/util/exec_cmd.c +++ b/trunk/tools/perf/util/exec_cmd.c @@ -6,6 +6,7 @@ #define MAX_ARGS 32 +extern char **environ; static const char *argv_exec_path; static const char *argv0_path; diff --git a/trunk/tools/perf/util/header.c b/trunk/tools/perf/util/header.c index a37a2221a0c3..b92a457ca32e 100644 --- a/trunk/tools/perf/util/header.c +++ b/trunk/tools/perf/util/header.c @@ -243,38 +243,3 @@ struct perf_header *perf_header__read(int fd) return self; } - -u64 perf_header__sample_type(struct perf_header *header) -{ - u64 type = 0; - int i; - - for (i = 0; i < header->attrs; i++) { - struct perf_header_attr *attr = header->attr[i]; - - if (!type) - type = attr->attr.sample_type; - else if (type != attr->attr.sample_type) - die("non matching sample_type"); - } - - return type; -} - -struct perf_counter_attr * -perf_header__find_attr(u64 id, struct perf_header *header) -{ - int i; - - for (i = 0; i < header->attrs; i++) { - struct perf_header_attr *attr = header->attr[i]; - int j; - - for (j = 0; j < attr->ids; j++) { - if (attr->id[j] == id) - return &attr->attr; - } - } - - return NULL; -} diff --git a/trunk/tools/perf/util/header.h b/trunk/tools/perf/util/header.h index 5d0a72ecc919..bf280449fcfd 100644 --- a/trunk/tools/perf/util/header.h +++ b/trunk/tools/perf/util/header.h @@ -31,10 +31,6 @@ struct perf_header_attr * perf_header_attr__new(struct perf_counter_attr *attr); void perf_header_attr__add_id(struct perf_header_attr *self, u64 id); -u64 perf_header__sample_type(struct perf_header *header); -struct perf_counter_attr * -perf_header__find_attr(u64 id, struct perf_header *header); - struct perf_header *perf_header__new(void); diff --git a/trunk/tools/perf/util/map.c b/trunk/tools/perf/util/map.c deleted file mode 100644 index 804e02382739..000000000000 --- a/trunk/tools/perf/util/map.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "event.h" -#include "symbol.h" -#include -#include -#include - -static inline int is_anon_memory(const char *filename) -{ - return strcmp(filename, "//anon") == 0; -} - -static int strcommon(const char *pathname, char *cwd, int cwdlen) -{ - int n = 0; - - while (n < cwdlen && pathname[n] == cwd[n]) - ++n; - - return n; -} - - struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) -{ - struct map *self = malloc(sizeof(*self)); - - if (self != NULL) { - const char *filename = event->filename; - char newfilename[PATH_MAX]; - int anon; - - if (cwd) { - int n = strcommon(filename, cwd, cwdlen); - - if (n == cwdlen) { - snprintf(newfilename, sizeof(newfilename), - ".%s", filename + n); - filename = newfilename; - } - } - - anon = is_anon_memory(filename); - - if (anon) { - snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); - filename = newfilename; - } - - self->start = event->start; - self->end = event->start + event->len; - self->pgoff = event->pgoff; - - self->dso = dsos__findnew(filename); - if (self->dso == NULL) - goto out_delete; - - if (self->dso == vdso || anon) - self->map_ip = vdso__map_ip; - else - self->map_ip = map__map_ip; - } - return self; -out_delete: - free(self); - return NULL; -} - -struct map *map__clone(struct map *self) -{ - struct map *map = malloc(sizeof(*self)); - - if (!map) - return NULL; - - memcpy(map, self, sizeof(*self)); - - return map; -} - -int map__overlap(struct map *l, struct map *r) -{ - if (l->start > r->start) { - struct map *t = l; - l = r; - r = t; - } - - if (l->end > r->start) - return 1; - - return 0; -} - -size_t map__fprintf(struct map *self, FILE *fp) -{ - return fprintf(fp, " %Lx-%Lx %Lx %s\n", - self->start, self->end, self->pgoff, self->dso->name); -} diff --git a/trunk/tools/perf/util/module.c b/trunk/tools/perf/util/module.c index 3d567fe59c79..ddabe925d65d 100644 --- a/trunk/tools/perf/util/module.c +++ b/trunk/tools/perf/util/module.c @@ -436,9 +436,9 @@ static int mod_dso__load_module_paths(struct mod_dso *self) goto out_failure; while (!feof(file)) { - char *name, *tmp; + char *path, *name, *tmp; struct module *module; - int line_len; + int line_len, len; line_len = getline(&line, &n, file); if (line_len < 0) diff --git a/trunk/tools/perf/util/parse-events.c b/trunk/tools/perf/util/parse-events.c index 1cda97b39118..044178408783 100644 --- a/trunk/tools/perf/util/parse-events.c +++ b/trunk/tools/perf/util/parse-events.c @@ -14,10 +14,10 @@ int nr_counters; struct perf_counter_attr attrs[MAX_COUNTERS]; struct event_symbol { - u8 type; - u64 config; - const char *symbol; - const char *alias; + u8 type; + u64 config; + char *symbol; + char *alias; }; char debugfs_path[MAXPATHLEN]; @@ -51,7 +51,7 @@ static struct event_symbol event_symbols[] = { #define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) #define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) -static const char *hw_event_names[] = { +static char *hw_event_names[] = { "cycles", "instructions", "cache-references", @@ -61,7 +61,7 @@ static const char *hw_event_names[] = { "bus-cycles", }; -static const char *sw_event_names[] = { +static char *sw_event_names[] = { "cpu-clock-msecs", "task-clock-msecs", "page-faults", @@ -73,7 +73,7 @@ static const char *sw_event_names[] = { #define MAX_ALIASES 8 -static const char *hw_cache[][MAX_ALIASES] = { +static char *hw_cache[][MAX_ALIASES] = { { "L1-dcache", "l1-d", "l1d", "L1-data", }, { "L1-icache", "l1-i", "l1i", "L1-instruction", }, { "LLC", "L2" }, @@ -82,13 +82,13 @@ static const char *hw_cache[][MAX_ALIASES] = { { "branch", "branches", "bpu", "btb", "bpc", }, }; -static const char *hw_cache_op[][MAX_ALIASES] = { +static char *hw_cache_op[][MAX_ALIASES] = { { "load", "loads", "read", }, { "store", "stores", "write", }, { "prefetch", "prefetches", "speculative-read", "speculative-load", }, }; -static const char *hw_cache_result[][MAX_ALIASES] = { +static char *hw_cache_result[][MAX_ALIASES] = { { "refs", "Reference", "ops", "access", }, { "misses", "miss", }, }; @@ -158,7 +158,7 @@ int valid_debugfs_mount(const char *debugfs) return 0; } -static const char *tracepoint_id_to_name(u64 config) +static char *tracepoint_id_to_name(u64 config) { static char tracepoint_name[2 * MAX_EVENT_LENGTH]; DIR *sys_dir, *evt_dir; @@ -235,7 +235,7 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) return name; } -const char *event_name(int counter) +char *event_name(int counter) { u64 config = attrs[counter].config; int type = attrs[counter].type; @@ -243,7 +243,7 @@ const char *event_name(int counter) return __event_name(type, config); } -const char *__event_name(int type, u64 config) +char *__event_name(int type, u64 config) { static char buf[32]; @@ -294,7 +294,7 @@ const char *__event_name(int type, u64 config) return "unknown"; } -static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) +static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size) { int i, j; int n, longest = -1; diff --git a/trunk/tools/perf/util/parse-events.h b/trunk/tools/perf/util/parse-events.h index 9b1aeea01636..192a962e3a0f 100644 --- a/trunk/tools/perf/util/parse-events.h +++ b/trunk/tools/perf/util/parse-events.h @@ -9,8 +9,8 @@ extern int nr_counters; extern struct perf_counter_attr attrs[MAX_COUNTERS]; -extern const char *event_name(int ctr); -extern const char *__event_name(int type, u64 config); +extern char *event_name(int ctr); +extern char *__event_name(int type, u64 config); extern int parse_events(const struct option *opt, const char *str, int unset); diff --git a/trunk/tools/perf/util/parse-options.c b/trunk/tools/perf/util/parse-options.c index 6d8af48c925e..1bf67190c820 100644 --- a/trunk/tools/perf/util/parse-options.c +++ b/trunk/tools/perf/util/parse-options.c @@ -53,12 +53,6 @@ static int get_value(struct parse_opt_ctx_t *p, case OPTION_SET_INT: case OPTION_SET_PTR: return opterror(opt, "takes no value", flags); - case OPTION_END: - case OPTION_ARGUMENT: - case OPTION_GROUP: - case OPTION_STRING: - case OPTION_INTEGER: - case OPTION_LONG: default: break; } @@ -136,9 +130,6 @@ static int get_value(struct parse_opt_ctx_t *p, return opterror(opt, "expects a numerical value", flags); return 0; - case OPTION_END: - case OPTION_ARGUMENT: - case OPTION_GROUP: default: die("should not happen, someone must be hit on the forehead"); } @@ -305,8 +296,6 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, return parse_options_usage(usagestr, options); case -2: goto unknown; - default: - break; } if (ctx->opt) check_typos(arg + 1, options); @@ -325,8 +314,6 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, ctx->argv[0] = strdup(ctx->opt - 1); *(char *)ctx->argv[0] = '-'; goto unknown; - default: - break; } } continue; @@ -349,8 +336,6 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, return parse_options_usage(usagestr, options); case -2: goto unknown; - default: - break; } continue; unknown: @@ -471,13 +456,6 @@ int usage_with_options_internal(const char * const *usagestr, } break; default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */ - case OPTION_END: - case OPTION_GROUP: - case OPTION_BIT: - case OPTION_BOOLEAN: - case OPTION_SET_INT: - case OPTION_SET_PTR: - case OPTION_LONG: break; } diff --git a/trunk/tools/perf/util/path.c b/trunk/tools/perf/util/path.c index fd1f2faaade4..a501a40dd2cb 100644 --- a/trunk/tools/perf/util/path.c +++ b/trunk/tools/perf/util/path.c @@ -17,7 +17,7 @@ static char bad_path[] = "/bad-path/"; * Two hacks: */ -static const char *get_perf_dir(void) +static char *get_perf_dir(void) { return "."; } @@ -38,9 +38,8 @@ size_t strlcpy(char *dest, const char *src, size_t size) static char *get_pathname(void) { static char pathname_array[4][PATH_MAX]; - static int idx; - - return pathname_array[3 & ++idx]; + static int index; + return pathname_array[3 & ++index]; } static char *cleanup_path(char *path) @@ -162,24 +161,20 @@ int perf_mkstemp(char *path, size_t len, const char *template) } -const char *make_relative_path(const char *abs_path, const char *base) +const char *make_relative_path(const char *abs, const char *base) { static char buf[PATH_MAX + 1]; int baselen; - if (!base) - return abs_path; - + return abs; baselen = strlen(base); - if (prefixcmp(abs_path, base)) - return abs_path; - if (abs_path[baselen] == '/') + if (prefixcmp(abs, base)) + return abs; + if (abs[baselen] == '/') baselen++; else if (base[baselen - 1] != '/') - return abs_path; - - strcpy(buf, abs_path + baselen); - + return abs; + strcpy(buf, abs + baselen); return buf; } diff --git a/trunk/tools/perf/util/run-command.c b/trunk/tools/perf/util/run-command.c index 2b615acf94d7..a3935343091a 100644 --- a/trunk/tools/perf/util/run-command.c +++ b/trunk/tools/perf/util/run-command.c @@ -262,7 +262,7 @@ int run_hook(const char *index_file, const char *name, ...) { struct child_process hook; const char **argv = NULL, *env[2]; - char idx[PATH_MAX]; + char index[PATH_MAX]; va_list args; int ret; size_t i = 0, alloc = 0; @@ -284,8 +284,8 @@ int run_hook(const char *index_file, const char *name, ...) hook.no_stdin = 1; hook.stdout_to_stderr = 1; if (index_file) { - snprintf(idx, sizeof(idx), "PERF_INDEX_FILE=%s", index_file); - env[0] = idx; + snprintf(index, sizeof(index), "PERF_INDEX_FILE=%s", index_file); + env[0] = index; env[1] = NULL; hook.env = env; } diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index fd3d9c8e90fc..5c0f42e6b33b 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -3,8 +3,6 @@ #include "string.h" #include "symbol.h" -#include "debug.h" - #include #include #include @@ -23,7 +21,7 @@ enum dso_origin { static struct symbol *symbol__new(u64 start, u64 len, const char *name, unsigned int priv_size, - u64 obj_start, int v) + u64 obj_start, int verbose) { size_t namelen = strlen(name) + 1; struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); @@ -31,7 +29,7 @@ static struct symbol *symbol__new(u64 start, u64 len, if (!self) return NULL; - if (v >= 2) + if (verbose >= 2) printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); @@ -158,7 +156,7 @@ size_t dso__fprintf(struct dso *self, FILE *fp) return ret; } -static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) +static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose) { struct rb_node *nd, *prevnd; char *line = NULL; @@ -200,7 +198,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) * Well fix up the end later, when we have all sorted. */ sym = symbol__new(start, 0xdead, line + len + 2, - self->sym_priv_size, 0, v); + self->sym_priv_size, 0, verbose); if (sym == NULL) goto out_delete_line; @@ -241,7 +239,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) return -1; } -static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) +static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose) { char *line = NULL; size_t n; @@ -279,7 +277,7 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) continue; sym = symbol__new(start, size, line + len, - self->sym_priv_size, start, v); + self->sym_priv_size, start, verbose); if (sym == NULL) goto out_delete_line; @@ -307,13 +305,13 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) * elf_symtab__for_each_symbol - iterate thru all the symbols * * @self: struct elf_symtab instance to iterate - * @idx: uint32_t idx + * @index: uint32_t index * @sym: GElf_Sym iterator */ -#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \ - for (idx = 0, gelf_getsym(syms, idx, &sym);\ - idx < nr_syms; \ - idx++, gelf_getsym(syms, idx, &sym)) +#define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \ + for (index = 0, gelf_getsym(syms, index, &sym);\ + index < nr_syms; \ + index++, gelf_getsym(syms, index, &sym)) static inline uint8_t elf_sym__type(const GElf_Sym *sym) { @@ -356,7 +354,7 @@ static inline const char *elf_sym__name(const GElf_Sym *sym, static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, GElf_Shdr *shp, const char *name, - size_t *idx) + size_t *index) { Elf_Scn *sec = NULL; size_t cnt = 1; @@ -367,8 +365,8 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, gelf_getshdr(sec, shp); str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); if (!strcmp(name, str)) { - if (idx) - *idx = cnt; + if (index) + *index = cnt; break; } ++cnt; @@ -394,7 +392,7 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, * And always look at the original dso, not at debuginfo packages, that * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). */ -static int dso__synthesize_plt_symbols(struct dso *self, int v) +static int dso__synthesize_plt_symbols(struct dso *self, int verbose) { uint32_t nr_rel_entries, idx; GElf_Sym sym; @@ -444,7 +442,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v) goto out_elf_end; /* - * Fetch the relocation section to find the idxes to the GOT + * Fetch the relocation section to find the indexes to the GOT * and the symbols in the .dynsym they refer to. */ reldata = elf_getdata(scn_plt_rel, NULL); @@ -478,7 +476,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v) "%s@plt", elf_sym__name(&sym, symstrs)); f = symbol__new(plt_offset, shdr_plt.sh_entsize, - sympltname, self->sym_priv_size, 0, v); + sympltname, self->sym_priv_size, 0, verbose); if (!f) goto out_elf_end; @@ -496,7 +494,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v) "%s@plt", elf_sym__name(&sym, symstrs)); f = symbol__new(plt_offset, shdr_plt.sh_entsize, - sympltname, self->sym_priv_size, 0, v); + sympltname, self->sym_priv_size, 0, verbose); if (!f) goto out_elf_end; @@ -520,12 +518,12 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v) } static int dso__load_sym(struct dso *self, int fd, const char *name, - symbol_filter_t filter, int v, struct module *mod) + symbol_filter_t filter, int verbose, struct module *mod) { Elf_Data *symstrs, *secstrs; uint32_t nr_syms; int err = -1; - uint32_t idx; + uint32_t index; GElf_Ehdr ehdr; GElf_Shdr shdr; Elf_Data *syms; @@ -536,14 +534,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (elf == NULL) { - if (v) + if (verbose) fprintf(stderr, "%s: cannot read %s ELF file.\n", __func__, name); goto out_close; } if (gelf_getehdr(elf, &ehdr) == NULL) { - if (v) + if (verbose) fprintf(stderr, "%s: cannot get elf header.\n", __func__); goto out_elf_end; } @@ -585,9 +583,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, NULL) != NULL); } else self->adjust_symbols = 0; - elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { + elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { struct symbol *f; - const char *elf_name; + const char *name; char *demangled; u64 obj_start; struct section *section = NULL; @@ -610,7 +608,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, obj_start = sym.st_value; if (self->adjust_symbols) { - if (v >= 2) + if (verbose >= 2) printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); @@ -632,13 +630,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, * DWARF DW_compile_unit has this, but we don't always have access * to it... */ - elf_name = elf_sym__name(&sym, symstrs); - demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); + name = elf_sym__name(&sym, symstrs); + demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); if (demangled != NULL) - elf_name = demangled; + name = demangled; - f = symbol__new(sym.st_value, sym.st_size, elf_name, - self->sym_priv_size, obj_start, v); + f = symbol__new(sym.st_value, sym.st_size, name, + self->sym_priv_size, obj_start, verbose); free(demangled); if (!f) goto out_elf_end; @@ -661,7 +659,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, #define BUILD_ID_SIZE 128 -static char *dso__read_build_id(struct dso *self, int v) +static char *dso__read_build_id(struct dso *self, int verbose) { int i; GElf_Ehdr ehdr; @@ -678,14 +676,14 @@ static char *dso__read_build_id(struct dso *self, int v) elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (elf == NULL) { - if (v) + if (verbose) fprintf(stderr, "%s: cannot read %s ELF file.\n", __func__, self->name); goto out_close; } if (gelf_getehdr(elf, &ehdr) == NULL) { - if (v) + if (verbose) fprintf(stderr, "%s: cannot get elf header.\n", __func__); goto out_elf_end; } @@ -708,7 +706,7 @@ static char *dso__read_build_id(struct dso *self, int v) ++raw; bid += 2; } - if (v >= 2) + if (verbose >= 2) printf("%s(%s): %s\n", __func__, self->name, build_id); out_elf_end: elf_end(elf); @@ -734,7 +732,7 @@ char dso__symtab_origin(const struct dso *self) return origin[self->origin]; } -int dso__load(struct dso *self, symbol_filter_t filter, int v) +int dso__load(struct dso *self, symbol_filter_t filter, int verbose) { int size = PATH_MAX; char *name = malloc(size), *build_id = NULL; @@ -747,7 +745,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v) self->adjust_symbols = 0; if (strncmp(self->name, "/tmp/perf-", 10) == 0) { - ret = dso__load_perf_map(self, filter, v); + ret = dso__load_perf_map(self, filter, verbose); self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : DSO__ORIG_NOT_FOUND; return ret; @@ -766,7 +764,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v) snprintf(name, size, "/usr/lib/debug%s", self->name); break; case DSO__ORIG_BUILDID: - build_id = dso__read_build_id(self, v); + build_id = dso__read_build_id(self, verbose); if (build_id != NULL) { snprintf(name, size, "/usr/lib/debug/.build-id/%.2s/%s.debug", @@ -787,7 +785,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v) fd = open(name, O_RDONLY); } while (fd < 0); - ret = dso__load_sym(self, fd, name, filter, v, NULL); + ret = dso__load_sym(self, fd, name, filter, verbose, NULL); close(fd); /* @@ -797,7 +795,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v) goto more; if (ret > 0) { - int nr_plt = dso__synthesize_plt_symbols(self, v); + int nr_plt = dso__synthesize_plt_symbols(self, verbose); if (nr_plt > 0) ret += nr_plt; } @@ -809,7 +807,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v) } static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, - symbol_filter_t filter, int v) + symbol_filter_t filter, int verbose) { struct module *mod = mod_dso__find_module(mods, name); int err = 0, fd; @@ -822,13 +820,13 @@ static int dso__load_module(struct dso *self, struct mod_dso *mods, const char * if (fd < 0) return err; - err = dso__load_sym(self, fd, name, filter, v, mod); + err = dso__load_sym(self, fd, name, filter, verbose, mod); close(fd); return err; } -int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) +int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) { struct mod_dso *mods = mod_dso__new_dso("modules"); struct module *pos; @@ -846,7 +844,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) next = rb_first(&mods->mods); while (next) { pos = rb_entry(next, struct module, rb_node); - err = dso__load_module(self, mods, pos->name, filter, v); + err = dso__load_module(self, mods, pos->name, filter, verbose); if (err < 0) break; @@ -889,14 +887,14 @@ static inline void dso__fill_symbol_holes(struct dso *self) } static int dso__load_vmlinux(struct dso *self, const char *vmlinux, - symbol_filter_t filter, int v) + symbol_filter_t filter, int verbose) { int err, fd = open(vmlinux, O_RDONLY); if (fd < 0) return -1; - err = dso__load_sym(self, fd, vmlinux, filter, v, NULL); + err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); if (err > 0) dso__fill_symbol_holes(self); @@ -907,18 +905,18 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux, } int dso__load_kernel(struct dso *self, const char *vmlinux, - symbol_filter_t filter, int v, int use_modules) + symbol_filter_t filter, int verbose, int modules) { int err = -1; if (vmlinux) { - err = dso__load_vmlinux(self, vmlinux, filter, v); - if (err > 0 && use_modules) - err = dso__load_modules(self, filter, v); + err = dso__load_vmlinux(self, vmlinux, filter, verbose); + if (err > 0 && modules) + err = dso__load_modules(self, filter, verbose); } if (err <= 0) - err = dso__load_kallsyms(self, filter, v); + err = dso__load_kallsyms(self, filter, verbose); if (err > 0) self->origin = DSO__ORIG_KERNEL; @@ -926,103 +924,6 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, return err; } -LIST_HEAD(dsos); -struct dso *kernel_dso; -struct dso *vdso; -struct dso *hypervisor_dso; - -const char *vmlinux_name = "vmlinux"; -int modules; - -static void dsos__add(struct dso *dso) -{ - list_add_tail(&dso->node, &dsos); -} - -static struct dso *dsos__find(const char *name) -{ - struct dso *pos; - - list_for_each_entry(pos, &dsos, node) - if (strcmp(pos->name, name) == 0) - return pos; - return NULL; -} - -struct dso *dsos__findnew(const char *name) -{ - struct dso *dso = dsos__find(name); - int nr; - - if (dso) - return dso; - - dso = dso__new(name, 0); - if (!dso) - goto out_delete_dso; - - nr = dso__load(dso, NULL, verbose); - if (nr < 0) { - eprintf("Failed to open: %s\n", name); - goto out_delete_dso; - } - if (!nr) - eprintf("No symbols found in: %s, maybe install a debug package?\n", name); - - dsos__add(dso); - - return dso; - -out_delete_dso: - dso__delete(dso); - return NULL; -} - -void dsos__fprintf(FILE *fp) -{ - struct dso *pos; - - list_for_each_entry(pos, &dsos, node) - dso__fprintf(pos, fp); -} - -static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) -{ - return dso__find_symbol(dso, ip); -} - -int load_kernel(void) -{ - int err; - - kernel_dso = dso__new("[kernel]", 0); - if (!kernel_dso) - return -1; - - err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules); - if (err <= 0) { - dso__delete(kernel_dso); - kernel_dso = NULL; - } else - dsos__add(kernel_dso); - - vdso = dso__new("[vdso]", 0); - if (!vdso) - return -1; - - vdso->find_symbol = vdso__find_symbol; - - dsos__add(vdso); - - hypervisor_dso = dso__new("[hypervisor]", 0); - if (!hypervisor_dso) - return -1; - dsos__add(hypervisor_dso); - - return err; -} - - void symbol__init(void) { elf_version(EV_CURRENT); diff --git a/trunk/tools/perf/util/symbol.h b/trunk/tools/perf/util/symbol.h index 6e8490716408..b53bf0125c1b 100644 --- a/trunk/tools/perf/util/symbol.h +++ b/trunk/tools/perf/util/symbol.h @@ -6,7 +6,6 @@ #include #include #include "module.h" -#include "event.h" #ifdef HAVE_CPLUS_DEMANGLE extern char *cplus_demangle(const char *, int); @@ -55,7 +54,7 @@ struct dso { char name[0]; }; -extern const char *sym_hist_filter; +const char *sym_hist_filter; typedef int (*symbol_filter_t)(struct dso *self, struct symbol *sym); @@ -73,20 +72,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, symbol_filter_t filter, int verbose, int modules); int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); int dso__load(struct dso *self, symbol_filter_t filter, int verbose); -struct dso *dsos__findnew(const char *name); -void dsos__fprintf(FILE *fp); size_t dso__fprintf(struct dso *self, FILE *fp); char dso__symtab_origin(const struct dso *self); -int load_kernel(void); - void symbol__init(void); - -extern struct list_head dsos; -extern struct dso *kernel_dso; -extern struct dso *vdso; -extern struct dso *hypervisor_dso; -extern const char *vmlinux_name; -extern int modules; #endif /* _PERF_SYMBOL_ */ diff --git a/trunk/tools/perf/util/thread.c b/trunk/tools/perf/util/thread.c deleted file mode 100644 index 00c14b98d651..000000000000 --- a/trunk/tools/perf/util/thread.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "../perf.h" -#include -#include -#include -#include "thread.h" -#include "util.h" - -static struct thread *thread__new(pid_t pid) -{ - struct thread *self = malloc(sizeof(*self)); - - if (self != NULL) { - self->pid = pid; - self->comm = malloc(32); - if (self->comm) - snprintf(self->comm, 32, ":%d", self->pid); - INIT_LIST_HEAD(&self->maps); - } - - return self; -} - -int thread__set_comm(struct thread *self, const char *comm) -{ - if (self->comm) - free(self->comm); - self->comm = strdup(comm); - return self->comm ? 0 : -ENOMEM; -} - -static size_t thread__fprintf(struct thread *self, FILE *fp) -{ - struct map *pos; - size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); - - list_for_each_entry(pos, &self->maps, node) - ret += map__fprintf(pos, fp); - - return ret; -} - -struct thread * -threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match) -{ - struct rb_node **p = &threads->rb_node; - struct rb_node *parent = NULL; - struct thread *th; - - /* - * Font-end cache - PID lookups come in blocks, - * so most of the time we dont have to look up - * the full rbtree: - */ - if (*last_match && (*last_match)->pid == pid) - return *last_match; - - while (*p != NULL) { - parent = *p; - th = rb_entry(parent, struct thread, rb_node); - - if (th->pid == pid) { - *last_match = th; - return th; - } - - if (pid < th->pid) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - th = thread__new(pid); - if (th != NULL) { - rb_link_node(&th->rb_node, parent, p); - rb_insert_color(&th->rb_node, threads); - *last_match = th; - } - - return th; -} - -void thread__insert_map(struct thread *self, struct map *map) -{ - struct map *pos, *tmp; - - list_for_each_entry_safe(pos, tmp, &self->maps, node) { - if (map__overlap(pos, map)) { - list_del_init(&pos->node); - /* XXX leaks dsos */ - free(pos); - } - } - - list_add_tail(&map->node, &self->maps); -} - -int thread__fork(struct thread *self, struct thread *parent) -{ - struct map *map; - - if (self->comm) - free(self->comm); - self->comm = strdup(parent->comm); - if (!self->comm) - return -ENOMEM; - - list_for_each_entry(map, &parent->maps, node) { - struct map *new = map__clone(map); - if (!new) - return -ENOMEM; - thread__insert_map(self, new); - } - - return 0; -} - -struct map *thread__find_map(struct thread *self, u64 ip) -{ - struct map *pos; - - if (self == NULL) - return NULL; - - list_for_each_entry(pos, &self->maps, node) - if (ip >= pos->start && ip <= pos->end) - return pos; - - return NULL; -} - -size_t threads__fprintf(FILE *fp, struct rb_root *threads) -{ - size_t ret = 0; - struct rb_node *nd; - - for (nd = rb_first(threads); nd; nd = rb_next(nd)) { - struct thread *pos = rb_entry(nd, struct thread, rb_node); - - ret += thread__fprintf(pos, fp); - } - - return ret; -} diff --git a/trunk/tools/perf/util/thread.h b/trunk/tools/perf/util/thread.h deleted file mode 100644 index b1c66719379b..000000000000 --- a/trunk/tools/perf/util/thread.h +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include -#include "symbol.h" - -struct thread { - struct rb_node rb_node; - struct list_head maps; - pid_t pid; - char *comm; -}; - -int thread__set_comm(struct thread *self, const char *comm); -struct thread * -threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match); -void thread__insert_map(struct thread *self, struct map *map); -int thread__fork(struct thread *self, struct thread *parent); -struct map *thread__find_map(struct thread *self, u64 ip); -size_t threads__fprintf(FILE *fp, struct rb_root *threads); diff --git a/trunk/tools/perf/util/util.h b/trunk/tools/perf/util/util.h index d61a6f037631..68fe157d72fb 100644 --- a/trunk/tools/perf/util/util.h +++ b/trunk/tools/perf/util/util.h @@ -83,7 +83,6 @@ #include #include "../../../include/linux/magic.h" - #ifndef NO_ICONV #include #endif diff --git a/trunk/tools/perf/util/values.c b/trunk/tools/perf/util/values.c deleted file mode 100644 index 1c15e39f99e3..000000000000 --- a/trunk/tools/perf/util/values.c +++ /dev/null @@ -1,230 +0,0 @@ -#include - -#include "util.h" -#include "values.h" - -void perf_read_values_init(struct perf_read_values *values) -{ - values->threads_max = 16; - values->pid = malloc(values->threads_max * sizeof(*values->pid)); - values->tid = malloc(values->threads_max * sizeof(*values->tid)); - values->value = malloc(values->threads_max * sizeof(*values->value)); - if (!values->pid || !values->tid || !values->value) - die("failed to allocate read_values threads arrays"); - values->threads = 0; - - values->counters_max = 16; - values->counterrawid = malloc(values->counters_max - * sizeof(*values->counterrawid)); - values->countername = malloc(values->counters_max - * sizeof(*values->countername)); - if (!values->counterrawid || !values->countername) - die("failed to allocate read_values counters arrays"); - values->counters = 0; -} - -void perf_read_values_destroy(struct perf_read_values *values) -{ - int i; - - if (!values->threads_max || !values->counters_max) - return; - - for (i = 0; i < values->threads; i++) - free(values->value[i]); - free(values->pid); - free(values->tid); - free(values->counterrawid); - for (i = 0; i < values->counters; i++) - free(values->countername[i]); - free(values->countername); -} - -static void perf_read_values__enlarge_threads(struct perf_read_values *values) -{ - values->threads_max *= 2; - values->pid = realloc(values->pid, - values->threads_max * sizeof(*values->pid)); - values->tid = realloc(values->tid, - values->threads_max * sizeof(*values->tid)); - values->value = realloc(values->value, - values->threads_max * sizeof(*values->value)); - if (!values->pid || !values->tid || !values->value) - die("failed to enlarge read_values threads arrays"); -} - -static int perf_read_values__findnew_thread(struct perf_read_values *values, - u32 pid, u32 tid) -{ - int i; - - for (i = 0; i < values->threads; i++) - if (values->pid[i] == pid && values->tid[i] == tid) - return i; - - if (values->threads == values->threads_max) - perf_read_values__enlarge_threads(values); - - i = values->threads++; - values->pid[i] = pid; - values->tid[i] = tid; - values->value[i] = malloc(values->counters_max * sizeof(**values->value)); - if (!values->value[i]) - die("failed to allocate read_values counters array"); - - return i; -} - -static void perf_read_values__enlarge_counters(struct perf_read_values *values) -{ - int i; - - values->counters_max *= 2; - values->counterrawid = realloc(values->counterrawid, - values->counters_max * sizeof(*values->counterrawid)); - values->countername = realloc(values->countername, - values->counters_max * sizeof(*values->countername)); - if (!values->counterrawid || !values->countername) - die("failed to enlarge read_values counters arrays"); - - for (i = 0; i < values->threads; i++) { - values->value[i] = realloc(values->value[i], - values->counters_max * sizeof(**values->value)); - if (!values->value[i]) - die("failed to enlarge read_values counters arrays"); - } -} - -static int perf_read_values__findnew_counter(struct perf_read_values *values, - u64 rawid, const char *name) -{ - int i; - - for (i = 0; i < values->counters; i++) - if (values->counterrawid[i] == rawid) - return i; - - if (values->counters == values->counters_max) - perf_read_values__enlarge_counters(values); - - i = values->counters++; - values->counterrawid[i] = rawid; - values->countername[i] = strdup(name); - - return i; -} - -void perf_read_values_add_value(struct perf_read_values *values, - u32 pid, u32 tid, - u64 rawid, const char *name, u64 value) -{ - int tindex, cindex; - - tindex = perf_read_values__findnew_thread(values, pid, tid); - cindex = perf_read_values__findnew_counter(values, rawid, name); - - values->value[tindex][cindex] = value; -} - -static void perf_read_values__display_pretty(FILE *fp, - struct perf_read_values *values) -{ - int i, j; - int pidwidth, tidwidth; - int *counterwidth; - - counterwidth = malloc(values->counters * sizeof(*counterwidth)); - if (!counterwidth) - die("failed to allocate counterwidth array"); - tidwidth = 3; - pidwidth = 3; - for (j = 0; j < values->counters; j++) - counterwidth[j] = strlen(values->countername[j]); - for (i = 0; i < values->threads; i++) { - int width; - - width = snprintf(NULL, 0, "%d", values->pid[i]); - if (width > pidwidth) - pidwidth = width; - width = snprintf(NULL, 0, "%d", values->tid[i]); - if (width > tidwidth) - tidwidth = width; - for (j = 0; j < values->counters; j++) { - width = snprintf(NULL, 0, "%Lu", values->value[i][j]); - if (width > counterwidth[j]) - counterwidth[j] = width; - } - } - - fprintf(fp, "# %*s %*s", pidwidth, "PID", tidwidth, "TID"); - for (j = 0; j < values->counters; j++) - fprintf(fp, " %*s", counterwidth[j], values->countername[j]); - fprintf(fp, "\n"); - - for (i = 0; i < values->threads; i++) { - fprintf(fp, " %*d %*d", pidwidth, values->pid[i], - tidwidth, values->tid[i]); - for (j = 0; j < values->counters; j++) - fprintf(fp, " %*Lu", - counterwidth[j], values->value[i][j]); - fprintf(fp, "\n"); - } -} - -static void perf_read_values__display_raw(FILE *fp, - struct perf_read_values *values) -{ - int width, pidwidth, tidwidth, namewidth, rawwidth, countwidth; - int i, j; - - tidwidth = 3; /* TID */ - pidwidth = 3; /* PID */ - namewidth = 4; /* "Name" */ - rawwidth = 3; /* "Raw" */ - countwidth = 5; /* "Count" */ - - for (i = 0; i < values->threads; i++) { - width = snprintf(NULL, 0, "%d", values->pid[i]); - if (width > pidwidth) - pidwidth = width; - width = snprintf(NULL, 0, "%d", values->tid[i]); - if (width > tidwidth) - tidwidth = width; - } - for (j = 0; j < values->counters; j++) { - width = strlen(values->countername[j]); - if (width > namewidth) - namewidth = width; - width = snprintf(NULL, 0, "%llx", values->counterrawid[j]); - if (width > rawwidth) - rawwidth = width; - } - for (i = 0; i < values->threads; i++) { - for (j = 0; j < values->counters; j++) { - width = snprintf(NULL, 0, "%Lu", values->value[i][j]); - if (width > countwidth) - countwidth = width; - } - } - - fprintf(fp, "# %*s %*s %*s %*s %*s\n", - pidwidth, "PID", tidwidth, "TID", - namewidth, "Name", rawwidth, "Raw", - countwidth, "Count"); - for (i = 0; i < values->threads; i++) - for (j = 0; j < values->counters; j++) - fprintf(fp, " %*d %*d %*s %*llx %*Lu\n", - pidwidth, values->pid[i], - tidwidth, values->tid[i], - namewidth, values->countername[j], - rawwidth, values->counterrawid[j], - countwidth, values->value[i][j]); -} - -void perf_read_values_display(FILE *fp, struct perf_read_values *values, int raw) -{ - if (raw) - perf_read_values__display_raw(fp, values); - else - perf_read_values__display_pretty(fp, values); -} diff --git a/trunk/tools/perf/util/values.h b/trunk/tools/perf/util/values.h deleted file mode 100644 index cadf8cf2a590..000000000000 --- a/trunk/tools/perf/util/values.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _PERF_VALUES_H -#define _PERF_VALUES_H - -#include "types.h" - -struct perf_read_values { - int threads; - int threads_max; - u32 *pid, *tid; - int counters; - int counters_max; - u64 *counterrawid; - char **countername; - u64 **value; -}; - -void perf_read_values_init(struct perf_read_values *values); -void perf_read_values_destroy(struct perf_read_values *values); - -void perf_read_values_add_value(struct perf_read_values *values, - u32 pid, u32 tid, - u64 rawid, const char *name, u64 value); - -void perf_read_values_display(FILE *fp, struct perf_read_values *values, - int raw); - -#endif /* _PERF_VALUES_H */