From 57118d359c1d7e340b0d7811bd2a28270eddcf6e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 18 Nov 2012 21:27:45 -0800 Subject: [PATCH] --- yaml --- r: 350036 b: refs/heads/master c: b736f48bda54ec75b7dc9306884c3843f1a78a0a h: refs/heads/master v: v3 --- [refs] | 2 +- .../sysfs-bus-event_source-devices-events | 62 - .../powerpc/include/asm/perf_event_server.h | 26 - trunk/arch/powerpc/perf/core-book3s.c | 12 - trunk/arch/powerpc/perf/power7-pmu.c | 80 +- trunk/arch/x86/kernel/cpu/perf_event.c | 13 +- trunk/include/linux/perf_event.h | 11 - trunk/include/uapi/linux/perf_event.h | 3 +- trunk/kernel/events/uprobes.c | 3 +- trunk/kernel/trace/trace.c | 2 +- trunk/tools/Makefile | 2 +- trunk/tools/lib/traceevent/event-parse.c | 49 +- trunk/tools/lib/traceevent/event-parse.h | 3 +- trunk/tools/lib/traceevent/event-utils.h | 3 +- trunk/tools/lib/traceevent/parse-filter.c | 3 +- trunk/tools/lib/traceevent/parse-utils.c | 19 - trunk/tools/lib/traceevent/trace-seq.c | 3 +- .../tools/perf/Documentation/perf-evlist.txt | 4 - .../tools/perf/Documentation/perf-report.txt | 41 +- .../perf/Documentation/perf-script-python.txt | 2 + trunk/tools/perf/Documentation/perf-stat.txt | 4 - trunk/tools/perf/Documentation/perf-test.txt | 4 - trunk/tools/perf/Makefile | 30 +- trunk/tools/perf/arch/common.c | 1 - trunk/tools/perf/bench/bench.h | 1 - trunk/tools/perf/bench/numa.c | 1731 ----------------- trunk/tools/perf/builtin-bench.c | 19 - trunk/tools/perf/builtin-diff.c | 92 +- trunk/tools/perf/builtin-evlist.c | 7 - trunk/tools/perf/builtin-kmem.c | 16 +- trunk/tools/perf/builtin-kvm.c | 3 +- trunk/tools/perf/builtin-record.c | 130 +- trunk/tools/perf/builtin-report.c | 53 +- trunk/tools/perf/builtin-sched.c | 6 +- trunk/tools/perf/builtin-script.c | 17 +- trunk/tools/perf/builtin-stat.c | 204 +- trunk/tools/perf/builtin-top.c | 166 +- trunk/tools/perf/config/feature-tests.mak | 11 - trunk/tools/perf/config/utilities.mak | 6 +- trunk/tools/perf/perf.c | 32 +- trunk/tools/perf/perf.h | 6 + .../scripts/perl/bin/workqueue-stats-record | 2 + .../scripts/perl/bin/workqueue-stats-report | 3 + .../perf/scripts/perl/workqueue-stats.pl | 129 ++ trunk/tools/perf/tests/attr.c | 9 +- trunk/tools/perf/tests/attr.py | 27 +- .../tools/perf/tests/attr/test-record-group1 | 2 +- trunk/tools/perf/tests/builtin-test.c | 40 +- trunk/tools/perf/tests/evsel-roundtrip-name.c | 4 +- trunk/tools/perf/tests/hists_link.c | 499 ----- .../tools/perf/tests/open-syscall-all-cpus.c | 1 - trunk/tools/perf/tests/parse-events.c | 126 +- trunk/tools/perf/tests/perf-record.c | 12 +- trunk/tools/perf/tests/pmu.c | 11 +- trunk/tools/perf/tests/python-use.c | 23 - trunk/tools/perf/tests/tests.h | 8 - trunk/tools/perf/tests/vmlinux-kallsyms.c | 7 +- trunk/tools/perf/ui/browser.c | 6 +- trunk/tools/perf/ui/browsers/annotate.c | 33 +- trunk/tools/perf/ui/browsers/hists.c | 217 +-- trunk/tools/perf/ui/gtk/browser.c | 227 ++- trunk/tools/perf/ui/gtk/gtk.h | 9 +- trunk/tools/perf/ui/gtk/hists.c | 312 --- trunk/tools/perf/ui/hist.c | 306 +-- trunk/tools/perf/ui/stdio/hist.c | 8 +- trunk/tools/perf/ui/util.c | 11 + trunk/tools/perf/util/PERF-VERSION-GEN | 4 +- trunk/tools/perf/util/debug.h | 1 + trunk/tools/perf/util/event.c | 4 +- trunk/tools/perf/util/evlist.c | 7 +- trunk/tools/perf/util/evlist.h | 1 - trunk/tools/perf/util/evsel.c | 188 +- trunk/tools/perf/util/evsel.h | 24 - trunk/tools/perf/util/header.c | 262 +-- trunk/tools/perf/util/header.h | 2 - trunk/tools/perf/util/hist.c | 138 +- trunk/tools/perf/util/hist.h | 4 +- trunk/tools/perf/util/include/linux/bitops.h | 1 - trunk/tools/perf/util/intlist.c | 36 +- trunk/tools/perf/util/intlist.h | 2 +- trunk/tools/perf/util/machine.c | 64 +- trunk/tools/perf/util/machine.h | 32 +- trunk/tools/perf/util/map.c | 121 +- trunk/tools/perf/util/map.h | 24 +- trunk/tools/perf/util/parse-events.c | 88 +- trunk/tools/perf/util/parse-events.h | 22 +- trunk/tools/perf/util/parse-events.y | 74 +- trunk/tools/perf/util/pmu.c | 46 +- trunk/tools/perf/util/pmu.h | 15 +- trunk/tools/perf/util/probe-finder.c | 10 +- trunk/tools/perf/util/python.c | 9 - .../util/scripting-engines/trace-event-perl.c | 1 - .../scripting-engines/trace-event-python.c | 1 - trunk/tools/perf/util/session.c | 75 +- trunk/tools/perf/util/session.h | 30 +- trunk/tools/perf/util/sort.c | 237 ++- trunk/tools/perf/util/sort.h | 8 +- trunk/tools/perf/util/string.c | 18 - trunk/tools/perf/util/strlist.c | 54 +- trunk/tools/perf/util/strlist.h | 42 +- trunk/tools/perf/util/symbol-elf.c | 3 + trunk/tools/perf/util/symbol-minimal.c | 1 + trunk/tools/perf/util/symbol.c | 14 +- trunk/tools/perf/util/symbol.h | 5 +- trunk/tools/perf/util/sysfs.c | 2 +- trunk/tools/perf/util/top.h | 2 + trunk/tools/perf/util/util.c | 24 - trunk/tools/perf/util/util.h | 4 - 108 files changed, 1607 insertions(+), 5007 deletions(-) delete mode 100644 trunk/Documentation/ABI/testing/sysfs-bus-event_source-devices-events delete mode 100644 trunk/tools/perf/bench/numa.c create mode 100644 trunk/tools/perf/scripts/perl/bin/workqueue-stats-record create mode 100644 trunk/tools/perf/scripts/perl/bin/workqueue-stats-report create mode 100644 trunk/tools/perf/scripts/perl/workqueue-stats.pl delete mode 100644 trunk/tools/perf/tests/hists_link.c delete mode 100644 trunk/tools/perf/tests/python-use.c delete mode 100644 trunk/tools/perf/ui/gtk/hists.c diff --git a/[refs] b/[refs] index 332b5dfde1e0..8fe132189a2b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9c4c5fd9e6207f04dbf59c5a9699fded144542e6 +refs/heads/master: b736f48bda54ec75b7dc9306884c3843f1a78a0a diff --git a/trunk/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/trunk/Documentation/ABI/testing/sysfs-bus-event_source-devices-events deleted file mode 100644 index 0adeb524c0d4..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-bus-event_source-devices-events +++ /dev/null @@ -1,62 +0,0 @@ -What: /sys/devices/cpu/events/ - /sys/devices/cpu/events/branch-misses - /sys/devices/cpu/events/cache-references - /sys/devices/cpu/events/cache-misses - /sys/devices/cpu/events/stalled-cycles-frontend - /sys/devices/cpu/events/branch-instructions - /sys/devices/cpu/events/stalled-cycles-backend - /sys/devices/cpu/events/instructions - /sys/devices/cpu/events/cpu-cycles - -Date: 2013/01/08 - -Contact: Linux kernel mailing list - -Description: Generic performance monitoring events - - A collection of performance monitoring events that may be - supported by many/most CPUs. These events can be monitored - using the 'perf(1)' tool. - - The contents of each file would look like: - - event=0xNNNN - - where 'N' is a hex digit and the number '0xNNNN' shows the - "raw code" for the perf event identified by the file's - "basename". - - -What: /sys/devices/cpu/events/PM_LD_MISS_L1 - /sys/devices/cpu/events/PM_LD_REF_L1 - /sys/devices/cpu/events/PM_CYC - /sys/devices/cpu/events/PM_BRU_FIN - /sys/devices/cpu/events/PM_GCT_NOSLOT_CYC - /sys/devices/cpu/events/PM_BRU_MPRED - /sys/devices/cpu/events/PM_INST_CMPL - /sys/devices/cpu/events/PM_CMPLU_STALL - -Date: 2013/01/08 - -Contact: Linux kernel mailing list - Linux Powerpc mailing list - -Description: POWER-systems specific performance monitoring events - - A collection of performance monitoring events that may be - supported by the POWER CPU. These events can be monitored - using the 'perf(1)' tool. - - These events may not be supported by other CPUs. - - The contents of each file would look like: - - event=0xNNNN - - where 'N' is a hex digit and the number '0xNNNN' shows the - "raw code" for the perf event identified by the file's - "basename". - - Further, multiple terms like 'event=0xNNNN' can be specified - and separated with comma. All available terms are defined in - the /sys/bus/event_source/devices//format file. diff --git a/trunk/arch/powerpc/include/asm/perf_event_server.h b/trunk/arch/powerpc/include/asm/perf_event_server.h index b29fcc651601..9710be3a2d17 100644 --- a/trunk/arch/powerpc/include/asm/perf_event_server.h +++ b/trunk/arch/powerpc/include/asm/perf_event_server.h @@ -11,7 +11,6 @@ #include #include -#include #define MAX_HWEVENTS 8 #define MAX_EVENT_ALTERNATIVES 8 @@ -36,7 +35,6 @@ struct power_pmu { void (*disable_pmc)(unsigned int pmc, unsigned long mmcr[]); int (*limited_pmc_event)(u64 event_id); u32 flags; - const struct attribute_group **attr_groups; int n_generic; int *generic_events; int (*cache_events)[PERF_COUNT_HW_CACHE_MAX] @@ -111,27 +109,3 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs); * If an event_id is not subject to the constraint expressed by a particular * field, then it will have 0 in both the mask and value for that field. */ - -extern ssize_t power_events_sysfs_show(struct device *dev, - struct device_attribute *attr, char *page); - -/* - * EVENT_VAR() is same as PMU_EVENT_VAR with a suffix. - * - * Having a suffix allows us to have aliases in sysfs - eg: the generic - * event 'cpu-cycles' can have two entries in sysfs: 'cpu-cycles' and - * 'PM_CYC' where the latter is the name by which the event is known in - * POWER CPU specification. - */ -#define EVENT_VAR(_id, _suffix) event_attr_##_id##_suffix -#define EVENT_PTR(_id, _suffix) &EVENT_VAR(_id, _suffix) - -#define EVENT_ATTR(_name, _id, _suffix) \ - PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_PM_##_id, \ - power_events_sysfs_show) - -#define GENERIC_EVENT_ATTR(_name, _id) EVENT_ATTR(_name, _id, _g) -#define GENERIC_EVENT_PTR(_id) EVENT_PTR(_id, _g) - -#define POWER_EVENT_ATTR(_name, _id) EVENT_ATTR(PM_##_name, _id, _p) -#define POWER_EVENT_PTR(_id) EVENT_PTR(_id, _p) diff --git a/trunk/arch/powerpc/perf/core-book3s.c b/trunk/arch/powerpc/perf/core-book3s.c index fa476d50791f..aa2465e21f1a 100644 --- a/trunk/arch/powerpc/perf/core-book3s.c +++ b/trunk/arch/powerpc/perf/core-book3s.c @@ -1305,16 +1305,6 @@ static int power_pmu_event_idx(struct perf_event *event) return event->hw.idx; } -ssize_t power_events_sysfs_show(struct device *dev, - struct device_attribute *attr, char *page) -{ - struct perf_pmu_events_attr *pmu_attr; - - pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); - - return sprintf(page, "event=0x%02llx\n", pmu_attr->id); -} - struct pmu power_pmu = { .pmu_enable = power_pmu_enable, .pmu_disable = power_pmu_disable, @@ -1547,8 +1537,6 @@ int __cpuinit register_power_pmu(struct power_pmu *pmu) pr_info("%s performance monitor hardware support registered\n", pmu->name); - power_pmu.attr_groups = ppmu->attr_groups; - #ifdef MSR_HV /* * Use FCHV to ignore kernel events if MSR.HV is set. diff --git a/trunk/arch/powerpc/perf/power7-pmu.c b/trunk/arch/powerpc/perf/power7-pmu.c index b554879bd31e..2ee01e38d5e2 100644 --- a/trunk/arch/powerpc/perf/power7-pmu.c +++ b/trunk/arch/powerpc/perf/power7-pmu.c @@ -50,18 +50,6 @@ #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8) #define MMCR1_PMCSEL_MSK 0xff -/* - * Power7 event codes. - */ -#define PME_PM_CYC 0x1e -#define PME_PM_GCT_NOSLOT_CYC 0x100f8 -#define PME_PM_CMPLU_STALL 0x4000a -#define PME_PM_INST_CMPL 0x2 -#define PME_PM_LD_REF_L1 0xc880 -#define PME_PM_LD_MISS_L1 0x400f0 -#define PME_PM_BRU_FIN 0x10068 -#define PME_PM_BRU_MPRED 0x400f6 - /* * Layout of constraint bits: * 6666555555555544444444443333333333222222222211111111110000000000 @@ -319,14 +307,14 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[]) } static int power7_generic_events[] = { - [PERF_COUNT_HW_CPU_CYCLES] = PME_PM_CYC, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = PME_PM_GCT_NOSLOT_CYC, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = PME_PM_CMPLU_STALL, - [PERF_COUNT_HW_INSTRUCTIONS] = PME_PM_INST_CMPL, - [PERF_COUNT_HW_CACHE_REFERENCES] = PME_PM_LD_REF_L1, - [PERF_COUNT_HW_CACHE_MISSES] = PME_PM_LD_MISS_L1, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PME_PM_BRU_FIN, - [PERF_COUNT_HW_BRANCH_MISSES] = PME_PM_BRU_MPRED, + [PERF_COUNT_HW_CPU_CYCLES] = 0x1e, + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x100f8, /* GCT_NOSLOT_CYC */ + [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x4000a, /* CMPLU_STALL */ + [PERF_COUNT_HW_INSTRUCTIONS] = 2, + [PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880, /* LD_REF_L1_LSU*/ + [PERF_COUNT_HW_CACHE_MISSES] = 0x400f0, /* LD_MISS_L1 */ + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x10068, /* BRU_FIN */ + [PERF_COUNT_HW_BRANCH_MISSES] = 0x400f6, /* BR_MPRED */ }; #define C(x) PERF_COUNT_HW_CACHE_##x @@ -374,57 +362,6 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { }, }; - -GENERIC_EVENT_ATTR(cpu-cycles, CYC); -GENERIC_EVENT_ATTR(stalled-cycles-frontend, GCT_NOSLOT_CYC); -GENERIC_EVENT_ATTR(stalled-cycles-backend, CMPLU_STALL); -GENERIC_EVENT_ATTR(instructions, INST_CMPL); -GENERIC_EVENT_ATTR(cache-references, LD_REF_L1); -GENERIC_EVENT_ATTR(cache-misses, LD_MISS_L1); -GENERIC_EVENT_ATTR(branch-instructions, BRU_FIN); -GENERIC_EVENT_ATTR(branch-misses, BRU_MPRED); - -POWER_EVENT_ATTR(CYC, CYC); -POWER_EVENT_ATTR(GCT_NOSLOT_CYC, GCT_NOSLOT_CYC); -POWER_EVENT_ATTR(CMPLU_STALL, CMPLU_STALL); -POWER_EVENT_ATTR(INST_CMPL, INST_CMPL); -POWER_EVENT_ATTR(LD_REF_L1, LD_REF_L1); -POWER_EVENT_ATTR(LD_MISS_L1, LD_MISS_L1); -POWER_EVENT_ATTR(BRU_FIN, BRU_FIN) -POWER_EVENT_ATTR(BRU_MPRED, BRU_MPRED); - -static struct attribute *power7_events_attr[] = { - GENERIC_EVENT_PTR(CYC), - GENERIC_EVENT_PTR(GCT_NOSLOT_CYC), - GENERIC_EVENT_PTR(CMPLU_STALL), - GENERIC_EVENT_PTR(INST_CMPL), - GENERIC_EVENT_PTR(LD_REF_L1), - GENERIC_EVENT_PTR(LD_MISS_L1), - GENERIC_EVENT_PTR(BRU_FIN), - GENERIC_EVENT_PTR(BRU_MPRED), - - POWER_EVENT_PTR(CYC), - POWER_EVENT_PTR(GCT_NOSLOT_CYC), - POWER_EVENT_PTR(CMPLU_STALL), - POWER_EVENT_PTR(INST_CMPL), - POWER_EVENT_PTR(LD_REF_L1), - POWER_EVENT_PTR(LD_MISS_L1), - POWER_EVENT_PTR(BRU_FIN), - POWER_EVENT_PTR(BRU_MPRED), - NULL -}; - - -static struct attribute_group power7_pmu_events_group = { - .name = "events", - .attrs = power7_events_attr, -}; - -static const struct attribute_group *power7_pmu_attr_groups[] = { - &power7_pmu_events_group, - NULL, -}; - static struct power_pmu power7_pmu = { .name = "POWER7", .n_counter = 6, @@ -436,7 +373,6 @@ static struct power_pmu power7_pmu = { .get_alternatives = power7_get_alternatives, .disable_pmc = power7_disable_pmc, .flags = PPMU_ALT_SIPR, - .attr_groups = power7_pmu_attr_groups, .n_generic = ARRAY_SIZE(power7_generic_events), .generic_events = power7_generic_events, .cache_events = &power7_cache_events, diff --git a/trunk/arch/x86/kernel/cpu/perf_event.c b/trunk/arch/x86/kernel/cpu/perf_event.c index c0df5ed2e048..6774c17a5576 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.c +++ b/trunk/arch/x86/kernel/cpu/perf_event.c @@ -1310,6 +1310,11 @@ static struct attribute_group x86_pmu_format_group = { .attrs = NULL, }; +struct perf_pmu_events_attr { + struct device_attribute attr; + u64 id; +}; + /* * Remove all undefined events (x86_pmu.event_map(id) == 0) * out of events_attr attributes. @@ -1343,9 +1348,11 @@ static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *at #define EVENT_VAR(_id) event_attr_##_id #define EVENT_PTR(_id) &event_attr_##_id.attr.attr -#define EVENT_ATTR(_name, _id) \ - PMU_EVENT_ATTR(_name, EVENT_VAR(_id), PERF_COUNT_HW_##_id, \ - events_sysfs_show) +#define EVENT_ATTR(_name, _id) \ +static struct perf_pmu_events_attr EVENT_VAR(_id) = { \ + .attr = __ATTR(_name, 0444, events_sysfs_show, NULL), \ + .id = PERF_COUNT_HW_##_id, \ +}; EVENT_ATTR(cpu-cycles, CPU_CYCLES ); EVENT_ATTR(instructions, INSTRUCTIONS ); diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index 42adf012145d..6bfb2faa0b19 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -817,17 +817,6 @@ do { \ } while (0) -struct perf_pmu_events_attr { - struct device_attribute attr; - u64 id; -}; - -#define PMU_EVENT_ATTR(_name, _var, _id, _show) \ -static struct perf_pmu_events_attr _var = { \ - .attr = __ATTR(_name, 0444, _show, NULL), \ - .id = _id, \ -}; - #define PMU_FORMAT_ATTR(_name, _format) \ static ssize_t \ _name##_show(struct device *dev, \ diff --git a/trunk/include/uapi/linux/perf_event.h b/trunk/include/uapi/linux/perf_event.h index 9fa9c622a7f4..4f63c05d27c9 100644 --- a/trunk/include/uapi/linux/perf_event.h +++ b/trunk/include/uapi/linux/perf_event.h @@ -579,8 +579,7 @@ enum perf_event_type { * { u32 size; * char data[size];}&& PERF_SAMPLE_RAW * - * { u64 nr; - * { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK + * { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK * * { u64 abi; # enum perf_sample_regs_abi * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER diff --git a/trunk/kernel/events/uprobes.c b/trunk/kernel/events/uprobes.c index 30ea9a4f4ab4..dea7acfbb071 100644 --- a/trunk/kernel/events/uprobes.c +++ b/trunk/kernel/events/uprobes.c @@ -901,7 +901,8 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume } mutex_unlock(uprobes_hash(inode)); - put_uprobe(uprobe); + if (uprobe) + put_uprobe(uprobe); } static struct rb_node * diff --git a/trunk/kernel/trace/trace.c b/trunk/kernel/trace/trace.c index d2a658349ca1..ca9b7dfed8ef 100644 --- a/trunk/kernel/trace/trace.c +++ b/trunk/kernel/trace/trace.c @@ -4506,7 +4506,7 @@ struct dentry *tracing_init_dentry(void) static struct dentry *d_percpu; -struct dentry *tracing_dentry_percpu(void) +static struct dentry *tracing_dentry_percpu(void) { static int once; struct dentry *d_tracer; diff --git a/trunk/tools/Makefile b/trunk/tools/Makefile index 798fa0ef048e..1f9a529fe544 100644 --- a/trunk/tools/Makefile +++ b/trunk/tools/Makefile @@ -15,7 +15,7 @@ help: @echo ' x86_energy_perf_policy - Intel energy policy tool' @echo '' @echo 'You can do:' - @echo ' $$ make -C tools/ _install' + @echo ' $$ make -C tools/_install' @echo '' @echo ' from the kernel command line to build and install one of' @echo ' the tools above' diff --git a/trunk/tools/lib/traceevent/event-parse.c b/trunk/tools/lib/traceevent/event-parse.c index 82b0606dcb8a..5a824e355d04 100644 --- a/trunk/tools/lib/traceevent/event-parse.c +++ b/trunk/tools/lib/traceevent/event-parse.c @@ -13,7 +13,8 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -1223,34 +1224,6 @@ static int field_is_long(struct format_field *field) return 0; } -static unsigned int type_size(const char *name) -{ - /* This covers all FIELD_IS_STRING types. */ - static struct { - const char *type; - unsigned int size; - } table[] = { - { "u8", 1 }, - { "u16", 2 }, - { "u32", 4 }, - { "u64", 8 }, - { "s8", 1 }, - { "s16", 2 }, - { "s32", 4 }, - { "s64", 8 }, - { "char", 1 }, - { }, - }; - int i; - - for (i = 0; table[i].type; i++) { - if (!strcmp(table[i].type, name)) - return table[i].size; - } - - return 0; -} - static int event_read_fields(struct event_format *event, struct format_field **fields) { struct format_field *field = NULL; @@ -1260,8 +1233,6 @@ static int event_read_fields(struct event_format *event, struct format_field **f int count = 0; do { - unsigned int size_dynamic = 0; - type = read_token(&token); if (type == EVENT_NEWLINE) { free_token(token); @@ -1420,7 +1391,6 @@ static int event_read_fields(struct event_format *event, struct format_field **f field->type = new_type; strcat(field->type, " "); strcat(field->type, field->name); - size_dynamic = type_size(field->name); free_token(field->name); strcat(field->type, brackets); field->name = token; @@ -1493,8 +1463,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f if (read_expect_type(EVENT_ITEM, &token)) goto fail; - if (strtoul(token, NULL, 0)) - field->flags |= FIELD_IS_SIGNED; + /* add signed type */ free_token(token); if (read_expected(EVENT_OP, ";") < 0) @@ -1509,14 +1478,10 @@ static int event_read_fields(struct event_format *event, struct format_field **f if (field->flags & FIELD_IS_ARRAY) { if (field->arraylen) field->elementsize = field->size / field->arraylen; - else if (field->flags & FIELD_IS_DYNAMIC) - field->elementsize = size_dynamic; else if (field->flags & FIELD_IS_STRING) field->elementsize = 1; - else if (field->flags & FIELD_IS_LONG) - field->elementsize = event->pevent ? - event->pevent->long_size : - sizeof(long); + else + field->elementsize = event->pevent->long_size; } else field->elementsize = field->size; @@ -1820,8 +1785,6 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) strcmp(token, "/") == 0 || strcmp(token, "<") == 0 || strcmp(token, ">") == 0 || - strcmp(token, "<=") == 0 || - strcmp(token, ">=") == 0 || strcmp(token, "==") == 0 || strcmp(token, "!=") == 0) { @@ -2518,7 +2481,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char ** free_token(token); arg = alloc_arg(); - if (!arg) { + if (!field) { do_warning("%s: not enough memory!", __func__); *tok = NULL; return EVENT_ERROR; diff --git a/trunk/tools/lib/traceevent/event-parse.h b/trunk/tools/lib/traceevent/event-parse.h index 7be7e89533e4..24a4bbabc5d5 100644 --- a/trunk/tools/lib/traceevent/event-parse.h +++ b/trunk/tools/lib/traceevent/event-parse.h @@ -13,7 +13,8 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/trunk/tools/lib/traceevent/event-utils.h b/trunk/tools/lib/traceevent/event-utils.h index e76c9acb92cd..bc075006966e 100644 --- a/trunk/tools/lib/traceevent/event-utils.h +++ b/trunk/tools/lib/traceevent/event-utils.h @@ -13,7 +13,8 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/trunk/tools/lib/traceevent/parse-filter.c b/trunk/tools/lib/traceevent/parse-filter.c index 2500e75583fc..5ea4326ad11f 100644 --- a/trunk/tools/lib/traceevent/parse-filter.c +++ b/trunk/tools/lib/traceevent/parse-filter.c @@ -13,7 +13,8 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/trunk/tools/lib/traceevent/parse-utils.c b/trunk/tools/lib/traceevent/parse-utils.c index bba701cf10e6..f023a133abb6 100644 --- a/trunk/tools/lib/traceevent/parse-utils.c +++ b/trunk/tools/lib/traceevent/parse-utils.c @@ -1,22 +1,3 @@ -/* - * Copyright (C) 2010 Red Hat Inc, Steven Rostedt - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License (not later!) - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ #include #include #include diff --git a/trunk/tools/lib/traceevent/trace-seq.c b/trunk/tools/lib/traceevent/trace-seq.c index a57db805136a..b1ccc923e8a5 100644 --- a/trunk/tools/lib/traceevent/trace-seq.c +++ b/trunk/tools/lib/traceevent/trace-seq.c @@ -13,7 +13,8 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ diff --git a/trunk/tools/perf/Documentation/perf-evlist.txt b/trunk/tools/perf/Documentation/perf-evlist.txt index 1ceb3700ffbb..15217345c2fa 100644 --- a/trunk/tools/perf/Documentation/perf-evlist.txt +++ b/trunk/tools/perf/Documentation/perf-evlist.txt @@ -28,10 +28,6 @@ OPTIONS --verbose=:: Show all fields. --g:: ---group:: - Show event group information. - SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-list[1], diff --git a/trunk/tools/perf/Documentation/perf-report.txt b/trunk/tools/perf/Documentation/perf-report.txt index 02284a0067f0..f4d91bebd59d 100644 --- a/trunk/tools/perf/Documentation/perf-report.txt +++ b/trunk/tools/perf/Documentation/perf-report.txt @@ -57,44 +57,11 @@ OPTIONS -s:: --sort=:: - Sort histogram entries by given key(s) - multiple keys can be specified - in CSV format. Following sort keys are available: - pid, comm, dso, symbol, parent, cpu, srcline. - - Each key has following meaning: - - - comm: command (name) of the task which can be read via /proc//comm - - pid: command and tid of the task - - dso: name of library or module executed at the time of sample - - symbol: name of function executed at the time of sample - - parent: name of function matched to the parent regex filter. Unmatched - entries are displayed as "[other]". - - cpu: cpu number the task ran at the time of sample - - srcline: filename and line number executed at the time of sample. The - DWARF debuggin info must be provided. - - By default, comm, dso and symbol keys are used. - (i.e. --sort comm,dso,symbol) - - If --branch-stack option is used, following sort keys are also - available: - dso_from, dso_to, symbol_from, symbol_to, mispredict. - - - dso_from: name of library or module branched from - - dso_to: name of library or module branched to - - symbol_from: name of function branched from - - symbol_to: name of function branched to - - mispredict: "N" for predicted branch, "Y" for mispredicted branch - - And default sort keys are changed to comm, dso_from, symbol_from, dso_to - and symbol_to, see '--branch-stack'. + Sort by key(s): pid, comm, dso, symbol, parent, srcline. -p:: --parent=:: - A regex filter to identify parent. The parent is a caller of this - function and searched through the callchain, thus it requires callchain - information recorded. The pattern is in the exteneded regex format and - defaults to "\^sys_|^do_page_fault", see '--sort parent'. + regex filter to identify parent, see: '--sort parent' -x:: --exclude-other:: @@ -107,6 +74,7 @@ OPTIONS -t:: --field-separator=:: + Use a special separator character and don't pad with spaces, replacing all occurrences of this separator in symbol names (and other output) with a '.' character, that thus it's the only non valid separator. @@ -203,9 +171,6 @@ OPTIONS --objdump=:: Path to objdump binary. ---group:: - Show event group information together. - SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-annotate[1] diff --git a/trunk/tools/perf/Documentation/perf-script-python.txt b/trunk/tools/perf/Documentation/perf-script-python.txt index 9f1f054b8432..a4027f221a53 100644 --- a/trunk/tools/perf/Documentation/perf-script-python.txt +++ b/trunk/tools/perf/Documentation/perf-script-python.txt @@ -336,6 +336,7 @@ scripts listed by the 'perf script -l' command e.g.: ---- root@tropicana:~# perf script -l List of available trace scripts: + workqueue-stats workqueue stats (ins/exe/create/destroy) wakeup-latency system-wide min/max/avg wakeup latency rw-by-file r/w activity for a program, by file rw-by-pid system-wide r/w activity @@ -401,6 +402,7 @@ should show a new entry for your script: ---- root@tropicana:~# perf script -l List of available trace scripts: + workqueue-stats workqueue stats (ins/exe/create/destroy) wakeup-latency system-wide min/max/avg wakeup latency rw-by-file r/w activity for a program, by file rw-by-pid system-wide r/w activity diff --git a/trunk/tools/perf/Documentation/perf-stat.txt b/trunk/tools/perf/Documentation/perf-stat.txt index 5289da3344e9..cf0c3107e06e 100644 --- a/trunk/tools/perf/Documentation/perf-stat.txt +++ b/trunk/tools/perf/Documentation/perf-stat.txt @@ -114,10 +114,6 @@ with it. --append may be used here. Examples: perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- make -s -j64 O=defconfig-build/ bzImage --I msecs:: ---interval-print msecs:: - print count deltas every N milliseconds (minimum: 100ms) - example: perf stat -I 1000 -e cycles -a sleep 5 EXAMPLES -------- diff --git a/trunk/tools/perf/Documentation/perf-test.txt b/trunk/tools/perf/Documentation/perf-test.txt index d1d3e5121f89..b24ac40fcd58 100644 --- a/trunk/tools/perf/Documentation/perf-test.txt +++ b/trunk/tools/perf/Documentation/perf-test.txt @@ -23,10 +23,6 @@ from 'perf test list'. OPTIONS ------- --s:: ---skip:: - Tests to skip (comma separater numeric list). - -v:: --verbose:: Be more verbose. diff --git a/trunk/tools/perf/Makefile b/trunk/tools/perf/Makefile index 4b1044cbd84c..2cbaad83a6e2 100644 --- a/trunk/tools/perf/Makefile +++ b/trunk/tools/perf/Makefile @@ -47,11 +47,10 @@ include config/utilities.mak # backtrace post unwind. # # Define NO_BACKTRACE if you do not want stack backtrace debug feature -# -# Define NO_LIBNUMA if you do not want numa perf benchmark $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) +-include $(OUTPUT)PERF-VERSION-FILE uname_M := $(shell uname -m 2>/dev/null || echo not) @@ -488,8 +487,6 @@ LIB_OBJS += $(OUTPUT)tests/rdpmc.o LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o LIB_OBJS += $(OUTPUT)tests/pmu.o -LIB_OBJS += $(OUTPUT)tests/hists_link.o -LIB_OBJS += $(OUTPUT)tests/python-use.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o @@ -535,6 +532,9 @@ ifneq ($(MAKECMDGOALS),tags) # because maintaining the nesting to match is a pain. If # we had "elif" things would have been much nicer... +-include config.mak.autogen +-include config.mak + ifdef NO_LIBELF NO_DWARF := 1 NO_DEMANGLE := 1 @@ -686,7 +686,6 @@ ifndef NO_GTK2 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) LIB_OBJS += $(OUTPUT)ui/gtk/browser.o - LIB_OBJS += $(OUTPUT)ui/gtk/hists.o LIB_OBJS += $(OUTPUT)ui/gtk/setup.o LIB_OBJS += $(OUTPUT)ui/gtk/util.o LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o @@ -840,17 +839,6 @@ ifndef NO_BACKTRACE endif endif -ifndef NO_LIBNUMA - FLAGS_LIBNUMA = $(ALL_CFLAGS) $(ALL_LDFLAGS) -lnuma - ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y) - msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); - else - BASIC_CFLAGS += -DLIBNUMA_SUPPORT - BUILTIN_OBJS += $(OUTPUT)bench/numa.o - EXTLIBS += -lnuma - endif -endif - ifdef ASCIIDOC8 export ASCIIDOC8 endif @@ -899,7 +887,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \ + $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \ '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@ @@ -963,13 +951,7 @@ $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS $(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ - '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \ - $< - -$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ - -DPYTHONPATH='"$(OUTPUT)python"' \ - -DPYTHON='"$(PYTHON_WORD)"' \ + '-DBINDIR="$(bindir_SQ)"' \ $< $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS diff --git a/trunk/tools/perf/arch/common.c b/trunk/tools/perf/arch/common.c index aacef07ebf31..3e975cb6232e 100644 --- a/trunk/tools/perf/arch/common.c +++ b/trunk/tools/perf/arch/common.c @@ -155,7 +155,6 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, if (lookup_path(buf)) goto out; free(buf); - buf = NULL; } if (!strcmp(arch, "arm")) diff --git a/trunk/tools/perf/bench/bench.h b/trunk/tools/perf/bench/bench.h index a5223e6a7b43..8f89998eeaf4 100644 --- a/trunk/tools/perf/bench/bench.h +++ b/trunk/tools/perf/bench/bench.h @@ -1,7 +1,6 @@ #ifndef BENCH_H #define BENCH_H -extern int bench_numa(int argc, const char **argv, const char *prefix); extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); extern int bench_mem_memcpy(int argc, const char **argv, diff --git a/trunk/tools/perf/bench/numa.c b/trunk/tools/perf/bench/numa.c deleted file mode 100644 index 30d1c3225b46..000000000000 --- a/trunk/tools/perf/bench/numa.c +++ /dev/null @@ -1,1731 +0,0 @@ -/* - * numa.c - * - * numa: Simulate NUMA-sensitive workload and measure their NUMA performance - */ - -#include "../perf.h" -#include "../builtin.h" -#include "../util/util.h" -#include "../util/parse-options.h" - -#include "bench.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* - * Regular printout to the terminal, supressed if -q is specified: - */ -#define tprintf(x...) do { if (g && g->p.show_details >= 0) printf(x); } while (0) - -/* - * Debug printf: - */ -#define dprintf(x...) do { if (g && g->p.show_details >= 1) printf(x); } while (0) - -struct thread_data { - int curr_cpu; - cpu_set_t bind_cpumask; - int bind_node; - u8 *process_data; - int process_nr; - int thread_nr; - int task_nr; - unsigned int loops_done; - u64 val; - u64 runtime_ns; - pthread_mutex_t *process_lock; -}; - -/* Parameters set by options: */ - -struct params { - /* Startup synchronization: */ - bool serialize_startup; - - /* Task hierarchy: */ - int nr_proc; - int nr_threads; - - /* Working set sizes: */ - const char *mb_global_str; - const char *mb_proc_str; - const char *mb_proc_locked_str; - const char *mb_thread_str; - - double mb_global; - double mb_proc; - double mb_proc_locked; - double mb_thread; - - /* Access patterns to the working set: */ - bool data_reads; - bool data_writes; - bool data_backwards; - bool data_zero_memset; - bool data_rand_walk; - u32 nr_loops; - u32 nr_secs; - u32 sleep_usecs; - - /* Working set initialization: */ - bool init_zero; - bool init_random; - bool init_cpu0; - - /* Misc options: */ - int show_details; - int run_all; - int thp; - - long bytes_global; - long bytes_process; - long bytes_process_locked; - long bytes_thread; - - int nr_tasks; - bool show_quiet; - - bool show_convergence; - bool measure_convergence; - - int perturb_secs; - int nr_cpus; - int nr_nodes; - - /* Affinity options -C and -N: */ - char *cpu_list_str; - char *node_list_str; -}; - - -/* Global, read-writable area, accessible to all processes and threads: */ - -struct global_info { - u8 *data; - - pthread_mutex_t startup_mutex; - int nr_tasks_started; - - pthread_mutex_t startup_done_mutex; - - pthread_mutex_t start_work_mutex; - int nr_tasks_working; - - pthread_mutex_t stop_work_mutex; - u64 bytes_done; - - struct thread_data *threads; - - /* Convergence latency measurement: */ - bool all_converged; - bool stop_work; - - int print_once; - - struct params p; -}; - -static struct global_info *g = NULL; - -static int parse_cpus_opt(const struct option *opt, const char *arg, int unset); -static int parse_nodes_opt(const struct option *opt, const char *arg, int unset); - -struct params p0; - -static const struct option options[] = { - OPT_INTEGER('p', "nr_proc" , &p0.nr_proc, "number of processes"), - OPT_INTEGER('t', "nr_threads" , &p0.nr_threads, "number of threads per process"), - - OPT_STRING('G', "mb_global" , &p0.mb_global_str, "MB", "global memory (MBs)"), - OPT_STRING('P', "mb_proc" , &p0.mb_proc_str, "MB", "process memory (MBs)"), - OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"), - OPT_STRING('T', "mb_thread" , &p0.mb_thread_str, "MB", "thread memory (MBs)"), - - OPT_UINTEGER('l', "nr_loops" , &p0.nr_loops, "max number of loops to run"), - OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run"), - OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"), - - OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"), - OPT_BOOLEAN('W', "data_writes" , &p0.data_writes, "access the data via writes (can be mixed with -R)"), - OPT_BOOLEAN('B', "data_backwards", &p0.data_backwards, "access the data backwards as well"), - OPT_BOOLEAN('Z', "data_zero_memset", &p0.data_zero_memset,"access the data via glibc bzero only"), - OPT_BOOLEAN('r', "data_rand_walk", &p0.data_rand_walk, "access the data with random (32bit LFSR) walk"), - - - OPT_BOOLEAN('z', "init_zero" , &p0.init_zero, "bzero the initial allocations"), - OPT_BOOLEAN('I', "init_random" , &p0.init_random, "randomize the contents of the initial allocations"), - OPT_BOOLEAN('0', "init_cpu0" , &p0.init_cpu0, "do the initial allocations on CPU#0"), - OPT_INTEGER('x', "perturb_secs", &p0.perturb_secs, "perturb thread 0/0 every X secs, to test convergence stability"), - - OPT_INCR ('d', "show_details" , &p0.show_details, "Show details"), - OPT_INCR ('a', "all" , &p0.run_all, "Run all tests in the suite"), - OPT_INTEGER('H', "thp" , &p0.thp, "MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"), - OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"), - OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"), - OPT_BOOLEAN('q', "quiet" , &p0.show_quiet, "bzero the initial allocations"), - OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"), - - /* Special option string parsing callbacks: */ - OPT_CALLBACK('C', "cpus", NULL, "cpu[,cpu2,...cpuN]", - "bind the first N tasks to these specific cpus (the rest is unbound)", - parse_cpus_opt), - OPT_CALLBACK('M', "memnodes", NULL, "node[,node2,...nodeN]", - "bind the first N tasks to these specific memory nodes (the rest is unbound)", - parse_nodes_opt), - OPT_END() -}; - -static const char * const bench_numa_usage[] = { - "perf bench numa ", - NULL -}; - -static const char * const numa_usage[] = { - "perf bench numa mem []", - NULL -}; - -static cpu_set_t bind_to_cpu(int target_cpu) -{ - cpu_set_t orig_mask, mask; - int ret; - - ret = sched_getaffinity(0, sizeof(orig_mask), &orig_mask); - BUG_ON(ret); - - CPU_ZERO(&mask); - - if (target_cpu == -1) { - int cpu; - - for (cpu = 0; cpu < g->p.nr_cpus; cpu++) - CPU_SET(cpu, &mask); - } else { - BUG_ON(target_cpu < 0 || target_cpu >= g->p.nr_cpus); - CPU_SET(target_cpu, &mask); - } - - ret = sched_setaffinity(0, sizeof(mask), &mask); - BUG_ON(ret); - - return orig_mask; -} - -static cpu_set_t bind_to_node(int target_node) -{ - int cpus_per_node = g->p.nr_cpus/g->p.nr_nodes; - cpu_set_t orig_mask, mask; - int cpu; - int ret; - - BUG_ON(cpus_per_node*g->p.nr_nodes != g->p.nr_cpus); - BUG_ON(!cpus_per_node); - - ret = sched_getaffinity(0, sizeof(orig_mask), &orig_mask); - BUG_ON(ret); - - CPU_ZERO(&mask); - - if (target_node == -1) { - for (cpu = 0; cpu < g->p.nr_cpus; cpu++) - CPU_SET(cpu, &mask); - } else { - int cpu_start = (target_node + 0) * cpus_per_node; - int cpu_stop = (target_node + 1) * cpus_per_node; - - BUG_ON(cpu_stop > g->p.nr_cpus); - - for (cpu = cpu_start; cpu < cpu_stop; cpu++) - CPU_SET(cpu, &mask); - } - - ret = sched_setaffinity(0, sizeof(mask), &mask); - BUG_ON(ret); - - return orig_mask; -} - -static void bind_to_cpumask(cpu_set_t mask) -{ - int ret; - - ret = sched_setaffinity(0, sizeof(mask), &mask); - BUG_ON(ret); -} - -static void mempol_restore(void) -{ - int ret; - - ret = set_mempolicy(MPOL_DEFAULT, NULL, g->p.nr_nodes-1); - - BUG_ON(ret); -} - -static void bind_to_memnode(int node) -{ - unsigned long nodemask; - int ret; - - if (node == -1) - return; - - BUG_ON(g->p.nr_nodes > (int)sizeof(nodemask)); - nodemask = 1L << node; - - ret = set_mempolicy(MPOL_BIND, &nodemask, sizeof(nodemask)*8); - dprintf("binding to node %d, mask: %016lx => %d\n", node, nodemask, ret); - - BUG_ON(ret); -} - -#define HPSIZE (2*1024*1024) - -#define set_taskname(fmt...) \ -do { \ - char name[20]; \ - \ - snprintf(name, 20, fmt); \ - prctl(PR_SET_NAME, name); \ -} while (0) - -static u8 *alloc_data(ssize_t bytes0, int map_flags, - int init_zero, int init_cpu0, int thp, int init_random) -{ - cpu_set_t orig_mask; - ssize_t bytes; - u8 *buf; - int ret; - - if (!bytes0) - return NULL; - - /* Allocate and initialize all memory on CPU#0: */ - if (init_cpu0) { - orig_mask = bind_to_node(0); - bind_to_memnode(0); - } - - bytes = bytes0 + HPSIZE; - - buf = (void *)mmap(0, bytes, PROT_READ|PROT_WRITE, MAP_ANON|map_flags, -1, 0); - BUG_ON(buf == (void *)-1); - - if (map_flags == MAP_PRIVATE) { - if (thp > 0) { - ret = madvise(buf, bytes, MADV_HUGEPAGE); - if (ret && !g->print_once) { - g->print_once = 1; - printf("WARNING: Could not enable THP - do: 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled'\n"); - } - } - if (thp < 0) { - ret = madvise(buf, bytes, MADV_NOHUGEPAGE); - if (ret && !g->print_once) { - g->print_once = 1; - printf("WARNING: Could not disable THP: run a CONFIG_TRANSPARENT_HUGEPAGE kernel?\n"); - } - } - } - - if (init_zero) { - bzero(buf, bytes); - } else { - /* Initialize random contents, different in each word: */ - if (init_random) { - u64 *wbuf = (void *)buf; - long off = rand(); - long i; - - for (i = 0; i < bytes/8; i++) - wbuf[i] = i + off; - } - } - - /* Align to 2MB boundary: */ - buf = (void *)(((unsigned long)buf + HPSIZE-1) & ~(HPSIZE-1)); - - /* Restore affinity: */ - if (init_cpu0) { - bind_to_cpumask(orig_mask); - mempol_restore(); - } - - return buf; -} - -static void free_data(void *data, ssize_t bytes) -{ - int ret; - - if (!data) - return; - - ret = munmap(data, bytes); - BUG_ON(ret); -} - -/* - * Create a shared memory buffer that can be shared between processes, zeroed: - */ -static void * zalloc_shared_data(ssize_t bytes) -{ - return alloc_data(bytes, MAP_SHARED, 1, g->p.init_cpu0, g->p.thp, g->p.init_random); -} - -/* - * Create a shared memory buffer that can be shared between processes: - */ -static void * setup_shared_data(ssize_t bytes) -{ - return alloc_data(bytes, MAP_SHARED, 0, g->p.init_cpu0, g->p.thp, g->p.init_random); -} - -/* - * Allocate process-local memory - this will either be shared between - * threads of this process, or only be accessed by this thread: - */ -static void * setup_private_data(ssize_t bytes) -{ - return alloc_data(bytes, MAP_PRIVATE, 0, g->p.init_cpu0, g->p.thp, g->p.init_random); -} - -/* - * Return a process-shared (global) mutex: - */ -static void init_global_mutex(pthread_mutex_t *mutex) -{ - pthread_mutexattr_t attr; - - pthread_mutexattr_init(&attr); - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); - pthread_mutex_init(mutex, &attr); -} - -static int parse_cpu_list(const char *arg) -{ - p0.cpu_list_str = strdup(arg); - - dprintf("got CPU list: {%s}\n", p0.cpu_list_str); - - return 0; -} - -static void parse_setup_cpu_list(void) -{ - struct thread_data *td; - char *str0, *str; - int t; - - if (!g->p.cpu_list_str) - return; - - dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); - - str0 = str = strdup(g->p.cpu_list_str); - t = 0; - - BUG_ON(!str); - - tprintf("# binding tasks to CPUs:\n"); - tprintf("# "); - - while (true) { - int bind_cpu, bind_cpu_0, bind_cpu_1; - char *tok, *tok_end, *tok_step, *tok_len, *tok_mul; - int bind_len; - int step; - int mul; - - tok = strsep(&str, ","); - if (!tok) - break; - - tok_end = strstr(tok, "-"); - - dprintf("\ntoken: {%s}, end: {%s}\n", tok, tok_end); - if (!tok_end) { - /* Single CPU specified: */ - bind_cpu_0 = bind_cpu_1 = atol(tok); - } else { - /* CPU range specified (for example: "5-11"): */ - bind_cpu_0 = atol(tok); - bind_cpu_1 = atol(tok_end + 1); - } - - step = 1; - tok_step = strstr(tok, "#"); - if (tok_step) { - step = atol(tok_step + 1); - BUG_ON(step <= 0 || step >= g->p.nr_cpus); - } - - /* - * Mask length. - * Eg: "--cpus 8_4-16#4" means: '--cpus 8_4,12_4,16_4', - * where the _4 means the next 4 CPUs are allowed. - */ - bind_len = 1; - tok_len = strstr(tok, "_"); - if (tok_len) { - bind_len = atol(tok_len + 1); - BUG_ON(bind_len <= 0 || bind_len > g->p.nr_cpus); - } - - /* Multiplicator shortcut, "0x8" is a shortcut for: "0,0,0,0,0,0,0,0" */ - mul = 1; - tok_mul = strstr(tok, "x"); - if (tok_mul) { - mul = atol(tok_mul + 1); - BUG_ON(mul <= 0); - } - - dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul); - - BUG_ON(bind_cpu_0 < 0 || bind_cpu_0 >= g->p.nr_cpus); - BUG_ON(bind_cpu_1 < 0 || bind_cpu_1 >= g->p.nr_cpus); - BUG_ON(bind_cpu_0 > bind_cpu_1); - - for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) { - int i; - - for (i = 0; i < mul; i++) { - int cpu; - - if (t >= g->p.nr_tasks) { - printf("\n# NOTE: ignoring bind CPUs starting at CPU#%d\n #", bind_cpu); - goto out; - } - td = g->threads + t; - - if (t) - tprintf(","); - if (bind_len > 1) { - tprintf("%2d/%d", bind_cpu, bind_len); - } else { - tprintf("%2d", bind_cpu); - } - - CPU_ZERO(&td->bind_cpumask); - for (cpu = bind_cpu; cpu < bind_cpu+bind_len; cpu++) { - BUG_ON(cpu < 0 || cpu >= g->p.nr_cpus); - CPU_SET(cpu, &td->bind_cpumask); - } - t++; - } - } - } -out: - - tprintf("\n"); - - if (t < g->p.nr_tasks) - printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t); - - free(str0); -} - -static int parse_cpus_opt(const struct option *opt __maybe_unused, - const char *arg, int unset __maybe_unused) -{ - if (!arg) - return -1; - - return parse_cpu_list(arg); -} - -static int parse_node_list(const char *arg) -{ - p0.node_list_str = strdup(arg); - - dprintf("got NODE list: {%s}\n", p0.node_list_str); - - return 0; -} - -static void parse_setup_node_list(void) -{ - struct thread_data *td; - char *str0, *str; - int t; - - if (!g->p.node_list_str) - return; - - dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); - - str0 = str = strdup(g->p.node_list_str); - t = 0; - - BUG_ON(!str); - - tprintf("# binding tasks to NODEs:\n"); - tprintf("# "); - - while (true) { - int bind_node, bind_node_0, bind_node_1; - char *tok, *tok_end, *tok_step, *tok_mul; - int step; - int mul; - - tok = strsep(&str, ","); - if (!tok) - break; - - tok_end = strstr(tok, "-"); - - dprintf("\ntoken: {%s}, end: {%s}\n", tok, tok_end); - if (!tok_end) { - /* Single NODE specified: */ - bind_node_0 = bind_node_1 = atol(tok); - } else { - /* NODE range specified (for example: "5-11"): */ - bind_node_0 = atol(tok); - bind_node_1 = atol(tok_end + 1); - } - - step = 1; - tok_step = strstr(tok, "#"); - if (tok_step) { - step = atol(tok_step + 1); - BUG_ON(step <= 0 || step >= g->p.nr_nodes); - } - - /* Multiplicator shortcut, "0x8" is a shortcut for: "0,0,0,0,0,0,0,0" */ - mul = 1; - tok_mul = strstr(tok, "x"); - if (tok_mul) { - mul = atol(tok_mul + 1); - BUG_ON(mul <= 0); - } - - dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step); - - BUG_ON(bind_node_0 < 0 || bind_node_0 >= g->p.nr_nodes); - BUG_ON(bind_node_1 < 0 || bind_node_1 >= g->p.nr_nodes); - BUG_ON(bind_node_0 > bind_node_1); - - for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) { - int i; - - for (i = 0; i < mul; i++) { - if (t >= g->p.nr_tasks) { - printf("\n# NOTE: ignoring bind NODEs starting at NODE#%d\n", bind_node); - goto out; - } - td = g->threads + t; - - if (!t) - tprintf(" %2d", bind_node); - else - tprintf(",%2d", bind_node); - - td->bind_node = bind_node; - t++; - } - } - } -out: - - tprintf("\n"); - - if (t < g->p.nr_tasks) - printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t); - - free(str0); -} - -static int parse_nodes_opt(const struct option *opt __maybe_unused, - const char *arg, int unset __maybe_unused) -{ - if (!arg) - return -1; - - return parse_node_list(arg); - - return 0; -} - -#define BIT(x) (1ul << x) - -static inline uint32_t lfsr_32(uint32_t lfsr) -{ - const uint32_t taps = BIT(1) | BIT(5) | BIT(6) | BIT(31); - return (lfsr>>1) ^ ((0x0u - (lfsr & 0x1u)) & taps); -} - -/* - * Make sure there's real data dependency to RAM (when read - * accesses are enabled), so the compiler, the CPU and the - * kernel (KSM, zero page, etc.) cannot optimize away RAM - * accesses: - */ -static inline u64 access_data(u64 *data __attribute__((unused)), u64 val) -{ - if (g->p.data_reads) - val += *data; - if (g->p.data_writes) - *data = val + 1; - return val; -} - -/* - * The worker process does two types of work, a forwards going - * loop and a backwards going loop. - * - * We do this so that on multiprocessor systems we do not create - * a 'train' of processing, with highly synchronized processes, - * skewing the whole benchmark. - */ -static u64 do_work(u8 *__data, long bytes, int nr, int nr_max, int loop, u64 val) -{ - long words = bytes/sizeof(u64); - u64 *data = (void *)__data; - long chunk_0, chunk_1; - u64 *d0, *d, *d1; - long off; - long i; - - BUG_ON(!data && words); - BUG_ON(data && !words); - - if (!data) - return val; - - /* Very simple memset() work variant: */ - if (g->p.data_zero_memset && !g->p.data_rand_walk) { - bzero(data, bytes); - return val; - } - - /* Spread out by PID/TID nr and by loop nr: */ - chunk_0 = words/nr_max; - chunk_1 = words/g->p.nr_loops; - off = nr*chunk_0 + loop*chunk_1; - - while (off >= words) - off -= words; - - if (g->p.data_rand_walk) { - u32 lfsr = nr + loop + val; - int j; - - for (i = 0; i < words/1024; i++) { - long start, end; - - lfsr = lfsr_32(lfsr); - - start = lfsr % words; - end = min(start + 1024, words-1); - - if (g->p.data_zero_memset) { - bzero(data + start, (end-start) * sizeof(u64)); - } else { - for (j = start; j < end; j++) - val = access_data(data + j, val); - } - } - } else if (!g->p.data_backwards || (nr + loop) & 1) { - - d0 = data + off; - d = data + off + 1; - d1 = data + words; - - /* Process data forwards: */ - for (;;) { - if (unlikely(d >= d1)) - d = data; - if (unlikely(d == d0)) - break; - - val = access_data(d, val); - - d++; - } - } else { - /* Process data backwards: */ - - d0 = data + off; - d = data + off - 1; - d1 = data + words; - - /* Process data forwards: */ - for (;;) { - if (unlikely(d < data)) - d = data + words-1; - if (unlikely(d == d0)) - break; - - val = access_data(d, val); - - d--; - } - } - - return val; -} - -static void update_curr_cpu(int task_nr, unsigned long bytes_worked) -{ - unsigned int cpu; - - cpu = sched_getcpu(); - - g->threads[task_nr].curr_cpu = cpu; - prctl(0, bytes_worked); -} - -#define MAX_NR_NODES 64 - -/* - * Count the number of nodes a process's threads - * are spread out on. - * - * A count of 1 means that the process is compressed - * to a single node. A count of g->p.nr_nodes means it's - * spread out on the whole system. - */ -static int count_process_nodes(int process_nr) -{ - char node_present[MAX_NR_NODES] = { 0, }; - int nodes; - int n, t; - - for (t = 0; t < g->p.nr_threads; t++) { - struct thread_data *td; - int task_nr; - int node; - - task_nr = process_nr*g->p.nr_threads + t; - td = g->threads + task_nr; - - node = numa_node_of_cpu(td->curr_cpu); - node_present[node] = 1; - } - - nodes = 0; - - for (n = 0; n < MAX_NR_NODES; n++) - nodes += node_present[n]; - - return nodes; -} - -/* - * Count the number of distinct process-threads a node contains. - * - * A count of 1 means that the node contains only a single - * process. If all nodes on the system contain at most one - * process then we are well-converged. - */ -static int count_node_processes(int node) -{ - int processes = 0; - int t, p; - - for (p = 0; p < g->p.nr_proc; p++) { - for (t = 0; t < g->p.nr_threads; t++) { - struct thread_data *td; - int task_nr; - int n; - - task_nr = p*g->p.nr_threads + t; - td = g->threads + task_nr; - - n = numa_node_of_cpu(td->curr_cpu); - if (n == node) { - processes++; - break; - } - } - } - - return processes; -} - -static void calc_convergence_compression(int *strong) -{ - unsigned int nodes_min, nodes_max; - int p; - - nodes_min = -1; - nodes_max = 0; - - for (p = 0; p < g->p.nr_proc; p++) { - unsigned int nodes = count_process_nodes(p); - - nodes_min = min(nodes, nodes_min); - nodes_max = max(nodes, nodes_max); - } - - /* Strong convergence: all threads compress on a single node: */ - if (nodes_min == 1 && nodes_max == 1) { - *strong = 1; - } else { - *strong = 0; - tprintf(" {%d-%d}", nodes_min, nodes_max); - } -} - -static void calc_convergence(double runtime_ns_max, double *convergence) -{ - unsigned int loops_done_min, loops_done_max; - int process_groups; - int nodes[MAX_NR_NODES]; - int distance; - int nr_min; - int nr_max; - int strong; - int sum; - int nr; - int node; - int cpu; - int t; - - if (!g->p.show_convergence && !g->p.measure_convergence) - return; - - for (node = 0; node < g->p.nr_nodes; node++) - nodes[node] = 0; - - loops_done_min = -1; - loops_done_max = 0; - - for (t = 0; t < g->p.nr_tasks; t++) { - struct thread_data *td = g->threads + t; - unsigned int loops_done; - - cpu = td->curr_cpu; - - /* Not all threads have written it yet: */ - if (cpu < 0) - continue; - - node = numa_node_of_cpu(cpu); - - nodes[node]++; - - loops_done = td->loops_done; - loops_done_min = min(loops_done, loops_done_min); - loops_done_max = max(loops_done, loops_done_max); - } - - nr_max = 0; - nr_min = g->p.nr_tasks; - sum = 0; - - for (node = 0; node < g->p.nr_nodes; node++) { - nr = nodes[node]; - nr_min = min(nr, nr_min); - nr_max = max(nr, nr_max); - sum += nr; - } - BUG_ON(nr_min > nr_max); - - BUG_ON(sum > g->p.nr_tasks); - - if (0 && (sum < g->p.nr_tasks)) - return; - - /* - * Count the number of distinct process groups present - * on nodes - when we are converged this will decrease - * to g->p.nr_proc: - */ - process_groups = 0; - - for (node = 0; node < g->p.nr_nodes; node++) { - int processes = count_node_processes(node); - - nr = nodes[node]; - tprintf(" %2d/%-2d", nr, processes); - - process_groups += processes; - } - - distance = nr_max - nr_min; - - tprintf(" [%2d/%-2d]", distance, process_groups); - - tprintf(" l:%3d-%-3d (%3d)", - loops_done_min, loops_done_max, loops_done_max-loops_done_min); - - if (loops_done_min && loops_done_max) { - double skew = 1.0 - (double)loops_done_min/loops_done_max; - - tprintf(" [%4.1f%%]", skew * 100.0); - } - - calc_convergence_compression(&strong); - - if (strong && process_groups == g->p.nr_proc) { - if (!*convergence) { - *convergence = runtime_ns_max; - tprintf(" (%6.1fs converged)\n", *convergence/1e9); - if (g->p.measure_convergence) { - g->all_converged = true; - g->stop_work = true; - } - } - } else { - if (*convergence) { - tprintf(" (%6.1fs de-converged)", runtime_ns_max/1e9); - *convergence = 0; - } - tprintf("\n"); - } -} - -static void show_summary(double runtime_ns_max, int l, double *convergence) -{ - tprintf("\r # %5.1f%% [%.1f mins]", - (double)(l+1)/g->p.nr_loops*100.0, runtime_ns_max/1e9 / 60.0); - - calc_convergence(runtime_ns_max, convergence); - - if (g->p.show_details >= 0) - fflush(stdout); -} - -static void *worker_thread(void *__tdata) -{ - struct thread_data *td = __tdata; - struct timeval start0, start, stop, diff; - int process_nr = td->process_nr; - int thread_nr = td->thread_nr; - unsigned long last_perturbance; - int task_nr = td->task_nr; - int details = g->p.show_details; - int first_task, last_task; - double convergence = 0; - u64 val = td->val; - double runtime_ns_max; - u8 *global_data; - u8 *process_data; - u8 *thread_data; - u64 bytes_done; - long work_done; - u32 l; - - bind_to_cpumask(td->bind_cpumask); - bind_to_memnode(td->bind_node); - - set_taskname("thread %d/%d", process_nr, thread_nr); - - global_data = g->data; - process_data = td->process_data; - thread_data = setup_private_data(g->p.bytes_thread); - - bytes_done = 0; - - last_task = 0; - if (process_nr == g->p.nr_proc-1 && thread_nr == g->p.nr_threads-1) - last_task = 1; - - first_task = 0; - if (process_nr == 0 && thread_nr == 0) - first_task = 1; - - if (details >= 2) { - printf("# thread %2d / %2d global mem: %p, process mem: %p, thread mem: %p\n", - process_nr, thread_nr, global_data, process_data, thread_data); - } - - if (g->p.serialize_startup) { - pthread_mutex_lock(&g->startup_mutex); - g->nr_tasks_started++; - pthread_mutex_unlock(&g->startup_mutex); - - /* Here we will wait for the main process to start us all at once: */ - pthread_mutex_lock(&g->start_work_mutex); - g->nr_tasks_working++; - - /* Last one wake the main process: */ - if (g->nr_tasks_working == g->p.nr_tasks) - pthread_mutex_unlock(&g->startup_done_mutex); - - pthread_mutex_unlock(&g->start_work_mutex); - } - - gettimeofday(&start0, NULL); - - start = stop = start0; - last_perturbance = start.tv_sec; - - for (l = 0; l < g->p.nr_loops; l++) { - start = stop; - - if (g->stop_work) - break; - - val += do_work(global_data, g->p.bytes_global, process_nr, g->p.nr_proc, l, val); - val += do_work(process_data, g->p.bytes_process, thread_nr, g->p.nr_threads, l, val); - val += do_work(thread_data, g->p.bytes_thread, 0, 1, l, val); - - if (g->p.sleep_usecs) { - pthread_mutex_lock(td->process_lock); - usleep(g->p.sleep_usecs); - pthread_mutex_unlock(td->process_lock); - } - /* - * Amount of work to be done under a process-global lock: - */ - if (g->p.bytes_process_locked) { - pthread_mutex_lock(td->process_lock); - val += do_work(process_data, g->p.bytes_process_locked, thread_nr, g->p.nr_threads, l, val); - pthread_mutex_unlock(td->process_lock); - } - - work_done = g->p.bytes_global + g->p.bytes_process + - g->p.bytes_process_locked + g->p.bytes_thread; - - update_curr_cpu(task_nr, work_done); - bytes_done += work_done; - - if (details < 0 && !g->p.perturb_secs && !g->p.measure_convergence && !g->p.nr_secs) - continue; - - td->loops_done = l; - - gettimeofday(&stop, NULL); - - /* Check whether our max runtime timed out: */ - if (g->p.nr_secs) { - timersub(&stop, &start0, &diff); - if (diff.tv_sec >= g->p.nr_secs) { - g->stop_work = true; - break; - } - } - - /* Update the summary at most once per second: */ - if (start.tv_sec == stop.tv_sec) - continue; - - /* - * Perturb the first task's equilibrium every g->p.perturb_secs seconds, - * by migrating to CPU#0: - */ - if (first_task && g->p.perturb_secs && (int)(stop.tv_sec - last_perturbance) >= g->p.perturb_secs) { - cpu_set_t orig_mask; - int target_cpu; - int this_cpu; - - last_perturbance = stop.tv_sec; - - /* - * Depending on where we are running, move into - * the other half of the system, to create some - * real disturbance: - */ - this_cpu = g->threads[task_nr].curr_cpu; - if (this_cpu < g->p.nr_cpus/2) - target_cpu = g->p.nr_cpus-1; - else - target_cpu = 0; - - orig_mask = bind_to_cpu(target_cpu); - - /* Here we are running on the target CPU already */ - if (details >= 1) - printf(" (injecting perturbalance, moved to CPU#%d)\n", target_cpu); - - bind_to_cpumask(orig_mask); - } - - if (details >= 3) { - timersub(&stop, &start, &diff); - runtime_ns_max = diff.tv_sec * 1000000000; - runtime_ns_max += diff.tv_usec * 1000; - - if (details >= 0) { - printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016lx]\n", - process_nr, thread_nr, runtime_ns_max / bytes_done, val); - } - fflush(stdout); - } - if (!last_task) - continue; - - timersub(&stop, &start0, &diff); - runtime_ns_max = diff.tv_sec * 1000000000ULL; - runtime_ns_max += diff.tv_usec * 1000ULL; - - show_summary(runtime_ns_max, l, &convergence); - } - - gettimeofday(&stop, NULL); - timersub(&stop, &start0, &diff); - td->runtime_ns = diff.tv_sec * 1000000000ULL; - td->runtime_ns += diff.tv_usec * 1000ULL; - - free_data(thread_data, g->p.bytes_thread); - - pthread_mutex_lock(&g->stop_work_mutex); - g->bytes_done += bytes_done; - pthread_mutex_unlock(&g->stop_work_mutex); - - return NULL; -} - -/* - * A worker process starts a couple of threads: - */ -static void worker_process(int process_nr) -{ - pthread_mutex_t process_lock; - struct thread_data *td; - pthread_t *pthreads; - u8 *process_data; - int task_nr; - int ret; - int t; - - pthread_mutex_init(&process_lock, NULL); - set_taskname("process %d", process_nr); - - /* - * Pick up the memory policy and the CPU binding of our first thread, - * so that we initialize memory accordingly: - */ - task_nr = process_nr*g->p.nr_threads; - td = g->threads + task_nr; - - bind_to_memnode(td->bind_node); - bind_to_cpumask(td->bind_cpumask); - - pthreads = zalloc(g->p.nr_threads * sizeof(pthread_t)); - process_data = setup_private_data(g->p.bytes_process); - - if (g->p.show_details >= 3) { - printf(" # process %2d global mem: %p, process mem: %p\n", - process_nr, g->data, process_data); - } - - for (t = 0; t < g->p.nr_threads; t++) { - task_nr = process_nr*g->p.nr_threads + t; - td = g->threads + task_nr; - - td->process_data = process_data; - td->process_nr = process_nr; - td->thread_nr = t; - td->task_nr = task_nr; - td->val = rand(); - td->curr_cpu = -1; - td->process_lock = &process_lock; - - ret = pthread_create(pthreads + t, NULL, worker_thread, td); - BUG_ON(ret); - } - - for (t = 0; t < g->p.nr_threads; t++) { - ret = pthread_join(pthreads[t], NULL); - BUG_ON(ret); - } - - free_data(process_data, g->p.bytes_process); - free(pthreads); -} - -static void print_summary(void) -{ - if (g->p.show_details < 0) - return; - - printf("\n ###\n"); - printf(" # %d %s will execute (on %d nodes, %d CPUs):\n", - g->p.nr_tasks, g->p.nr_tasks == 1 ? "task" : "tasks", g->p.nr_nodes, g->p.nr_cpus); - printf(" # %5dx %5ldMB global shared mem operations\n", - g->p.nr_loops, g->p.bytes_global/1024/1024); - printf(" # %5dx %5ldMB process shared mem operations\n", - g->p.nr_loops, g->p.bytes_process/1024/1024); - printf(" # %5dx %5ldMB thread local mem operations\n", - g->p.nr_loops, g->p.bytes_thread/1024/1024); - - printf(" ###\n"); - - printf("\n ###\n"); fflush(stdout); -} - -static void init_thread_data(void) -{ - ssize_t size = sizeof(*g->threads)*g->p.nr_tasks; - int t; - - g->threads = zalloc_shared_data(size); - - for (t = 0; t < g->p.nr_tasks; t++) { - struct thread_data *td = g->threads + t; - int cpu; - - /* Allow all nodes by default: */ - td->bind_node = -1; - - /* Allow all CPUs by default: */ - CPU_ZERO(&td->bind_cpumask); - for (cpu = 0; cpu < g->p.nr_cpus; cpu++) - CPU_SET(cpu, &td->bind_cpumask); - } -} - -static void deinit_thread_data(void) -{ - ssize_t size = sizeof(*g->threads)*g->p.nr_tasks; - - free_data(g->threads, size); -} - -static int init(void) -{ - g = (void *)alloc_data(sizeof(*g), MAP_SHARED, 1, 0, 0 /* THP */, 0); - - /* Copy over options: */ - g->p = p0; - - g->p.nr_cpus = numa_num_configured_cpus(); - - g->p.nr_nodes = numa_max_node() + 1; - - /* char array in count_process_nodes(): */ - BUG_ON(g->p.nr_nodes > MAX_NR_NODES || g->p.nr_nodes < 0); - - if (g->p.show_quiet && !g->p.show_details) - g->p.show_details = -1; - - /* Some memory should be specified: */ - if (!g->p.mb_global_str && !g->p.mb_proc_str && !g->p.mb_thread_str) - return -1; - - if (g->p.mb_global_str) { - g->p.mb_global = atof(g->p.mb_global_str); - BUG_ON(g->p.mb_global < 0); - } - - if (g->p.mb_proc_str) { - g->p.mb_proc = atof(g->p.mb_proc_str); - BUG_ON(g->p.mb_proc < 0); - } - - if (g->p.mb_proc_locked_str) { - g->p.mb_proc_locked = atof(g->p.mb_proc_locked_str); - BUG_ON(g->p.mb_proc_locked < 0); - BUG_ON(g->p.mb_proc_locked > g->p.mb_proc); - } - - if (g->p.mb_thread_str) { - g->p.mb_thread = atof(g->p.mb_thread_str); - BUG_ON(g->p.mb_thread < 0); - } - - BUG_ON(g->p.nr_threads <= 0); - BUG_ON(g->p.nr_proc <= 0); - - g->p.nr_tasks = g->p.nr_proc*g->p.nr_threads; - - g->p.bytes_global = g->p.mb_global *1024L*1024L; - g->p.bytes_process = g->p.mb_proc *1024L*1024L; - g->p.bytes_process_locked = g->p.mb_proc_locked *1024L*1024L; - g->p.bytes_thread = g->p.mb_thread *1024L*1024L; - - g->data = setup_shared_data(g->p.bytes_global); - - /* Startup serialization: */ - init_global_mutex(&g->start_work_mutex); - init_global_mutex(&g->startup_mutex); - init_global_mutex(&g->startup_done_mutex); - init_global_mutex(&g->stop_work_mutex); - - init_thread_data(); - - tprintf("#\n"); - parse_setup_cpu_list(); - parse_setup_node_list(); - tprintf("#\n"); - - print_summary(); - - return 0; -} - -static void deinit(void) -{ - free_data(g->data, g->p.bytes_global); - g->data = NULL; - - deinit_thread_data(); - - free_data(g, sizeof(*g)); - g = NULL; -} - -/* - * Print a short or long result, depending on the verbosity setting: - */ -static void print_res(const char *name, double val, - const char *txt_unit, const char *txt_short, const char *txt_long) -{ - if (!name) - name = "main,"; - - if (g->p.show_quiet) - printf(" %-30s %15.3f, %-15s %s\n", name, val, txt_unit, txt_short); - else - printf(" %14.3f %s\n", val, txt_long); -} - -static int __bench_numa(const char *name) -{ - struct timeval start, stop, diff; - u64 runtime_ns_min, runtime_ns_sum; - pid_t *pids, pid, wpid; - double delta_runtime; - double runtime_avg; - double runtime_sec_max; - double runtime_sec_min; - int wait_stat; - double bytes; - int i, t; - - if (init()) - return -1; - - pids = zalloc(g->p.nr_proc * sizeof(*pids)); - pid = -1; - - /* All threads try to acquire it, this way we can wait for them to start up: */ - pthread_mutex_lock(&g->start_work_mutex); - - if (g->p.serialize_startup) { - tprintf(" #\n"); - tprintf(" # Startup synchronization: ..."); fflush(stdout); - } - - gettimeofday(&start, NULL); - - for (i = 0; i < g->p.nr_proc; i++) { - pid = fork(); - dprintf(" # process %2d: PID %d\n", i, pid); - - BUG_ON(pid < 0); - if (!pid) { - /* Child process: */ - worker_process(i); - - exit(0); - } - pids[i] = pid; - - } - /* Wait for all the threads to start up: */ - while (g->nr_tasks_started != g->p.nr_tasks) - usleep(1000); - - BUG_ON(g->nr_tasks_started != g->p.nr_tasks); - - if (g->p.serialize_startup) { - double startup_sec; - - pthread_mutex_lock(&g->startup_done_mutex); - - /* This will start all threads: */ - pthread_mutex_unlock(&g->start_work_mutex); - - /* This mutex is locked - the last started thread will wake us: */ - pthread_mutex_lock(&g->startup_done_mutex); - - gettimeofday(&stop, NULL); - - timersub(&stop, &start, &diff); - - startup_sec = diff.tv_sec * 1000000000.0; - startup_sec += diff.tv_usec * 1000.0; - startup_sec /= 1e9; - - tprintf(" threads initialized in %.6f seconds.\n", startup_sec); - tprintf(" #\n"); - - start = stop; - pthread_mutex_unlock(&g->startup_done_mutex); - } else { - gettimeofday(&start, NULL); - } - - /* Parent process: */ - - - for (i = 0; i < g->p.nr_proc; i++) { - wpid = waitpid(pids[i], &wait_stat, 0); - BUG_ON(wpid < 0); - BUG_ON(!WIFEXITED(wait_stat)); - - } - - runtime_ns_sum = 0; - runtime_ns_min = -1LL; - - for (t = 0; t < g->p.nr_tasks; t++) { - u64 thread_runtime_ns = g->threads[t].runtime_ns; - - runtime_ns_sum += thread_runtime_ns; - runtime_ns_min = min(thread_runtime_ns, runtime_ns_min); - } - - gettimeofday(&stop, NULL); - timersub(&stop, &start, &diff); - - BUG_ON(bench_format != BENCH_FORMAT_DEFAULT); - - tprintf("\n ###\n"); - tprintf("\n"); - - runtime_sec_max = diff.tv_sec * 1000000000.0; - runtime_sec_max += diff.tv_usec * 1000.0; - runtime_sec_max /= 1e9; - - runtime_sec_min = runtime_ns_min/1e9; - - bytes = g->bytes_done; - runtime_avg = (double)runtime_ns_sum / g->p.nr_tasks / 1e9; - - if (g->p.measure_convergence) { - print_res(name, runtime_sec_max, - "secs,", "NUMA-convergence-latency", "secs latency to NUMA-converge"); - } - - print_res(name, runtime_sec_max, - "secs,", "runtime-max/thread", "secs slowest (max) thread-runtime"); - - print_res(name, runtime_sec_min, - "secs,", "runtime-min/thread", "secs fastest (min) thread-runtime"); - - print_res(name, runtime_avg, - "secs,", "runtime-avg/thread", "secs average thread-runtime"); - - delta_runtime = (runtime_sec_max - runtime_sec_min)/2.0; - print_res(name, delta_runtime / runtime_sec_max * 100.0, - "%,", "spread-runtime/thread", "% difference between max/avg runtime"); - - print_res(name, bytes / g->p.nr_tasks / 1e9, - "GB,", "data/thread", "GB data processed, per thread"); - - print_res(name, bytes / 1e9, - "GB,", "data-total", "GB data processed, total"); - - print_res(name, runtime_sec_max * 1e9 / (bytes / g->p.nr_tasks), - "nsecs,", "runtime/byte/thread","nsecs/byte/thread runtime"); - - print_res(name, bytes / g->p.nr_tasks / 1e9 / runtime_sec_max, - "GB/sec,", "thread-speed", "GB/sec/thread speed"); - - print_res(name, bytes / runtime_sec_max / 1e9, - "GB/sec,", "total-speed", "GB/sec total speed"); - - free(pids); - - deinit(); - - return 0; -} - -#define MAX_ARGS 50 - -static int command_size(const char **argv) -{ - int size = 0; - - while (*argv) { - size++; - argv++; - } - - BUG_ON(size >= MAX_ARGS); - - return size; -} - -static void init_params(struct params *p, const char *name, int argc, const char **argv) -{ - int i; - - printf("\n # Running %s \"perf bench numa", name); - - for (i = 0; i < argc; i++) - printf(" %s", argv[i]); - - printf("\"\n"); - - memset(p, 0, sizeof(*p)); - - /* Initialize nonzero defaults: */ - - p->serialize_startup = 1; - p->data_reads = true; - p->data_writes = true; - p->data_backwards = true; - p->data_rand_walk = true; - p->nr_loops = -1; - p->init_random = true; -} - -static int run_bench_numa(const char *name, const char **argv) -{ - int argc = command_size(argv); - - init_params(&p0, name, argc, argv); - argc = parse_options(argc, argv, options, bench_numa_usage, 0); - if (argc) - goto err; - - if (__bench_numa(name)) - goto err; - - return 0; - -err: - usage_with_options(numa_usage, options); - return -1; -} - -#define OPT_BW_RAM "-s", "20", "-zZq", "--thp", " 1", "--no-data_rand_walk" -#define OPT_BW_RAM_NOTHP OPT_BW_RAM, "--thp", "-1" - -#define OPT_CONV "-s", "100", "-zZ0qcm", "--thp", " 1" -#define OPT_CONV_NOTHP OPT_CONV, "--thp", "-1" - -#define OPT_BW "-s", "20", "-zZ0q", "--thp", " 1" -#define OPT_BW_NOTHP OPT_BW, "--thp", "-1" - -/* - * The built-in test-suite executed by "perf bench numa -a". - * - * (A minimum of 4 nodes and 16 GB of RAM is recommended.) - */ -static const char *tests[][MAX_ARGS] = { - /* Basic single-stream NUMA bandwidth measurements: */ - { "RAM-bw-local,", "mem", "-p", "1", "-t", "1", "-P", "1024", - "-C" , "0", "-M", "0", OPT_BW_RAM }, - { "RAM-bw-local-NOTHP,", - "mem", "-p", "1", "-t", "1", "-P", "1024", - "-C" , "0", "-M", "0", OPT_BW_RAM_NOTHP }, - { "RAM-bw-remote,", "mem", "-p", "1", "-t", "1", "-P", "1024", - "-C" , "0", "-M", "1", OPT_BW_RAM }, - - /* 2-stream NUMA bandwidth measurements: */ - { "RAM-bw-local-2x,", "mem", "-p", "2", "-t", "1", "-P", "1024", - "-C", "0,2", "-M", "0x2", OPT_BW_RAM }, - { "RAM-bw-remote-2x,", "mem", "-p", "2", "-t", "1", "-P", "1024", - "-C", "0,2", "-M", "1x2", OPT_BW_RAM }, - - /* Cross-stream NUMA bandwidth measurement: */ - { "RAM-bw-cross,", "mem", "-p", "2", "-t", "1", "-P", "1024", - "-C", "0,8", "-M", "1,0", OPT_BW_RAM }, - - /* Convergence latency measurements: */ - { " 1x3-convergence,", "mem", "-p", "1", "-t", "3", "-P", "512", OPT_CONV }, - { " 1x4-convergence,", "mem", "-p", "1", "-t", "4", "-P", "512", OPT_CONV }, - { " 1x6-convergence,", "mem", "-p", "1", "-t", "6", "-P", "1020", OPT_CONV }, - { " 2x3-convergence,", "mem", "-p", "3", "-t", "3", "-P", "1020", OPT_CONV }, - { " 3x3-convergence,", "mem", "-p", "3", "-t", "3", "-P", "1020", OPT_CONV }, - { " 4x4-convergence,", "mem", "-p", "4", "-t", "4", "-P", "512", OPT_CONV }, - { " 4x4-convergence-NOTHP,", - "mem", "-p", "4", "-t", "4", "-P", "512", OPT_CONV_NOTHP }, - { " 4x6-convergence,", "mem", "-p", "4", "-t", "6", "-P", "1020", OPT_CONV }, - { " 4x8-convergence,", "mem", "-p", "4", "-t", "8", "-P", "512", OPT_CONV }, - { " 8x4-convergence,", "mem", "-p", "8", "-t", "4", "-P", "512", OPT_CONV }, - { " 8x4-convergence-NOTHP,", - "mem", "-p", "8", "-t", "4", "-P", "512", OPT_CONV_NOTHP }, - { " 3x1-convergence,", "mem", "-p", "3", "-t", "1", "-P", "512", OPT_CONV }, - { " 4x1-convergence,", "mem", "-p", "4", "-t", "1", "-P", "512", OPT_CONV }, - { " 8x1-convergence,", "mem", "-p", "8", "-t", "1", "-P", "512", OPT_CONV }, - { "16x1-convergence,", "mem", "-p", "16", "-t", "1", "-P", "256", OPT_CONV }, - { "32x1-convergence,", "mem", "-p", "32", "-t", "1", "-P", "128", OPT_CONV }, - - /* Various NUMA process/thread layout bandwidth measurements: */ - { " 2x1-bw-process,", "mem", "-p", "2", "-t", "1", "-P", "1024", OPT_BW }, - { " 3x1-bw-process,", "mem", "-p", "3", "-t", "1", "-P", "1024", OPT_BW }, - { " 4x1-bw-process,", "mem", "-p", "4", "-t", "1", "-P", "1024", OPT_BW }, - { " 8x1-bw-process,", "mem", "-p", "8", "-t", "1", "-P", " 512", OPT_BW }, - { " 8x1-bw-process-NOTHP,", - "mem", "-p", "8", "-t", "1", "-P", " 512", OPT_BW_NOTHP }, - { "16x1-bw-process,", "mem", "-p", "16", "-t", "1", "-P", "256", OPT_BW }, - - { " 4x1-bw-thread,", "mem", "-p", "1", "-t", "4", "-T", "256", OPT_BW }, - { " 8x1-bw-thread,", "mem", "-p", "1", "-t", "8", "-T", "256", OPT_BW }, - { "16x1-bw-thread,", "mem", "-p", "1", "-t", "16", "-T", "128", OPT_BW }, - { "32x1-bw-thread,", "mem", "-p", "1", "-t", "32", "-T", "64", OPT_BW }, - - { " 2x3-bw-thread,", "mem", "-p", "2", "-t", "3", "-P", "512", OPT_BW }, - { " 4x4-bw-thread,", "mem", "-p", "4", "-t", "4", "-P", "512", OPT_BW }, - { " 4x6-bw-thread,", "mem", "-p", "4", "-t", "6", "-P", "512", OPT_BW }, - { " 4x8-bw-thread,", "mem", "-p", "4", "-t", "8", "-P", "512", OPT_BW }, - { " 4x8-bw-thread-NOTHP,", - "mem", "-p", "4", "-t", "8", "-P", "512", OPT_BW_NOTHP }, - { " 3x3-bw-thread,", "mem", "-p", "3", "-t", "3", "-P", "512", OPT_BW }, - { " 5x5-bw-thread,", "mem", "-p", "5", "-t", "5", "-P", "512", OPT_BW }, - - { "2x16-bw-thread,", "mem", "-p", "2", "-t", "16", "-P", "512", OPT_BW }, - { "1x32-bw-thread,", "mem", "-p", "1", "-t", "32", "-P", "2048", OPT_BW }, - - { "numa02-bw,", "mem", "-p", "1", "-t", "32", "-T", "32", OPT_BW }, - { "numa02-bw-NOTHP,", "mem", "-p", "1", "-t", "32", "-T", "32", OPT_BW_NOTHP }, - { "numa01-bw-thread,", "mem", "-p", "2", "-t", "16", "-T", "192", OPT_BW }, - { "numa01-bw-thread-NOTHP,", - "mem", "-p", "2", "-t", "16", "-T", "192", OPT_BW_NOTHP }, -}; - -static int bench_all(void) -{ - int nr = ARRAY_SIZE(tests); - int ret; - int i; - - ret = system("echo ' #'; echo ' # Running test on: '$(uname -a); echo ' #'"); - BUG_ON(ret < 0); - - for (i = 0; i < nr; i++) { - if (run_bench_numa(tests[i][0], tests[i] + 1)) - return -1; - } - - printf("\n"); - - return 0; -} - -int bench_numa(int argc, const char **argv, const char *prefix __maybe_unused) -{ - init_params(&p0, "main,", argc, argv); - argc = parse_options(argc, argv, options, bench_numa_usage, 0); - if (argc) - goto err; - - if (p0.run_all) - return bench_all(); - - if (__bench_numa(NULL)) - goto err; - - return 0; - -err: - usage_with_options(numa_usage, options); - return -1; -} diff --git a/trunk/tools/perf/builtin-bench.c b/trunk/tools/perf/builtin-bench.c index 77298bf892b8..cae9a5fd2ecf 100644 --- a/trunk/tools/perf/builtin-bench.c +++ b/trunk/tools/perf/builtin-bench.c @@ -35,18 +35,6 @@ struct bench_suite { /* sentinel: easy for help */ #define suite_all { "all", "Test all benchmark suites", NULL } -#ifdef LIBNUMA_SUPPORT -static struct bench_suite numa_suites[] = { - { "mem", - "Benchmark for NUMA workloads", - bench_numa }, - suite_all, - { NULL, - NULL, - NULL } -}; -#endif - static struct bench_suite sched_suites[] = { { "messaging", "Benchmark for scheduler and IPC mechanisms", @@ -80,11 +68,6 @@ struct bench_subsys { }; static struct bench_subsys subsystems[] = { -#ifdef LIBNUMA_SUPPORT - { "numa", - "NUMA scheduling and MM behavior", - numa_suites }, -#endif { "sched", "scheduler and IPC mechanism", sched_suites }, @@ -176,7 +159,6 @@ static void all_suite(struct bench_subsys *subsys) /* FROM HERE */ printf("# Running %s/%s benchmark...\n", subsys->name, suites[i].name); - fflush(stdout); argv[1] = suites[i].name; suites[i].fn(1, argv, NULL); @@ -243,7 +225,6 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) printf("# Running %s/%s benchmark...\n", subsystems[i].name, subsystems[i].suites[j].name); - fflush(stdout); status = subsystems[i].suites[j].fn(argc - 1, argv + 1, prefix); goto end; diff --git a/trunk/tools/perf/builtin-diff.c b/trunk/tools/perf/builtin-diff.c index 4af0b580b046..b2e7d39f099b 100644 --- a/trunk/tools/perf/builtin-diff.c +++ b/trunk/tools/perf/builtin-diff.c @@ -275,6 +275,43 @@ static struct perf_tool tool = { .ordering_requires_timestamps = true, }; +static void insert_hist_entry_by_name(struct rb_root *root, + struct hist_entry *he) +{ + struct rb_node **p = &root->rb_node; + struct rb_node *parent = NULL; + struct hist_entry *iter; + + while (*p != NULL) { + parent = *p; + iter = rb_entry(parent, struct hist_entry, rb_node); + if (hist_entry__cmp(he, iter) < 0) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&he->rb_node, parent, p); + rb_insert_color(&he->rb_node, root); +} + +static void hists__name_resort(struct hists *self) +{ + struct rb_root tmp = RB_ROOT; + struct rb_node *next = rb_first(&self->entries); + + while (next != NULL) { + struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); + + next = rb_next(&n->rb_node); + + rb_erase(&n->rb_node, &self->entries); + insert_hist_entry_by_name(&tmp, n); + } + + self->entries = tmp; +} + static struct perf_evsel *evsel_match(struct perf_evsel *evsel, struct perf_evlist *evlist) { @@ -287,34 +324,30 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel, return NULL; } -static void perf_evlist__collapse_resort(struct perf_evlist *evlist) +static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name) { struct perf_evsel *evsel; list_for_each_entry(evsel, &evlist->entries, node) { struct hists *hists = &evsel->hists; - hists__collapse_resort(hists); + hists__output_resort(hists); + + if (name) + hists__name_resort(hists); } } static void hists__baseline_only(struct hists *hists) { - struct rb_root *root; - struct rb_node *next; - - if (sort__need_collapse) - root = &hists->entries_collapsed; - else - root = hists->entries_in; + struct rb_node *next = rb_first(&hists->entries); - next = rb_first(root); while (next != NULL) { - struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); + struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); - next = rb_next(&he->rb_node_in); + next = rb_next(&he->rb_node); if (!hist_entry__next_pair(he)) { - rb_erase(&he->rb_node_in, root); + rb_erase(&he->rb_node, &hists->entries); hist_entry__free(he); } } @@ -414,30 +447,19 @@ static void insert_hist_entry_by_compute(struct rb_root *root, static void hists__compute_resort(struct hists *hists) { - struct rb_root *root; - struct rb_node *next; - - if (sort__need_collapse) - root = &hists->entries_collapsed; - else - root = hists->entries_in; - - hists->entries = RB_ROOT; - next = rb_first(root); - - hists->nr_entries = 0; - hists->stats.total_period = 0; - hists__reset_col_len(hists); + struct rb_root tmp = RB_ROOT; + struct rb_node *next = rb_first(&hists->entries); while (next != NULL) { - struct hist_entry *he; + struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); - he = rb_entry(next, struct hist_entry, rb_node_in); - next = rb_next(&he->rb_node_in); + next = rb_next(&he->rb_node); - insert_hist_entry_by_compute(&hists->entries, he, compute); - hists__inc_nr_entries(hists, he); + rb_erase(&he->rb_node, &hists->entries); + insert_hist_entry_by_compute(&tmp, he, compute); } + + hists->entries = tmp; } static void hists__process(struct hists *old, struct hists *new) @@ -452,8 +474,6 @@ static void hists__process(struct hists *old, struct hists *new) if (sort_compute) { hists__precompute(new); hists__compute_resort(new); - } else { - hists__output_resort(new); } hists__fprintf(new, true, 0, 0, stdout); @@ -485,8 +505,8 @@ static int __cmd_diff(void) evlist_old = older->evlist; evlist_new = newer->evlist; - perf_evlist__collapse_resort(evlist_old); - perf_evlist__collapse_resort(evlist_new); + perf_evlist__resort_hists(evlist_old, true); + perf_evlist__resort_hists(evlist_new, false); list_for_each_entry(evsel, &evlist_new->entries, node) { struct perf_evsel *evsel_old; diff --git a/trunk/tools/perf/builtin-evlist.c b/trunk/tools/perf/builtin-evlist.c index 85a5e35dd147..1312a5e03ec7 100644 --- a/trunk/tools/perf/builtin-evlist.c +++ b/trunk/tools/perf/builtin-evlist.c @@ -39,8 +39,6 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"), OPT_BOOLEAN('v', "verbose", &details.verbose, "Show all event attr details"), - OPT_BOOLEAN('g', "group", &symbol_conf.event_group, - "Show event group information"), OPT_END() }; const char * const evlist_usage[] = { @@ -52,10 +50,5 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) if (argc) usage_with_options(evlist_usage, options); - if (symbol_conf.event_group && (details.verbose || details.freq)) { - pr_err("--group option is not compatible with other options\n"); - usage_with_options(evlist_usage, options); - } - return __cmd_evlist(input_name, &details); } diff --git a/trunk/tools/perf/builtin-kmem.c b/trunk/tools/perf/builtin-kmem.c index 46878daca5cc..0b4b796167be 100644 --- a/trunk/tools/perf/builtin-kmem.c +++ b/trunk/tools/perf/builtin-kmem.c @@ -17,7 +17,6 @@ #include "util/debug.h" #include -#include struct alloc_stat; typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); @@ -341,7 +340,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, int n_lines, int is_caller) { struct rb_node *next; - struct machine *machine = &session->machines.host; + struct machine *machine; printf("%.102s\n", graph_dotted_line); printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); @@ -350,6 +349,11 @@ static void __print_result(struct rb_root *root, struct perf_session *session, next = rb_first(root); + machine = perf_session__find_host_machine(session); + if (!machine) { + pr_err("__print_result: couldn't find kernel information\n"); + return; + } while (next && n_lines--) { struct alloc_stat *data = rb_entry(next, struct alloc_stat, node); @@ -610,7 +614,8 @@ static struct sort_dimension *avail_sorts[] = { &pingpong_sort_dimension, }; -#define NUM_AVAIL_SORTS ((int)ARRAY_SIZE(avail_sorts)) +#define NUM_AVAIL_SORTS \ + (int)(sizeof(avail_sorts) / sizeof(struct sort_dimension *)) static int sort_dimension__add(const char *tok, struct list_head *list) { @@ -619,11 +624,12 @@ static int sort_dimension__add(const char *tok, struct list_head *list) for (i = 0; i < NUM_AVAIL_SORTS; i++) { if (!strcmp(avail_sorts[i]->name, tok)) { - sort = memdup(avail_sorts[i], sizeof(*avail_sorts[i])); + sort = malloc(sizeof(*sort)); if (!sort) { - pr_err("%s: memdup failed\n", __func__); + pr_err("%s: malloc failed\n", __func__); return -1; } + memcpy(sort, avail_sorts[i], sizeof(*sort)); list_add_tail(&sort->list, list); return 0; } diff --git a/trunk/tools/perf/builtin-kvm.c b/trunk/tools/perf/builtin-kvm.c index 37a769d7f9fe..ca3f80ebc100 100644 --- a/trunk/tools/perf/builtin-kvm.c +++ b/trunk/tools/perf/builtin-kvm.c @@ -973,7 +973,8 @@ __cmd_buildid_list(const char *file_name, int argc, const char **argv) int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) { - const char *file_name = NULL; + const char *file_name; + const struct option kvm_options[] = { OPT_STRING('i', "input", &file_name, "file", "Input file name"), diff --git a/trunk/tools/perf/builtin-record.c b/trunk/tools/perf/builtin-record.c index 774c90713a53..028de726b832 100644 --- a/trunk/tools/perf/builtin-record.c +++ b/trunk/tools/perf/builtin-record.c @@ -224,7 +224,6 @@ static bool perf_evlist__equal(struct perf_evlist *evlist, static int perf_record__open(struct perf_record *rec) { - char msg[512]; struct perf_evsel *pos; struct perf_evlist *evlist = rec->evlist; struct perf_session *session = rec->session; @@ -234,18 +233,114 @@ static int perf_record__open(struct perf_record *rec) perf_evlist__config(evlist, opts); list_for_each_entry(pos, &evlist->entries, node) { + struct perf_event_attr *attr = &pos->attr; + /* + * Check if parse_single_tracepoint_event has already asked for + * PERF_SAMPLE_TIME. + * + * XXX this is kludgy but short term fix for problems introduced by + * eac23d1c that broke 'perf script' by having different sample_types + * when using multiple tracepoint events when we use a perf binary + * that tries to use sample_id_all on an older kernel. + * + * We need to move counter creation to perf_session, support + * different sample_types, etc. + */ + bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; + +fallback_missing_features: + if (opts->exclude_guest_missing) + attr->exclude_guest = attr->exclude_host = 0; +retry_sample_id: + attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; try_again: if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { - if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { + int err = errno; + + if (err == EPERM || err == EACCES) { + ui__error_paranoid(); + rc = -err; + goto out; + } else if (err == ENODEV && opts->target.cpu_list) { + pr_err("No such device - did you specify" + " an out-of-range profile CPU?\n"); + rc = -err; + goto out; + } else if (err == EINVAL) { + if (!opts->exclude_guest_missing && + (attr->exclude_guest || attr->exclude_host)) { + pr_debug("Old kernel, cannot exclude " + "guest or host samples.\n"); + opts->exclude_guest_missing = true; + goto fallback_missing_features; + } else if (!opts->sample_id_all_missing) { + /* + * Old kernel, no attr->sample_id_type_all field + */ + opts->sample_id_all_missing = true; + if (!opts->sample_time && !opts->raw_samples && !time_needed) + perf_evsel__reset_sample_bit(pos, TIME); + + goto retry_sample_id; + } + } + + /* + * If it's cycles then fall back to hrtimer + * based cpu-clock-tick sw counter, which + * is always available even if no PMU support. + * + * PPC returns ENXIO until 2.6.37 (behavior changed + * with commit b0a873e). + */ + if ((err == ENOENT || err == ENXIO) + && attr->type == PERF_TYPE_HARDWARE + && attr->config == PERF_COUNT_HW_CPU_CYCLES) { + if (verbose) - ui__warning("%s\n", msg); + ui__warning("The cycles event is not supported, " + "trying to fall back to cpu-clock-ticks\n"); + attr->type = PERF_TYPE_SOFTWARE; + attr->config = PERF_COUNT_SW_CPU_CLOCK; + if (pos->name) { + free(pos->name); + pos->name = NULL; + } goto try_again; } - rc = -errno; - perf_evsel__open_strerror(pos, &opts->target, - errno, msg, sizeof(msg)); - ui__error("%s\n", msg); + if (err == ENOENT) { + ui__error("The %s event is not supported.\n", + perf_evsel__name(pos)); + rc = -err; + goto out; + } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { + ui__error("\'precise\' request may not be supported. " + "Try removing 'p' modifier\n"); + rc = -err; + goto out; + } + + printf("\n"); + error("sys_perf_event_open() syscall returned with %d " + "(%s) for event %s. /bin/dmesg may provide " + "additional information.\n", + err, strerror(err), perf_evsel__name(pos)); + +#if defined(__i386__) || defined(__x86_64__) + if (attr->type == PERF_TYPE_HARDWARE && + err == EOPNOTSUPP) { + pr_err("No hardware sampling interrupt available." + " No APIC? If so then you can boot the kernel" + " with the \"lapic\" boot parameter to" + " force-enable it.\n"); + rc = -err; + goto out; + } +#endif + + pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); + rc = -err; goto out; } } @@ -328,6 +423,10 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data) { int err; struct perf_tool *tool = data; + + if (machine__is_host(machine)) + return; + /* *As for guest kernel when processing subcommand record&report, *we arrange module mmap prior to guest kernel mmap and trigger @@ -486,9 +585,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) goto out_delete_session; } - if (!evsel_list->nr_groups) - perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); - /* * perf_session__delete(session) will be called at perf_record__exit() */ @@ -515,7 +611,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) rec->post_processing_offset = lseek(output, 0, SEEK_CUR); - machine = &session->machines.host; + machine = perf_session__find_host_machine(session); + if (!machine) { + pr_err("Couldn't find native kernel information.\n"); + err = -1; + goto out_delete_session; + } if (opts->pipe_output) { err = perf_event__synthesize_attrs(tool, session, @@ -568,10 +669,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" "Check /proc/modules permission or run as root.\n"); - if (perf_guest) { - machines__process_guests(&session->machines, - perf_event__synthesize_guest_os, tool); - } + if (perf_guest) + perf_session__process_machines(session, tool, + perf_event__synthesize_guest_os); if (!opts->target.system_wide) err = perf_event__synthesize_thread_map(tool, evsel_list->threads, diff --git a/trunk/tools/perf/builtin-report.c b/trunk/tools/perf/builtin-report.c index 0d221870561a..5134acf1c39a 100644 --- a/trunk/tools/perf/builtin-report.c +++ b/trunk/tools/perf/builtin-report.c @@ -8,7 +8,6 @@ #include "builtin.h" #include "util/util.h" -#include "util/cache.h" #include "util/annotate.h" #include "util/color.h" @@ -55,16 +54,6 @@ struct perf_report { DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); }; -static int perf_report_config(const char *var, const char *value, void *cb) -{ - if (!strcmp(var, "report.group")) { - symbol_conf.event_group = perf_config_bool(var, value); - return 0; - } - - return perf_default_config(var, value, cb); -} - static int perf_report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al, struct perf_sample *sample, @@ -310,21 +299,6 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self, char unit; unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = self->stats.total_period; - struct perf_evsel *evsel = hists_to_evsel(self); - char buf[512]; - size_t size = sizeof(buf); - - if (symbol_conf.event_group && evsel->nr_members > 1) { - struct perf_evsel *pos; - - perf_evsel__group_desc(evsel, buf, size); - evname = buf; - - for_each_group_member(pos, evsel) { - nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; - nr_events += pos->hists.stats.total_period; - } - } nr_samples = convert_unit(nr_samples, &unit); ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit); @@ -345,10 +319,6 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, struct hists *hists = &pos->hists; const char *evname = perf_evsel__name(pos); - if (symbol_conf.event_group && - !perf_evsel__is_group_leader(pos)) - continue; - hists__fprintf_nr_sample_events(hists, evname, stdout); hists__fprintf(hists, true, 0, 0, stdout); fprintf(stdout, "\n\n"); @@ -402,7 +372,7 @@ static int __cmd_report(struct perf_report *rep) if (ret) goto out_delete; - kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION]; + kernel_map = session->host_machine.vmlinux_maps[MAP__FUNCTION]; kernel_kmap = map__kmap(kernel_map); if (kernel_map == NULL || (kernel_map->dso->hit && @@ -446,16 +416,8 @@ static int __cmd_report(struct perf_report *rep) hists->symbol_filter_str = rep->symbol_filter_str; hists__collapse_resort(hists); + hists__output_resort(hists); nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE]; - - /* Non-group events are considered as leader */ - if (symbol_conf.event_group && - !perf_evsel__is_group_leader(pos)) { - struct hists *leader_hists = &pos->leader->hists; - - hists__match(leader_hists, hists); - hists__link(leader_hists, hists); - } } if (nr_samples == 0) { @@ -463,9 +425,6 @@ static int __cmd_report(struct perf_report *rep) goto out_delete; } - list_for_each_entry(pos, &session->evlist->entries, node) - hists__output_resort(&pos->hists); - if (use_browser > 0) { if (use_browser == 1) { perf_evlist__tui_browse_hists(session->evlist, help, @@ -636,8 +595,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN(0, "stdio", &report.use_stdio, "Use the stdio interface"), OPT_STRING('s', "sort", &sort_order, "key[,key2...]", - "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," - " dso_to, dso_from, symbol_to, symbol_from, mispredict"), + "sort by key(s): pid, comm, dso, symbol, parent, dso_to," + " dso_from, symbol_to, symbol_from, mispredict"), OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, "Show sample percentage for different cpu modes"), OPT_STRING('p', "parent", &parent_pattern, "regex", @@ -679,8 +638,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, "Show a column with the sum of periods"), - OPT_BOOLEAN(0, "group", &symbol_conf.event_group, - "Show event group information together"), OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "", "use branch records for histogram filling", parse_branch_mode), OPT_STRING(0, "objdump", &objdump_path, "path", @@ -688,8 +645,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) OPT_END() }; - perf_config(perf_report_config, NULL); - argc = parse_options(argc, argv, options, report_usage, 0); if (report.use_stdio) diff --git a/trunk/tools/perf/builtin-sched.c b/trunk/tools/perf/builtin-sched.c index 138229439a93..cc28b85dabd5 100644 --- a/trunk/tools/perf/builtin-sched.c +++ b/trunk/tools/perf/builtin-sched.c @@ -1475,9 +1475,9 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy, goto out_delete; } - sched->nr_events = session->stats.nr_events[0]; - sched->nr_lost_events = session->stats.total_lost; - sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; + sched->nr_events = session->hists.stats.nr_events[0]; + sched->nr_lost_events = session->hists.stats.total_lost; + sched->nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; } if (destroy) diff --git a/trunk/tools/perf/builtin-script.c b/trunk/tools/perf/builtin-script.c index 92d4658f56fb..b363e7b292b2 100644 --- a/trunk/tools/perf/builtin-script.c +++ b/trunk/tools/perf/builtin-script.c @@ -692,7 +692,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused, const char *arg, int unset __maybe_unused) { char *tok; - int i, imax = ARRAY_SIZE(all_output_options); + int i, imax = sizeof(all_output_options) / sizeof(struct output_option); int j; int rc = 0; char *str = strdup(arg); @@ -909,6 +909,18 @@ static const char *ends_with(const char *str, const char *suffix) return NULL; } +static char *ltrim(char *str) +{ + int len = strlen(str); + + while (len && isspace(*str)) { + len--; + str++; + } + + return str; +} + static int read_script_info(struct script_desc *desc, const char *filename) { char line[BUFSIZ], *p; @@ -1475,8 +1487,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) return -1; } - if (!script_name && !generate_script_lang) - perf_session__fprintf_info(session, stdout, show_full_info); + perf_session__fprintf_info(session, stdout, show_full_info); if (!no_callchain) symbol_conf.use_callchain = true; diff --git a/trunk/tools/perf/builtin-stat.c b/trunk/tools/perf/builtin-stat.c index 0368a1036ad6..c12655af2b88 100644 --- a/trunk/tools/perf/builtin-stat.c +++ b/trunk/tools/perf/builtin-stat.c @@ -65,10 +65,6 @@ #define CNTR_NOT_SUPPORTED "" #define CNTR_NOT_COUNTED "" -static void print_stat(int argc, const char **argv); -static void print_counter_aggr(struct perf_evsel *counter, char *prefix); -static void print_counter(struct perf_evsel *counter, char *prefix); - static struct perf_evlist *evsel_list; static struct perf_target target = { @@ -91,8 +87,6 @@ static FILE *output = NULL; static const char *pre_cmd = NULL; static const char *post_cmd = NULL; static bool sync_run = false; -static unsigned int interval = 0; -static struct timespec ref_time; static volatile int done = 0; @@ -100,28 +94,6 @@ struct perf_stat { struct stats res_stats[3]; }; -static inline void diff_timespec(struct timespec *r, struct timespec *a, - struct timespec *b) -{ - r->tv_sec = a->tv_sec - b->tv_sec; - if (a->tv_nsec < b->tv_nsec) { - r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec; - r->tv_sec--; - } else { - r->tv_nsec = a->tv_nsec - b->tv_nsec ; - } -} - -static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) -{ - return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; -} - -static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) -{ - return perf_evsel__cpus(evsel)->nr; -} - static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) { evsel->priv = zalloc(sizeof(struct perf_stat)); @@ -134,27 +106,14 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) evsel->priv = NULL; } -static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) +static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) { - void *addr; - size_t sz; - - sz = sizeof(*evsel->counts) + - (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values)); - - addr = zalloc(sz); - if (!addr) - return -ENOMEM; - - evsel->prev_raw_counts = addr; - - return 0; + return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; } -static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) +static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) { - free(evsel->prev_raw_counts); - evsel->prev_raw_counts = NULL; + return perf_evsel__cpus(evsel)->nr; } static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; @@ -173,6 +132,8 @@ static struct stats walltime_nsecs_stats; static int create_perf_stat_counter(struct perf_evsel *evsel) { struct perf_event_attr *attr = &evsel->attr; + bool exclude_guest_missing = false; + int ret; if (scale) attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | @@ -180,8 +141,16 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) attr->inherit = !no_inherit; - if (perf_target__has_cpu(&target)) - return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); +retry: + if (exclude_guest_missing) + evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; + + if (perf_target__has_cpu(&target)) { + ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); + if (ret) + goto check_ret; + return 0; + } if (!perf_target__has_task(&target) && perf_evsel__is_group_leader(evsel)) { @@ -189,7 +158,21 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) attr->enable_on_exec = 1; } - return perf_evsel__open_per_thread(evsel, evsel_list->threads); + ret = perf_evsel__open_per_thread(evsel, evsel_list->threads); + if (!ret) + return 0; + /* fall through */ +check_ret: + if (ret && errno == EINVAL) { + if (!exclude_guest_missing && + (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { + pr_debug("Old kernel, cannot exclude " + "guest or host samples.\n"); + exclude_guest_missing = true; + goto retry; + } + } + return ret; } /* @@ -286,69 +269,15 @@ static int read_counter(struct perf_evsel *counter) return 0; } -static void print_interval(void) -{ - static int num_print_interval; - struct perf_evsel *counter; - struct perf_stat *ps; - struct timespec ts, rs; - char prefix[64]; - - if (no_aggr) { - list_for_each_entry(counter, &evsel_list->entries, node) { - ps = counter->priv; - memset(ps->res_stats, 0, sizeof(ps->res_stats)); - read_counter(counter); - } - } else { - list_for_each_entry(counter, &evsel_list->entries, node) { - ps = counter->priv; - memset(ps->res_stats, 0, sizeof(ps->res_stats)); - read_counter_aggr(counter); - } - } - clock_gettime(CLOCK_MONOTONIC, &ts); - diff_timespec(&rs, &ts, &ref_time); - sprintf(prefix, "%6lu.%09lu%s", rs.tv_sec, rs.tv_nsec, csv_sep); - - if (num_print_interval == 0 && !csv_output) { - if (no_aggr) - fprintf(output, "# time CPU counts events\n"); - else - fprintf(output, "# time counts events\n"); - } - - if (++num_print_interval == 25) - num_print_interval = 0; - - if (no_aggr) { - list_for_each_entry(counter, &evsel_list->entries, node) - print_counter(counter, prefix); - } else { - list_for_each_entry(counter, &evsel_list->entries, node) - print_counter_aggr(counter, prefix); - } -} - static int __run_perf_stat(int argc __maybe_unused, const char **argv) { - char msg[512]; unsigned long long t0, t1; struct perf_evsel *counter; - struct timespec ts; int status = 0; int child_ready_pipe[2], go_pipe[2]; const bool forks = (argc > 0); char buf; - if (interval) { - ts.tv_sec = interval / 1000; - ts.tv_nsec = (interval % 1000) * 1000000; - } else { - ts.tv_sec = 1; - ts.tv_nsec = 0; - } - if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { perror("failed to create pipes"); return -1; @@ -419,13 +348,20 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv) continue; } - perf_evsel__open_strerror(counter, &target, - errno, msg, sizeof(msg)); - ui__error("%s\n", msg); - + if (errno == EPERM || errno == EACCES) { + error("You may not have permission to collect %sstats.\n" + "\t Consider tweaking" + " /proc/sys/kernel/perf_event_paranoid or running as root.", + target.system_wide ? "system-wide " : ""); + } else { + error("open_counter returned with %d (%s). " + "/bin/dmesg may provide additional information.\n", + errno, strerror(errno)); + } if (child_pid != -1) kill(child_pid, SIGTERM); + pr_err("Not all events could be opened.\n"); return -1; } counter->supported = true; @@ -441,25 +377,14 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv) * Enable counters and exec the command: */ t0 = rdclock(); - clock_gettime(CLOCK_MONOTONIC, &ref_time); if (forks) { close(go_pipe[1]); - if (interval) { - while (!waitpid(child_pid, &status, WNOHANG)) { - nanosleep(&ts, NULL); - print_interval(); - } - } wait(&status); if (WIFSIGNALED(status)) psignal(WTERMSIG(status), argv[0]); } else { - while (!done) { - nanosleep(&ts, NULL); - if (interval) - print_interval(); - } + while(!done) sleep(1); } t1 = rdclock(); @@ -545,7 +470,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) if (evsel->cgrp) fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); - if (csv_output || interval) + if (csv_output) return; if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) @@ -759,11 +684,12 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) if (evsel->cgrp) fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); - if (csv_output || interval) + if (csv_output) return; if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { total = avg_stats(&runtime_cycles_stats[cpu]); + if (total) ratio = avg / total; @@ -857,15 +783,12 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) * Print out the results of a single counter: * aggregated counts in system-wide mode */ -static void print_counter_aggr(struct perf_evsel *counter, char *prefix) +static void print_counter_aggr(struct perf_evsel *counter) { struct perf_stat *ps = counter->priv; double avg = avg_stats(&ps->res_stats[0]); int scaled = counter->counts->scaled; - if (prefix) - fprintf(output, "%s", prefix); - if (scaled == -1) { fprintf(output, "%*s%s%*s", csv_output ? 0 : 18, @@ -908,7 +831,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix) * Print out the results of a single counter: * does not use aggregated count in system-wide */ -static void print_counter(struct perf_evsel *counter, char *prefix) +static void print_counter(struct perf_evsel *counter) { u64 ena, run, val; int cpu; @@ -917,10 +840,6 @@ static void print_counter(struct perf_evsel *counter, char *prefix) val = counter->counts->cpu[cpu].val; ena = counter->counts->cpu[cpu].ena; run = counter->counts->cpu[cpu].run; - - if (prefix) - fprintf(output, "%s", prefix); - if (run == 0 || ena == 0) { fprintf(output, "CPU%*d%s%*s%s%*s", csv_output ? 0 : -4, @@ -982,10 +901,10 @@ static void print_stat(int argc, const char **argv) if (no_aggr) { list_for_each_entry(counter, &evsel_list->entries, node) - print_counter(counter, NULL); + print_counter(counter); } else { list_for_each_entry(counter, &evsel_list->entries, node) - print_counter_aggr(counter, NULL); + print_counter_aggr(counter); } if (!csv_output) { @@ -1006,7 +925,7 @@ static volatile int signr = -1; static void skip_signal(int signo) { - if ((child_pid == -1) || interval) + if(child_pid == -1) done = 1; signr = signo; @@ -1226,8 +1145,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "command to run prior to the measured command"), OPT_STRING(0, "post", &post_cmd, "command", "command to run after to the measured command"), - OPT_UINTEGER('I', "interval-print", &interval, - "print counts at regular interval in ms (>= 100)"), OPT_END() }; const char * const stat_usage[] = { @@ -1328,23 +1245,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) usage_with_options(stat_usage, options); return -1; } - if (interval && interval < 100) { - pr_err("print interval must be >= 100ms\n"); - usage_with_options(stat_usage, options); - return -1; - } list_for_each_entry(pos, &evsel_list->entries, node) { if (perf_evsel__alloc_stat_priv(pos) < 0 || perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0) goto out_free_fd; } - if (interval) { - list_for_each_entry(pos, &evsel_list->entries, node) { - if (perf_evsel__alloc_prev_raw_counts(pos) < 0) - goto out_free_fd; - } - } /* * We dont want to block the signals - that would cause @@ -1354,7 +1260,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) */ atexit(sig_atexit); signal(SIGINT, skip_signal); - signal(SIGCHLD, skip_signal); signal(SIGALRM, skip_signal); signal(SIGABRT, skip_signal); @@ -1367,14 +1272,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) status = run_perf_stat(argc, argv); } - if (status != -1 && !interval) + if (status != -1) print_stat(argc, argv); out_free_fd: - list_for_each_entry(pos, &evsel_list->entries, node) { + list_for_each_entry(pos, &evsel_list->entries, node) perf_evsel__free_stat_priv(pos); - perf_evsel__free_counts(pos); - perf_evsel__free_prev_raw_counts(pos); - } perf_evlist__delete_maps(evsel_list); out: perf_evlist__delete(evsel_list); diff --git a/trunk/tools/perf/builtin-top.c b/trunk/tools/perf/builtin-top.c index f561757b1bfa..b7d2ea62dbc6 100644 --- a/trunk/tools/perf/builtin-top.c +++ b/trunk/tools/perf/builtin-top.c @@ -68,7 +68,27 @@ #include #include -static volatile int done; +void get_term_dimensions(struct winsize *ws) +{ + char *s = getenv("LINES"); + + if (s != NULL) { + ws->ws_row = atoi(s); + s = getenv("COLUMNS"); + if (s != NULL) { + ws->ws_col = atoi(s); + if (ws->ws_row && ws->ws_col) + return; + } + } +#ifdef TIOCGWINSZ + if (ioctl(1, TIOCGWINSZ, ws) == 0 && + ws->ws_row && ws->ws_col) + return; +#endif + ws->ws_row = 25; + ws->ws_col = 80; +} static void perf_top__update_print_entries(struct perf_top *top) { @@ -433,10 +453,8 @@ static int perf_top__key_mapped(struct perf_top *top, int c) return 0; } -static bool perf_top__handle_keypress(struct perf_top *top, int c) +static void perf_top__handle_keypress(struct perf_top *top, int c) { - bool ret = true; - if (!perf_top__key_mapped(top, c)) { struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; struct termios tc, save; @@ -457,7 +475,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) tcsetattr(0, TCSAFLUSH, &save); if (!perf_top__key_mapped(top, c)) - return ret; + return; } switch (c) { @@ -519,8 +537,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) printf("exiting.\n"); if (top->dump_symtab) perf_session__fprintf_dsos(top->session, stderr); - ret = false; - break; + exit(0); case 's': perf_top__prompt_symbol(top, "Enter details symbol"); break; @@ -543,8 +560,6 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) default: break; } - - return ret; } static void perf_top__sort_new_samples(void *arg) @@ -586,7 +601,8 @@ static void *display_thread_tui(void *arg) perf_evlist__tui_browse_hists(top->evlist, help, &hbt, &top->session->header.env); - done = 1; + exit_browser(0); + exit(0); return NULL; } @@ -610,7 +626,7 @@ static void *display_thread(void *arg) /* trash return*/ getc(stdin); - while (!done) { + while (1) { perf_top__print_sym_table(top); /* * Either timeout expired or we got an EINTR due to SIGWINCH, @@ -624,14 +640,15 @@ static void *display_thread(void *arg) continue; /* Fall trhu */ default: - c = getc(stdin); - tcsetattr(0, TCSAFLUSH, &save); - - if (perf_top__handle_keypress(top, c)) - goto repeat; - done = 1; + goto process_hotkey; } } +process_hotkey: + c = getc(stdin); + tcsetattr(0, TCSAFLUSH, &save); + + perf_top__handle_keypress(top, c); + goto repeat; return NULL; } @@ -699,7 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool, static struct intlist *seen; if (!seen) - seen = intlist__new(NULL); + seen = intlist__new(); if (!intlist__has_entry(seen, event->ip.pid)) { pr_err("Can't find guest [%d]'s kernel information\n", @@ -710,8 +727,8 @@ static void perf_event__process_sample(struct perf_tool *tool, } if (!machine) { - pr_err("%u unprocessable samples recorded.\r", - top->session->stats.nr_unprocessable_samples++); + pr_err("%u unprocessable samples recorded.\n", + top->session->hists.stats.nr_unprocessable_samples++); return; } @@ -830,13 +847,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) ++top->us_samples; if (top->hide_user_symbols) continue; - machine = &session->machines.host; + machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_KERNEL: ++top->kernel_samples; if (top->hide_kernel_symbols) continue; - machine = &session->machines.host; + machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_GUEST_KERNEL: ++top->guest_kernel_samples; @@ -861,7 +878,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) hists__inc_nr_events(&evsel->hists, event->header.type); machine__process_event(machine, event); } else - ++session->stats.nr_unknown_events; + ++session->hists.stats.nr_unknown_events; } } @@ -873,9 +890,8 @@ static void perf_top__mmap_read(struct perf_top *top) perf_top__mmap_read_idx(top, i); } -static int perf_top__start_counters(struct perf_top *top) +static void perf_top__start_counters(struct perf_top *top) { - char msg[512]; struct perf_evsel *counter; struct perf_evlist *evlist = top->evlist; struct perf_record_opts *opts = &top->record_opts; @@ -883,18 +899,77 @@ static int perf_top__start_counters(struct perf_top *top) perf_evlist__config(evlist, opts); list_for_each_entry(counter, &evlist->entries, node) { + struct perf_event_attr *attr = &counter->attr; + +fallback_missing_features: + if (top->exclude_guest_missing) + attr->exclude_guest = attr->exclude_host = 0; +retry_sample_id: + attr->sample_id_all = top->sample_id_all_missing ? 0 : 1; try_again: if (perf_evsel__open(counter, top->evlist->cpus, top->evlist->threads) < 0) { - if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { + int err = errno; + + if (err == EPERM || err == EACCES) { + ui__error_paranoid(); + goto out_err; + } else if (err == EINVAL) { + if (!top->exclude_guest_missing && + (attr->exclude_guest || attr->exclude_host)) { + pr_debug("Old kernel, cannot exclude " + "guest or host samples.\n"); + top->exclude_guest_missing = true; + goto fallback_missing_features; + } else if (!top->sample_id_all_missing) { + /* + * Old kernel, no attr->sample_id_type_all field + */ + top->sample_id_all_missing = true; + goto retry_sample_id; + } + } + /* + * If it's cycles then fall back to hrtimer + * based cpu-clock-tick sw counter, which + * is always available even if no PMU support: + */ + if ((err == ENOENT || err == ENXIO) && + (attr->type == PERF_TYPE_HARDWARE) && + (attr->config == PERF_COUNT_HW_CPU_CYCLES)) { + if (verbose) - ui__warning("%s\n", msg); + ui__warning("Cycles event not supported,\n" + "trying to fall back to cpu-clock-ticks\n"); + + attr->type = PERF_TYPE_SOFTWARE; + attr->config = PERF_COUNT_SW_CPU_CLOCK; + if (counter->name) { + free(counter->name); + counter->name = NULL; + } goto try_again; } - perf_evsel__open_strerror(counter, &opts->target, - errno, msg, sizeof(msg)); - ui__error("%s\n", msg); + if (err == ENOENT) { + ui__error("The %s event is not supported.\n", + perf_evsel__name(counter)); + goto out_err; + } else if (err == EMFILE) { + ui__error("Too many events are opened.\n" + "Try again after reducing the number of events\n"); + goto out_err; + } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { + ui__error("\'precise\' request may not be supported. " + "Try removing 'p' modifier\n"); + goto out_err; + } + + ui__error("The sys_perf_event_open() syscall " + "returned with %d (%s). /bin/dmesg " + "may provide additional information.\n" + "No CONFIG_PERF_EVENTS=y kernel support " + "configured?\n", err, strerror(err)); goto out_err; } } @@ -905,10 +980,11 @@ static int perf_top__start_counters(struct perf_top *top) goto out_err; } - return 0; + return; out_err: - return -1; + exit_browser(0); + exit(0); } static int perf_top__setup_sample_type(struct perf_top *top) @@ -948,15 +1024,11 @@ static int __cmd_top(struct perf_top *top) if (perf_target__has_task(&opts->target)) perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, perf_event__process, - &top->session->machines.host); + &top->session->host_machine); else perf_event__synthesize_threads(&top->tool, perf_event__process, - &top->session->machines.host); - - ret = perf_top__start_counters(top); - if (ret) - goto out_delete; - + &top->session->host_machine); + perf_top__start_counters(top); top->session->evlist = top->evlist; perf_session__set_id_hdr_size(top->session); @@ -976,11 +1048,10 @@ static int __cmd_top(struct perf_top *top) perf_top__mmap_read(top); - ret = -1; if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : display_thread), top)) { ui__error("Could not create display thread.\n"); - goto out_delete; + exit(-1); } if (top->realtime_prio) { @@ -989,11 +1060,11 @@ static int __cmd_top(struct perf_top *top) param.sched_priority = top->realtime_prio; if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { ui__error("Could not set realtime priority.\n"); - goto out_delete; + exit(-1); } } - while (!done) { + while (1) { u64 hits = top->samples; perf_top__mmap_read(top); @@ -1002,12 +1073,11 @@ static int __cmd_top(struct perf_top *top) ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); } - ret = 0; out_delete: perf_session__delete(top->session); top->session = NULL; - return ret; + return 0; } static int @@ -1164,7 +1234,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) if (!top.evlist->nr_entries && perf_evlist__add_default(top.evlist) < 0) { ui__error("Not enough memory for event selector list\n"); - goto out_delete_maps; + return -ENOMEM; } symbol_conf.nr_events = top.evlist->nr_entries; @@ -1187,7 +1257,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) } else { ui__error("frequency and count are zero, aborting\n"); status = -EINVAL; - goto out_delete_maps; + goto out_delete_evlist; } top.sym_evsel = perf_evlist__first(top.evlist); @@ -1220,8 +1290,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) status = __cmd_top(&top); -out_delete_maps: - perf_evlist__delete_maps(top.evlist); out_delete_evlist: perf_evlist__delete(top.evlist); diff --git a/trunk/tools/perf/config/feature-tests.mak b/trunk/tools/perf/config/feature-tests.mak index b4eabb44e381..f5ac77485a4f 100644 --- a/trunk/tools/perf/config/feature-tests.mak +++ b/trunk/tools/perf/config/feature-tests.mak @@ -225,14 +225,3 @@ int main(void) return on_exit(NULL, NULL); } endef - -define SOURCE_LIBNUMA -#include -#include - -int main(void) -{ - numa_available(); - return 0; -} -endef \ No newline at end of file diff --git a/trunk/tools/perf/config/utilities.mak b/trunk/tools/perf/config/utilities.mak index 8ef3bd30a549..e5413125e6bb 100644 --- a/trunk/tools/perf/config/utilities.mak +++ b/trunk/tools/perf/config/utilities.mak @@ -13,7 +13,7 @@ newline := $(newline) # what should replace a newline when escaping # newlines; the default is a bizarre string. # -nl-escape = $(if $(1),$(1),m822df3020w6a44id34bt574ctac44eb9f4n) +nl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n) # escape-nl # @@ -173,9 +173,9 @@ _ge-abspath = $(if $(is-executable),$(1)) # Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default) # define get-executable-or-default -$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2),$(1))) +$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) endef -_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) +_ge_attempt = $(or $(get-executable),$(_gea_warn),$(call _gea_err,$(2))) _gea_warn = $(warning The path '$(1)' is not executable.) _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) diff --git a/trunk/tools/perf/perf.c b/trunk/tools/perf/perf.c index 095b88207cd3..0f661fbce6a8 100644 --- a/trunk/tools/perf/perf.c +++ b/trunk/tools/perf/perf.c @@ -328,23 +328,14 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) return 0; - status = 1; /* Check for ENOSPC and EIO errors.. */ - if (fflush(stdout)) { - fprintf(stderr, "write failure on standard output: %s", strerror(errno)); - goto out; - } - if (ferror(stdout)) { - fprintf(stderr, "unknown write failure on standard output"); - goto out; - } - if (fclose(stdout)) { - fprintf(stderr, "close failed on standard output: %s", strerror(errno)); - goto out; - } - status = 0; -out: - return status; + if (fflush(stdout)) + die("write failure on standard output: %s", strerror(errno)); + if (ferror(stdout)) + die("unknown write failure on standard output"); + if (fclose(stdout)) + die("close failed on standard output: %s", strerror(errno)); + return 0; } static void handle_internal_command(int argc, const char **argv) @@ -476,8 +467,7 @@ int main(int argc, const char **argv) cmd += 5; argv[0] = cmd; handle_internal_command(argc, argv); - fprintf(stderr, "cannot handle %s internally", cmd); - goto out; + die("cannot handle %s internally", cmd); } /* Look for flags.. */ @@ -495,7 +485,7 @@ int main(int argc, const char **argv) printf("\n usage: %s\n\n", perf_usage_string); list_common_cmds_help(); printf("\n %s\n\n", perf_more_info_string); - goto out; + exit(1); } cmd = argv[0]; @@ -527,7 +517,7 @@ int main(int argc, const char **argv) fprintf(stderr, "Expansion of alias '%s' failed; " "'%s' is not a perf-command\n", cmd, argv[0]); - goto out; + exit(1); } if (!done_help) { cmd = argv[0] = help_unknown_cmd(cmd); @@ -538,6 +528,6 @@ int main(int argc, const char **argv) fprintf(stderr, "Failed to run command '%s': %s\n", cmd, strerror(errno)); -out: + return 1; } diff --git a/trunk/tools/perf/perf.h b/trunk/tools/perf/perf.h index 8f3bf388e414..2c340e7da458 100644 --- a/trunk/tools/perf/perf.h +++ b/trunk/tools/perf/perf.h @@ -1,6 +1,10 @@ #ifndef _PERF_PERF_H #define _PERF_PERF_H +struct winsize; + +void get_term_dimensions(struct winsize *ws); + #include #if defined(__i386__) @@ -233,6 +237,8 @@ struct perf_record_opts { bool raw_samples; bool sample_address; bool sample_time; + bool sample_id_all_missing; + bool exclude_guest_missing; bool period; unsigned int freq; unsigned int mmap_pages; diff --git a/trunk/tools/perf/scripts/perl/bin/workqueue-stats-record b/trunk/tools/perf/scripts/perl/bin/workqueue-stats-record new file mode 100644 index 000000000000..8edda9078d5d --- /dev/null +++ b/trunk/tools/perf/scripts/perl/bin/workqueue-stats-record @@ -0,0 +1,2 @@ +#!/bin/bash +perf record -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ diff --git a/trunk/tools/perf/scripts/perl/bin/workqueue-stats-report b/trunk/tools/perf/scripts/perl/bin/workqueue-stats-report new file mode 100644 index 000000000000..6d91411d248c --- /dev/null +++ b/trunk/tools/perf/scripts/perl/bin/workqueue-stats-report @@ -0,0 +1,3 @@ +#!/bin/bash +# description: workqueue stats (ins/exe/create/destroy) +perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl diff --git a/trunk/tools/perf/scripts/perl/workqueue-stats.pl b/trunk/tools/perf/scripts/perl/workqueue-stats.pl new file mode 100644 index 000000000000..a8eaff5119e0 --- /dev/null +++ b/trunk/tools/perf/scripts/perl/workqueue-stats.pl @@ -0,0 +1,129 @@ +#!/usr/bin/perl -w +# (c) 2009, Tom Zanussi +# Licensed under the terms of the GNU GPL License version 2 + +# Displays workqueue stats +# +# Usage: +# +# perf record -c 1 -f -a -R -e workqueue:workqueue_creation -e +# workqueue:workqueue_destruction -e workqueue:workqueue_execution +# -e workqueue:workqueue_insertion +# +# perf script -p -s tools/perf/scripts/perl/workqueue-stats.pl + +use 5.010000; +use strict; +use warnings; + +use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; +use lib "./Perf-Trace-Util/lib"; +use Perf::Trace::Core; +use Perf::Trace::Util; + +my @cpus; + +sub workqueue::workqueue_destruction +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $thread_comm, $thread_pid) = @_; + + $cpus[$common_cpu]{$thread_pid}{destroyed}++; + $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm; +} + +sub workqueue::workqueue_creation +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $thread_comm, $thread_pid, $cpu) = @_; + + $cpus[$common_cpu]{$thread_pid}{created}++; + $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm; +} + +sub workqueue::workqueue_execution +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $thread_comm, $thread_pid, $func) = @_; + + $cpus[$common_cpu]{$thread_pid}{executed}++; + $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm; +} + +sub workqueue::workqueue_insertion +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $thread_comm, $thread_pid, $func) = @_; + + $cpus[$common_cpu]{$thread_pid}{inserted}++; + $cpus[$common_cpu]{$thread_pid}{comm} = $thread_comm; +} + +sub trace_end +{ + print "workqueue work stats:\n\n"; + my $cpu = 0; + printf("%3s %6s %6s\t%-20s\n", "cpu", "ins", "exec", "name"); + printf("%3s %6s %6s\t%-20s\n", "---", "---", "----", "----"); + foreach my $pidhash (@cpus) { + while ((my $pid, my $wqhash) = each %$pidhash) { + my $ins = $$wqhash{'inserted'} || 0; + my $exe = $$wqhash{'executed'} || 0; + my $comm = $$wqhash{'comm'} || ""; + if ($ins || $exe) { + printf("%3u %6u %6u\t%-20s\n", $cpu, $ins, $exe, $comm); + } + } + $cpu++; + } + + $cpu = 0; + print "\nworkqueue lifecycle stats:\n\n"; + printf("%3s %6s %6s\t%-20s\n", "cpu", "created", "destroyed", "name"); + printf("%3s %6s %6s\t%-20s\n", "---", "-------", "---------", "----"); + foreach my $pidhash (@cpus) { + while ((my $pid, my $wqhash) = each %$pidhash) { + my $created = $$wqhash{'created'} || 0; + my $destroyed = $$wqhash{'destroyed'} || 0; + my $comm = $$wqhash{'comm'} || ""; + if ($created || $destroyed) { + printf("%3u %6u %6u\t%-20s\n", $cpu, $created, $destroyed, + $comm); + } + } + $cpu++; + } + + print_unhandled(); +} + +my %unhandled; + +sub print_unhandled +{ + if ((scalar keys %unhandled) == 0) { + return; + } + + print "\nunhandled events:\n\n"; + + printf("%-40s %10s\n", "event", "count"); + printf("%-40s %10s\n", "----------------------------------------", + "-----------"); + + foreach my $event_name (keys %unhandled) { + printf("%-40s %10d\n", $event_name, $unhandled{$event_name}); + } +} + +sub trace_unhandled +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm) = @_; + + $unhandled{$event_name}++; +} diff --git a/trunk/tools/perf/tests/attr.c b/trunk/tools/perf/tests/attr.c index bdcceb886f77..25638a986257 100644 --- a/trunk/tools/perf/tests/attr.c +++ b/trunk/tools/perf/tests/attr.c @@ -19,11 +19,6 @@ * permissions. All the event text files are stored there. */ -/* - * Powerpc needs __SANE_USERSPACE_TYPES__ before to select - * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu. - */ -#define __SANE_USERSPACE_TYPES__ #include #include #include @@ -38,6 +33,8 @@ extern int verbose; +bool test_attr__enabled; + static char *dir; void test_attr__init(void) @@ -149,7 +146,7 @@ static int run_dir(const char *d, const char *perf) { char cmd[3*PATH_MAX]; - snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %s", + snprintf(cmd, 3*PATH_MAX, "python %s/attr.py -d %s/attr/ -p %s %s", d, d, perf, verbose ? "-v" : ""); return system(cmd); diff --git a/trunk/tools/perf/tests/attr.py b/trunk/tools/perf/tests/attr.py index 2f629ca485bc..e702b82dcb86 100644 --- a/trunk/tools/perf/tests/attr.py +++ b/trunk/tools/perf/tests/attr.py @@ -68,7 +68,7 @@ def add(self, data): self[key] = val def __init__(self, name, data, base): - log.debug(" Event %s" % name); + log.info(" Event %s" % name); self.name = name; self.group = '' self.add(base) @@ -97,14 +97,6 @@ def equal(self, other): return False return True - def diff(self, other): - for t in Event.terms: - if not self.has_key(t) or not other.has_key(t): - continue - if not self.compare_data(self[t], other[t]): - log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) - - # Test file description needs to have following sections: # [config] # - just single instance in file @@ -121,7 +113,7 @@ def __init__(self, path, options): parser = ConfigParser.SafeConfigParser() parser.read(path) - log.debug("running '%s'" % path) + log.warning("running '%s'" % path) self.path = path self.test_dir = options.test_dir @@ -136,7 +128,7 @@ def __init__(self, path, options): self.expect = {} self.result = {} - log.debug(" loading expected events"); + log.info(" loading expected events"); self.load_events(path, self.expect) def is_event(self, name): @@ -172,7 +164,7 @@ def run_cmd(self, tempdir): self.perf, self.command, tempdir, self.args) ret = os.WEXITSTATUS(os.system(cmd)) - log.warning(" running '%s' ret %d " % (cmd, ret)) + log.info(" running '%s' ret %d " % (cmd, ret)) if ret != int(self.ret): raise Unsup(self) @@ -180,7 +172,7 @@ def run_cmd(self, tempdir): def compare(self, expect, result): match = {} - log.debug(" compare"); + log.info(" compare"); # For each expected event find all matching # events in result. Fail if there's not any. @@ -195,11 +187,10 @@ def compare(self, expect, result): else: log.debug(" ->FAIL"); - log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list))) + log.info(" match: [%s] matches %s" % (exp_name, str(exp_list))) # we did not any matching event - fail if (not exp_list): - exp_event.diff(res_event) raise Fail(self, 'match failure'); match[exp_name] = exp_list @@ -217,10 +208,10 @@ def compare(self, expect, result): if res_group not in match[group]: raise Fail(self, 'group failure') - log.debug(" group: [%s] matches group leader %s" % + log.info(" group: [%s] matches group leader %s" % (exp_name, str(match[group]))) - log.debug(" matched") + log.info(" matched") def resolve_groups(self, events): for name, event in events.items(): @@ -242,7 +233,7 @@ def run(self): self.run_cmd(tempdir); # load events expectation for the test - log.debug(" loading result events"); + log.info(" loading result events"); for f in glob.glob(tempdir + '/event*'): self.load_events(f, self.result); diff --git a/trunk/tools/perf/tests/attr/test-record-group1 b/trunk/tools/perf/tests/attr/test-record-group1 index c5548d054aff..4d688a13fd2f 100644 --- a/trunk/tools/perf/tests/attr/test-record-group1 +++ b/trunk/tools/perf/tests/attr/test-record-group1 @@ -1,6 +1,6 @@ [config] command = record -args = -e '{cycles,instructions}' kill >/dev/null 2>&1 +args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1 [event-1:base-record] fd=1 diff --git a/trunk/tools/perf/tests/builtin-test.c b/trunk/tools/perf/tests/builtin-test.c index acb98e0e39f2..186f67535494 100644 --- a/trunk/tools/perf/tests/builtin-test.c +++ b/trunk/tools/perf/tests/builtin-test.c @@ -4,7 +4,6 @@ * Builtin regression testing command: ever growing number of sanity tests */ #include "builtin.h" -#include "intlist.h" #include "tests.h" #include "debug.h" #include "color.h" @@ -69,14 +68,6 @@ static struct test { .desc = "struct perf_event_attr setup", .func = test__attr, }, - { - .desc = "Test matching and linking mutliple hists", - .func = test__hists_link, - }, - { - .desc = "Try 'use perf' in python, checking link problems", - .func = test__python_use, - }, { .func = NULL, }, @@ -106,7 +97,7 @@ static bool perf_test__matches(int curr, int argc, const char *argv[]) return false; } -static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) +static int __cmd_test(int argc, const char *argv[]) { int i = 0; int width = 0; @@ -127,28 +118,13 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) continue; pr_info("%2d: %-*s:", i, width, tests[curr].desc); - - if (intlist__find(skiplist, i)) { - color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); - continue; - } - pr_debug("\n--- start ---\n"); err = tests[curr].func(); pr_debug("---- end ----\n%s:", tests[curr].desc); - - switch (err) { - case TEST_OK: - pr_info(" Ok\n"); - break; - case TEST_SKIP: - color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n"); - break; - case TEST_FAIL: - default: + if (err) color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n"); - break; - } + else + pr_info(" Ok\n"); } return 0; @@ -176,14 +152,11 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) "perf test [] [{list |[|]}]", NULL, }; - const char *skip = NULL; const struct option test_options[] = { - OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_END() }; - struct intlist *skiplist = NULL; argc = parse_options(argc, argv, test_options, test_usage, 0); if (argc >= 1 && !strcmp(argv[0], "list")) @@ -196,8 +169,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) if (symbol__init() < 0) return -1; - if (skip != NULL) - skiplist = intlist__new(skip); - - return __cmd_test(argc, argv, skiplist); + return __cmd_test(argc, argv); } diff --git a/trunk/tools/perf/tests/evsel-roundtrip-name.c b/trunk/tools/perf/tests/evsel-roundtrip-name.c index 0fd99a9adb91..e61fc828a158 100644 --- a/trunk/tools/perf/tests/evsel-roundtrip-name.c +++ b/trunk/tools/perf/tests/evsel-roundtrip-name.c @@ -22,7 +22,7 @@ static int perf_evsel__roundtrip_cache_name_test(void) for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { __perf_evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name)); - err = parse_events(evlist, name); + err = parse_events(evlist, name, 0); if (err) ret = err; } @@ -70,7 +70,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names) return -ENOMEM; for (i = 0; i < nr_names; ++i) { - err = parse_events(evlist, names[i]); + err = parse_events(evlist, names[i], 0); if (err) { pr_debug("failed to parse event '%s', err %d\n", names[i], err); diff --git a/trunk/tools/perf/tests/hists_link.c b/trunk/tools/perf/tests/hists_link.c deleted file mode 100644 index 0afd9223bde7..000000000000 --- a/trunk/tools/perf/tests/hists_link.c +++ /dev/null @@ -1,499 +0,0 @@ -#include "perf.h" -#include "tests.h" -#include "debug.h" -#include "symbol.h" -#include "sort.h" -#include "evsel.h" -#include "evlist.h" -#include "machine.h" -#include "thread.h" -#include "parse-events.h" - -static struct { - u32 pid; - const char *comm; -} fake_threads[] = { - { 100, "perf" }, - { 200, "perf" }, - { 300, "bash" }, -}; - -static struct { - u32 pid; - u64 start; - const char *filename; -} fake_mmap_info[] = { - { 100, 0x40000, "perf" }, - { 100, 0x50000, "libc" }, - { 100, 0xf0000, "[kernel]" }, - { 200, 0x40000, "perf" }, - { 200, 0x50000, "libc" }, - { 200, 0xf0000, "[kernel]" }, - { 300, 0x40000, "bash" }, - { 300, 0x50000, "libc" }, - { 300, 0xf0000, "[kernel]" }, -}; - -struct fake_sym { - u64 start; - u64 length; - const char *name; -}; - -static struct fake_sym perf_syms[] = { - { 700, 100, "main" }, - { 800, 100, "run_command" }, - { 900, 100, "cmd_record" }, -}; - -static struct fake_sym bash_syms[] = { - { 700, 100, "main" }, - { 800, 100, "xmalloc" }, - { 900, 100, "xfree" }, -}; - -static struct fake_sym libc_syms[] = { - { 700, 100, "malloc" }, - { 800, 100, "free" }, - { 900, 100, "realloc" }, -}; - -static struct fake_sym kernel_syms[] = { - { 700, 100, "schedule" }, - { 800, 100, "page_fault" }, - { 900, 100, "sys_perf_event_open" }, -}; - -static struct { - const char *dso_name; - struct fake_sym *syms; - size_t nr_syms; -} fake_symbols[] = { - { "perf", perf_syms, ARRAY_SIZE(perf_syms) }, - { "bash", bash_syms, ARRAY_SIZE(bash_syms) }, - { "libc", libc_syms, ARRAY_SIZE(libc_syms) }, - { "[kernel]", kernel_syms, ARRAY_SIZE(kernel_syms) }, -}; - -static struct machine *setup_fake_machine(struct machines *machines) -{ - struct machine *machine = machines__find(machines, HOST_KERNEL_ID); - size_t i; - - if (machine == NULL) { - pr_debug("Not enough memory for machine setup\n"); - return NULL; - } - - for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { - struct thread *thread; - - thread = machine__findnew_thread(machine, fake_threads[i].pid); - if (thread == NULL) - goto out; - - thread__set_comm(thread, fake_threads[i].comm); - } - - for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { - union perf_event fake_mmap_event = { - .mmap = { - .header = { .misc = PERF_RECORD_MISC_USER, }, - .pid = fake_mmap_info[i].pid, - .start = fake_mmap_info[i].start, - .len = 0x1000ULL, - .pgoff = 0ULL, - }, - }; - - strcpy(fake_mmap_event.mmap.filename, - fake_mmap_info[i].filename); - - machine__process_mmap_event(machine, &fake_mmap_event); - } - - for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { - size_t k; - struct dso *dso; - - dso = __dsos__findnew(&machine->user_dsos, - fake_symbols[i].dso_name); - if (dso == NULL) - goto out; - - /* emulate dso__load() */ - dso__set_loaded(dso, MAP__FUNCTION); - - for (k = 0; k < fake_symbols[i].nr_syms; k++) { - struct symbol *sym; - struct fake_sym *fsym = &fake_symbols[i].syms[k]; - - sym = symbol__new(fsym->start, fsym->length, - STB_GLOBAL, fsym->name); - if (sym == NULL) - goto out; - - symbols__insert(&dso->symbols[MAP__FUNCTION], sym); - } - } - - return machine; - -out: - pr_debug("Not enough memory for machine setup\n"); - machine__delete_threads(machine); - machine__delete(machine); - return NULL; -} - -struct sample { - u32 pid; - u64 ip; - struct thread *thread; - struct map *map; - struct symbol *sym; -}; - -static struct sample fake_common_samples[] = { - /* perf [kernel] schedule() */ - { .pid = 100, .ip = 0xf0000 + 700, }, - /* perf [perf] main() */ - { .pid = 200, .ip = 0x40000 + 700, }, - /* perf [perf] cmd_record() */ - { .pid = 200, .ip = 0x40000 + 900, }, - /* bash [bash] xmalloc() */ - { .pid = 300, .ip = 0x40000 + 800, }, - /* bash [libc] malloc() */ - { .pid = 300, .ip = 0x50000 + 700, }, -}; - -static struct sample fake_samples[][5] = { - { - /* perf [perf] run_command() */ - { .pid = 100, .ip = 0x40000 + 800, }, - /* perf [libc] malloc() */ - { .pid = 100, .ip = 0x50000 + 700, }, - /* perf [kernel] page_fault() */ - { .pid = 100, .ip = 0xf0000 + 800, }, - /* perf [kernel] sys_perf_event_open() */ - { .pid = 200, .ip = 0xf0000 + 900, }, - /* bash [libc] free() */ - { .pid = 300, .ip = 0x50000 + 800, }, - }, - { - /* perf [libc] free() */ - { .pid = 200, .ip = 0x50000 + 800, }, - /* bash [libc] malloc() */ - { .pid = 300, .ip = 0x50000 + 700, }, /* will be merged */ - /* bash [bash] xfee() */ - { .pid = 300, .ip = 0x40000 + 900, }, - /* bash [libc] realloc() */ - { .pid = 300, .ip = 0x50000 + 900, }, - /* bash [kernel] page_fault() */ - { .pid = 300, .ip = 0xf0000 + 800, }, - }, -}; - -static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) -{ - struct perf_evsel *evsel; - struct addr_location al; - struct hist_entry *he; - struct perf_sample sample = { .cpu = 0, }; - size_t i = 0, k; - - /* - * each evsel will have 10 samples - 5 common and 5 distinct. - * However the second evsel also has a collapsed entry for - * "bash [libc] malloc" so total 9 entries will be in the tree. - */ - list_for_each_entry(evsel, &evlist->entries, node) { - for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { - const union perf_event event = { - .ip = { - .header = { - .misc = PERF_RECORD_MISC_USER, - }, - .pid = fake_common_samples[k].pid, - .ip = fake_common_samples[k].ip, - }, - }; - - if (perf_event__preprocess_sample(&event, machine, &al, - &sample, 0) < 0) - goto out; - - he = __hists__add_entry(&evsel->hists, &al, NULL, 1); - if (he == NULL) - goto out; - - fake_common_samples[k].thread = al.thread; - fake_common_samples[k].map = al.map; - fake_common_samples[k].sym = al.sym; - } - - for (k = 0; k < ARRAY_SIZE(fake_samples[i]); k++) { - const union perf_event event = { - .ip = { - .header = { - .misc = PERF_RECORD_MISC_USER, - }, - .pid = fake_samples[i][k].pid, - .ip = fake_samples[i][k].ip, - }, - }; - - if (perf_event__preprocess_sample(&event, machine, &al, - &sample, 0) < 0) - goto out; - - he = __hists__add_entry(&evsel->hists, &al, NULL, 1); - if (he == NULL) - goto out; - - fake_samples[i][k].thread = al.thread; - fake_samples[i][k].map = al.map; - fake_samples[i][k].sym = al.sym; - } - i++; - } - - return 0; - -out: - pr_debug("Not enough memory for adding a hist entry\n"); - return -1; -} - -static int find_sample(struct sample *samples, size_t nr_samples, - struct thread *t, struct map *m, struct symbol *s) -{ - while (nr_samples--) { - if (samples->thread == t && samples->map == m && - samples->sym == s) - return 1; - samples++; - } - return 0; -} - -static int __validate_match(struct hists *hists) -{ - size_t count = 0; - struct rb_root *root; - struct rb_node *node; - - /* - * Only entries from fake_common_samples should have a pair. - */ - if (sort__need_collapse) - root = &hists->entries_collapsed; - else - root = hists->entries_in; - - node = rb_first(root); - while (node) { - struct hist_entry *he; - - he = rb_entry(node, struct hist_entry, rb_node_in); - - if (hist_entry__has_pairs(he)) { - if (find_sample(fake_common_samples, - ARRAY_SIZE(fake_common_samples), - he->thread, he->ms.map, he->ms.sym)) { - count++; - } else { - pr_debug("Can't find the matched entry\n"); - return -1; - } - } - - node = rb_next(node); - } - - if (count != ARRAY_SIZE(fake_common_samples)) { - pr_debug("Invalid count for matched entries: %zd of %zd\n", - count, ARRAY_SIZE(fake_common_samples)); - return -1; - } - - return 0; -} - -static int validate_match(struct hists *leader, struct hists *other) -{ - return __validate_match(leader) || __validate_match(other); -} - -static int __validate_link(struct hists *hists, int idx) -{ - size_t count = 0; - size_t count_pair = 0; - size_t count_dummy = 0; - struct rb_root *root; - struct rb_node *node; - - /* - * Leader hists (idx = 0) will have dummy entries from other, - * and some entries will have no pair. However every entry - * in other hists should have (dummy) pair. - */ - if (sort__need_collapse) - root = &hists->entries_collapsed; - else - root = hists->entries_in; - - node = rb_first(root); - while (node) { - struct hist_entry *he; - - he = rb_entry(node, struct hist_entry, rb_node_in); - - if (hist_entry__has_pairs(he)) { - if (!find_sample(fake_common_samples, - ARRAY_SIZE(fake_common_samples), - he->thread, he->ms.map, he->ms.sym) && - !find_sample(fake_samples[idx], - ARRAY_SIZE(fake_samples[idx]), - he->thread, he->ms.map, he->ms.sym)) { - count_dummy++; - } - count_pair++; - } else if (idx) { - pr_debug("A entry from the other hists should have pair\n"); - return -1; - } - - count++; - node = rb_next(node); - } - - /* - * Note that we have a entry collapsed in the other (idx = 1) hists. - */ - if (idx == 0) { - if (count_dummy != ARRAY_SIZE(fake_samples[1]) - 1) { - pr_debug("Invalid count of dummy entries: %zd of %zd\n", - count_dummy, ARRAY_SIZE(fake_samples[1]) - 1); - return -1; - } - if (count != count_pair + ARRAY_SIZE(fake_samples[0])) { - pr_debug("Invalid count of total leader entries: %zd of %zd\n", - count, count_pair + ARRAY_SIZE(fake_samples[0])); - return -1; - } - } else { - if (count != count_pair) { - pr_debug("Invalid count of total other entries: %zd of %zd\n", - count, count_pair); - return -1; - } - if (count_dummy > 0) { - pr_debug("Other hists should not have dummy entries: %zd\n", - count_dummy); - return -1; - } - } - - return 0; -} - -static int validate_link(struct hists *leader, struct hists *other) -{ - return __validate_link(leader, 0) || __validate_link(other, 1); -} - -static void print_hists(struct hists *hists) -{ - int i = 0; - struct rb_root *root; - struct rb_node *node; - - if (sort__need_collapse) - root = &hists->entries_collapsed; - else - root = hists->entries_in; - - pr_info("----- %s --------\n", __func__); - node = rb_first(root); - while (node) { - struct hist_entry *he; - - he = rb_entry(node, struct hist_entry, rb_node_in); - - pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", - i, he->thread->comm, he->ms.map->dso->short_name, - he->ms.sym->name, he->stat.period); - - i++; - node = rb_next(node); - } -} - -int test__hists_link(void) -{ - int err = -1; - struct machines machines; - struct machine *machine = NULL; - struct perf_evsel *evsel, *first; - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - - if (evlist == NULL) - return -ENOMEM; - - err = parse_events(evlist, "cpu-clock"); - if (err) - goto out; - err = parse_events(evlist, "task-clock"); - if (err) - goto out; - - /* default sort order (comm,dso,sym) will be used */ - setup_sorting(NULL, NULL); - - machines__init(&machines); - - /* setup threads/dso/map/symbols also */ - machine = setup_fake_machine(&machines); - if (!machine) - goto out; - - if (verbose > 1) - machine__fprintf(machine, stderr); - - /* process sample events */ - err = add_hist_entries(evlist, machine); - if (err < 0) - goto out; - - list_for_each_entry(evsel, &evlist->entries, node) { - hists__collapse_resort(&evsel->hists); - - if (verbose > 2) - print_hists(&evsel->hists); - } - - first = perf_evlist__first(evlist); - evsel = perf_evlist__last(evlist); - - /* match common entries */ - hists__match(&first->hists, &evsel->hists); - err = validate_match(&first->hists, &evsel->hists); - if (err) - goto out; - - /* link common and/or dummy entries */ - hists__link(&first->hists, &evsel->hists); - err = validate_link(&first->hists, &evsel->hists); - if (err) - goto out; - - err = 0; - -out: - /* tear down everything */ - perf_evlist__delete(evlist); - machines__exit(&machines); - - return err; -} diff --git a/trunk/tools/perf/tests/open-syscall-all-cpus.c b/trunk/tools/perf/tests/open-syscall-all-cpus.c index b0657a9ccda6..9b920a0cce79 100644 --- a/trunk/tools/perf/tests/open-syscall-all-cpus.c +++ b/trunk/tools/perf/tests/open-syscall-all-cpus.c @@ -98,7 +98,6 @@ int test__open_syscall_event_on_all_cpus(void) } } - perf_evsel__free_counts(evsel); out_close_fd: perf_evsel__close_fd(evsel, 1, threads->nr); out_evsel_delete: diff --git a/trunk/tools/perf/tests/parse-events.c b/trunk/tools/perf/tests/parse-events.c index 80a8daf54a63..294ffddfbf42 100644 --- a/trunk/tools/perf/tests/parse-events.c +++ b/trunk/tools/perf/tests/parse-events.c @@ -3,7 +3,6 @@ #include "evsel.h" #include "evlist.h" #include "sysfs.h" -#include "debugfs.h" #include "tests.h" #include @@ -23,7 +22,6 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist) struct perf_evsel *evsel = perf_evlist__first(evlist); TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); - TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); TEST_ASSERT_VAL("wrong sample_type", PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); @@ -36,7 +34,6 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) struct perf_evsel *evsel; TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); - TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); list_for_each_entry(evsel, &evlist->entries, node) { TEST_ASSERT_VAL("wrong type", @@ -466,10 +463,10 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist) static int test__checkterms_simple(struct list_head *terms) { - struct parse_events_term *term; + struct parse_events__term *term; /* config=10 */ - term = list_entry(terms->next, struct parse_events_term, list); + term = list_entry(terms->next, struct parse_events__term, list); TEST_ASSERT_VAL("wrong type term", term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG); TEST_ASSERT_VAL("wrong type val", @@ -478,7 +475,7 @@ static int test__checkterms_simple(struct list_head *terms) TEST_ASSERT_VAL("wrong config", !term->config); /* config1 */ - term = list_entry(term->list.next, struct parse_events_term, list); + term = list_entry(term->list.next, struct parse_events__term, list); TEST_ASSERT_VAL("wrong type term", term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1); TEST_ASSERT_VAL("wrong type val", @@ -487,7 +484,7 @@ static int test__checkterms_simple(struct list_head *terms) TEST_ASSERT_VAL("wrong config", !term->config); /* config2=3 */ - term = list_entry(term->list.next, struct parse_events_term, list); + term = list_entry(term->list.next, struct parse_events__term, list); TEST_ASSERT_VAL("wrong type term", term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2); TEST_ASSERT_VAL("wrong type val", @@ -496,7 +493,7 @@ static int test__checkterms_simple(struct list_head *terms) TEST_ASSERT_VAL("wrong config", !term->config); /* umask=1*/ - term = list_entry(term->list.next, struct parse_events_term, list); + term = list_entry(term->list.next, struct parse_events__term, list); TEST_ASSERT_VAL("wrong type term", term->type_term == PARSE_EVENTS__TERM_TYPE_USER); TEST_ASSERT_VAL("wrong type val", @@ -512,7 +509,6 @@ static int test__group1(struct perf_evlist *evlist) struct perf_evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* instructions:k */ evsel = leader = perf_evlist__first(evlist); @@ -526,8 +522,6 @@ static int test__group1(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* cycles:upp */ evsel = perf_evsel__next(evsel); @@ -542,7 +536,6 @@ static int test__group1(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); return 0; } @@ -552,7 +545,6 @@ static int test__group2(struct perf_evlist *evlist) struct perf_evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* faults + :ku modifier */ evsel = leader = perf_evlist__first(evlist); @@ -566,8 +558,6 @@ static int test__group2(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* cache-references + :u modifier */ evsel = perf_evsel__next(evsel); @@ -581,7 +571,6 @@ static int test__group2(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); /* cycles:k */ evsel = perf_evsel__next(evsel); @@ -604,7 +593,6 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) struct perf_evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); - TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); /* group1 syscalls:sys_enter_open:H */ evsel = leader = perf_evlist__first(evlist); @@ -621,8 +609,6 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group1")); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* group1 cycles:kppp */ evsel = perf_evsel__next(evsel); @@ -638,7 +624,6 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); /* group2 cycles + G modifier */ evsel = leader = perf_evsel__next(evsel); @@ -654,8 +639,6 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group2")); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* group2 1:3 + G modifier */ evsel = perf_evsel__next(evsel); @@ -668,7 +651,6 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); /* instructions:u */ evsel = perf_evsel__next(evsel); @@ -691,7 +673,6 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) struct perf_evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); - TEST_ASSERT_VAL("wrong number of groups", 1 == evlist->nr_groups); /* cycles:u + p */ evsel = leader = perf_evlist__first(evlist); @@ -707,8 +688,6 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* instructions:kp + p */ evsel = perf_evsel__next(evsel); @@ -723,7 +702,6 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); return 0; } @@ -733,7 +711,6 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) struct perf_evsel *evsel, *leader; TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries); - TEST_ASSERT_VAL("wrong number of groups", 2 == evlist->nr_groups); /* cycles + G */ evsel = leader = perf_evlist__first(evlist); @@ -748,8 +725,6 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* instructions + G */ evsel = perf_evsel__next(evsel); @@ -763,7 +738,6 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); /* cycles:G */ evsel = leader = perf_evsel__next(evsel); @@ -778,8 +752,6 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); - TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); /* instructions:G */ evsel = perf_evsel__next(evsel); @@ -793,7 +765,6 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); - TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); /* cycles */ evsel = perf_evsel__next(evsel); @@ -811,70 +782,13 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) return 0; } -static int count_tracepoints(void) -{ - char events_path[PATH_MAX]; - struct dirent *events_ent; - DIR *events_dir; - int cnt = 0; - - scnprintf(events_path, PATH_MAX, "%s/tracing/events", - debugfs_find_mountpoint()); - - events_dir = opendir(events_path); - - TEST_ASSERT_VAL("Can't open events dir", events_dir); - - while ((events_ent = readdir(events_dir))) { - char sys_path[PATH_MAX]; - struct dirent *sys_ent; - DIR *sys_dir; - - if (!strcmp(events_ent->d_name, ".") - || !strcmp(events_ent->d_name, "..") - || !strcmp(events_ent->d_name, "enable") - || !strcmp(events_ent->d_name, "header_event") - || !strcmp(events_ent->d_name, "header_page")) - continue; - - scnprintf(sys_path, PATH_MAX, "%s/%s", - events_path, events_ent->d_name); - - sys_dir = opendir(sys_path); - TEST_ASSERT_VAL("Can't open sys dir", sys_dir); - - while ((sys_ent = readdir(sys_dir))) { - if (!strcmp(sys_ent->d_name, ".") - || !strcmp(sys_ent->d_name, "..") - || !strcmp(sys_ent->d_name, "enable") - || !strcmp(sys_ent->d_name, "filter")) - continue; - - cnt++; - } - - closedir(sys_dir); - } - - closedir(events_dir); - return cnt; -} - -static int test__all_tracepoints(struct perf_evlist *evlist) -{ - TEST_ASSERT_VAL("wrong events count", - count_tracepoints() == evlist->nr_entries); - - return test__checkevent_tracepoint_multi(evlist); -} - -struct evlist_test { +struct test__event_st { const char *name; __u32 type; int (*check)(struct perf_evlist *evlist); }; -static struct evlist_test test__events[] = { +static struct test__event_st test__events[] = { [0] = { .name = "syscalls:sys_enter_open", .check = test__checkevent_tracepoint, @@ -1007,13 +921,9 @@ static struct evlist_test test__events[] = { .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles", .check = test__group5, }, - [33] = { - .name = "*:*", - .check = test__all_tracepoints, - }, }; -static struct evlist_test test__events_pmu[] = { +static struct test__event_st test__events_pmu[] = { [0] = { .name = "cpu/config=10,config1,config2=3,period=1000/u", .check = test__checkevent_pmu, @@ -1024,20 +934,20 @@ static struct evlist_test test__events_pmu[] = { }, }; -struct terms_test { +struct test__term { const char *str; __u32 type; int (*check)(struct list_head *terms); }; -static struct terms_test test__terms[] = { +static struct test__term test__terms[] = { [0] = { .str = "config=10,config1,config2=3,umask=1", .check = test__checkterms_simple, }, }; -static int test_event(struct evlist_test *e) +static int test_event(struct test__event_st *e) { struct perf_evlist *evlist; int ret; @@ -1046,7 +956,7 @@ static int test_event(struct evlist_test *e) if (evlist == NULL) return -ENOMEM; - ret = parse_events(evlist, e->name); + ret = parse_events(evlist, e->name, 0); if (ret) { pr_debug("failed to parse event '%s', err %d\n", e->name, ret); @@ -1059,13 +969,13 @@ static int test_event(struct evlist_test *e) return ret; } -static int test_events(struct evlist_test *events, unsigned cnt) +static int test_events(struct test__event_st *events, unsigned cnt) { int ret1, ret2 = 0; unsigned i; for (i = 0; i < cnt; i++) { - struct evlist_test *e = &events[i]; + struct test__event_st *e = &events[i]; pr_debug("running test %d '%s'\n", i, e->name); ret1 = test_event(e); @@ -1076,7 +986,7 @@ static int test_events(struct evlist_test *events, unsigned cnt) return ret2; } -static int test_term(struct terms_test *t) +static int test_term(struct test__term *t) { struct list_head *terms; int ret; @@ -1100,13 +1010,13 @@ static int test_term(struct terms_test *t) return ret; } -static int test_terms(struct terms_test *terms, unsigned cnt) +static int test_terms(struct test__term *terms, unsigned cnt) { int ret = 0; unsigned i; for (i = 0; i < cnt; i++) { - struct terms_test *t = &terms[i]; + struct test__term *t = &terms[i]; pr_debug("running test %d '%s'\n", i, t->str); ret = test_term(t); @@ -1157,7 +1067,7 @@ static int test_pmu_events(void) while (!ret && (ent = readdir(dir))) { #define MAX_NAME 100 - struct evlist_test e; + struct test__event_st e; char name[MAX_NAME]; if (!strcmp(ent->d_name, ".") || diff --git a/trunk/tools/perf/tests/perf-record.c b/trunk/tools/perf/tests/perf-record.c index 1e8e5128d0da..6ea66cf6791b 100644 --- a/trunk/tools/perf/tests/perf-record.c +++ b/trunk/tools/perf/tests/perf-record.c @@ -96,7 +96,7 @@ int test__PERF_RECORD(void) err = perf_evlist__prepare_workload(evlist, &opts, argv); if (err < 0) { pr_debug("Couldn't run the workload!\n"); - goto out_delete_maps; + goto out_delete_evlist; } /* @@ -111,7 +111,7 @@ int test__PERF_RECORD(void) err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); if (err < 0) { pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); - goto out_delete_maps; + goto out_delete_evlist; } cpu = err; @@ -121,7 +121,7 @@ int test__PERF_RECORD(void) */ if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { pr_debug("sched_setaffinity: %s\n", strerror(errno)); - goto out_delete_maps; + goto out_delete_evlist; } /* @@ -131,7 +131,7 @@ int test__PERF_RECORD(void) err = perf_evlist__open(evlist); if (err < 0) { pr_debug("perf_evlist__open: %s\n", strerror(errno)); - goto out_delete_maps; + goto out_delete_evlist; } /* @@ -142,7 +142,7 @@ int test__PERF_RECORD(void) err = perf_evlist__mmap(evlist, opts.mmap_pages, false); if (err < 0) { pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); - goto out_delete_maps; + goto out_delete_evlist; } /* @@ -305,8 +305,6 @@ int test__PERF_RECORD(void) } out_err: perf_evlist__munmap(evlist); -out_delete_maps: - perf_evlist__delete_maps(evlist); out_delete_evlist: perf_evlist__delete(evlist); out: diff --git a/trunk/tools/perf/tests/pmu.c b/trunk/tools/perf/tests/pmu.c index 12b322fa3475..a5f379863b8f 100644 --- a/trunk/tools/perf/tests/pmu.c +++ b/trunk/tools/perf/tests/pmu.c @@ -19,8 +19,10 @@ static struct test_format { { "krava23", "config2:28-29,38\n", }, }; +#define TEST_FORMATS_CNT (sizeof(test_formats) / sizeof(struct test_format)) + /* Simulated users input. */ -static struct parse_events_term test_terms[] = { +static struct parse_events__term test_terms[] = { { .config = (char *) "krava01", .val.num = 15, @@ -76,6 +78,7 @@ static struct parse_events_term test_terms[] = { .type_term = PARSE_EVENTS__TERM_TYPE_USER, }, }; +#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term)) /* * Prepare format directory data, exported by kernel @@ -90,7 +93,7 @@ static char *test_format_dir_get(void) if (!mkdtemp(dir)) return NULL; - for (i = 0; i < ARRAY_SIZE(test_formats); i++) { + for (i = 0; i < TEST_FORMATS_CNT; i++) { static char name[PATH_MAX]; struct test_format *format = &test_formats[i]; FILE *file; @@ -127,12 +130,14 @@ static struct list_head *test_terms_list(void) static LIST_HEAD(terms); unsigned int i; - for (i = 0; i < ARRAY_SIZE(test_terms); i++) + for (i = 0; i < TERMS_CNT; i++) list_add_tail(&test_terms[i].list, &terms); return &terms; } +#undef TERMS_CNT + int test__pmu(void) { char *format = test_format_dir_get(); diff --git a/trunk/tools/perf/tests/python-use.c b/trunk/tools/perf/tests/python-use.c deleted file mode 100644 index 7760277c6def..000000000000 --- a/trunk/tools/perf/tests/python-use.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Just test if we can load the python binding. - */ - -#include -#include -#include "tests.h" - -extern int verbose; - -int test__python_use(void) -{ - char *cmd; - int ret; - - if (asprintf(&cmd, "echo \"import sys ; sys.path.append('%s'); import perf\" | %s %s", - PYTHONPATH, PYTHON, verbose ? "" : "2> /dev/null") < 0) - return -1; - - ret = system(cmd) ? -1 : 0; - free(cmd); - return ret; -} diff --git a/trunk/tools/perf/tests/tests.h b/trunk/tools/perf/tests/tests.h index 5de0be1ff4b6..0fd94657960e 100644 --- a/trunk/tools/perf/tests/tests.h +++ b/trunk/tools/perf/tests/tests.h @@ -1,12 +1,6 @@ #ifndef TESTS_H #define TESTS_H -enum { - TEST_OK = 0, - TEST_FAIL = -1, - TEST_SKIP = -2, -}; - /* Tests */ int test__vmlinux_matches_kallsyms(void); int test__open_syscall_event(void); @@ -21,7 +15,5 @@ int test__pmu(void); int test__attr(void); int test__dso_data(void); int test__parse_events(void); -int test__hists_link(void); -int test__python_use(void); #endif /* TESTS_H */ diff --git a/trunk/tools/perf/tests/vmlinux-kallsyms.c b/trunk/tools/perf/tests/vmlinux-kallsyms.c index 7b4c4d26d1ba..0d1cdbee2f59 100644 --- a/trunk/tools/perf/tests/vmlinux-kallsyms.c +++ b/trunk/tools/perf/tests/vmlinux-kallsyms.c @@ -44,7 +44,7 @@ int test__vmlinux_matches_kallsyms(void) */ if (machine__create_kernel_maps(&kallsyms) < 0) { pr_debug("machine__create_kernel_maps "); - goto out; + return -1; } /* @@ -101,8 +101,7 @@ int test__vmlinux_matches_kallsyms(void) */ if (machine__load_vmlinux_path(&vmlinux, type, vmlinux_matches_kallsyms_filter) <= 0) { - pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n"); - err = TEST_SKIP; + pr_debug("machine__load_vmlinux_path "); goto out; } @@ -227,7 +226,5 @@ int test__vmlinux_matches_kallsyms(void) map__fprintf(pos, stderr); } out: - machine__exit(&kallsyms); - machine__exit(&vmlinux); return err; } diff --git a/trunk/tools/perf/ui/browser.c b/trunk/tools/perf/ui/browser.c index 809ea4632a34..4aeb7d5df939 100644 --- a/trunk/tools/perf/ui/browser.c +++ b/trunk/tools/perf/ui/browser.c @@ -273,8 +273,6 @@ void ui_browser__hide(struct ui_browser *browser __maybe_unused) { pthread_mutex_lock(&ui__lock); ui_helpline__pop(); - free(browser->helpline); - browser->helpline = NULL; pthread_mutex_unlock(&ui__lock); } @@ -473,7 +471,7 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *browser) return row; } -static struct ui_browser_colorset { +static struct ui_browser__colorset { const char *name, *fg, *bg; int colorset; } ui_browser__colorsets[] = { @@ -708,7 +706,7 @@ void ui_browser__init(void) perf_config(ui_browser__color_config, NULL); while (ui_browser__colorsets[i].name) { - struct ui_browser_colorset *c = &ui_browser__colorsets[i++]; + struct ui_browser__colorset *c = &ui_browser__colorsets[i++]; sltt_set_color(c->colorset, c->name, c->fg, c->bg); } diff --git a/trunk/tools/perf/ui/browsers/annotate.c b/trunk/tools/perf/ui/browsers/annotate.c index 7dca1555c610..5dab3ca96980 100644 --- a/trunk/tools/perf/ui/browsers/annotate.c +++ b/trunk/tools/perf/ui/browsers/annotate.c @@ -182,16 +182,6 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ab->selection = dl; } -static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) -{ - if (!dl || !dl->ins || !ins__is_jump(dl->ins) - || !disasm_line__has_offset(dl) - || dl->ops.target.offset >= symbol__size(sym)) - return false; - - return true; -} - static void annotate_browser__draw_current_jump(struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); @@ -205,7 +195,8 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) if (strstr(sym->name, "@plt")) return; - if (!disasm_line__is_valid_jump(cursor, sym)) + if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) || + !disasm_line__has_offset(cursor)) return; target = ab->offsets[cursor->ops.target.offset]; @@ -797,9 +788,17 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser struct disasm_line *dl = browser->offsets[offset], *dlt; struct browser_disasm_line *bdlt; - if (!disasm_line__is_valid_jump(dl, sym)) + if (!dl || !dl->ins || !ins__is_jump(dl->ins) || + !disasm_line__has_offset(dl)) continue; + if (dl->ops.target.offset >= size) { + ui__error("jump to after symbol!\n" + "size: %zx, jump target: %" PRIx64, + size, dl->ops.target.offset); + continue; + } + dlt = browser->offsets[dl->ops.target.offset]; /* * FIXME: Oops, no jump target? Buggy disassembler? Or do we @@ -922,11 +921,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, #define ANNOTATE_CFG(n) \ { .name = #n, .value = &annotate_browser__opts.n, } - + /* * Keep the entries sorted, they are bsearch'ed */ -static struct annotate_config { +static struct annotate__config { const char *name; bool *value; } annotate__configs[] = { @@ -940,7 +939,7 @@ static struct annotate_config { static int annotate_config__cmp(const void *name, const void *cfgp) { - const struct annotate_config *cfg = cfgp; + const struct annotate__config *cfg = cfgp; return strcmp(name, cfg->name); } @@ -948,7 +947,7 @@ static int annotate_config__cmp(const void *name, const void *cfgp) static int annotate__config(const char *var, const char *value, void *data __maybe_unused) { - struct annotate_config *cfg; + struct annotate__config *cfg; const char *name; if (prefixcmp(var, "annotate.") != 0) @@ -956,7 +955,7 @@ static int annotate__config(const char *var, const char *value, name = var + 9; cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), - sizeof(struct annotate_config), annotate_config__cmp); + sizeof(struct annotate__config), annotate_config__cmp); if (cfg == NULL) return -1; diff --git a/trunk/tools/perf/ui/browsers/hists.c b/trunk/tools/perf/ui/browsers/hists.c index 20ccd57753f7..57b82c26cd05 100644 --- a/trunk/tools/perf/ui/browsers/hists.c +++ b/trunk/tools/perf/ui/browsers/hists.c @@ -567,123 +567,23 @@ static int hist_browser__show_callchain(struct hist_browser *browser, return row - first_row; } -struct hpp_arg { - struct ui_browser *b; - char folded_sign; - bool current_entry; -}; - -static int __hpp__color_callchain(struct hpp_arg *arg) -{ - if (!symbol_conf.use_callchain) - return 0; - - slsmg_printf("%c ", arg->folded_sign); - return 2; -} - -static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he, - u64 (*get_field)(struct hist_entry *), - int (*callchain_cb)(struct hpp_arg *)) -{ - int ret = 0; - double percent = 0.0; - struct hists *hists = he->hists; - struct hpp_arg *arg = hpp->ptr; - - if (hists->stats.total_period) - percent = 100.0 * get_field(he) / hists->stats.total_period; - - ui_browser__set_percent_color(arg->b, percent, arg->current_entry); - - if (callchain_cb) - ret += callchain_cb(arg); - - ret += scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); - slsmg_printf("%s", hpp->buf); - - if (symbol_conf.event_group) { - int prev_idx, idx_delta; - struct perf_evsel *evsel = hists_to_evsel(hists); - struct hist_entry *pair; - int nr_members = evsel->nr_members; - - if (nr_members <= 1) - goto out; - - prev_idx = perf_evsel__group_idx(evsel); - - list_for_each_entry(pair, &he->pairs.head, pairs.node) { - u64 period = get_field(pair); - u64 total = pair->hists->stats.total_period; - - if (!total) - continue; - - evsel = hists_to_evsel(pair->hists); - idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1; - - while (idx_delta--) { - /* - * zero-fill group members in the middle which - * have no sample - */ - ui_browser__set_percent_color(arg->b, 0.0, - arg->current_entry); - ret += scnprintf(hpp->buf, hpp->size, - " %6.2f%%", 0.0); - slsmg_printf("%s", hpp->buf); - } - - percent = 100.0 * period / total; - ui_browser__set_percent_color(arg->b, percent, - arg->current_entry); - ret += scnprintf(hpp->buf, hpp->size, - " %6.2f%%", percent); - slsmg_printf("%s", hpp->buf); - - prev_idx = perf_evsel__group_idx(evsel); - } - - idx_delta = nr_members - prev_idx - 1; - - while (idx_delta--) { - /* - * zero-fill group members at last which have no sample - */ - ui_browser__set_percent_color(arg->b, 0.0, - arg->current_entry); - ret += scnprintf(hpp->buf, hpp->size, - " %6.2f%%", 0.0); - slsmg_printf("%s", hpp->buf); - } - } -out: - if (!arg->current_entry || !arg->b->navkeypressed) - ui_browser__set_color(arg->b, HE_COLORSET_NORMAL); - - return ret; -} - -#define __HPP_COLOR_PERCENT_FN(_type, _field, _cb) \ -static u64 __hpp_get_##_field(struct hist_entry *he) \ +#define HPP__COLOR_FN(_name, _field) \ +static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ + struct hist_entry *he) \ { \ - return he->stat._field; \ -} \ - \ -static int hist_browser__hpp_color_##_type(struct perf_hpp *hpp, \ - struct hist_entry *he) \ -{ \ - return __hpp__color_fmt(hpp, he, __hpp_get_##_field, _cb); \ + struct hists *hists = he->hists; \ + double percent = 100.0 * he->stat._field / hists->stats.total_period; \ + *(double *)hpp->ptr = percent; \ + return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \ } -__HPP_COLOR_PERCENT_FN(overhead, period, __hpp__color_callchain) -__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, NULL) -__HPP_COLOR_PERCENT_FN(overhead_us, period_us, NULL) -__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, NULL) -__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, NULL) +HPP__COLOR_FN(overhead, period) +HPP__COLOR_FN(overhead_sys, period_sys) +HPP__COLOR_FN(overhead_us, period_us) +HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) +HPP__COLOR_FN(overhead_guest_us, period_guest_us) -#undef __HPP_COLOR_PERCENT_FN +#undef HPP__COLOR_FN void hist_browser__init_hpp(void) { @@ -708,6 +608,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, unsigned short row) { char s[256]; + double percent; int printed = 0; int width = browser->b.width; char folded_sign = ' '; @@ -727,20 +628,16 @@ static int hist_browser__show_entry(struct hist_browser *browser, } if (row_offset == 0) { - struct hpp_arg arg = { - .b = &browser->b, - .folded_sign = folded_sign, - .current_entry = current_entry, - }; struct perf_hpp hpp = { .buf = s, .size = sizeof(s), - .ptr = &arg, }; + int i = 0; ui_browser__gotorc(&browser->b, row, 0); perf_hpp__for_each_format(fmt) { + if (!first) { slsmg_printf(" "); width -= 2; @@ -748,11 +645,27 @@ static int hist_browser__show_entry(struct hist_browser *browser, first = false; if (fmt->color) { + hpp.ptr = &percent; + /* It will set percent for us. See HPP__COLOR_FN above. */ width -= fmt->color(&hpp, entry); + + ui_browser__set_percent_color(&browser->b, percent, current_entry); + + if (!i && symbol_conf.use_callchain) { + slsmg_printf("%c ", folded_sign); + width -= 2; + } + + slsmg_printf("%s", s); + + if (!current_entry || !browser->b.navkeypressed) + ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); } else { width -= fmt->entry(&hpp, entry); slsmg_printf("%s", s); } + + i++; } /* The scroll bar isn't being used */ @@ -1189,21 +1102,6 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size, const struct thread *thread = hists->thread_filter; unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = hists->stats.total_period; - struct perf_evsel *evsel = hists_to_evsel(hists); - char buf[512]; - size_t buflen = sizeof(buf); - - if (symbol_conf.event_group && evsel->nr_members > 1) { - struct perf_evsel *pos; - - perf_evsel__group_desc(evsel, buf, buflen); - ev_name = buf; - - for_each_group_member(pos, evsel) { - nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; - nr_events += pos->hists.stats.total_period; - } - } nr_samples = convert_unit(nr_samples, &unit); printed = scnprintf(bf, size, @@ -1600,16 +1498,6 @@ static void perf_evsel_menu__write(struct ui_browser *browser, ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : HE_COLORSET_NORMAL); - if (symbol_conf.event_group && evsel->nr_members > 1) { - struct perf_evsel *pos; - - ev_name = perf_evsel__group_name(evsel); - - for_each_group_member(pos, evsel) { - nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; - } - } - nr_events = convert_unit(nr_events, &unit); printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events, unit, unit == ' ' ? "" : " ", ev_name); @@ -1720,19 +1608,8 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, return key; } -static bool filter_group_entries(struct ui_browser *self __maybe_unused, - void *entry) -{ - struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); - - if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel)) - return true; - - return false; -} - static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, - int nr_entries, const char *help, + const char *help, struct hist_browser_timer *hbt, struct perf_session_env *env) { @@ -1743,8 +1620,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, .refresh = ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = perf_evsel_menu__write, - .filter = filter_group_entries, - .nr_entries = nr_entries, + .nr_entries = evlist->nr_entries, .priv = evlist, }, .env = env, @@ -1760,37 +1636,20 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, menu.b.width = line_len; } - return perf_evsel_menu__run(&menu, nr_entries, help, hbt); + return perf_evsel_menu__run(&menu, evlist->nr_entries, help, hbt); } int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, struct hist_browser_timer *hbt, struct perf_session_env *env) { - int nr_entries = evlist->nr_entries; - -single_entry: - if (nr_entries == 1) { + if (evlist->nr_entries == 1) { struct perf_evsel *first = list_entry(evlist->entries.next, struct perf_evsel, node); const char *ev_name = perf_evsel__name(first); - - return perf_evsel__hists_browse(first, nr_entries, help, + return perf_evsel__hists_browse(first, evlist->nr_entries, help, ev_name, false, hbt, env); } - if (symbol_conf.event_group) { - struct perf_evsel *pos; - - nr_entries = 0; - list_for_each_entry(pos, &evlist->entries, node) - if (perf_evsel__is_group_leader(pos)) - nr_entries++; - - if (nr_entries == 1) - goto single_entry; - } - - return __perf_evlist__tui_browse_hists(evlist, nr_entries, help, - hbt, env); + return __perf_evlist__tui_browse_hists(evlist, help, hbt, env); } diff --git a/trunk/tools/perf/ui/gtk/browser.c b/trunk/tools/perf/ui/gtk/browser.c index c95012cdb438..e59ba337f494 100644 --- a/trunk/tools/perf/ui/gtk/browser.c +++ b/trunk/tools/perf/ui/gtk/browser.c @@ -8,13 +8,15 @@ #include -void perf_gtk__signal(int sig) +#define MAX_COLUMNS 32 + +static void perf_gtk__signal(int sig) { perf_gtk__exit(false); psignal(sig, "perf"); } -void perf_gtk__resize_window(GtkWidget *window) +static void perf_gtk__resize_window(GtkWidget *window) { GdkRectangle rect; GdkScreen *screen; @@ -34,7 +36,7 @@ void perf_gtk__resize_window(GtkWidget *window) gtk_window_resize(GTK_WINDOW(window), width, height); } -const char *perf_gtk__get_percent_color(double percent) +static const char *perf_gtk__get_percent_color(double percent) { if (percent >= MIN_RED) return ""; @@ -43,8 +45,147 @@ const char *perf_gtk__get_percent_color(double percent) return NULL; } +#define HPP__COLOR_FN(_name, _field) \ +static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ + struct hist_entry *he) \ +{ \ + struct hists *hists = he->hists; \ + double percent = 100.0 * he->stat._field / hists->stats.total_period; \ + const char *markup; \ + int ret = 0; \ + \ + markup = perf_gtk__get_percent_color(percent); \ + if (markup) \ + ret += scnprintf(hpp->buf, hpp->size, "%s", markup); \ + ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent); \ + if (markup) \ + ret += scnprintf(hpp->buf + ret, hpp->size - ret, ""); \ + \ + return ret; \ +} + +HPP__COLOR_FN(overhead, period) +HPP__COLOR_FN(overhead_sys, period_sys) +HPP__COLOR_FN(overhead_us, period_us) +HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) +HPP__COLOR_FN(overhead_guest_us, period_guest_us) + +#undef HPP__COLOR_FN + +void perf_gtk__init_hpp(void) +{ + perf_hpp__column_enable(PERF_HPP__OVERHEAD); + + perf_hpp__init(); + + perf_hpp__format[PERF_HPP__OVERHEAD].color = + perf_gtk__hpp_color_overhead; + perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = + perf_gtk__hpp_color_overhead_sys; + perf_hpp__format[PERF_HPP__OVERHEAD_US].color = + perf_gtk__hpp_color_overhead_us; + perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = + perf_gtk__hpp_color_overhead_guest_sys; + perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = + perf_gtk__hpp_color_overhead_guest_us; +} + +static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) +{ + struct perf_hpp_fmt *fmt; + GType col_types[MAX_COLUMNS]; + GtkCellRenderer *renderer; + struct sort_entry *se; + GtkListStore *store; + struct rb_node *nd; + GtkWidget *view; + int col_idx; + int nr_cols; + char s[512]; + + struct perf_hpp hpp = { + .buf = s, + .size = sizeof(s), + }; + + nr_cols = 0; + + perf_hpp__for_each_format(fmt) + col_types[nr_cols++] = G_TYPE_STRING; + + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (se->elide) + continue; + + col_types[nr_cols++] = G_TYPE_STRING; + } + + store = gtk_list_store_newv(nr_cols, col_types); + + view = gtk_tree_view_new(); + + renderer = gtk_cell_renderer_text_new(); + + col_idx = 0; + + perf_hpp__for_each_format(fmt) { + fmt->header(&hpp); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), + -1, s, + renderer, "markup", + col_idx++, NULL); + } + + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (se->elide) + continue; + + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), + -1, se->se_header, + renderer, "text", + col_idx++, NULL); + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); + + g_object_unref(GTK_TREE_MODEL(store)); + + for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { + struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + GtkTreeIter iter; + + if (h->filtered) + continue; + + gtk_list_store_append(store, &iter); + + col_idx = 0; + + perf_hpp__for_each_format(fmt) { + if (fmt->color) + fmt->color(&hpp, h); + else + fmt->entry(&hpp, h); + + gtk_list_store_set(store, &iter, col_idx++, s, -1); + } + + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (se->elide) + continue; + + se->se_snprintf(h, s, ARRAY_SIZE(s), + hists__col_len(hists, se->se_width_idx)); + + gtk_list_store_set(store, &iter, col_idx++, s, -1); + } + } + + gtk_container_add(GTK_CONTAINER(window), view); +} + #ifdef HAVE_GTK_INFO_BAR -GtkWidget *perf_gtk__setup_info_bar(void) +static GtkWidget *perf_gtk__setup_info_bar(void) { GtkWidget *info_bar; GtkWidget *label; @@ -71,7 +212,7 @@ GtkWidget *perf_gtk__setup_info_bar(void) } #endif -GtkWidget *perf_gtk__setup_statusbar(void) +static GtkWidget *perf_gtk__setup_statusbar(void) { GtkWidget *stbar; unsigned ctxid; @@ -85,3 +226,79 @@ GtkWidget *perf_gtk__setup_statusbar(void) return stbar; } + +int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, + const char *help, + struct hist_browser_timer *hbt __maybe_unused) +{ + struct perf_evsel *pos; + GtkWidget *vbox; + GtkWidget *notebook; + GtkWidget *info_bar; + GtkWidget *statbar; + GtkWidget *window; + + signal(SIGSEGV, perf_gtk__signal); + signal(SIGFPE, perf_gtk__signal); + signal(SIGINT, perf_gtk__signal); + signal(SIGQUIT, perf_gtk__signal); + signal(SIGTERM, perf_gtk__signal); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + gtk_window_set_title(GTK_WINDOW(window), "perf report"); + + g_signal_connect(window, "delete_event", gtk_main_quit, NULL); + + pgctx = perf_gtk__activate_context(window); + if (!pgctx) + return -1; + + vbox = gtk_vbox_new(FALSE, 0); + + notebook = gtk_notebook_new(); + + list_for_each_entry(pos, &evlist->entries, node) { + struct hists *hists = &pos->hists; + const char *evname = perf_evsel__name(pos); + GtkWidget *scrolled_window; + GtkWidget *tab_label; + + scrolled_window = gtk_scrolled_window_new(NULL, NULL); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + perf_gtk__show_hists(scrolled_window, hists); + + tab_label = gtk_label_new(evname); + + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); + } + + gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + + info_bar = perf_gtk__setup_info_bar(); + if (info_bar) + gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0); + + statbar = perf_gtk__setup_statusbar(); + gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(window), vbox); + + gtk_widget_show_all(window); + + perf_gtk__resize_window(window); + + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + + ui_helpline__push(help); + + gtk_main(); + + perf_gtk__deactivate_context(&pgctx); + + return 0; +} diff --git a/trunk/tools/perf/ui/gtk/gtk.h b/trunk/tools/perf/ui/gtk/gtk.h index 5d3693754828..856320e2cc05 100644 --- a/trunk/tools/perf/ui/gtk/gtk.h +++ b/trunk/tools/perf/ui/gtk/gtk.h @@ -33,14 +33,7 @@ void perf_gtk__init_helpline(void); void perf_gtk__init_progress(void); void perf_gtk__init_hpp(void); -void perf_gtk__signal(int sig); -void perf_gtk__resize_window(GtkWidget *window); -const char *perf_gtk__get_percent_color(double percent); -GtkWidget *perf_gtk__setup_statusbar(void); - -#ifdef HAVE_GTK_INFO_BAR -GtkWidget *perf_gtk__setup_info_bar(void); -#else +#ifndef HAVE_GTK_INFO_BAR static inline GtkWidget *perf_gtk__setup_info_bar(void) { return NULL; diff --git a/trunk/tools/perf/ui/gtk/hists.c b/trunk/tools/perf/ui/gtk/hists.c deleted file mode 100644 index 1e764a8ad259..000000000000 --- a/trunk/tools/perf/ui/gtk/hists.c +++ /dev/null @@ -1,312 +0,0 @@ -#include "../evlist.h" -#include "../cache.h" -#include "../evsel.h" -#include "../sort.h" -#include "../hist.h" -#include "../helpline.h" -#include "gtk.h" - -#define MAX_COLUMNS 32 - -static int __percent_color_snprintf(char *buf, size_t size, double percent) -{ - int ret = 0; - const char *markup; - - markup = perf_gtk__get_percent_color(percent); - if (markup) - ret += scnprintf(buf, size, markup); - - ret += scnprintf(buf + ret, size - ret, " %6.2f%%", percent); - - if (markup) - ret += scnprintf(buf + ret, size - ret, ""); - - return ret; -} - - -static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he, - u64 (*get_field)(struct hist_entry *)) -{ - int ret; - double percent = 0.0; - struct hists *hists = he->hists; - - if (hists->stats.total_period) - percent = 100.0 * get_field(he) / hists->stats.total_period; - - ret = __percent_color_snprintf(hpp->buf, hpp->size, percent); - - if (symbol_conf.event_group) { - int prev_idx, idx_delta; - struct perf_evsel *evsel = hists_to_evsel(hists); - struct hist_entry *pair; - int nr_members = evsel->nr_members; - - if (nr_members <= 1) - return ret; - - prev_idx = perf_evsel__group_idx(evsel); - - list_for_each_entry(pair, &he->pairs.head, pairs.node) { - u64 period = get_field(pair); - u64 total = pair->hists->stats.total_period; - - evsel = hists_to_evsel(pair->hists); - idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1; - - while (idx_delta--) { - /* - * zero-fill group members in the middle which - * have no sample - */ - ret += __percent_color_snprintf(hpp->buf + ret, - hpp->size - ret, - 0.0); - } - - percent = 100.0 * period / total; - ret += __percent_color_snprintf(hpp->buf + ret, - hpp->size - ret, - percent); - - prev_idx = perf_evsel__group_idx(evsel); - } - - idx_delta = nr_members - prev_idx - 1; - - while (idx_delta--) { - /* - * zero-fill group members at last which have no sample - */ - ret += __percent_color_snprintf(hpp->buf + ret, - hpp->size - ret, - 0.0); - } - } - return ret; -} - -#define __HPP_COLOR_PERCENT_FN(_type, _field) \ -static u64 he_get_##_field(struct hist_entry *he) \ -{ \ - return he->stat._field; \ -} \ - \ -static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp, \ - struct hist_entry *he) \ -{ \ - return __hpp__color_fmt(hpp, he, he_get_##_field); \ -} - -__HPP_COLOR_PERCENT_FN(overhead, period) -__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys) -__HPP_COLOR_PERCENT_FN(overhead_us, period_us) -__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys) -__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us) - -#undef __HPP_COLOR_PERCENT_FN - - -void perf_gtk__init_hpp(void) -{ - perf_hpp__column_enable(PERF_HPP__OVERHEAD); - - perf_hpp__init(); - - perf_hpp__format[PERF_HPP__OVERHEAD].color = - perf_gtk__hpp_color_overhead; - perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = - perf_gtk__hpp_color_overhead_sys; - perf_hpp__format[PERF_HPP__OVERHEAD_US].color = - perf_gtk__hpp_color_overhead_us; - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = - perf_gtk__hpp_color_overhead_guest_sys; - perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = - perf_gtk__hpp_color_overhead_guest_us; -} - -static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) -{ - struct perf_hpp_fmt *fmt; - GType col_types[MAX_COLUMNS]; - GtkCellRenderer *renderer; - struct sort_entry *se; - GtkListStore *store; - struct rb_node *nd; - GtkWidget *view; - int col_idx; - int nr_cols; - char s[512]; - - struct perf_hpp hpp = { - .buf = s, - .size = sizeof(s), - .ptr = hists_to_evsel(hists), - }; - - nr_cols = 0; - - perf_hpp__for_each_format(fmt) - col_types[nr_cols++] = G_TYPE_STRING; - - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (se->elide) - continue; - - col_types[nr_cols++] = G_TYPE_STRING; - } - - store = gtk_list_store_newv(nr_cols, col_types); - - view = gtk_tree_view_new(); - - renderer = gtk_cell_renderer_text_new(); - - col_idx = 0; - - perf_hpp__for_each_format(fmt) { - fmt->header(&hpp); - - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), - -1, ltrim(s), - renderer, "markup", - col_idx++, NULL); - } - - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (se->elide) - continue; - - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), - -1, se->se_header, - renderer, "text", - col_idx++, NULL); - } - - gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); - - g_object_unref(GTK_TREE_MODEL(store)); - - for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { - struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - GtkTreeIter iter; - - if (h->filtered) - continue; - - gtk_list_store_append(store, &iter); - - col_idx = 0; - - perf_hpp__for_each_format(fmt) { - if (fmt->color) - fmt->color(&hpp, h); - else - fmt->entry(&hpp, h); - - gtk_list_store_set(store, &iter, col_idx++, s, -1); - } - - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (se->elide) - continue; - - se->se_snprintf(h, s, ARRAY_SIZE(s), - hists__col_len(hists, se->se_width_idx)); - - gtk_list_store_set(store, &iter, col_idx++, s, -1); - } - } - - gtk_container_add(GTK_CONTAINER(window), view); -} - -int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, - const char *help, - struct hist_browser_timer *hbt __maybe_unused) -{ - struct perf_evsel *pos; - GtkWidget *vbox; - GtkWidget *notebook; - GtkWidget *info_bar; - GtkWidget *statbar; - GtkWidget *window; - - signal(SIGSEGV, perf_gtk__signal); - signal(SIGFPE, perf_gtk__signal); - signal(SIGINT, perf_gtk__signal); - signal(SIGQUIT, perf_gtk__signal); - signal(SIGTERM, perf_gtk__signal); - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title(GTK_WINDOW(window), "perf report"); - - g_signal_connect(window, "delete_event", gtk_main_quit, NULL); - - pgctx = perf_gtk__activate_context(window); - if (!pgctx) - return -1; - - vbox = gtk_vbox_new(FALSE, 0); - - notebook = gtk_notebook_new(); - - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); - - info_bar = perf_gtk__setup_info_bar(); - if (info_bar) - gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0); - - statbar = perf_gtk__setup_statusbar(); - gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); - - gtk_container_add(GTK_CONTAINER(window), vbox); - - list_for_each_entry(pos, &evlist->entries, node) { - struct hists *hists = &pos->hists; - const char *evname = perf_evsel__name(pos); - GtkWidget *scrolled_window; - GtkWidget *tab_label; - char buf[512]; - size_t size = sizeof(buf); - - if (symbol_conf.event_group) { - if (!perf_evsel__is_group_leader(pos)) - continue; - - if (pos->nr_members > 1) { - perf_evsel__group_desc(pos, buf, size); - evname = buf; - } - } - - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - perf_gtk__show_hists(scrolled_window, hists); - - tab_label = gtk_label_new(evname); - - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); - } - - gtk_widget_show_all(window); - - perf_gtk__resize_window(window); - - gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); - - ui_helpline__push(help); - - gtk_main(); - - perf_gtk__deactivate_context(&pgctx); - - return 0; -} diff --git a/trunk/tools/perf/ui/hist.c b/trunk/tools/perf/ui/hist.c index a47ce98c2cb1..1889c12ca81f 100644 --- a/trunk/tools/perf/ui/hist.c +++ b/trunk/tools/perf/ui/hist.c @@ -3,164 +3,151 @@ #include "../util/hist.h" #include "../util/util.h" #include "../util/sort.h" -#include "../util/evsel.h" + /* hist period print (hpp) functions */ +static int hpp__header_overhead(struct perf_hpp *hpp) +{ + return scnprintf(hpp->buf, hpp->size, "Overhead"); +} -typedef int (*hpp_snprint_fn)(char *buf, size_t size, const char *fmt, ...); +static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) +{ + return 8; +} -static int __hpp__percent_fmt(struct perf_hpp *hpp, struct hist_entry *he, - u64 (*get_field)(struct hist_entry *), - const char *fmt, hpp_snprint_fn print_fn) +static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) { - int ret; - double percent = 0.0; struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period / hists->stats.total_period; - if (hists->stats.total_period) - percent = 100.0 * get_field(he) / hists->stats.total_period; + return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); +} - ret = print_fn(hpp->buf, hpp->size, fmt, percent); +static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period / hists->stats.total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; - if (symbol_conf.event_group) { - int prev_idx, idx_delta; - struct perf_evsel *evsel = hists_to_evsel(hists); - struct hist_entry *pair; - int nr_members = evsel->nr_members; + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} - if (nr_members <= 1) - return ret; +static int hpp__header_overhead_sys(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; - prev_idx = perf_evsel__group_idx(evsel); + return scnprintf(hpp->buf, hpp->size, fmt, "sys"); +} - list_for_each_entry(pair, &he->pairs.head, pairs.node) { - u64 period = get_field(pair); - u64 total = pair->hists->stats.total_period; +static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) +{ + return 7; +} - if (!total) - continue; +static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_sys / hists->stats.total_period; - evsel = hists_to_evsel(pair->hists); - idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1; + return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); +} - while (idx_delta--) { - /* - * zero-fill group members in the middle which - * have no sample - */ - ret += print_fn(hpp->buf + ret, hpp->size - ret, - fmt, 0.0); - } +static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_sys / hists->stats.total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; - ret += print_fn(hpp->buf + ret, hpp->size - ret, - fmt, 100.0 * period / total); + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} - prev_idx = perf_evsel__group_idx(evsel); - } +static int hpp__header_overhead_us(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; - idx_delta = nr_members - prev_idx - 1; + return scnprintf(hpp->buf, hpp->size, fmt, "user"); +} - while (idx_delta--) { - /* - * zero-fill group members at last which have no sample - */ - ret += print_fn(hpp->buf + ret, hpp->size - ret, - fmt, 0.0); - } - } - return ret; +static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) +{ + return 7; } -static int __hpp__raw_fmt(struct perf_hpp *hpp, struct hist_entry *he, - u64 (*get_field)(struct hist_entry *), - const char *fmt, hpp_snprint_fn print_fn) +static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) { - int ret; + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_us / hists->stats.total_period; - ret = print_fn(hpp->buf, hpp->size, fmt, get_field(he)); - return ret; + return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); +} + +static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_us / hists->stats.total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} + +static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp) +{ + return scnprintf(hpp->buf, hpp->size, "guest sys"); +} + +static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused) +{ + return 9; +} + +static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, + struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period; + + return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); +} + +static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, + struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} + +static int hpp__header_overhead_guest_us(struct perf_hpp *hpp) +{ + return scnprintf(hpp->buf, hpp->size, "guest usr"); +} + +static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused) +{ + return 9; } +static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, + struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period; -#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ -static int hpp__header_##_type(struct perf_hpp *hpp) \ -{ \ - int len = _min_width; \ - \ - if (symbol_conf.event_group) { \ - struct perf_evsel *evsel = hpp->ptr; \ - \ - len = max(len, evsel->nr_members * _unit_width); \ - } \ - return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \ -} - -#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ -static int hpp__width_##_type(struct perf_hpp *hpp __maybe_unused) \ -{ \ - int len = _min_width; \ - \ - if (symbol_conf.event_group) { \ - struct perf_evsel *evsel = hpp->ptr; \ - \ - len = max(len, evsel->nr_members * _unit_width); \ - } \ - return len; \ -} - -#define __HPP_COLOR_PERCENT_FN(_type, _field) \ -static u64 he_get_##_field(struct hist_entry *he) \ -{ \ - return he->stat._field; \ -} \ - \ -static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ -{ \ - return __hpp__percent_fmt(hpp, he, he_get_##_field, " %6.2f%%", \ - (hpp_snprint_fn)percent_color_snprintf); \ -} - -#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ -static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ -{ \ - const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ - return __hpp__percent_fmt(hpp, he, he_get_##_field, fmt, \ - scnprintf); \ -} - -#define __HPP_ENTRY_RAW_FN(_type, _field) \ -static u64 he_get_raw_##_field(struct hist_entry *he) \ -{ \ - return he->stat._field; \ -} \ - \ -static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ -{ \ - const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ - return __hpp__raw_fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf); \ -} - -#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \ -__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ -__HPP_WIDTH_FN(_type, _min_width, _unit_width) \ -__HPP_COLOR_PERCENT_FN(_type, _field) \ -__HPP_ENTRY_PERCENT_FN(_type, _field) - -#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width) \ -__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ -__HPP_WIDTH_FN(_type, _min_width, _unit_width) \ -__HPP_ENTRY_RAW_FN(_type, _field) - - -HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8) -HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8) -HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8) -HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8) -HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8) - -HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) -HPP_RAW_FNS(period, "Period", period, 12, 12) + return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); +} +static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, + struct hist_entry *he) +{ + struct hists *hists = he->hists; + double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period; + const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; + + return scnprintf(hpp->buf, hpp->size, fmt, percent); +} static int hpp__header_baseline(struct perf_hpp *hpp) { @@ -192,7 +179,7 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) { double percent = baseline_percent(he); - if (hist_entry__has_pairs(he) || symbol_conf.field_sep) + if (hist_entry__has_pairs(he)) return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); else return scnprintf(hpp->buf, hpp->size, " "); @@ -209,6 +196,44 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) return scnprintf(hpp->buf, hpp->size, " "); } +static int hpp__header_samples(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; + + return scnprintf(hpp->buf, hpp->size, fmt, "Samples"); +} + +static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused) +{ + return 11; +} + +static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he) +{ + const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; + + return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events); +} + +static int hpp__header_period(struct perf_hpp *hpp) +{ + const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; + + return scnprintf(hpp->buf, hpp->size, fmt, "Period"); +} + +static int hpp__width_period(struct perf_hpp *hpp __maybe_unused) +{ + return 12; +} + +static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he) +{ + const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; + + return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period); +} + static int hpp__header_period_baseline(struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; @@ -229,7 +254,6 @@ static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *h return scnprintf(hpp->buf, hpp->size, fmt, period); } - static int hpp__header_delta(struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; @@ -384,20 +408,9 @@ struct perf_hpp_fmt perf_hpp__format[] = { LIST_HEAD(perf_hpp__list); - #undef HPP__COLOR_PRINT_FNS #undef HPP__PRINT_FNS -#undef HPP_PERCENT_FNS -#undef HPP_RAW_FNS - -#undef __HPP_HEADER_FN -#undef __HPP_WIDTH_FN -#undef __HPP_COLOR_PERCENT_FN -#undef __HPP_ENTRY_PERCENT_FN -#undef __HPP_ENTRY_RAW_FN - - void perf_hpp__init(void) { if (symbol_conf.show_cpu_utilization) { @@ -495,15 +508,12 @@ unsigned int hists__sort_list_width(struct hists *hists) struct perf_hpp_fmt *fmt; struct sort_entry *se; int i = 0, ret = 0; - struct perf_hpp dummy_hpp = { - .ptr = hists_to_evsel(hists), - }; perf_hpp__for_each_format(fmt) { if (i) ret += 2; - ret += fmt->width(&dummy_hpp); + ret += fmt->width(NULL); } list_for_each_entry(se, &hist_entry__sort_list, list) diff --git a/trunk/tools/perf/ui/stdio/hist.c b/trunk/tools/perf/ui/stdio/hist.c index ff1f60cf442e..0eae3b2c32f2 100644 --- a/trunk/tools/perf/ui/stdio/hist.c +++ b/trunk/tools/perf/ui/stdio/hist.c @@ -3,7 +3,6 @@ #include "../../util/util.h" #include "../../util/hist.h" #include "../../util/sort.h" -#include "../../util/evsel.h" static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) @@ -348,7 +347,6 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, struct perf_hpp dummy_hpp = { .buf = bf, .size = sizeof(bf), - .ptr = hists_to_evsel(hists), }; bool first = true; @@ -461,7 +459,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, return ret; } -size_t events_stats__fprintf(struct events_stats *stats, FILE *fp) +size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp) { int i; size_t ret = 0; @@ -469,7 +467,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp) for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { const char *name; - if (stats->nr_events[i] == 0) + if (hists->stats.nr_events[i] == 0) continue; name = perf_event__name(i); @@ -477,7 +475,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp) continue; ret += fprintf(fp, "%16s events: %10d\n", name, - stats->nr_events[i]); + hists->stats.nr_events[i]); } return ret; diff --git a/trunk/tools/perf/ui/util.c b/trunk/tools/perf/ui/util.c index e3e0a963d03a..3014a7cd5271 100644 --- a/trunk/tools/perf/ui/util.c +++ b/trunk/tools/perf/ui/util.c @@ -52,6 +52,17 @@ int ui__warning(const char *format, ...) return ret; } +int ui__error_paranoid(void) +{ + return ui__error("Permission error - are you root?\n" + "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" + " -1 - Not paranoid at all\n" + " 0 - Disallow raw tracepoint access for unpriv\n" + " 1 - Disallow cpu events for unpriv\n" + " 2 - Disallow kernel profiling for unpriv\n"); +} + + /** * perf_error__register - Register error logging functions * @eops: The pointer to error logging function struct diff --git a/trunk/tools/perf/util/PERF-VERSION-GEN b/trunk/tools/perf/util/PERF-VERSION-GEN index 055fef34b6f6..6aa34e5afdcf 100755 --- a/trunk/tools/perf/util/PERF-VERSION-GEN +++ b/trunk/tools/perf/util/PERF-VERSION-GEN @@ -26,13 +26,13 @@ VN=$(expr "$VN" : v*'\(.*\)') if test -r $GVF then - VC=$(sed -e 's/^#define PERF_VERSION "\(.*\)"/\1/' <$GVF) + VC=$(sed -e 's/^PERF_VERSION = //' <$GVF) else VC=unset fi test "$VN" = "$VC" || { echo >&2 "PERF_VERSION = $VN" - echo "#define PERF_VERSION \"$VN\"" >$GVF + echo "PERF_VERSION = $VN" >$GVF } diff --git a/trunk/tools/perf/util/debug.h b/trunk/tools/perf/util/debug.h index efbd98805ad0..6e2667fb8211 100644 --- a/trunk/tools/perf/util/debug.h +++ b/trunk/tools/perf/util/debug.h @@ -16,5 +16,6 @@ void trace_event(union perf_event *event); int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); +int ui__error_paranoid(void); #endif /* __PERF_DEBUG_H */ diff --git a/trunk/tools/perf/util/event.c b/trunk/tools/perf/util/event.c index 5cd13d768cec..3cf2c3e0605f 100644 --- a/trunk/tools/perf/util/event.c +++ b/trunk/tools/perf/util/event.c @@ -476,10 +476,8 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, } } - if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) { - free(event); + if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) return -ENOENT; - } map = machine->vmlinux_maps[MAP__FUNCTION]; size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), diff --git a/trunk/tools/perf/util/evlist.c b/trunk/tools/perf/util/evlist.c index eddd5ebcd690..dc8aee97a488 100644 --- a/trunk/tools/perf/util/evlist.c +++ b/trunk/tools/perf/util/evlist.c @@ -117,9 +117,6 @@ void __perf_evlist__set_leader(struct list_head *list) struct perf_evsel *evsel, *leader; leader = list_entry(list->next, struct perf_evsel, node); - evsel = list_entry(list->prev, struct perf_evsel, node); - - leader->nr_members = evsel->idx - leader->idx + 1; list_for_each_entry(evsel, list, node) { if (evsel != leader) @@ -129,10 +126,8 @@ void __perf_evlist__set_leader(struct list_head *list) void perf_evlist__set_leader(struct perf_evlist *evlist) { - if (evlist->nr_entries) { - evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0; + if (evlist->nr_entries) __perf_evlist__set_leader(&evlist->entries); - } } int perf_evlist__add_default(struct perf_evlist *evlist) diff --git a/trunk/tools/perf/util/evlist.h b/trunk/tools/perf/util/evlist.h index 73579a25a93e..457e2350d21d 100644 --- a/trunk/tools/perf/util/evlist.h +++ b/trunk/tools/perf/util/evlist.h @@ -21,7 +21,6 @@ struct perf_evlist { struct list_head entries; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; int nr_entries; - int nr_groups; int nr_fds; int nr_mmaps; int mmap_len; diff --git a/trunk/tools/perf/util/evsel.c b/trunk/tools/perf/util/evsel.c index a54701504606..7a2a3dc3ff03 100644 --- a/trunk/tools/perf/util/evsel.c +++ b/trunk/tools/perf/util/evsel.c @@ -22,11 +22,6 @@ #include #include "perf_regs.h" -static struct { - bool sample_id_all; - bool exclude_guest; -} perf_missing_features; - #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) static int __perf_evsel__sample_size(u64 sample_type) @@ -434,31 +429,6 @@ const char *perf_evsel__name(struct perf_evsel *evsel) return evsel->name ?: "unknown"; } -const char *perf_evsel__group_name(struct perf_evsel *evsel) -{ - return evsel->group_name ?: "anon group"; -} - -int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) -{ - int ret; - struct perf_evsel *pos; - const char *group_name = perf_evsel__group_name(evsel); - - ret = scnprintf(buf, size, "%s", group_name); - - ret += scnprintf(buf + ret, size - ret, " { %s", - perf_evsel__name(evsel)); - - for_each_group_member(pos, evsel) - ret += scnprintf(buf + ret, size - ret, ", %s", - perf_evsel__name(pos)); - - ret += scnprintf(buf + ret, size - ret, " }"); - - return ret; -} - /* * The enable_on_exec/disabled value strategy: * @@ -493,7 +463,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_event_attr *attr = &evsel->attr; int track = !evsel->idx; /* only the first counter needs these */ - attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; + attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; attr->inherit = !opts->no_inherit; perf_evsel__set_sample_bit(evsel, IP); @@ -543,7 +513,7 @@ void perf_evsel__config(struct perf_evsel *evsel, if (opts->period) perf_evsel__set_sample_bit(evsel, PERIOD); - if (!perf_missing_features.sample_id_all && + if (!opts->sample_id_all_missing && (opts->sample_time || !opts->no_inherit || perf_target__has_cpu(&opts->target))) perf_evsel__set_sample_bit(evsel, TIME); @@ -665,11 +635,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) } } -void perf_evsel__free_counts(struct perf_evsel *evsel) -{ - free(evsel->counts); -} - void perf_evsel__exit(struct perf_evsel *evsel) { assert(list_empty(&evsel->node)); @@ -689,28 +654,6 @@ void perf_evsel__delete(struct perf_evsel *evsel) free(evsel); } -static inline void compute_deltas(struct perf_evsel *evsel, - int cpu, - struct perf_counts_values *count) -{ - struct perf_counts_values tmp; - - if (!evsel->prev_raw_counts) - return; - - if (cpu == -1) { - tmp = evsel->prev_raw_counts->aggr; - evsel->prev_raw_counts->aggr = *count; - } else { - tmp = evsel->prev_raw_counts->cpu[cpu]; - evsel->prev_raw_counts->cpu[cpu] = *count; - } - - count->val = count->val - tmp.val; - count->ena = count->ena - tmp.ena; - count->run = count->run - tmp.run; -} - int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, int cpu, int thread, bool scale) { @@ -726,8 +669,6 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) return -errno; - compute_deltas(evsel, cpu, &count); - if (scale) { if (count.run == 0) count.val = 0; @@ -766,8 +707,6 @@ int __perf_evsel__read(struct perf_evsel *evsel, } } - compute_deltas(evsel, -1, aggr); - evsel->counts->scaled = 0; if (scale) { if (aggr->run == 0) { @@ -822,13 +761,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, pid = evsel->cgrp->fd; } -fallback_missing_features: - if (perf_missing_features.exclude_guest) - evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; -retry_sample_id: - if (perf_missing_features.sample_id_all) - evsel->attr.sample_id_all = 0; - for (cpu = 0; cpu < cpus->nr; cpu++) { for (thread = 0; thread < threads->nr; thread++) { @@ -845,26 +777,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, group_fd, flags); if (FD(evsel, cpu, thread) < 0) { err = -errno; - goto try_fallback; + goto out_close; } } } return 0; -try_fallback: - if (err != -EINVAL || cpu > 0 || thread > 0) - goto out_close; - - if (!perf_missing_features.exclude_guest && - (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { - perf_missing_features.exclude_guest = true; - goto fallback_missing_features; - } else if (!perf_missing_features.sample_id_all) { - perf_missing_features.sample_id_all = true; - goto retry_sample_id; - } - out_close: do { while (--thread >= 0) { @@ -1389,27 +1308,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, struct perf_attr_details *details, FILE *fp) { bool first = true; - int printed = 0; - - if (symbol_conf.event_group) { - struct perf_evsel *pos; - - if (!perf_evsel__is_group_leader(evsel)) - return 0; - - if (evsel->nr_members > 1) - printed += fprintf(fp, "%s{", evsel->group_name ?: ""); - - printed += fprintf(fp, "%s", perf_evsel__name(evsel)); - for_each_group_member(pos, evsel) - printed += fprintf(fp, ",%s", perf_evsel__name(pos)); - - if (evsel->nr_members > 1) - printed += fprintf(fp, "}"); - goto out; - } - - printed += fprintf(fp, "%s", perf_evsel__name(evsel)); + int printed = fprintf(fp, "%s", perf_evsel__name(evsel)); if (details->verbose || details->freq) { printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64, @@ -1450,84 +1349,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, if_print(bp_type); if_print(branch_sample_type); } -out: + fputc('\n', fp); return ++printed; } - -bool perf_evsel__fallback(struct perf_evsel *evsel, int err, - char *msg, size_t msgsize) -{ - if ((err == ENOENT || err == ENXIO) && - evsel->attr.type == PERF_TYPE_HARDWARE && - evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) { - /* - * If it's cycles then fall back to hrtimer based - * cpu-clock-tick sw counter, which is always available even if - * no PMU support. - * - * PPC returns ENXIO until 2.6.37 (behavior changed with commit - * b0a873e). - */ - scnprintf(msg, msgsize, "%s", -"The cycles event is not supported, trying to fall back to cpu-clock-ticks"); - - evsel->attr.type = PERF_TYPE_SOFTWARE; - evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; - - free(evsel->name); - evsel->name = NULL; - return true; - } - - return false; -} - -int perf_evsel__open_strerror(struct perf_evsel *evsel, - struct perf_target *target, - int err, char *msg, size_t size) -{ - switch (err) { - case EPERM: - case EACCES: - return scnprintf(msg, size, "%s", - "You may not have permission to collect %sstats.\n" - "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" - " -1 - Not paranoid at all\n" - " 0 - Disallow raw tracepoint access for unpriv\n" - " 1 - Disallow cpu events for unpriv\n" - " 2 - Disallow kernel profiling for unpriv", - target->system_wide ? "system-wide " : ""); - case ENOENT: - return scnprintf(msg, size, "The %s event is not supported.", - perf_evsel__name(evsel)); - case EMFILE: - return scnprintf(msg, size, "%s", - "Too many events are opened.\n" - "Try again after reducing the number of events."); - case ENODEV: - if (target->cpu_list) - return scnprintf(msg, size, "%s", - "No such device - did you specify an out-of-range profile CPU?\n"); - break; - case EOPNOTSUPP: - if (evsel->attr.precise_ip) - return scnprintf(msg, size, "%s", - "\'precise\' request may not be supported. Try removing 'p' modifier."); -#if defined(__i386__) || defined(__x86_64__) - if (evsel->attr.type == PERF_TYPE_HARDWARE) - return scnprintf(msg, size, "%s", - "No hardware sampling interrupt available.\n" - "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); -#endif - break; - default: - break; - } - - return scnprintf(msg, size, - "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" - "/bin/dmesg may provide additional information.\n" - "No CONFIG_PERF_EVENTS=y kernel support configured?\n", - err, strerror(err), perf_evsel__name(evsel)); -} diff --git a/trunk/tools/perf/util/evsel.h b/trunk/tools/perf/util/evsel.h index 8512f6a8a6ea..9cb8a0215711 100644 --- a/trunk/tools/perf/util/evsel.h +++ b/trunk/tools/perf/util/evsel.h @@ -53,7 +53,6 @@ struct perf_evsel { struct xyarray *sample_id; u64 *id; struct perf_counts *counts; - struct perf_counts *prev_raw_counts; int idx; u32 ids; struct hists hists; @@ -74,13 +73,10 @@ struct perf_evsel { bool needs_swap; /* parse modifier helper */ int exclude_GH; - int nr_members; struct perf_evsel *leader; char *group_name; }; -#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists) - struct cpu_map; struct thread_map; struct perf_evlist; @@ -114,15 +110,12 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX]; int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size); const char *perf_evsel__name(struct perf_evsel *evsel); -const char *perf_evsel__group_name(struct perf_evsel *evsel); -int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); void perf_evsel__free_fd(struct perf_evsel *evsel); void perf_evsel__free_id(struct perf_evsel *evsel); -void perf_evsel__free_counts(struct perf_evsel *evsel); void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, @@ -258,21 +251,4 @@ struct perf_attr_details { int perf_evsel__fprintf(struct perf_evsel *evsel, struct perf_attr_details *details, FILE *fp); - -bool perf_evsel__fallback(struct perf_evsel *evsel, int err, - char *msg, size_t msgsize); -int perf_evsel__open_strerror(struct perf_evsel *evsel, - struct perf_target *target, - int err, char *msg, size_t size); - -static inline int perf_evsel__group_idx(struct perf_evsel *evsel) -{ - return evsel->idx - evsel->leader->idx; -} - -#define for_each_group_member(_evsel, _leader) \ -for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \ - (_evsel) && (_evsel)->leader == (_leader); \ - (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) - #endif /* __PERF_EVSEL_H */ diff --git a/trunk/tools/perf/util/header.c b/trunk/tools/perf/util/header.c index 8022b5254f75..b7da4634a047 100644 --- a/trunk/tools/perf/util/header.c +++ b/trunk/tools/perf/util/header.c @@ -148,7 +148,7 @@ static char *do_read_string(int fd, struct perf_header *ph) u32 len; char *buf; - sz = readn(fd, &len, sizeof(len)); + sz = read(fd, &len, sizeof(len)); if (sz < (ssize_t)sizeof(len)) return NULL; @@ -159,7 +159,7 @@ static char *do_read_string(int fd, struct perf_header *ph) if (!buf) return NULL; - ret = readn(fd, buf, len); + ret = read(fd, buf, len); if (ret == (ssize_t)len) { /* * strings are padded by zeroes @@ -287,12 +287,12 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) struct perf_session *session = container_of(header, struct perf_session, header); struct rb_node *nd; - int err = machine__write_buildid_table(&session->machines.host, fd); + int err = machine__write_buildid_table(&session->host_machine, fd); if (err) return err; - for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); err = machine__write_buildid_table(pos, fd); if (err) @@ -313,8 +313,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, if (is_kallsyms) { if (symbol_conf.kptr_restrict) { pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); - err = 0; - goto out_free; + return 0; } realname = (char *) name; } else @@ -449,9 +448,9 @@ static int perf_session__cache_build_ids(struct perf_session *session) if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) return -1; - ret = machine__cache_build_ids(&session->machines.host, debugdir); + ret = machine__cache_build_ids(&session->host_machine, debugdir); - for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret |= machine__cache_build_ids(pos, debugdir); } @@ -468,9 +467,9 @@ static bool machine__read_build_ids(struct machine *machine, bool with_hits) static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits) { struct rb_node *nd; - bool ret = machine__read_build_ids(&session->machines.host, with_hits); + bool ret = machine__read_build_ids(&session->host_machine, with_hits); - for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret |= machine__read_build_ids(pos, with_hits); } @@ -955,7 +954,6 @@ static int write_topo_node(int fd, int node) } fclose(fp); - fp = NULL; ret = do_write(fd, &mem_total, sizeof(u64)); if (ret) @@ -982,8 +980,7 @@ static int write_topo_node(int fd, int node) ret = do_write_string(fd, buf); done: free(buf); - if (fp) - fclose(fp); + fclose(fp); return ret; } @@ -1054,25 +1051,16 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, struct perf_pmu *pmu = NULL; off_t offset = lseek(fd, 0, SEEK_CUR); __u32 pmu_num = 0; - int ret; /* write real pmu_num later */ - ret = do_write(fd, &pmu_num, sizeof(pmu_num)); - if (ret < 0) - return ret; + do_write(fd, &pmu_num, sizeof(pmu_num)); while ((pmu = perf_pmu__scan(pmu))) { if (!pmu->name) continue; pmu_num++; - - ret = do_write(fd, &pmu->type, sizeof(pmu->type)); - if (ret < 0) - return ret; - - ret = do_write_string(fd, pmu->name); - if (ret < 0) - return ret; + do_write(fd, &pmu->type, sizeof(pmu->type)); + do_write_string(fd, pmu->name); } if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) { @@ -1084,52 +1072,6 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, return 0; } -/* - * File format: - * - * struct group_descs { - * u32 nr_groups; - * struct group_desc { - * char name[]; - * u32 leader_idx; - * u32 nr_members; - * }[nr_groups]; - * }; - */ -static int write_group_desc(int fd, struct perf_header *h __maybe_unused, - struct perf_evlist *evlist) -{ - u32 nr_groups = evlist->nr_groups; - struct perf_evsel *evsel; - int ret; - - ret = do_write(fd, &nr_groups, sizeof(nr_groups)); - if (ret < 0) - return ret; - - list_for_each_entry(evsel, &evlist->entries, node) { - if (perf_evsel__is_group_leader(evsel) && - evsel->nr_members > 1) { - const char *name = evsel->group_name ?: "{anon_group}"; - u32 leader_idx = evsel->idx; - u32 nr_members = evsel->nr_members; - - ret = do_write_string(fd, name); - if (ret < 0) - return ret; - - ret = do_write(fd, &leader_idx, sizeof(leader_idx)); - if (ret < 0) - return ret; - - ret = do_write(fd, &nr_members, sizeof(nr_members)); - if (ret < 0) - return ret; - } - } - return 0; -} - /* * default get_cpuid(): nothing gets recorded * actual implementation must be in arch/$(ARCH)/util/header.c @@ -1267,14 +1209,14 @@ read_event_desc(struct perf_header *ph, int fd) size_t msz; /* number of events */ - ret = readn(fd, &nre, sizeof(nre)); + ret = read(fd, &nre, sizeof(nre)); if (ret != (ssize_t)sizeof(nre)) goto error; if (ph->needs_swap) nre = bswap_32(nre); - ret = readn(fd, &sz, sizeof(sz)); + ret = read(fd, &sz, sizeof(sz)); if (ret != (ssize_t)sizeof(sz)) goto error; @@ -1302,7 +1244,7 @@ read_event_desc(struct perf_header *ph, int fd) * must read entire on-file attr struct to * sync up with layout. */ - ret = readn(fd, buf, sz); + ret = read(fd, buf, sz); if (ret != (ssize_t)sz) goto error; @@ -1311,7 +1253,7 @@ read_event_desc(struct perf_header *ph, int fd) memcpy(&evsel->attr, buf, msz); - ret = readn(fd, &nr, sizeof(nr)); + ret = read(fd, &nr, sizeof(nr)); if (ret != (ssize_t)sizeof(nr)) goto error; @@ -1332,7 +1274,7 @@ read_event_desc(struct perf_header *ph, int fd) evsel->id = id; for (j = 0 ; j < nr; j++) { - ret = readn(fd, id, sizeof(*id)); + ret = read(fd, id, sizeof(*id)); if (ret != (ssize_t)sizeof(*id)) goto error; if (ph->needs_swap) @@ -1493,31 +1435,6 @@ static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused, fprintf(fp, "# pmu mappings: unable to read\n"); } -static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, - FILE *fp) -{ - struct perf_session *session; - struct perf_evsel *evsel; - u32 nr = 0; - - session = container_of(ph, struct perf_session, header); - - list_for_each_entry(evsel, &session->evlist->entries, node) { - if (perf_evsel__is_group_leader(evsel) && - evsel->nr_members > 1) { - fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", - perf_evsel__name(evsel)); - - nr = evsel->nr_members - 1; - } else if (nr) { - fprintf(fp, ",%s", perf_evsel__name(evsel)); - - if (--nr == 0) - fprintf(fp, "}\n"); - } - } -} - static int __event_process_build_id(struct build_id_event *bev, char *filename, struct perf_session *session) @@ -1589,14 +1506,14 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, while (offset < limit) { ssize_t len; - if (readn(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev)) + if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev)) return -1; if (header->needs_swap) perf_event_header__bswap(&old_bev.header); len = old_bev.header.size - sizeof(old_bev); - if (readn(input, filename, len) != len) + if (read(input, filename, len) != len) return -1; bev.header = old_bev.header; @@ -1631,14 +1548,14 @@ static int perf_header__read_build_ids(struct perf_header *header, while (offset < limit) { ssize_t len; - if (readn(input, &bev, sizeof(bev)) != sizeof(bev)) + if (read(input, &bev, sizeof(bev)) != sizeof(bev)) goto out; if (header->needs_swap) perf_event_header__bswap(&bev.header); len = bev.header.size - sizeof(bev); - if (readn(input, filename, len) != len) + if (read(input, filename, len) != len) goto out; /* * The a1645ce1 changeset: @@ -1724,7 +1641,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, size_t ret; u32 nr; - ret = readn(fd, &nr, sizeof(nr)); + ret = read(fd, &nr, sizeof(nr)); if (ret != sizeof(nr)) return -1; @@ -1733,7 +1650,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, ph->env.nr_cpus_online = nr; - ret = readn(fd, &nr, sizeof(nr)); + ret = read(fd, &nr, sizeof(nr)); if (ret != sizeof(nr)) return -1; @@ -1767,7 +1684,7 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused, uint64_t mem; size_t ret; - ret = readn(fd, &mem, sizeof(mem)); + ret = read(fd, &mem, sizeof(mem)); if (ret != sizeof(mem)) return -1; @@ -1839,7 +1756,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused, u32 nr, i; struct strbuf sb; - ret = readn(fd, &nr, sizeof(nr)); + ret = read(fd, &nr, sizeof(nr)); if (ret != sizeof(nr)) return -1; @@ -1875,7 +1792,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused char *str; struct strbuf sb; - ret = readn(fd, &nr, sizeof(nr)); + ret = read(fd, &nr, sizeof(nr)); if (ret != sizeof(nr)) return -1; @@ -1896,7 +1813,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused } ph->env.sibling_cores = strbuf_detach(&sb, NULL); - ret = readn(fd, &nr, sizeof(nr)); + ret = read(fd, &nr, sizeof(nr)); if (ret != sizeof(nr)) return -1; @@ -1933,7 +1850,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse struct strbuf sb; /* nr nodes */ - ret = readn(fd, &nr, sizeof(nr)); + ret = read(fd, &nr, sizeof(nr)); if (ret != sizeof(nr)) goto error; @@ -1945,15 +1862,15 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse for (i = 0; i < nr; i++) { /* node number */ - ret = readn(fd, &node, sizeof(node)); + ret = read(fd, &node, sizeof(node)); if (ret != sizeof(node)) goto error; - ret = readn(fd, &mem_total, sizeof(u64)); + ret = read(fd, &mem_total, sizeof(u64)); if (ret != sizeof(u64)) goto error; - ret = readn(fd, &mem_free, sizeof(u64)); + ret = read(fd, &mem_free, sizeof(u64)); if (ret != sizeof(u64)) goto error; @@ -1992,7 +1909,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused u32 type; struct strbuf sb; - ret = readn(fd, &pmu_num, sizeof(pmu_num)); + ret = read(fd, &pmu_num, sizeof(pmu_num)); if (ret != sizeof(pmu_num)) return -1; @@ -2008,7 +1925,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused strbuf_init(&sb, 128); while (pmu_num) { - if (readn(fd, &type, sizeof(type)) != sizeof(type)) + if (read(fd, &type, sizeof(type)) != sizeof(type)) goto error; if (ph->needs_swap) type = bswap_32(type); @@ -2032,98 +1949,6 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused return -1; } -static int process_group_desc(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int fd, - void *data __maybe_unused) -{ - size_t ret = -1; - u32 i, nr, nr_groups; - struct perf_session *session; - struct perf_evsel *evsel, *leader = NULL; - struct group_desc { - char *name; - u32 leader_idx; - u32 nr_members; - } *desc; - - if (readn(fd, &nr_groups, sizeof(nr_groups)) != sizeof(nr_groups)) - return -1; - - if (ph->needs_swap) - nr_groups = bswap_32(nr_groups); - - ph->env.nr_groups = nr_groups; - if (!nr_groups) { - pr_debug("group desc not available\n"); - return 0; - } - - desc = calloc(nr_groups, sizeof(*desc)); - if (!desc) - return -1; - - for (i = 0; i < nr_groups; i++) { - desc[i].name = do_read_string(fd, ph); - if (!desc[i].name) - goto out_free; - - if (readn(fd, &desc[i].leader_idx, sizeof(u32)) != sizeof(u32)) - goto out_free; - - if (readn(fd, &desc[i].nr_members, sizeof(u32)) != sizeof(u32)) - goto out_free; - - if (ph->needs_swap) { - desc[i].leader_idx = bswap_32(desc[i].leader_idx); - desc[i].nr_members = bswap_32(desc[i].nr_members); - } - } - - /* - * Rebuild group relationship based on the group_desc - */ - session = container_of(ph, struct perf_session, header); - session->evlist->nr_groups = nr_groups; - - i = nr = 0; - list_for_each_entry(evsel, &session->evlist->entries, node) { - if (evsel->idx == (int) desc[i].leader_idx) { - evsel->leader = evsel; - /* {anon_group} is a dummy name */ - if (strcmp(desc[i].name, "{anon_group}")) - evsel->group_name = desc[i].name; - evsel->nr_members = desc[i].nr_members; - - if (i >= nr_groups || nr > 0) { - pr_debug("invalid group desc\n"); - goto out_free; - } - - leader = evsel; - nr = evsel->nr_members - 1; - i++; - } else if (nr) { - /* This is a group member */ - evsel->leader = leader; - - nr--; - } - } - - if (i != nr_groups || nr != 0) { - pr_debug("invalid group desc\n"); - goto out_free; - } - - ret = 0; -out_free: - while ((int) --i >= 0) - free(desc[i].name); - free(desc); - - return ret; -} - struct feature_ops { int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); void (*print)(struct perf_header *h, int fd, FILE *fp); @@ -2163,7 +1988,6 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings), - FEAT_OPP(HEADER_GROUP_DESC, group_desc), }; struct header_print_data { @@ -3088,22 +2912,16 @@ int perf_event__process_tracing_data(union perf_event *event, session->repipe); padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; - if (readn(session->fd, buf, padding) < 0) { - pr_err("%s: reading input file", __func__); - return -1; - } + if (read(session->fd, buf, padding) < 0) + die("reading input file"); if (session->repipe) { int retw = write(STDOUT_FILENO, buf, padding); - if (retw <= 0 || retw != padding) { - pr_err("%s: repiping tracing data padding", __func__); - return -1; - } + if (retw <= 0 || retw != padding) + die("repiping tracing data padding"); } - if (size_read + padding != size) { - pr_err("%s: tracing data size mismatch", __func__); - return -1; - } + if (size_read + padding != size) + die("tracing data size mismatch"); perf_evlist__prepare_tracepoint_events(session->evlist, session->pevent); diff --git a/trunk/tools/perf/util/header.h b/trunk/tools/perf/util/header.h index c9fc55cada6d..20f0344accb1 100644 --- a/trunk/tools/perf/util/header.h +++ b/trunk/tools/perf/util/header.h @@ -29,7 +29,6 @@ enum { HEADER_NUMA_TOPOLOGY, HEADER_BRANCH_STACK, HEADER_PMU_MAPPINGS, - HEADER_GROUP_DESC, HEADER_LAST_FEATURE, HEADER_FEAT_BITS = 256, }; @@ -80,7 +79,6 @@ struct perf_session_env { char *numa_nodes; int nr_pmu_mappings; char *pmu_mappings; - int nr_groups; }; struct perf_header { diff --git a/trunk/tools/perf/util/hist.c b/trunk/tools/perf/util/hist.c index f855941bebea..82df1b26f0d4 100644 --- a/trunk/tools/perf/util/hist.c +++ b/trunk/tools/perf/util/hist.c @@ -4,7 +4,6 @@ #include "hist.h" #include "session.h" #include "sort.h" -#include "evsel.h" #include static bool hists__filter_entry_by_dso(struct hists *hists, @@ -83,9 +82,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) hists__new_col_len(hists, HISTC_DSO, len); } - if (h->parent) - hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen); - if (h->branch_info) { int symlen; /* @@ -246,14 +242,6 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) if (he->ms.map) he->ms.map->referenced = true; - - if (he->branch_info) { - if (he->branch_info->from.map) - he->branch_info->from.map->referenced = true; - if (he->branch_info->to.map) - he->branch_info->to.map->referenced = true; - } - if (symbol_conf.use_callchain) callchain_init(he->callchain); @@ -263,7 +251,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) return he; } -void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h) +static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h) { if (!h->filtered) { hists__calc_col_len(hists, h); @@ -297,13 +285,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, parent = *p; he = rb_entry(parent, struct hist_entry, rb_node_in); - /* - * Make sure that it receives arguments in a same order as - * hist_entry__collapse() so that we can use an appropriate - * function when searching an entry regardless which sort - * keys were used. - */ - cmp = hist_entry__cmp(he, entry); + cmp = hist_entry__cmp(entry, he); if (!cmp) { he_stat__add_period(&he->stat, period); @@ -541,62 +523,6 @@ void hists__collapse_resort_threaded(struct hists *hists) * reverse the map, sort on period. */ -static int period_cmp(u64 period_a, u64 period_b) -{ - if (period_a > period_b) - return 1; - if (period_a < period_b) - return -1; - return 0; -} - -static int hist_entry__sort_on_period(struct hist_entry *a, - struct hist_entry *b) -{ - int ret; - int i, nr_members; - struct perf_evsel *evsel; - struct hist_entry *pair; - u64 *periods_a, *periods_b; - - ret = period_cmp(a->stat.period, b->stat.period); - if (ret || !symbol_conf.event_group) - return ret; - - evsel = hists_to_evsel(a->hists); - nr_members = evsel->nr_members; - if (nr_members <= 1) - return ret; - - periods_a = zalloc(sizeof(periods_a) * nr_members); - periods_b = zalloc(sizeof(periods_b) * nr_members); - - if (!periods_a || !periods_b) - goto out; - - list_for_each_entry(pair, &a->pairs.head, pairs.node) { - evsel = hists_to_evsel(pair->hists); - periods_a[perf_evsel__group_idx(evsel)] = pair->stat.period; - } - - list_for_each_entry(pair, &b->pairs.head, pairs.node) { - evsel = hists_to_evsel(pair->hists); - periods_b[perf_evsel__group_idx(evsel)] = pair->stat.period; - } - - for (i = 1; i < nr_members; i++) { - ret = period_cmp(periods_a[i], periods_b[i]); - if (ret) - break; - } - -out: - free(periods_a); - free(periods_b); - - return ret; -} - static void __hists__insert_output_entry(struct rb_root *entries, struct hist_entry *he, u64 min_callchain_hits) @@ -613,7 +539,7 @@ static void __hists__insert_output_entry(struct rb_root *entries, parent = *p; iter = rb_entry(parent, struct hist_entry, rb_node); - if (hist_entry__sort_on_period(he, iter) > 0) + if (he->stat.period > iter->stat.period) p = &(*p)->rb_left; else p = &(*p)->rb_right; @@ -785,38 +711,25 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize) return symbol__annotate(he->ms.sym, he->ms.map, privsize); } -void events_stats__inc(struct events_stats *stats, u32 type) -{ - ++stats->nr_events[0]; - ++stats->nr_events[type]; -} - void hists__inc_nr_events(struct hists *hists, u32 type) { - events_stats__inc(&hists->stats, type); + ++hists->stats.nr_events[0]; + ++hists->stats.nr_events[type]; } static struct hist_entry *hists__add_dummy_entry(struct hists *hists, struct hist_entry *pair) { - struct rb_root *root; - struct rb_node **p; + struct rb_node **p = &hists->entries.rb_node; struct rb_node *parent = NULL; struct hist_entry *he; int cmp; - if (sort__need_collapse) - root = &hists->entries_collapsed; - else - root = hists->entries_in; - - p = &root->rb_node; - while (*p != NULL) { parent = *p; - he = rb_entry(parent, struct hist_entry, rb_node_in); + he = rb_entry(parent, struct hist_entry, rb_node); - cmp = hist_entry__collapse(he, pair); + cmp = hist_entry__cmp(pair, he); if (!cmp) goto out; @@ -831,8 +744,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, if (he) { memset(&he->stat, 0, sizeof(he->stat)); he->hists = hists; - rb_link_node(&he->rb_node_in, parent, p); - rb_insert_color(&he->rb_node_in, root); + rb_link_node(&he->rb_node, parent, p); + rb_insert_color(&he->rb_node, &hists->entries); hists__inc_nr_entries(hists, he); } out: @@ -842,16 +755,11 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, static struct hist_entry *hists__find_entry(struct hists *hists, struct hist_entry *he) { - struct rb_node *n; - - if (sort__need_collapse) - n = hists->entries_collapsed.rb_node; - else - n = hists->entries_in->rb_node; + struct rb_node *n = hists->entries.rb_node; while (n) { - struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node_in); - int64_t cmp = hist_entry__collapse(iter, he); + struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node); + int64_t cmp = hist_entry__cmp(he, iter); if (cmp < 0) n = n->rb_left; @@ -869,17 +777,11 @@ static struct hist_entry *hists__find_entry(struct hists *hists, */ void hists__match(struct hists *leader, struct hists *other) { - struct rb_root *root; struct rb_node *nd; struct hist_entry *pos, *pair; - if (sort__need_collapse) - root = &leader->entries_collapsed; - else - root = leader->entries_in; - - for (nd = rb_first(root); nd; nd = rb_next(nd)) { - pos = rb_entry(nd, struct hist_entry, rb_node_in); + for (nd = rb_first(&leader->entries); nd; nd = rb_next(nd)) { + pos = rb_entry(nd, struct hist_entry, rb_node); pair = hists__find_entry(other, pos); if (pair) @@ -894,17 +796,11 @@ void hists__match(struct hists *leader, struct hists *other) */ int hists__link(struct hists *leader, struct hists *other) { - struct rb_root *root; struct rb_node *nd; struct hist_entry *pos, *pair; - if (sort__need_collapse) - root = &other->entries_collapsed; - else - root = other->entries_in; - - for (nd = rb_first(root); nd; nd = rb_next(nd)) { - pos = rb_entry(nd, struct hist_entry, rb_node_in); + for (nd = rb_first(&other->entries); nd; nd = rb_next(nd)) { + pos = rb_entry(nd, struct hist_entry, rb_node); if (!hist_entry__has_pairs(pos)) { pair = hists__add_dummy_entry(leader, pos); diff --git a/trunk/tools/perf/util/hist.h b/trunk/tools/perf/util/hist.h index 38624686ee9a..5b3b0075be64 100644 --- a/trunk/tools/perf/util/hist.h +++ b/trunk/tools/perf/util/hist.h @@ -96,10 +96,8 @@ void hists__decay_entries_threaded(struct hists *hists, bool zap_user, bool zap_kernel); void hists__output_recalc_col_len(struct hists *hists, int max_rows); -void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); void hists__inc_nr_events(struct hists *self, u32 type); -void events_stats__inc(struct events_stats *stats, u32 type); -size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); +size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); size_t hists__fprintf(struct hists *self, bool show_header, int max_rows, int max_cols, FILE *fp); diff --git a/trunk/tools/perf/util/include/linux/bitops.h b/trunk/tools/perf/util/include/linux/bitops.h index 45cf10a562bd..a55d8cf083c9 100644 --- a/trunk/tools/perf/util/include/linux/bitops.h +++ b/trunk/tools/perf/util/include/linux/bitops.h @@ -14,7 +14,6 @@ #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) -#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE) #define for_each_set_bit(bit, addr, size) \ for ((bit) = find_first_bit((addr), (size)); \ diff --git a/trunk/tools/perf/util/intlist.c b/trunk/tools/perf/util/intlist.c index 11a8d86f7fea..9d0740024ba8 100644 --- a/trunk/tools/perf/util/intlist.c +++ b/trunk/tools/perf/util/intlist.c @@ -59,40 +59,16 @@ void intlist__remove(struct intlist *ilist, struct int_node *node) struct int_node *intlist__find(struct intlist *ilist, int i) { - struct int_node *node; - struct rb_node *rb_node; - - if (ilist == NULL) - return NULL; + struct int_node *node = NULL; + struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); - node = NULL; - rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); if (rb_node) node = container_of(rb_node, struct int_node, rb_node); return node; } -static int intlist__parse_list(struct intlist *ilist, const char *s) -{ - char *sep; - int err; - - do { - long value = strtol(s, &sep, 10); - err = -EINVAL; - if (*sep != ',' && *sep != '\0') - break; - err = intlist__add(ilist, value); - if (err) - break; - s = sep + 1; - } while (*sep != '\0'); - - return err; -} - -struct intlist *intlist__new(const char *slist) +struct intlist *intlist__new(void) { struct intlist *ilist = malloc(sizeof(*ilist)); @@ -101,15 +77,9 @@ struct intlist *intlist__new(const char *slist) ilist->rblist.node_cmp = intlist__node_cmp; ilist->rblist.node_new = intlist__node_new; ilist->rblist.node_delete = intlist__node_delete; - - if (slist && intlist__parse_list(ilist, slist)) - goto out_delete; } return ilist; -out_delete: - intlist__delete(ilist); - return NULL; } void intlist__delete(struct intlist *ilist) diff --git a/trunk/tools/perf/util/intlist.h b/trunk/tools/perf/util/intlist.h index 62351dad848f..6d63ab90db50 100644 --- a/trunk/tools/perf/util/intlist.h +++ b/trunk/tools/perf/util/intlist.h @@ -15,7 +15,7 @@ struct intlist { struct rblist rblist; }; -struct intlist *intlist__new(const char *slist); +struct intlist *intlist__new(void); void intlist__delete(struct intlist *ilist); void intlist__remove(struct intlist *ilist, struct int_node *in); diff --git a/trunk/tools/perf/util/machine.c b/trunk/tools/perf/util/machine.c index efdb38e65a92..71fa90391fe4 100644 --- a/trunk/tools/perf/util/machine.c +++ b/trunk/tools/perf/util/machine.c @@ -91,22 +91,10 @@ void machine__delete(struct machine *machine) free(machine); } -void machines__init(struct machines *machines) -{ - machine__init(&machines->host, "", HOST_KERNEL_ID); - machines->guests = RB_ROOT; -} - -void machines__exit(struct machines *machines) -{ - machine__exit(&machines->host); - /* XXX exit guest */ -} - -struct machine *machines__add(struct machines *machines, pid_t pid, +struct machine *machines__add(struct rb_root *machines, pid_t pid, const char *root_dir) { - struct rb_node **p = &machines->guests.rb_node; + struct rb_node **p = &machines->rb_node; struct rb_node *parent = NULL; struct machine *pos, *machine = malloc(sizeof(*machine)); @@ -128,21 +116,18 @@ struct machine *machines__add(struct machines *machines, pid_t pid, } rb_link_node(&machine->rb_node, parent, p); - rb_insert_color(&machine->rb_node, &machines->guests); + rb_insert_color(&machine->rb_node, machines); return machine; } -struct machine *machines__find(struct machines *machines, pid_t pid) +struct machine *machines__find(struct rb_root *machines, pid_t pid) { - struct rb_node **p = &machines->guests.rb_node; + struct rb_node **p = &machines->rb_node; struct rb_node *parent = NULL; struct machine *machine; struct machine *default_machine = NULL; - if (pid == HOST_KERNEL_ID) - return &machines->host; - while (*p != NULL) { parent = *p; machine = rb_entry(parent, struct machine, rb_node); @@ -159,7 +144,7 @@ struct machine *machines__find(struct machines *machines, pid_t pid) return default_machine; } -struct machine *machines__findnew(struct machines *machines, pid_t pid) +struct machine *machines__findnew(struct rb_root *machines, pid_t pid) { char path[PATH_MAX]; const char *root_dir = ""; @@ -193,12 +178,12 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid) return machine; } -void machines__process_guests(struct machines *machines, - machine__process_t process, void *data) +void machines__process(struct rb_root *machines, + machine__process_t process, void *data) { struct rb_node *nd; - for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); process(pos, data); } @@ -218,14 +203,12 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size) return bf; } -void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size) +void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size) { struct rb_node *node; struct machine *machine; - machines->host.id_hdr_size = id_hdr_size; - - for (node = rb_first(&machines->guests); node; node = rb_next(node)) { + for (node = rb_first(machines); node; node = rb_next(node)) { machine = rb_entry(node, struct machine, rb_node); machine->id_hdr_size = id_hdr_size; } @@ -330,13 +313,12 @@ struct map *machine__new_module(struct machine *machine, u64 start, return map; } -size_t machines__fprintf_dsos(struct machines *machines, FILE *fp) +size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) { struct rb_node *nd; - size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) + - __dsos__fprintf(&machines->host.user_dsos, fp); + size_t ret = 0; - for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret += __dsos__fprintf(&pos->kernel_dsos, fp); ret += __dsos__fprintf(&pos->user_dsos, fp); @@ -352,13 +334,13 @@ size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm); } -size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, +size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp, bool (skip)(struct dso *dso, int parm), int parm) { struct rb_node *nd; - size_t ret = machine__fprintf_dsos_buildid(&machines->host, fp, skip, parm); + size_t ret = 0; - for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm); } @@ -529,7 +511,7 @@ void machine__destroy_kernel_maps(struct machine *machine) } } -int machines__create_guest_kernel_maps(struct machines *machines) +int machines__create_guest_kernel_maps(struct rb_root *machines) { int ret = 0; struct dirent **namelist = NULL; @@ -578,22 +560,20 @@ int machines__create_guest_kernel_maps(struct machines *machines) return ret; } -void machines__destroy_kernel_maps(struct machines *machines) +void machines__destroy_guest_kernel_maps(struct rb_root *machines) { - struct rb_node *next = rb_first(&machines->guests); - - machine__destroy_kernel_maps(&machines->host); + struct rb_node *next = rb_first(machines); while (next) { struct machine *pos = rb_entry(next, struct machine, rb_node); next = rb_next(&pos->rb_node); - rb_erase(&pos->rb_node, &machines->guests); + rb_erase(&pos->rb_node, machines); machine__delete(pos); } } -int machines__create_kernel_maps(struct machines *machines, pid_t pid) +int machines__create_kernel_maps(struct rb_root *machines, pid_t pid) { struct machine *machine = machines__findnew(machines, pid); diff --git a/trunk/tools/perf/util/machine.h b/trunk/tools/perf/util/machine.h index 5ac5892f2326..e11236878ec1 100644 --- a/trunk/tools/perf/util/machine.h +++ b/trunk/tools/perf/util/machine.h @@ -47,24 +47,16 @@ int machine__process_event(struct machine *machine, union perf_event *event); typedef void (*machine__process_t)(struct machine *machine, void *data); -struct machines { - struct machine host; - struct rb_root guests; -}; - -void machines__init(struct machines *machines); -void machines__exit(struct machines *machines); - -void machines__process_guests(struct machines *machines, - machine__process_t process, void *data); +void machines__process(struct rb_root *machines, + machine__process_t process, void *data); -struct machine *machines__add(struct machines *machines, pid_t pid, +struct machine *machines__add(struct rb_root *machines, pid_t pid, const char *root_dir); -struct machine *machines__find_host(struct machines *machines); -struct machine *machines__find(struct machines *machines, pid_t pid); -struct machine *machines__findnew(struct machines *machines, pid_t pid); +struct machine *machines__find_host(struct rb_root *machines); +struct machine *machines__find(struct rb_root *machines, pid_t pid); +struct machine *machines__findnew(struct rb_root *machines, pid_t pid); -void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); +void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size); char *machine__mmap_name(struct machine *machine, char *bf, size_t size); int machine__init(struct machine *machine, const char *root_dir, pid_t pid); @@ -140,17 +132,17 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type, size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, bool (skip)(struct dso *dso, int parm), int parm); -size_t machines__fprintf_dsos(struct machines *machines, FILE *fp); -size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, +size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); +size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp, bool (skip)(struct dso *dso, int parm), int parm); void machine__destroy_kernel_maps(struct machine *machine); int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); int machine__create_kernel_maps(struct machine *machine); -int machines__create_kernel_maps(struct machines *machines, pid_t pid); -int machines__create_guest_kernel_maps(struct machines *machines); -void machines__destroy_kernel_maps(struct machines *machines); +int machines__create_kernel_maps(struct rb_root *machines, pid_t pid); +int machines__create_guest_kernel_maps(struct rb_root *machines); +void machines__destroy_guest_kernel_maps(struct rb_root *machines); size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); diff --git a/trunk/tools/perf/util/map.c b/trunk/tools/perf/util/map.c index 6fcb9de62340..0328d45c4f2a 100644 --- a/trunk/tools/perf/util/map.c +++ b/trunk/tools/perf/util/map.c @@ -11,7 +11,6 @@ #include "strlist.h" #include "vdso.h" #include "build-id.h" -#include const char *map_type__name[MAP__NR_TYPES] = { [MAP__FUNCTION] = "Functions", @@ -20,8 +19,7 @@ const char *map_type__name[MAP__NR_TYPES] = { static inline int is_anon_memory(const char *filename) { - return !strcmp(filename, "//anon") || - !strcmp(filename, "/anon_hugepage (deleted)"); + return strcmp(filename, "//anon") == 0; } static inline int is_no_dso_memory(const char *filename) @@ -30,29 +28,29 @@ static inline int is_no_dso_memory(const char *filename) !strcmp(filename, "[heap]"); } -void map__init(struct map *map, enum map_type type, +void map__init(struct map *self, enum map_type type, u64 start, u64 end, u64 pgoff, struct dso *dso) { - map->type = type; - map->start = start; - map->end = end; - map->pgoff = pgoff; - map->dso = dso; - map->map_ip = map__map_ip; - map->unmap_ip = map__unmap_ip; - RB_CLEAR_NODE(&map->rb_node); - map->groups = NULL; - map->referenced = false; - map->erange_warned = false; + self->type = type; + self->start = start; + self->end = end; + self->pgoff = pgoff; + self->dso = dso; + self->map_ip = map__map_ip; + self->unmap_ip = map__unmap_ip; + RB_CLEAR_NODE(&self->rb_node); + self->groups = NULL; + self->referenced = false; + self->erange_warned = false; } struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, u64 pgoff, u32 pid, char *filename, enum map_type type) { - struct map *map = malloc(sizeof(*map)); + struct map *self = malloc(sizeof(*self)); - if (map != NULL) { + if (self != NULL) { char newfilename[PATH_MAX]; struct dso *dso; int anon, no_dso, vdso; @@ -75,10 +73,10 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, if (dso == NULL) goto out_delete; - map__init(map, type, start, start + len, pgoff, dso); + map__init(self, type, start, start + len, pgoff, dso); if (anon || no_dso) { - map->map_ip = map->unmap_ip = identity__map_ip; + self->map_ip = self->unmap_ip = identity__map_ip; /* * Set memory without DSO as loaded. All map__find_* @@ -86,12 +84,12 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, * unnecessary map__load warning. */ if (no_dso) - dso__set_loaded(dso, map->type); + dso__set_loaded(dso, self->type); } } - return map; + return self; out_delete: - free(map); + free(self); return NULL; } @@ -114,48 +112,48 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type) return map; } -void map__delete(struct map *map) +void map__delete(struct map *self) { - free(map); + free(self); } -void map__fixup_start(struct map *map) +void map__fixup_start(struct map *self) { - struct rb_root *symbols = &map->dso->symbols[map->type]; + struct rb_root *symbols = &self->dso->symbols[self->type]; struct rb_node *nd = rb_first(symbols); if (nd != NULL) { struct symbol *sym = rb_entry(nd, struct symbol, rb_node); - map->start = sym->start; + self->start = sym->start; } } -void map__fixup_end(struct map *map) +void map__fixup_end(struct map *self) { - struct rb_root *symbols = &map->dso->symbols[map->type]; + struct rb_root *symbols = &self->dso->symbols[self->type]; struct rb_node *nd = rb_last(symbols); if (nd != NULL) { struct symbol *sym = rb_entry(nd, struct symbol, rb_node); - map->end = sym->end; + self->end = sym->end; } } #define DSO__DELETED "(deleted)" -int map__load(struct map *map, symbol_filter_t filter) +int map__load(struct map *self, symbol_filter_t filter) { - const char *name = map->dso->long_name; + const char *name = self->dso->long_name; int nr; - if (dso__loaded(map->dso, map->type)) + if (dso__loaded(self->dso, self->type)) return 0; - nr = dso__load(map->dso, map, filter); + nr = dso__load(self->dso, self, filter); if (nr < 0) { - if (map->dso->has_build_id) { + if (self->dso->has_build_id) { char sbuild_id[BUILD_ID_SIZE * 2 + 1]; - build_id__sprintf(map->dso->build_id, - sizeof(map->dso->build_id), + build_id__sprintf(self->dso->build_id, + sizeof(self->dso->build_id), sbuild_id); pr_warning("%s with build id %s not found", name, sbuild_id); @@ -185,36 +183,43 @@ int map__load(struct map *map, symbol_filter_t filter) * Only applies to the kernel, as its symtabs aren't relative like the * module ones. */ - if (map->dso->kernel) - map__reloc_vmlinux(map); + if (self->dso->kernel) + map__reloc_vmlinux(self); return 0; } -struct symbol *map__find_symbol(struct map *map, u64 addr, +struct symbol *map__find_symbol(struct map *self, u64 addr, symbol_filter_t filter) { - if (map__load(map, filter) < 0) + if (map__load(self, filter) < 0) return NULL; - return dso__find_symbol(map->dso, map->type, addr); + return dso__find_symbol(self->dso, self->type, addr); } -struct symbol *map__find_symbol_by_name(struct map *map, const char *name, +struct symbol *map__find_symbol_by_name(struct map *self, const char *name, symbol_filter_t filter) { - if (map__load(map, filter) < 0) + if (map__load(self, filter) < 0) return NULL; - if (!dso__sorted_by_name(map->dso, map->type)) - dso__sort_by_name(map->dso, map->type); + if (!dso__sorted_by_name(self->dso, self->type)) + dso__sort_by_name(self->dso, self->type); - return dso__find_symbol_by_name(map->dso, map->type, name); + return dso__find_symbol_by_name(self->dso, self->type, name); } -struct map *map__clone(struct map *map) +struct map *map__clone(struct map *self) { - return memdup(map, sizeof(*map)); + 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) @@ -231,10 +236,10 @@ int map__overlap(struct map *l, struct map *r) return 0; } -size_t map__fprintf(struct map *map, FILE *fp) +size_t map__fprintf(struct map *self, FILE *fp) { return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", - map->start, map->end, map->pgoff, map->dso->name); + self->start, self->end, self->pgoff, self->dso->name); } size_t map__fprintf_dsoname(struct map *map, FILE *fp) @@ -522,9 +527,9 @@ static u64 map__reloc_unmap_ip(struct map *map, u64 ip) return ip - (s64)map->pgoff; } -void map__reloc_vmlinux(struct map *map) +void map__reloc_vmlinux(struct map *self) { - struct kmap *kmap = map__kmap(map); + struct kmap *kmap = map__kmap(self); s64 reloc; if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr) @@ -536,9 +541,9 @@ void map__reloc_vmlinux(struct map *map) if (!reloc) return; - map->map_ip = map__reloc_map_ip; - map->unmap_ip = map__reloc_unmap_ip; - map->pgoff = reloc; + self->map_ip = map__reloc_map_ip; + self->unmap_ip = map__reloc_unmap_ip; + self->pgoff = reloc; } void maps__insert(struct rb_root *maps, struct map *map) @@ -561,9 +566,9 @@ void maps__insert(struct rb_root *maps, struct map *map) rb_insert_color(&map->rb_node, maps); } -void maps__remove(struct rb_root *maps, struct map *map) +void maps__remove(struct rb_root *self, struct map *map) { - rb_erase(&map->rb_node, maps); + rb_erase(&map->rb_node, self); } struct map *maps__find(struct rb_root *maps, u64 ip) diff --git a/trunk/tools/perf/util/map.h b/trunk/tools/perf/util/map.h index a887f2c9dfbb..bcb39e2a6965 100644 --- a/trunk/tools/perf/util/map.h +++ b/trunk/tools/perf/util/map.h @@ -57,9 +57,9 @@ struct map_groups { struct machine *machine; }; -static inline struct kmap *map__kmap(struct map *map) +static inline struct kmap *map__kmap(struct map *self) { - return (struct kmap *)(map + 1); + return (struct kmap *)(self + 1); } static inline u64 map__map_ip(struct map *map, u64 ip) @@ -85,27 +85,27 @@ struct symbol; typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); -void map__init(struct map *map, enum map_type type, +void map__init(struct map *self, enum map_type type, u64 start, u64 end, u64 pgoff, struct dso *dso); struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, u64 pgoff, u32 pid, char *filename, enum map_type type); struct map *map__new2(u64 start, struct dso *dso, enum map_type type); -void map__delete(struct map *map); -struct map *map__clone(struct map *map); +void map__delete(struct map *self); +struct map *map__clone(struct map *self); int map__overlap(struct map *l, struct map *r); -size_t map__fprintf(struct map *map, FILE *fp); +size_t map__fprintf(struct map *self, FILE *fp); size_t map__fprintf_dsoname(struct map *map, FILE *fp); -int map__load(struct map *map, symbol_filter_t filter); -struct symbol *map__find_symbol(struct map *map, +int map__load(struct map *self, symbol_filter_t filter); +struct symbol *map__find_symbol(struct map *self, u64 addr, symbol_filter_t filter); -struct symbol *map__find_symbol_by_name(struct map *map, const char *name, +struct symbol *map__find_symbol_by_name(struct map *self, const char *name, symbol_filter_t filter); -void map__fixup_start(struct map *map); -void map__fixup_end(struct map *map); +void map__fixup_start(struct map *self); +void map__fixup_end(struct map *self); -void map__reloc_vmlinux(struct map *map); +void map__reloc_vmlinux(struct map *self); size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, int verbose, FILE *fp); diff --git a/trunk/tools/perf/util/parse-events.c b/trunk/tools/perf/util/parse-events.c index 4e0f5c2a9fda..2d8d53bec17e 100644 --- a/trunk/tools/perf/util/parse-events.c +++ b/trunk/tools/perf/util/parse-events.c @@ -380,8 +380,8 @@ static int add_tracepoint(struct list_head **listp, int *idx, return 0; } -static int add_tracepoint_multi_event(struct list_head **list, int *idx, - char *sys_name, char *evt_name) +static int add_tracepoint_multi(struct list_head **list, int *idx, + char *sys_name, char *evt_name) { char evt_path[MAXPATHLEN]; struct dirent *evt_ent; @@ -408,47 +408,6 @@ static int add_tracepoint_multi_event(struct list_head **list, int *idx, ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name); } - closedir(evt_dir); - return ret; -} - -static int add_tracepoint_event(struct list_head **list, int *idx, - char *sys_name, char *evt_name) -{ - return strpbrk(evt_name, "*?") ? - add_tracepoint_multi_event(list, idx, sys_name, evt_name) : - add_tracepoint(list, idx, sys_name, evt_name); -} - -static int add_tracepoint_multi_sys(struct list_head **list, int *idx, - char *sys_name, char *evt_name) -{ - struct dirent *events_ent; - DIR *events_dir; - int ret = 0; - - events_dir = opendir(tracing_events_path); - if (!events_dir) { - perror("Can't open event dir"); - return -1; - } - - while (!ret && (events_ent = readdir(events_dir))) { - if (!strcmp(events_ent->d_name, ".") - || !strcmp(events_ent->d_name, "..") - || !strcmp(events_ent->d_name, "enable") - || !strcmp(events_ent->d_name, "header_event") - || !strcmp(events_ent->d_name, "header_page")) - continue; - - if (!strglobmatch(events_ent->d_name, sys_name)) - continue; - - ret = add_tracepoint_event(list, idx, events_ent->d_name, - evt_name); - } - - closedir(events_dir); return ret; } @@ -461,10 +420,9 @@ int parse_events_add_tracepoint(struct list_head **list, int *idx, if (ret) return ret; - if (strpbrk(sys, "*?")) - return add_tracepoint_multi_sys(list, idx, sys, event); - else - return add_tracepoint_event(list, idx, sys, event); + return strpbrk(event, "*?") ? + add_tracepoint_multi(list, idx, sys, event) : + add_tracepoint(list, idx, sys, event); } static int @@ -534,7 +492,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, } static int config_term(struct perf_event_attr *attr, - struct parse_events_term *term) + struct parse_events__term *term) { #define CHECK_TYPE_VAL(type) \ do { \ @@ -579,7 +537,7 @@ do { \ static int config_attr(struct perf_event_attr *attr, struct list_head *head, int fail) { - struct parse_events_term *term; + struct parse_events__term *term; list_for_each_entry(term, head, list) if (config_term(attr, term) && fail) @@ -605,14 +563,14 @@ int parse_events_add_numeric(struct list_head **list, int *idx, return add_event(list, idx, &attr, NULL); } -static int parse_events__is_name_term(struct parse_events_term *term) +static int parse_events__is_name_term(struct parse_events__term *term) { return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; } static char *pmu_event_name(struct list_head *head_terms) { - struct parse_events_term *term; + struct parse_events__term *term; list_for_each_entry(term, head_terms, list) if (parse_events__is_name_term(term)) @@ -856,7 +814,7 @@ static int parse_events__scanner(const char *str, void *data, int start_token) */ int parse_events_terms(struct list_head *terms, const char *str) { - struct parse_events_terms data = { + struct parse_events_data__terms data = { .terms = NULL, }; int ret; @@ -872,9 +830,10 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct perf_evlist *evlist, const char *str) +int parse_events(struct perf_evlist *evlist, const char *str, + int unset __maybe_unused) { - struct parse_events_evlist data = { + struct parse_events_data__events data = { .list = LIST_HEAD_INIT(data.list), .idx = evlist->nr_entries, }; @@ -884,7 +843,6 @@ int parse_events(struct perf_evlist *evlist, const char *str) if (!ret) { int entries = data.idx - evlist->nr_entries; perf_evlist__splice_list_tail(evlist, &data.list, entries); - evlist->nr_groups += data.nr_groups; return 0; } @@ -900,7 +858,7 @@ int parse_events_option(const struct option *opt, const char *str, int unset __maybe_unused) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; - int ret = parse_events(evlist, str); + int ret = parse_events(evlist, str, unset); if (ret) { fprintf(stderr, "invalid or unsupported event: '%s'\n", str); @@ -1163,16 +1121,16 @@ void print_events(const char *event_glob, bool name_only) print_tracepoint_events(NULL, NULL, name_only); } -int parse_events__is_hardcoded_term(struct parse_events_term *term) +int parse_events__is_hardcoded_term(struct parse_events__term *term) { return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; } -static int new_term(struct parse_events_term **_term, int type_val, +static int new_term(struct parse_events__term **_term, int type_val, int type_term, char *config, char *str, u64 num) { - struct parse_events_term *term; + struct parse_events__term *term; term = zalloc(sizeof(*term)); if (!term) @@ -1198,21 +1156,21 @@ static int new_term(struct parse_events_term **_term, int type_val, return 0; } -int parse_events_term__num(struct parse_events_term **term, +int parse_events__term_num(struct parse_events__term **term, int type_term, char *config, u64 num) { return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, config, NULL, num); } -int parse_events_term__str(struct parse_events_term **term, +int parse_events__term_str(struct parse_events__term **term, int type_term, char *config, char *str) { return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term, config, str, 0); } -int parse_events_term__sym_hw(struct parse_events_term **term, +int parse_events__term_sym_hw(struct parse_events__term **term, char *config, unsigned idx) { struct event_symbol *sym; @@ -1230,8 +1188,8 @@ int parse_events_term__sym_hw(struct parse_events_term **term, (char *) "event", (char *) sym->symbol, 0); } -int parse_events_term__clone(struct parse_events_term **new, - struct parse_events_term *term) +int parse_events__term_clone(struct parse_events__term **new, + struct parse_events__term *term) { return new_term(new, term->type_val, term->type_term, term->config, term->val.str, term->val.num); @@ -1239,7 +1197,7 @@ int parse_events_term__clone(struct parse_events_term **new, void parse_events__free_terms(struct list_head *terms) { - struct parse_events_term *term, *h; + struct parse_events__term *term, *h; list_for_each_entry_safe(term, h, terms, list) free(term); diff --git a/trunk/tools/perf/util/parse-events.h b/trunk/tools/perf/util/parse-events.h index 8a4859315fd9..b7af80b8bdda 100644 --- a/trunk/tools/perf/util/parse-events.h +++ b/trunk/tools/perf/util/parse-events.h @@ -29,7 +29,8 @@ const char *event_type(int type); extern int parse_events_option(const struct option *opt, const char *str, int unset); -extern int parse_events(struct perf_evlist *evlist, const char *str); +extern int parse_events(struct perf_evlist *evlist, const char *str, + int unset); extern int parse_events_terms(struct list_head *terms, const char *str); extern int parse_filter(const struct option *opt, const char *str, int unset); @@ -50,7 +51,7 @@ enum { PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, }; -struct parse_events_term { +struct parse_events__term { char *config; union { char *str; @@ -61,25 +62,24 @@ struct parse_events_term { struct list_head list; }; -struct parse_events_evlist { +struct parse_events_data__events { struct list_head list; int idx; - int nr_groups; }; -struct parse_events_terms { +struct parse_events_data__terms { struct list_head *terms; }; -int parse_events__is_hardcoded_term(struct parse_events_term *term); -int parse_events_term__num(struct parse_events_term **_term, +int parse_events__is_hardcoded_term(struct parse_events__term *term); +int parse_events__term_num(struct parse_events__term **_term, int type_term, char *config, u64 num); -int parse_events_term__str(struct parse_events_term **_term, +int parse_events__term_str(struct parse_events__term **_term, int type_term, char *config, char *str); -int parse_events_term__sym_hw(struct parse_events_term **term, +int parse_events__term_sym_hw(struct parse_events__term **term, char *config, unsigned idx); -int parse_events_term__clone(struct parse_events_term **new, - struct parse_events_term *term); +int parse_events__term_clone(struct parse_events__term **new, + struct parse_events__term *term); void parse_events__free_terms(struct list_head *terms); int parse_events__modifier_event(struct list_head *list, char *str, bool add); int parse_events__modifier_group(struct list_head *list, char *event_mod); diff --git a/trunk/tools/perf/util/parse-events.y b/trunk/tools/perf/util/parse-events.y index 4de2fdca98c8..0f9914ae6bac 100644 --- a/trunk/tools/perf/util/parse-events.y +++ b/trunk/tools/perf/util/parse-events.y @@ -23,14 +23,6 @@ do { \ YYABORT; \ } while (0) -static inc_group_count(struct list_head *list, - struct parse_events_evlist *data) -{ - /* Count groups only have more than 1 members */ - if (!list_is_last(list->next, list)) - data->nr_groups++; -} - %} %token PE_START_EVENTS PE_START_TERMS @@ -76,7 +68,7 @@ static inc_group_count(struct list_head *list, char *str; u64 num; struct list_head *head; - struct parse_events_term *term; + struct parse_events__term *term; } %% @@ -87,7 +79,7 @@ PE_START_TERMS start_terms start_events: groups { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; parse_events_update_lists($1, &data->list); } @@ -131,7 +123,6 @@ PE_NAME '{' events '}' { struct list_head *list = $3; - inc_group_count(list, _data); parse_events__set_leader($1, list); $$ = list; } @@ -140,7 +131,6 @@ PE_NAME '{' events '}' { struct list_head *list = $2; - inc_group_count(list, _data); parse_events__set_leader(NULL, list); $$ = list; } @@ -196,7 +186,7 @@ event_def: event_pmu | event_pmu: PE_NAME '/' event_config '/' { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3)); @@ -212,7 +202,7 @@ PE_VALUE_SYM_SW event_legacy_symbol: value_sym '/' event_config '/' { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; int type = $1 >> 16; int config = $1 & 255; @@ -225,7 +215,7 @@ value_sym '/' event_config '/' | value_sym sep_slash_dc { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; int type = $1 >> 16; int config = $1 & 255; @@ -238,7 +228,7 @@ value_sym sep_slash_dc event_legacy_cache: PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5)); @@ -247,7 +237,7 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT | PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL)); @@ -256,7 +246,7 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT | PE_NAME_CACHE_TYPE { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL)); @@ -266,7 +256,7 @@ PE_NAME_CACHE_TYPE event_legacy_mem: PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_breakpoint(&list, &data->idx, @@ -276,7 +266,7 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc | PE_PREFIX_MEM PE_VALUE sep_dc { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_breakpoint(&list, &data->idx, @@ -287,7 +277,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc event_legacy_tracepoint: PE_NAME ':' PE_NAME { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3)); @@ -297,7 +287,7 @@ PE_NAME ':' PE_NAME event_legacy_numeric: PE_VALUE ':' PE_VALUE { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_numeric(&list, &data->idx, (u32)$1, $3, NULL)); @@ -307,7 +297,7 @@ PE_VALUE ':' PE_VALUE event_legacy_raw: PE_RAW { - struct parse_events_evlist *data = _data; + struct parse_events_data__events *data = _data; struct list_head *list = NULL; ABORT_ON(parse_events_add_numeric(&list, &data->idx, @@ -317,7 +307,7 @@ PE_RAW start_terms: event_config { - struct parse_events_terms *data = _data; + struct parse_events_data__terms *data = _data; data->terms = $1; } @@ -325,7 +315,7 @@ event_config: event_config ',' event_term { struct list_head *head = $1; - struct parse_events_term *term = $3; + struct parse_events__term *term = $3; ABORT_ON(!head); list_add_tail(&term->list, head); @@ -335,7 +325,7 @@ event_config ',' event_term event_term { struct list_head *head = malloc(sizeof(*head)); - struct parse_events_term *term = $1; + struct parse_events__term *term = $1; ABORT_ON(!head); INIT_LIST_HEAD(head); @@ -346,70 +336,70 @@ event_term event_term: PE_NAME '=' PE_NAME { - struct parse_events_term *term; + struct parse_events__term *term; - ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, + ABORT_ON(parse_events__term_str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3)); $$ = term; } | PE_NAME '=' PE_VALUE { - struct parse_events_term *term; + struct parse_events__term *term; - ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, + ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3)); $$ = term; } | PE_NAME '=' PE_VALUE_SYM_HW { - struct parse_events_term *term; + struct parse_events__term *term; int config = $3 & 255; - ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); + ABORT_ON(parse_events__term_sym_hw(&term, $1, config)); $$ = term; } | PE_NAME { - struct parse_events_term *term; + struct parse_events__term *term; - ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, + ABORT_ON(parse_events__term_num(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, 1)); $$ = term; } | PE_VALUE_SYM_HW { - struct parse_events_term *term; + struct parse_events__term *term; int config = $1 & 255; - ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); + ABORT_ON(parse_events__term_sym_hw(&term, NULL, config)); $$ = term; } | PE_TERM '=' PE_NAME { - struct parse_events_term *term; + struct parse_events__term *term; - ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3)); + ABORT_ON(parse_events__term_str(&term, (int)$1, NULL, $3)); $$ = term; } | PE_TERM '=' PE_VALUE { - struct parse_events_term *term; + struct parse_events__term *term; - ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3)); + ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, $3)); $$ = term; } | PE_TERM { - struct parse_events_term *term; + struct parse_events__term *term; - ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1)); + ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, 1)); $$ = term; } diff --git a/trunk/tools/perf/util/pmu.c b/trunk/tools/perf/util/pmu.c index 4c6f9c490a8d..9bdc60c6f138 100644 --- a/trunk/tools/perf/util/pmu.c +++ b/trunk/tools/perf/util/pmu.c @@ -1,3 +1,4 @@ + #include #include #include @@ -10,19 +11,6 @@ #include "parse-events.h" #include "cpumap.h" -struct perf_pmu_alias { - char *name; - struct list_head terms; - struct list_head list; -}; - -struct perf_pmu_format { - char *name; - int value; - DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); - struct list_head list; -}; - #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" int perf_pmu_parse(struct list_head *list, char *name); @@ -97,7 +85,7 @@ static int pmu_format(char *name, struct list_head *format) static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) { - struct perf_pmu_alias *alias; + struct perf_pmu__alias *alias; char buf[256]; int ret; @@ -184,15 +172,15 @@ static int pmu_aliases(char *name, struct list_head *head) return 0; } -static int pmu_alias_terms(struct perf_pmu_alias *alias, +static int pmu_alias_terms(struct perf_pmu__alias *alias, struct list_head *terms) { - struct parse_events_term *term, *clone; + struct parse_events__term *term, *clone; LIST_HEAD(list); int ret; list_for_each_entry(term, &alias->terms, list) { - ret = parse_events_term__clone(&clone, term); + ret = parse_events__term_clone(&clone, term); if (ret) { parse_events__free_terms(&list); return ret; @@ -372,10 +360,10 @@ struct perf_pmu *perf_pmu__find(char *name) return pmu_lookup(name); } -static struct perf_pmu_format * +static struct perf_pmu__format* pmu_find_format(struct list_head *formats, char *name) { - struct perf_pmu_format *format; + struct perf_pmu__format *format; list_for_each_entry(format, formats, list) if (!strcmp(format->name, name)) @@ -415,9 +403,9 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value) */ static int pmu_config_term(struct list_head *formats, struct perf_event_attr *attr, - struct parse_events_term *term) + struct parse_events__term *term) { - struct perf_pmu_format *format; + struct perf_pmu__format *format; __u64 *vp; /* @@ -462,7 +450,7 @@ int perf_pmu__config_terms(struct list_head *formats, struct perf_event_attr *attr, struct list_head *head_terms) { - struct parse_events_term *term; + struct parse_events__term *term; list_for_each_entry(term, head_terms, list) if (pmu_config_term(formats, attr, term)) @@ -483,10 +471,10 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, return perf_pmu__config_terms(&pmu->format, attr, head_terms); } -static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, - struct parse_events_term *term) +static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu, + struct parse_events__term *term) { - struct perf_pmu_alias *alias; + struct perf_pmu__alias *alias; char *name; if (parse_events__is_hardcoded_term(term)) @@ -519,8 +507,8 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, */ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) { - struct parse_events_term *term, *h; - struct perf_pmu_alias *alias; + struct parse_events__term *term, *h; + struct perf_pmu__alias *alias; int ret; list_for_each_entry_safe(term, h, head_terms, list) { @@ -539,7 +527,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) int perf_pmu__new_format(struct list_head *list, char *name, int config, unsigned long *bits) { - struct perf_pmu_format *format; + struct perf_pmu__format *format; format = zalloc(sizeof(*format)); if (!format) @@ -560,7 +548,7 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to) if (!to) to = from; - memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS)); + memset(bits, 0, BITS_TO_LONGS(PERF_PMU_FORMAT_BITS)); for (b = from; b <= to; b++) set_bit(b, bits); } diff --git a/trunk/tools/perf/util/pmu.h b/trunk/tools/perf/util/pmu.h index 32fe55b659fa..a313ed76a49a 100644 --- a/trunk/tools/perf/util/pmu.h +++ b/trunk/tools/perf/util/pmu.h @@ -12,6 +12,19 @@ enum { #define PERF_PMU_FORMAT_BITS 64 +struct perf_pmu__format { + char *name; + int value; + DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); + struct list_head list; +}; + +struct perf_pmu__alias { + char *name; + struct list_head terms; + struct list_head list; +}; + struct perf_pmu { char *name; __u32 type; @@ -29,7 +42,7 @@ int perf_pmu__config_terms(struct list_head *formats, struct list_head *head_terms); int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms); struct list_head *perf_pmu__alias(struct perf_pmu *pmu, - struct list_head *head_terms); + struct list_head *head_terms); int perf_pmu_wrap(void); void perf_pmu_error(struct list_head *list, char *name, char const *msg); diff --git a/trunk/tools/perf/util/probe-finder.c b/trunk/tools/perf/util/probe-finder.c index be0329394d56..1daf5c14e751 100644 --- a/trunk/tools/perf/util/probe-finder.c +++ b/trunk/tools/perf/util/probe-finder.c @@ -413,12 +413,12 @@ static int convert_variable_type(Dwarf_Die *vr_die, dwarf_diename(vr_die), dwarf_diename(&type)); return -EINVAL; } - if (die_get_real_type(&type, &type) == NULL) { - pr_warning("Failed to get a type" - " information.\n"); - return -ENOENT; - } if (ret == DW_TAG_pointer_type) { + if (die_get_real_type(&type, &type) == NULL) { + pr_warning("Failed to get a type" + " information.\n"); + return -ENOENT; + } while (*ref_ptr) ref_ptr = &(*ref_ptr)->next; /* Add new reference with offset +0 */ diff --git a/trunk/tools/perf/util/python.c b/trunk/tools/perf/util/python.c index 925e0c3e6d91..a2657fd96837 100644 --- a/trunk/tools/perf/util/python.c +++ b/trunk/tools/perf/util/python.c @@ -1045,12 +1045,3 @@ PyMODINIT_FUNC initperf(void) if (PyErr_Occurred()) PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); } - -/* - * Dummy, to avoid dragging all the test_attr infrastructure in the python - * binding. - */ -void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, - int fd, int group_fd, unsigned long flags) -{ -} diff --git a/trunk/tools/perf/util/scripting-engines/trace-event-perl.c b/trunk/tools/perf/util/scripting-engines/trace-event-perl.c index eacec859f299..f80605eb1855 100644 --- a/trunk/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/trunk/tools/perf/util/scripting-engines/trace-event-perl.c @@ -292,7 +292,6 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, ns = nsecs - s * NSECS_PER_SEC; scripting_context->event_data = data; - scripting_context->pevent = evsel->tp_format->pevent; ENTER; SAVETMPS; diff --git a/trunk/tools/perf/util/scripting-engines/trace-event-python.c b/trunk/tools/perf/util/scripting-engines/trace-event-python.c index e87aa5d9696b..14683dfca2ee 100644 --- a/trunk/tools/perf/util/scripting-engines/trace-event-python.c +++ b/trunk/tools/perf/util/scripting-engines/trace-event-python.c @@ -265,7 +265,6 @@ static void python_process_tracepoint(union perf_event *perf_event ns = nsecs - s * NSECS_PER_SEC; scripting_context->event_data = data; - scripting_context->pevent = evsel->tp_format->pevent; context = PyCObject_FromVoidPtr(scripting_context, NULL); diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index bd85280bb6e8..76d6e257b8a4 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -86,12 +86,13 @@ void perf_session__set_id_hdr_size(struct perf_session *session) { u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist); + session->host_machine.id_hdr_size = id_hdr_size; machines__set_id_hdr_size(&session->machines, id_hdr_size); } int perf_session__create_kernel_maps(struct perf_session *self) { - int ret = machine__create_kernel_maps(&self->machines.host); + int ret = machine__create_kernel_maps(&self->host_machine); if (ret >= 0) ret = machines__create_guest_kernel_maps(&self->machines); @@ -100,7 +101,8 @@ int perf_session__create_kernel_maps(struct perf_session *self) static void perf_session__destroy_kernel_maps(struct perf_session *self) { - machines__destroy_kernel_maps(&self->machines); + machine__destroy_kernel_maps(&self->host_machine); + machines__destroy_guest_kernel_maps(&self->machines); } struct perf_session *perf_session__new(const char *filename, int mode, @@ -125,11 +127,13 @@ struct perf_session *perf_session__new(const char *filename, int mode, goto out; memcpy(self->filename, filename, len); + self->machines = RB_ROOT; self->repipe = repipe; INIT_LIST_HEAD(&self->ordered_samples.samples); INIT_LIST_HEAD(&self->ordered_samples.sample_cache); INIT_LIST_HEAD(&self->ordered_samples.to_free); - machines__init(&self->machines); + machine__init(&self->host_machine, "", HOST_KERNEL_ID); + hists__init(&self->hists); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) @@ -159,12 +163,12 @@ struct perf_session *perf_session__new(const char *filename, int mode, static void perf_session__delete_dead_threads(struct perf_session *session) { - machine__delete_dead_threads(&session->machines.host); + machine__delete_dead_threads(&session->host_machine); } static void perf_session__delete_threads(struct perf_session *session) { - machine__delete_threads(&session->machines.host); + machine__delete_threads(&session->host_machine); } static void perf_session_env__delete(struct perf_session_env *env) @@ -189,7 +193,7 @@ void perf_session__delete(struct perf_session *self) perf_session__delete_dead_threads(self); perf_session__delete_threads(self); perf_session_env__delete(&self->header.env); - machines__exit(&self->machines); + machine__exit(&self->host_machine); close(self->fd); free(self); vdso__exit(); @@ -821,7 +825,7 @@ static struct machine * return perf_session__findnew_machine(session, pid); } - return &session->machines.host; + return perf_session__find_host_machine(session); } static int perf_session_deliver_event(struct perf_session *session, @@ -859,11 +863,11 @@ static int perf_session_deliver_event(struct perf_session *session, case PERF_RECORD_SAMPLE: dump_sample(evsel, event, sample); if (evsel == NULL) { - ++session->stats.nr_unknown_id; + ++session->hists.stats.nr_unknown_id; return 0; } if (machine == NULL) { - ++session->stats.nr_unprocessable_samples; + ++session->hists.stats.nr_unprocessable_samples; return 0; } return tool->sample(tool, event, sample, evsel, machine); @@ -877,7 +881,7 @@ static int perf_session_deliver_event(struct perf_session *session, return tool->exit(tool, event, sample, machine); case PERF_RECORD_LOST: if (tool->lost == perf_event__process_lost) - session->stats.total_lost += event->lost.lost; + session->hists.stats.total_lost += event->lost.lost; return tool->lost(tool, event, sample, machine); case PERF_RECORD_READ: return tool->read(tool, event, sample, evsel, machine); @@ -886,7 +890,7 @@ static int perf_session_deliver_event(struct perf_session *session, case PERF_RECORD_UNTHROTTLE: return tool->unthrottle(tool, event, sample, machine); default: - ++session->stats.nr_unknown_events; + ++session->hists.stats.nr_unknown_events; return -1; } } @@ -900,8 +904,8 @@ static int perf_session__preprocess_sample(struct perf_session *session, if (!ip_callchain__valid(sample->callchain, event)) { pr_debug("call-chain problem with event, skipping it.\n"); - ++session->stats.nr_invalid_chains; - session->stats.total_invalid_chains += sample->period; + ++session->hists.stats.nr_invalid_chains; + session->hists.stats.total_invalid_chains += sample->period; return -EINVAL; } return 0; @@ -959,7 +963,7 @@ static int perf_session__process_event(struct perf_session *session, if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; - events_stats__inc(&session->stats, event->header.type); + hists__inc_nr_events(&session->hists, event->header.type); if (event->header.type >= PERF_RECORD_USER_TYPE_START) return perf_session__process_user_event(session, event, tool, file_offset); @@ -995,7 +999,7 @@ void perf_event_header__bswap(struct perf_event_header *self) struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) { - return machine__findnew_thread(&session->machines.host, pid); + return machine__findnew_thread(&session->host_machine, pid); } static struct thread *perf_session__register_idle_thread(struct perf_session *self) @@ -1014,39 +1018,39 @@ static void perf_session__warn_about_errors(const struct perf_session *session, const struct perf_tool *tool) { if (tool->lost == perf_event__process_lost && - session->stats.nr_events[PERF_RECORD_LOST] != 0) { + session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) { ui__warning("Processed %d events and lost %d chunks!\n\n" "Check IO/CPU overload!\n\n", - session->stats.nr_events[0], - session->stats.nr_events[PERF_RECORD_LOST]); + session->hists.stats.nr_events[0], + session->hists.stats.nr_events[PERF_RECORD_LOST]); } - if (session->stats.nr_unknown_events != 0) { + if (session->hists.stats.nr_unknown_events != 0) { ui__warning("Found %u unknown events!\n\n" "Is this an older tool processing a perf.data " "file generated by a more recent tool?\n\n" "If that is not the case, consider " "reporting to linux-kernel@vger.kernel.org.\n\n", - session->stats.nr_unknown_events); + session->hists.stats.nr_unknown_events); } - if (session->stats.nr_unknown_id != 0) { + if (session->hists.stats.nr_unknown_id != 0) { ui__warning("%u samples with id not present in the header\n", - session->stats.nr_unknown_id); + session->hists.stats.nr_unknown_id); } - if (session->stats.nr_invalid_chains != 0) { + if (session->hists.stats.nr_invalid_chains != 0) { ui__warning("Found invalid callchains!\n\n" "%u out of %u events were discarded for this reason.\n\n" "Consider reporting to linux-kernel@vger.kernel.org.\n\n", - session->stats.nr_invalid_chains, - session->stats.nr_events[PERF_RECORD_SAMPLE]); + session->hists.stats.nr_invalid_chains, + session->hists.stats.nr_events[PERF_RECORD_SAMPLE]); } - if (session->stats.nr_unprocessable_samples != 0) { + if (session->hists.stats.nr_unprocessable_samples != 0) { ui__warning("%u unprocessable samples recorded.\n" "Do you have a KVM guest running and not using 'perf kvm'?\n", - session->stats.nr_unprocessable_samples); + session->hists.stats.nr_unprocessable_samples); } } @@ -1332,13 +1336,16 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps, size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) { - return machines__fprintf_dsos(&self->machines, fp); + return __dsos__fprintf(&self->host_machine.kernel_dsos, fp) + + __dsos__fprintf(&self->host_machine.user_dsos, fp) + + machines__fprintf_dsos(&self->machines, fp); } size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, bool (skip)(struct dso *dso, int parm), int parm) { - return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm); + size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, skip, parm); + return ret + machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm); } size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) @@ -1346,11 +1353,11 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) struct perf_evsel *pos; size_t ret = fprintf(fp, "Aggregated stats:\n"); - ret += events_stats__fprintf(&session->stats, fp); + ret += hists__fprintf_nr_events(&session->hists, fp); list_for_each_entry(pos, &session->evlist->entries, node) { ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); - ret += events_stats__fprintf(&pos->hists.stats, fp); + ret += hists__fprintf_nr_events(&pos->hists, fp); } return ret; @@ -1362,7 +1369,7 @@ size_t perf_session__fprintf(struct perf_session *session, FILE *fp) * FIXME: Here we have to actually print all the machines in this * session, not just the host... */ - return machine__fprintf(&session->machines.host, fp); + return machine__fprintf(&session->host_machine, fp); } void perf_session__remove_thread(struct perf_session *session, @@ -1371,10 +1378,10 @@ void perf_session__remove_thread(struct perf_session *session, /* * FIXME: This one makes no sense, we need to remove the thread from * the machine it belongs to, perf_session can have many machines, so - * doing it always on ->machines.host is wrong. Fix when auditing all + * doing it always on ->host_machine is wrong. Fix when auditing all * the 'perf kvm' code. */ - machine__remove_thread(&session->machines.host, th); + machine__remove_thread(&session->host_machine, th); } struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, diff --git a/trunk/tools/perf/util/session.h b/trunk/tools/perf/util/session.h index b5c0847edfa9..8c2302504199 100644 --- a/trunk/tools/perf/util/session.h +++ b/trunk/tools/perf/util/session.h @@ -30,10 +30,15 @@ struct ordered_samples { struct perf_session { struct perf_header header; unsigned long size; - struct machines machines; + struct machine host_machine; + struct rb_root machines; struct perf_evlist *evlist; struct pevent *pevent; - struct events_stats stats; + /* + * FIXME: Need to split this up further, we need global + * stats + per event stats. + */ + struct hists hists; int fd; bool fd_pipe; bool repipe; @@ -48,7 +53,7 @@ struct perf_tool; struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe, struct perf_tool *tool); -void perf_session__delete(struct perf_session *session); +void perf_session__delete(struct perf_session *self); void perf_event_header__bswap(struct perf_event_header *self); @@ -74,18 +79,37 @@ int perf_session__create_kernel_maps(struct perf_session *self); void perf_session__set_id_hdr_size(struct perf_session *session); void perf_session__remove_thread(struct perf_session *self, struct thread *th); +static inline +struct machine *perf_session__find_host_machine(struct perf_session *self) +{ + return &self->host_machine; +} + static inline struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) { + if (pid == HOST_KERNEL_ID) + return &self->host_machine; return machines__find(&self->machines, pid); } static inline struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) { + if (pid == HOST_KERNEL_ID) + return &self->host_machine; return machines__findnew(&self->machines, pid); } +static inline +void perf_session__process_machines(struct perf_session *self, + struct perf_tool *tool, + machine__process_t process) +{ + process(&self->host_machine, tool); + return machines__process(&self->machines, process, tool); +} + struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); size_t perf_session__fprintf(struct perf_session *self, FILE *fp); diff --git a/trunk/tools/perf/util/sort.c b/trunk/tools/perf/util/sort.c index 83336610faa9..cfd1c0feb32d 100644 --- a/trunk/tools/perf/util/sort.c +++ b/trunk/tools/perf/util/sort.c @@ -60,7 +60,7 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%*s:%5d", width - 6, + return repsep_snprintf(bf, size, "%*s:%5d", width, self->thread->comm ?: "", self->thread->pid); } @@ -97,16 +97,6 @@ static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); } -struct sort_entry sort_comm = { - .se_header = "Command", - .se_cmp = sort__comm_cmp, - .se_collapse = sort__comm_collapse, - .se_snprintf = hist_entry__comm_snprintf, - .se_width_idx = HISTC_COMM, -}; - -/* --sort dso */ - static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r) { struct dso *dso_l = map_l ? map_l->dso : NULL; @@ -127,38 +117,22 @@ static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r) return strcmp(dso_name_l, dso_name_r); } +struct sort_entry sort_comm = { + .se_header = "Command", + .se_cmp = sort__comm_cmp, + .se_collapse = sort__comm_collapse, + .se_snprintf = hist_entry__comm_snprintf, + .se_width_idx = HISTC_COMM, +}; + +/* --sort dso */ + static int64_t sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) { return _sort__dso_cmp(left->ms.map, right->ms.map); } -static int _hist_entry__dso_snprintf(struct map *map, char *bf, - size_t size, unsigned int width) -{ - if (map && map->dso) { - const char *dso_name = !verbose ? map->dso->short_name : - map->dso->long_name; - return repsep_snprintf(bf, size, "%-*s", width, dso_name); - } - - return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); -} - -static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width) -{ - return _hist_entry__dso_snprintf(self->ms.map, bf, size, width); -} - -struct sort_entry sort_dso = { - .se_header = "Shared Object", - .se_cmp = sort__dso_cmp, - .se_snprintf = hist_entry__dso_snprintf, - .se_width_idx = HISTC_DSO, -}; - -/* --sort symbol */ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r, u64 ip_l, u64 ip_r) @@ -169,35 +143,35 @@ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r, if (sym_l == sym_r) return 0; - ip_l = sym_l->start; - ip_r = sym_r->start; + if (sym_l) + ip_l = sym_l->start; + if (sym_r) + ip_r = sym_r->start; return (int64_t)(ip_r - ip_l); } -static int64_t -sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) +static int _hist_entry__dso_snprintf(struct map *map, char *bf, + size_t size, unsigned int width) { - u64 ip_l, ip_r; - - if (!left->ms.sym && !right->ms.sym) - return right->level - left->level; - - if (!left->ms.sym || !right->ms.sym) - return cmp_null(left->ms.sym, right->ms.sym); - - if (left->ms.sym == right->ms.sym) - return 0; + if (map && map->dso) { + const char *dso_name = !verbose ? map->dso->short_name : + map->dso->long_name; + return repsep_snprintf(bf, size, "%-*s", width, dso_name); + } - ip_l = left->ms.sym->start; - ip_r = right->ms.sym->start; + return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); +} - return _sort__sym_cmp(left->ms.sym, right->ms.sym, ip_l, ip_r); +static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width) +{ + return _hist_entry__dso_snprintf(self->ms.map, bf, size, width); } static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, u64 ip, char level, char *bf, size_t size, - unsigned int width) + unsigned int width __maybe_unused) { size_t ret = 0; @@ -223,13 +197,43 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, return ret; } + +struct sort_entry sort_dso = { + .se_header = "Shared Object", + .se_cmp = sort__dso_cmp, + .se_snprintf = hist_entry__dso_snprintf, + .se_width_idx = HISTC_DSO, +}; + static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width) + size_t size, + unsigned int width __maybe_unused) { return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, self->level, bf, size, width); } +/* --sort symbol */ +static int64_t +sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) +{ + u64 ip_l, ip_r; + + if (!left->ms.sym && !right->ms.sym) + return right->level - left->level; + + if (!left->ms.sym || !right->ms.sym) + return cmp_null(left->ms.sym, right->ms.sym); + + if (left->ms.sym == right->ms.sym) + return 0; + + ip_l = left->ms.sym->start; + ip_r = right->ms.sym->start; + + return _sort__sym_cmp(left->ms.sym, right->ms.sym, ip_l, ip_r); +} + struct sort_entry sort_sym = { .se_header = "Symbol", .se_cmp = sort__sym_cmp, @@ -249,7 +253,7 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width __maybe_unused) { - FILE *fp = NULL; + FILE *fp; char cmd[PATH_MAX + 2], *path = self->srcline, *nl; size_t line_len; @@ -270,6 +274,7 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, if (getline(&path, &line_len, fp) < 0 || !line_len) goto out_ip; + fclose(fp); self->srcline = strdup(path); if (self->srcline == NULL) goto out_ip; @@ -279,12 +284,8 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, *nl = '\0'; path = self->srcline; out_path: - if (fp) - pclose(fp); return repsep_snprintf(bf, size, "%s", path); out_ip: - if (fp) - pclose(fp); return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip); } @@ -334,7 +335,7 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%*d", width, self->cpu); + return repsep_snprintf(bf, size, "%-*d", width, self->cpu); } struct sort_entry sort_cpu = { @@ -344,8 +345,6 @@ struct sort_entry sort_cpu = { .se_width_idx = HISTC_CPU, }; -/* sort keys for branch stacks */ - static int64_t sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) { @@ -360,6 +359,13 @@ static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf, bf, size, width); } +struct sort_entry sort_dso_from = { + .se_header = "Source Shared Object", + .se_cmp = sort__dso_from_cmp, + .se_snprintf = hist_entry__dso_from_snprintf, + .se_width_idx = HISTC_DSO_FROM, +}; + static int64_t sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) { @@ -400,7 +406,8 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) } static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width) + size_t size, + unsigned int width __maybe_unused) { struct addr_map_symbol *from = &self->branch_info->from; return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, @@ -409,7 +416,8 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, } static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width) + size_t size, + unsigned int width __maybe_unused) { struct addr_map_symbol *to = &self->branch_info->to; return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, @@ -417,13 +425,6 @@ static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, } -struct sort_entry sort_dso_from = { - .se_header = "Source Shared Object", - .se_cmp = sort__dso_from_cmp, - .se_snprintf = hist_entry__dso_from_snprintf, - .se_width_idx = HISTC_DSO_FROM, -}; - struct sort_entry sort_dso_to = { .se_header = "Target Shared Object", .se_cmp = sort__dso_to_cmp, @@ -483,40 +484,30 @@ struct sort_dimension { #define DIM(d, n, func) [d] = { .name = n, .entry = &(func) } -static struct sort_dimension common_sort_dimensions[] = { +static struct sort_dimension sort_dimensions[] = { DIM(SORT_PID, "pid", sort_thread), DIM(SORT_COMM, "comm", sort_comm), DIM(SORT_DSO, "dso", sort_dso), + DIM(SORT_DSO_FROM, "dso_from", sort_dso_from), + DIM(SORT_DSO_TO, "dso_to", sort_dso_to), DIM(SORT_SYM, "symbol", sort_sym), + DIM(SORT_SYM_TO, "symbol_from", sort_sym_from), + DIM(SORT_SYM_FROM, "symbol_to", sort_sym_to), DIM(SORT_PARENT, "parent", sort_parent), DIM(SORT_CPU, "cpu", sort_cpu), - DIM(SORT_SRCLINE, "srcline", sort_srcline), -}; - -#undef DIM - -#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) } - -static struct sort_dimension bstack_sort_dimensions[] = { - DIM(SORT_DSO_FROM, "dso_from", sort_dso_from), - DIM(SORT_DSO_TO, "dso_to", sort_dso_to), - DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from), - DIM(SORT_SYM_TO, "symbol_to", sort_sym_to), DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), + DIM(SORT_SRCLINE, "srcline", sort_srcline), }; -#undef DIM - int sort_dimension__add(const char *tok) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) { - struct sort_dimension *sd = &common_sort_dimensions[i]; + for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { + struct sort_dimension *sd = &sort_dimensions[i]; if (strncasecmp(tok, sd->name, strlen(tok))) continue; - if (sd->entry == &sort_parent) { int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); if (ret) { @@ -527,7 +518,9 @@ int sort_dimension__add(const char *tok) return -EINVAL; } sort__has_parent = 1; - } else if (sd->entry == &sort_sym) { + } else if (sd->entry == &sort_sym || + sd->entry == &sort_sym_from || + sd->entry == &sort_sym_to) { sort__has_sym = 1; } @@ -537,42 +530,36 @@ int sort_dimension__add(const char *tok) if (sd->entry->se_collapse) sort__need_collapse = 1; - if (list_empty(&hist_entry__sort_list)) - sort__first_dimension = i; - - list_add_tail(&sd->entry->list, &hist_entry__sort_list); - sd->taken = 1; - - return 0; - } - - for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { - struct sort_dimension *sd = &bstack_sort_dimensions[i]; - - if (strncasecmp(tok, sd->name, strlen(tok))) - continue; - - if (sort__branch_mode != 1) - return -EINVAL; - - if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) - sort__has_sym = 1; - - if (sd->taken) - return 0; - - if (sd->entry->se_collapse) - sort__need_collapse = 1; - - if (list_empty(&hist_entry__sort_list)) - sort__first_dimension = i + __SORT_BRANCH_STACK; + if (list_empty(&hist_entry__sort_list)) { + if (!strcmp(sd->name, "pid")) + sort__first_dimension = SORT_PID; + else if (!strcmp(sd->name, "comm")) + sort__first_dimension = SORT_COMM; + else if (!strcmp(sd->name, "dso")) + sort__first_dimension = SORT_DSO; + else if (!strcmp(sd->name, "symbol")) + sort__first_dimension = SORT_SYM; + else if (!strcmp(sd->name, "parent")) + sort__first_dimension = SORT_PARENT; + else if (!strcmp(sd->name, "cpu")) + sort__first_dimension = SORT_CPU; + else if (!strcmp(sd->name, "symbol_from")) + sort__first_dimension = SORT_SYM_FROM; + else if (!strcmp(sd->name, "symbol_to")) + sort__first_dimension = SORT_SYM_TO; + else if (!strcmp(sd->name, "dso_from")) + sort__first_dimension = SORT_DSO_FROM; + else if (!strcmp(sd->name, "dso_to")) + sort__first_dimension = SORT_DSO_TO; + else if (!strcmp(sd->name, "mispredict")) + sort__first_dimension = SORT_MISPREDICT; + } list_add_tail(&sd->entry->list, &hist_entry__sort_list); sd->taken = 1; return 0; } - return -ESRCH; } @@ -582,11 +569,7 @@ void setup_sorting(const char * const usagestr[], const struct option *opts) for (tok = strtok_r(str, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { - int ret = sort_dimension__add(tok); - if (ret == -EINVAL) { - error("Invalid --sort key: `%s'", tok); - usage_with_options(usagestr, opts); - } else if (ret == -ESRCH) { + if (sort_dimension__add(tok) < 0) { error("Unknown --sort key: `%s'", tok); usage_with_options(usagestr, opts); } diff --git a/trunk/tools/perf/util/sort.h b/trunk/tools/perf/util/sort.h index e994ad3e9897..a1c0d56b6885 100644 --- a/trunk/tools/perf/util/sort.h +++ b/trunk/tools/perf/util/sort.h @@ -122,22 +122,18 @@ static inline void hist_entry__add_pair(struct hist_entry *he, } enum sort_type { - /* common sort keys */ SORT_PID, SORT_COMM, SORT_DSO, SORT_SYM, SORT_PARENT, SORT_CPU, - SORT_SRCLINE, - - /* branch stack specific sort keys */ - __SORT_BRANCH_STACK, - SORT_DSO_FROM = __SORT_BRANCH_STACK, + SORT_DSO_FROM, SORT_DSO_TO, SORT_SYM_FROM, SORT_SYM_TO, SORT_MISPREDICT, + SORT_SRCLINE, }; /* diff --git a/trunk/tools/perf/util/string.c b/trunk/tools/perf/util/string.c index 29c7b2cb2521..346707df04b9 100644 --- a/trunk/tools/perf/util/string.c +++ b/trunk/tools/perf/util/string.c @@ -331,24 +331,6 @@ char *strxfrchar(char *s, char from, char to) return s; } -/** - * ltrim - Removes leading whitespace from @s. - * @s: The string to be stripped. - * - * Return pointer to the first non-whitespace character in @s. - */ -char *ltrim(char *s) -{ - int len = strlen(s); - - while (len && isspace(*s)) { - len--; - s++; - } - - return s; -} - /** * rtrim - Removes trailing whitespace from @s. * @s: The string to be stripped. diff --git a/trunk/tools/perf/util/strlist.c b/trunk/tools/perf/util/strlist.c index 55433aa42c8f..155d8b7078a7 100644 --- a/trunk/tools/perf/util/strlist.c +++ b/trunk/tools/perf/util/strlist.c @@ -35,11 +35,11 @@ struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry) return NULL; } -static void str_node__delete(struct str_node *snode, bool dupstr) +static void str_node__delete(struct str_node *self, bool dupstr) { if (dupstr) - free((void *)snode->s); - free(snode); + free((void *)self->s); + free(self); } static @@ -59,12 +59,12 @@ static int strlist__node_cmp(struct rb_node *rb_node, const void *entry) return strcmp(snode->s, str); } -int strlist__add(struct strlist *slist, const char *new_entry) +int strlist__add(struct strlist *self, const char *new_entry) { - return rblist__add_node(&slist->rblist, new_entry); + return rblist__add_node(&self->rblist, new_entry); } -int strlist__load(struct strlist *slist, const char *filename) +int strlist__load(struct strlist *self, const char *filename) { char entry[1024]; int err; @@ -80,7 +80,7 @@ int strlist__load(struct strlist *slist, const char *filename) continue; entry[len - 1] = '\0'; - err = strlist__add(slist, entry); + err = strlist__add(self, entry); if (err != 0) goto out; } @@ -107,56 +107,56 @@ struct str_node *strlist__find(struct strlist *slist, const char *entry) return snode; } -static int strlist__parse_list_entry(struct strlist *slist, const char *s) +static int strlist__parse_list_entry(struct strlist *self, const char *s) { if (strncmp(s, "file://", 7) == 0) - return strlist__load(slist, s + 7); + return strlist__load(self, s + 7); - return strlist__add(slist, s); + return strlist__add(self, s); } -int strlist__parse_list(struct strlist *slist, const char *s) +int strlist__parse_list(struct strlist *self, const char *s) { char *sep; int err; while ((sep = strchr(s, ',')) != NULL) { *sep = '\0'; - err = strlist__parse_list_entry(slist, s); + err = strlist__parse_list_entry(self, s); *sep = ','; if (err != 0) return err; s = sep + 1; } - return *s ? strlist__parse_list_entry(slist, s) : 0; + return *s ? strlist__parse_list_entry(self, s) : 0; } -struct strlist *strlist__new(bool dupstr, const char *list) +struct strlist *strlist__new(bool dupstr, const char *slist) { - struct strlist *slist = malloc(sizeof(*slist)); + struct strlist *self = malloc(sizeof(*self)); - if (slist != NULL) { - rblist__init(&slist->rblist); - slist->rblist.node_cmp = strlist__node_cmp; - slist->rblist.node_new = strlist__node_new; - slist->rblist.node_delete = strlist__node_delete; + if (self != NULL) { + rblist__init(&self->rblist); + self->rblist.node_cmp = strlist__node_cmp; + self->rblist.node_new = strlist__node_new; + self->rblist.node_delete = strlist__node_delete; - slist->dupstr = dupstr; - if (slist && strlist__parse_list(slist, list) != 0) + self->dupstr = dupstr; + if (slist && strlist__parse_list(self, slist) != 0) goto out_error; } - return slist; + return self; out_error: - free(slist); + free(self); return NULL; } -void strlist__delete(struct strlist *slist) +void strlist__delete(struct strlist *self) { - if (slist != NULL) - rblist__delete(&slist->rblist); + if (self != NULL) + rblist__delete(&self->rblist); } struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx) diff --git a/trunk/tools/perf/util/strlist.h b/trunk/tools/perf/util/strlist.h index 5c7f87069d9c..dd9f922ec67c 100644 --- a/trunk/tools/perf/util/strlist.h +++ b/trunk/tools/perf/util/strlist.h @@ -17,34 +17,34 @@ struct strlist { }; struct strlist *strlist__new(bool dupstr, const char *slist); -void strlist__delete(struct strlist *slist); +void strlist__delete(struct strlist *self); -void strlist__remove(struct strlist *slist, struct str_node *sn); -int strlist__load(struct strlist *slist, const char *filename); -int strlist__add(struct strlist *slist, const char *str); +void strlist__remove(struct strlist *self, struct str_node *sn); +int strlist__load(struct strlist *self, const char *filename); +int strlist__add(struct strlist *self, const char *str); -struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx); -struct str_node *strlist__find(struct strlist *slist, const char *entry); +struct str_node *strlist__entry(const struct strlist *self, unsigned int idx); +struct str_node *strlist__find(struct strlist *self, const char *entry); -static inline bool strlist__has_entry(struct strlist *slist, const char *entry) +static inline bool strlist__has_entry(struct strlist *self, const char *entry) { - return strlist__find(slist, entry) != NULL; + return strlist__find(self, entry) != NULL; } -static inline bool strlist__empty(const struct strlist *slist) +static inline bool strlist__empty(const struct strlist *self) { - return rblist__empty(&slist->rblist); + return rblist__empty(&self->rblist); } -static inline unsigned int strlist__nr_entries(const struct strlist *slist) +static inline unsigned int strlist__nr_entries(const struct strlist *self) { - return rblist__nr_entries(&slist->rblist); + return rblist__nr_entries(&self->rblist); } /* For strlist iteration */ -static inline struct str_node *strlist__first(struct strlist *slist) +static inline struct str_node *strlist__first(struct strlist *self) { - struct rb_node *rn = rb_first(&slist->rblist.entries); + struct rb_node *rn = rb_first(&self->rblist.entries); return rn ? rb_entry(rn, struct str_node, rb_node) : NULL; } static inline struct str_node *strlist__next(struct str_node *sn) @@ -59,21 +59,21 @@ static inline struct str_node *strlist__next(struct str_node *sn) /** * strlist_for_each - iterate over a strlist * @pos: the &struct str_node to use as a loop cursor. - * @slist: the &struct strlist for loop. + * @self: the &struct strlist for loop. */ -#define strlist__for_each(pos, slist) \ - for (pos = strlist__first(slist); pos; pos = strlist__next(pos)) +#define strlist__for_each(pos, self) \ + for (pos = strlist__first(self); pos; pos = strlist__next(pos)) /** * strlist_for_each_safe - iterate over a strlist safe against removal of * str_node * @pos: the &struct str_node to use as a loop cursor. * @n: another &struct str_node to use as temporary storage. - * @slist: the &struct strlist for loop. + * @self: the &struct strlist for loop. */ -#define strlist__for_each_safe(pos, n, slist) \ - for (pos = strlist__first(slist), n = strlist__next(pos); pos;\ +#define strlist__for_each_safe(pos, n, self) \ + for (pos = strlist__first(self), n = strlist__next(pos); pos;\ pos = n, n = strlist__next(n)) -int strlist__parse_list(struct strlist *slist, const char *s); +int strlist__parse_list(struct strlist *self, const char *s); #endif /* __PERF_STRLIST_H */ diff --git a/trunk/tools/perf/util/symbol-elf.c b/trunk/tools/perf/util/symbol-elf.c index 54efcb5659ac..f63557b59c06 100644 --- a/trunk/tools/perf/util/symbol-elf.c +++ b/trunk/tools/perf/util/symbol-elf.c @@ -1,3 +1,6 @@ +#include +#include +#include #include #include #include diff --git a/trunk/tools/perf/util/symbol-minimal.c b/trunk/tools/perf/util/symbol-minimal.c index a7390cde63bc..259f8f2ea9c9 100644 --- a/trunk/tools/perf/util/symbol-minimal.c +++ b/trunk/tools/perf/util/symbol-minimal.c @@ -1,5 +1,6 @@ #include "symbol.h" +#include #include #include #include diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index e6432d85b43d..2960284d6ae1 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -768,6 +768,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) else machine = NULL; + name = malloc(PATH_MAX); + if (!name) + return -1; + dso->adjust_symbols = 0; if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { @@ -791,10 +795,6 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) if (machine) root_dir = machine->root_dir; - name = malloc(PATH_MAX); - if (!name) - return -1; - /* Iterate over candidate debug images. * Keep track of "interesting" ones (those which have a symtab, dynsym, * and/or opd section) for processing. @@ -923,10 +923,8 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, filename = dso__build_id_filename(dso, NULL, 0); if (filename != NULL) { err = dso__load_vmlinux(dso, map, filename, filter); - if (err > 0) { - dso->lname_alloc = 1; + if (err > 0) goto out; - } free(filename); } @@ -934,7 +932,6 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); if (err > 0) { dso__set_long_name(dso, strdup(vmlinux_path[i])); - dso->lname_alloc = 1; break; } } @@ -974,7 +971,6 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, if (err > 0) { dso__set_long_name(dso, strdup(symbol_conf.vmlinux_name)); - dso->lname_alloc = 1; goto out_fixup; } return err; diff --git a/trunk/tools/perf/util/symbol.h b/trunk/tools/perf/util/symbol.h index b62ca37c4b77..ec7b2405c377 100644 --- a/trunk/tools/perf/util/symbol.h +++ b/trunk/tools/perf/util/symbol.h @@ -16,8 +16,8 @@ #ifdef LIBELF_SUPPORT #include #include -#endif #include +#endif #include "dso.h" @@ -96,8 +96,7 @@ struct symbol_conf { initialized, kptr_restrict, annotate_asm_raw, - annotate_src, - event_group; + annotate_src; const char *vmlinux_name, *kallsyms_name, *source_prefix, diff --git a/trunk/tools/perf/util/sysfs.c b/trunk/tools/perf/util/sysfs.c index f71e9eafe15a..48c6902e749f 100644 --- a/trunk/tools/perf/util/sysfs.c +++ b/trunk/tools/perf/util/sysfs.c @@ -8,7 +8,7 @@ static const char * const sysfs_known_mountpoints[] = { }; static int sysfs_found; -char sysfs_mountpoint[PATH_MAX + 1]; +char sysfs_mountpoint[PATH_MAX]; static int sysfs_valid_mountpoint(const char *sysfs) { diff --git a/trunk/tools/perf/util/top.h b/trunk/tools/perf/util/top.h index 7ebf357dc9e1..927c229c2d9a 100644 --- a/trunk/tools/perf/util/top.h +++ b/trunk/tools/perf/util/top.h @@ -29,6 +29,8 @@ struct perf_top { bool sort_has_symbols; bool kptr_restrict_warned; bool vmlinux_warned; + bool sample_id_all_missing; + bool exclude_guest_missing; bool dump_symtab; struct hist_entry *sym_filter_entry; struct perf_evsel *sym_evsel; diff --git a/trunk/tools/perf/util/util.c b/trunk/tools/perf/util/util.c index 805d1f52c5b4..5906e8426cc7 100644 --- a/trunk/tools/perf/util/util.c +++ b/trunk/tools/perf/util/util.c @@ -12,8 +12,6 @@ */ unsigned int page_size; -bool test_attr__enabled; - bool perf_host = true; bool perf_guest = false; @@ -220,25 +218,3 @@ void dump_stack(void) #else void dump_stack(void) {} #endif - -void get_term_dimensions(struct winsize *ws) -{ - char *s = getenv("LINES"); - - if (s != NULL) { - ws->ws_row = atoi(s); - s = getenv("COLUMNS"); - if (s != NULL) { - ws->ws_col = atoi(s); - if (ws->ws_row && ws->ws_col) - return; - } - } -#ifdef TIOCGWINSZ - if (ioctl(1, TIOCGWINSZ, ws) == 0 && - ws->ws_row && ws->ws_col) - return; -#endif - ws->ws_row = 25; - ws->ws_col = 80; -} diff --git a/trunk/tools/perf/util/util.h b/trunk/tools/perf/util/util.h index 09b4c26b71aa..c2330918110c 100644 --- a/trunk/tools/perf/util/util.h +++ b/trunk/tools/perf/util/util.h @@ -265,14 +265,10 @@ bool is_power_of_2(unsigned long n) size_t hex_width(u64 v); int hex2u64(const char *ptr, u64 *val); -char *ltrim(char *s); char *rtrim(char *s); void dump_stack(void); extern unsigned int page_size; -struct winsize; -void get_term_dimensions(struct winsize *ws); - #endif