mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
perf tools fixes for 5.16: 1st batch
- Fix the 'local_weight', 'weight' (memory access latency), 'local_ins_lat', 'ins_lat' (instruction latency) and 'pstage_cyc' (pipeline stage cycles) sort key sample aggregation. - Fix 'perf test' entry for watchpoints on s/390. - Fix branch_stack entry endianness check in the 'perf test' sample parsing test. - Fix ARM SPE handling on 'perf inject'. - Fix memory leaks detected with ASan. - Fix build on arm64 related to reallocarray() availability. - Sync copies of kernel headers: cpufeatures, kvm, MIPS syscalltable (futex_waitv). Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQR2GiIUctdOfX2qHhGyPKLppCJ+JwUCYZelOQAKCRCyPKLppCJ+ J2ScAQDwQpuzK8d9KYBGe2D/MHYm48bndjC3qU0vExrRGPvvXwD/SBZTIjzXFGTg OIHDO2wd6CmXzsu3SKS0pTsx+SxW2gA= =+sen -----END PGP SIGNATURE----- Merge tag 'perf-tools-fixes-for-v5.16-2021-11-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux Pull perf tools fixes from Arnaldo Carvalho de Melo: - Fix the 'local_weight', 'weight' (memory access latency), 'local_ins_lat', 'ins_lat' (instruction latency) and 'pstage_cyc' (pipeline stage cycles) sort key sample aggregation. - Fix 'perf test' entry for watchpoints on s/390. - Fix branch_stack entry endianness check in the 'perf test' sample parsing test. - Fix ARM SPE handling on 'perf inject'. - Fix memory leaks detected with ASan. - Fix build on arm64 related to reallocarray() availability. - Sync copies of kernel headers: cpufeatures, kvm, MIPS syscalltable (futex_waitv). * tag 'perf-tools-fixes-for-v5.16-2021-11-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: perf evsel: Fix memory leaks relating to unit perf report: Fix memory leaks around perf_tip() perf hist: Fix memory leak of a perf_hpp_fmt tools headers UAPI: Sync MIPS syscall table file changed by new futex_waitv syscall tools build: Fix removal of feature-sync-compare-and-swap feature detection perf inject: Fix ARM SPE handling perf bench: Fix two memory leaks detected with ASan perf test sample-parsing: Fix branch_stack entry endianness check tools headers UAPI: Sync x86's asm/kvm.h with the kernel sources perf sort: Fix the 'p_stage_cyc' sort key behavior perf sort: Fix the 'ins_lat' sort key behavior perf sort: Fix the 'weight' sort key behavior perf tools: Set COMPAT_NEED_REALLOCARRAY for CONFIG_AUXTRACE=1 perf tests wp: Remove unused functions on s390 tools headers UAPI: Sync linux/kvm.h with the kernel sources tools headers cpufeatures: Sync with the kernel sources
This commit is contained in:
commit
8b98436af2
@ -277,6 +277,7 @@
|
||||
#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC instruction */
|
||||
#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 instruction */
|
||||
#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS instructions */
|
||||
#define X86_FEATURE_XFD (10*32+ 4) /* "" eXtended Feature Disabling */
|
||||
|
||||
/*
|
||||
* Extended auxiliary flags: Linux defined - for features scattered in various
|
||||
@ -298,6 +299,7 @@
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
|
||||
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */
|
||||
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */
|
||||
#define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */
|
||||
|
||||
/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
|
||||
#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */
|
||||
|
@ -504,4 +504,8 @@ struct kvm_pmu_event_filter {
|
||||
#define KVM_PMU_EVENT_ALLOW 0
|
||||
#define KVM_PMU_EVENT_DENY 1
|
||||
|
||||
/* for KVM_{GET,SET,HAS}_DEVICE_ATTR */
|
||||
#define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */
|
||||
#define KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */
|
||||
|
||||
#endif /* _ASM_X86_KVM_H */
|
||||
|
@ -200,7 +200,6 @@ int main(int argc, char *argv[])
|
||||
main_test_timerfd();
|
||||
main_test_stackprotector_all();
|
||||
main_test_libdw_dwarf_unwind();
|
||||
main_test_sync_compare_and_swap(argc, argv);
|
||||
main_test_zlib();
|
||||
main_test_pthread_attr_setaffinity_np();
|
||||
main_test_pthread_barrier();
|
||||
|
@ -269,6 +269,7 @@ struct kvm_xen_exit {
|
||||
#define KVM_EXIT_AP_RESET_HOLD 32
|
||||
#define KVM_EXIT_X86_BUS_LOCK 33
|
||||
#define KVM_EXIT_XEN 34
|
||||
#define KVM_EXIT_RISCV_SBI 35
|
||||
|
||||
/* For KVM_EXIT_INTERNAL_ERROR */
|
||||
/* Emulate instruction failed. */
|
||||
@ -397,13 +398,23 @@ struct kvm_run {
|
||||
* "ndata" is correct, that new fields are enumerated in "flags",
|
||||
* and that each flag enumerates fields that are 64-bit aligned
|
||||
* and sized (so that ndata+internal.data[] is valid/accurate).
|
||||
*
|
||||
* Space beyond the defined fields may be used to store arbitrary
|
||||
* debug information relating to the emulation failure. It is
|
||||
* accounted for in "ndata" but the format is unspecified and is
|
||||
* not represented in "flags". Any such information is *not* ABI!
|
||||
*/
|
||||
struct {
|
||||
__u32 suberror;
|
||||
__u32 ndata;
|
||||
__u64 flags;
|
||||
__u8 insn_size;
|
||||
__u8 insn_bytes[15];
|
||||
union {
|
||||
struct {
|
||||
__u8 insn_size;
|
||||
__u8 insn_bytes[15];
|
||||
};
|
||||
};
|
||||
/* Arbitrary debug data may follow. */
|
||||
} emulation_failure;
|
||||
/* KVM_EXIT_OSI */
|
||||
struct {
|
||||
@ -469,6 +480,13 @@ struct kvm_run {
|
||||
} msr;
|
||||
/* KVM_EXIT_XEN */
|
||||
struct kvm_xen_exit xen;
|
||||
/* KVM_EXIT_RISCV_SBI */
|
||||
struct {
|
||||
unsigned long extension_id;
|
||||
unsigned long function_id;
|
||||
unsigned long args[6];
|
||||
unsigned long ret[2];
|
||||
} riscv_sbi;
|
||||
/* Fix the size of the union. */
|
||||
char padding[256];
|
||||
};
|
||||
@ -1112,6 +1130,7 @@ struct kvm_ppc_resize_hpt {
|
||||
#define KVM_CAP_BINARY_STATS_FD 203
|
||||
#define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
|
||||
#define KVM_CAP_ARM_MTE 205
|
||||
#define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
@ -1223,11 +1242,16 @@ struct kvm_irqfd {
|
||||
|
||||
/* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags. */
|
||||
#define KVM_CLOCK_TSC_STABLE 2
|
||||
#define KVM_CLOCK_REALTIME (1 << 2)
|
||||
#define KVM_CLOCK_HOST_TSC (1 << 3)
|
||||
|
||||
struct kvm_clock_data {
|
||||
__u64 clock;
|
||||
__u32 flags;
|
||||
__u32 pad[9];
|
||||
__u32 pad0;
|
||||
__u64 realtime;
|
||||
__u64 host_tsc;
|
||||
__u32 pad[4];
|
||||
};
|
||||
|
||||
/* For KVM_CAP_SW_TLB */
|
||||
|
@ -1010,6 +1010,9 @@ ifndef NO_AUXTRACE
|
||||
ifndef NO_AUXTRACE
|
||||
$(call detected,CONFIG_AUXTRACE)
|
||||
CFLAGS += -DHAVE_AUXTRACE_SUPPORT
|
||||
ifeq ($(feature-reallocarray), 0)
|
||||
CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -363,3 +363,4 @@
|
||||
446 n64 landlock_restrict_self sys_landlock_restrict_self
|
||||
# 447 reserved for memfd_secret
|
||||
448 n64 process_mrelease sys_process_mrelease
|
||||
449 n64 futex_waitv sys_futex_waitv
|
||||
|
@ -223,6 +223,8 @@ static unsigned int group(pthread_t *pth,
|
||||
snd_ctx->out_fds[i] = fds[1];
|
||||
if (!thread_mode)
|
||||
close(fds[0]);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/* Now we have all the fds, fork the senders */
|
||||
@ -239,6 +241,8 @@ static unsigned int group(pthread_t *pth,
|
||||
for (i = 0; i < num_fds; i++)
|
||||
close(snd_ctx->out_fds[i]);
|
||||
|
||||
free(snd_ctx);
|
||||
|
||||
/* Return number of children to reap */
|
||||
return num_fds * 2;
|
||||
}
|
||||
|
@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep)
|
||||
int ret;
|
||||
struct perf_session *session = rep->session;
|
||||
struct evlist *evlist = session->evlist;
|
||||
const char *help = perf_tip(system_path(TIPDIR));
|
||||
char *help = NULL, *path = NULL;
|
||||
|
||||
if (help == NULL) {
|
||||
path = system_path(TIPDIR);
|
||||
if (perf_tip(&help, path) || help == NULL) {
|
||||
/* fallback for people who don't install perf ;-) */
|
||||
help = perf_tip(DOCDIR);
|
||||
if (help == NULL)
|
||||
help = "Cannot load tips.txt file, please install perf!";
|
||||
free(path);
|
||||
path = system_path(DOCDIR);
|
||||
if (perf_tip(&help, path) || help == NULL)
|
||||
help = strdup("Cannot load tips.txt file, please install perf!");
|
||||
}
|
||||
free(path);
|
||||
|
||||
switch (use_browser) {
|
||||
case 1:
|
||||
@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep)
|
||||
ret = evlist__tty_browse_hists(evlist, rep, help);
|
||||
break;
|
||||
}
|
||||
|
||||
free(help);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
|
||||
struct evsel *evsel;
|
||||
struct event_name tmp;
|
||||
struct evlist *evlist = evlist__new_default();
|
||||
char *unit = strdup("KRAVA");
|
||||
|
||||
TEST_ASSERT_VAL("failed to get evlist", evlist);
|
||||
|
||||
@ -99,7 +98,8 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
|
||||
|
||||
perf_evlist__id_add(&evlist->core, &evsel->core, 0, 0, 123);
|
||||
|
||||
evsel->unit = unit;
|
||||
free((char *)evsel->unit);
|
||||
evsel->unit = strdup("KRAVA");
|
||||
|
||||
TEST_ASSERT_VAL("failed to synthesize attr update unit",
|
||||
!perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
|
||||
@ -119,7 +119,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
|
||||
TEST_ASSERT_VAL("failed to synthesize attr update cpus",
|
||||
!perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
|
||||
|
||||
free(unit);
|
||||
evlist__delete(evlist);
|
||||
return 0;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
* These are based on the input value (213) specified
|
||||
* in branch_stack variable.
|
||||
*/
|
||||
#define BS_EXPECTED_BE 0xa00d000000000000
|
||||
#define BS_EXPECTED_BE 0xa000d00000000000
|
||||
#define BS_EXPECTED_LE 0xd5000000
|
||||
#define FLAG(s) s->branch_stack->entries[i].flags
|
||||
|
||||
|
@ -21,6 +21,7 @@ do { \
|
||||
volatile u64 data1;
|
||||
volatile u8 data2[3];
|
||||
|
||||
#ifndef __s390x__
|
||||
static int wp_read(int fd, long long *count, int size)
|
||||
{
|
||||
int ret = read(fd, count, size);
|
||||
@ -48,7 +49,6 @@ static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
|
||||
attr->exclude_hv = 1;
|
||||
}
|
||||
|
||||
#ifndef __s390x__
|
||||
static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
|
||||
{
|
||||
int fd;
|
||||
|
@ -535,6 +535,18 @@ struct perf_hpp_list perf_hpp_list = {
|
||||
#undef __HPP_SORT_ACC_FN
|
||||
#undef __HPP_SORT_RAW_FN
|
||||
|
||||
static void fmt_free(struct perf_hpp_fmt *fmt)
|
||||
{
|
||||
/*
|
||||
* At this point fmt should be completely
|
||||
* unhooked, if not it's a bug.
|
||||
*/
|
||||
BUG_ON(!list_empty(&fmt->list));
|
||||
BUG_ON(!list_empty(&fmt->sort_list));
|
||||
|
||||
if (fmt->free)
|
||||
fmt->free(fmt);
|
||||
}
|
||||
|
||||
void perf_hpp__init(void)
|
||||
{
|
||||
@ -598,9 +610,10 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
|
||||
list_add(&format->sort_list, &list->sorts);
|
||||
}
|
||||
|
||||
void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
|
||||
static void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
|
||||
{
|
||||
list_del_init(&format->list);
|
||||
fmt_free(format);
|
||||
}
|
||||
|
||||
void perf_hpp__cancel_cumulate(void)
|
||||
@ -672,19 +685,6 @@ next:
|
||||
}
|
||||
|
||||
|
||||
static void fmt_free(struct perf_hpp_fmt *fmt)
|
||||
{
|
||||
/*
|
||||
* At this point fmt should be completely
|
||||
* unhooked, if not it's a bug.
|
||||
*/
|
||||
BUG_ON(!list_empty(&fmt->list));
|
||||
BUG_ON(!list_empty(&fmt->sort_list));
|
||||
|
||||
if (fmt->free)
|
||||
fmt->free(fmt);
|
||||
}
|
||||
|
||||
void perf_hpp__reset_output_field(struct perf_hpp_list *list)
|
||||
{
|
||||
struct perf_hpp_fmt *fmt, *tmp;
|
||||
|
@ -51,6 +51,7 @@ struct arm_spe {
|
||||
u8 timeless_decoding;
|
||||
u8 data_queued;
|
||||
|
||||
u64 sample_type;
|
||||
u8 sample_flc;
|
||||
u8 sample_llc;
|
||||
u8 sample_tlb;
|
||||
@ -287,6 +288,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
|
||||
event->sample.header.size = sizeof(struct perf_event_header);
|
||||
}
|
||||
|
||||
static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
|
||||
{
|
||||
event->header.size = perf_event__sample_event_size(sample, type, 0);
|
||||
return perf_event__synthesize_sample(event, type, 0, sample);
|
||||
}
|
||||
|
||||
static inline int
|
||||
arm_spe_deliver_synth_event(struct arm_spe *spe,
|
||||
struct arm_spe_queue *speq __maybe_unused,
|
||||
@ -295,6 +302,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe,
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (spe->synth_opts.inject) {
|
||||
ret = arm_spe__inject_event(event, sample, spe->sample_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = perf_session__deliver_synth_event(spe->session, event, sample);
|
||||
if (ret)
|
||||
pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
|
||||
@ -986,6 +999,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
|
||||
else
|
||||
attr.sample_type |= PERF_SAMPLE_TIME;
|
||||
|
||||
spe->sample_type = attr.sample_type;
|
||||
|
||||
attr.exclude_user = evsel->core.attr.exclude_user;
|
||||
attr.exclude_kernel = evsel->core.attr.exclude_kernel;
|
||||
attr.exclude_hv = evsel->core.attr.exclude_hv;
|
||||
|
@ -241,7 +241,7 @@ void evsel__init(struct evsel *evsel,
|
||||
{
|
||||
perf_evsel__init(&evsel->core, attr, idx);
|
||||
evsel->tracking = !idx;
|
||||
evsel->unit = "";
|
||||
evsel->unit = strdup("");
|
||||
evsel->scale = 1.0;
|
||||
evsel->max_events = ULONG_MAX;
|
||||
evsel->evlist = NULL;
|
||||
@ -276,13 +276,8 @@ struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx)
|
||||
}
|
||||
|
||||
if (evsel__is_clock(evsel)) {
|
||||
/*
|
||||
* The evsel->unit points to static alias->unit
|
||||
* so it's ok to use static string in here.
|
||||
*/
|
||||
static const char *unit = "msec";
|
||||
|
||||
evsel->unit = unit;
|
||||
free((char *)evsel->unit);
|
||||
evsel->unit = strdup("msec");
|
||||
evsel->scale = 1e-6;
|
||||
}
|
||||
|
||||
@ -420,7 +415,11 @@ struct evsel *evsel__clone(struct evsel *orig)
|
||||
|
||||
evsel->max_events = orig->max_events;
|
||||
evsel->tool_event = orig->tool_event;
|
||||
evsel->unit = orig->unit;
|
||||
free((char *)evsel->unit);
|
||||
evsel->unit = strdup(orig->unit);
|
||||
if (evsel->unit == NULL)
|
||||
goto out_err;
|
||||
|
||||
evsel->scale = orig->scale;
|
||||
evsel->snapshot = orig->snapshot;
|
||||
evsel->per_pkg = orig->per_pkg;
|
||||
@ -1441,6 +1440,7 @@ void evsel__exit(struct evsel *evsel)
|
||||
zfree(&evsel->group_name);
|
||||
zfree(&evsel->name);
|
||||
zfree(&evsel->pmu_name);
|
||||
zfree(&evsel->unit);
|
||||
zfree(&evsel->metric_id);
|
||||
evsel__zero_per_pkg(evsel);
|
||||
hashmap__free(evsel->per_pkg_mask);
|
||||
|
@ -4257,9 +4257,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
|
||||
|
||||
switch (ev->type) {
|
||||
case PERF_EVENT_UPDATE__UNIT:
|
||||
free((char *)evsel->unit);
|
||||
evsel->unit = strdup(ev->data);
|
||||
break;
|
||||
case PERF_EVENT_UPDATE__NAME:
|
||||
free(evsel->name);
|
||||
evsel->name = strdup(ev->data);
|
||||
break;
|
||||
case PERF_EVENT_UPDATE__SCALE:
|
||||
@ -4268,11 +4270,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
|
||||
break;
|
||||
case PERF_EVENT_UPDATE__CPUS:
|
||||
ev_cpus = (struct perf_record_event_update_cpus *)ev->data;
|
||||
|
||||
map = cpu_map__new_data(&ev_cpus->cpus);
|
||||
if (map)
|
||||
if (map) {
|
||||
perf_cpu_map__put(evsel->core.own_cpus);
|
||||
evsel->core.own_cpus = map;
|
||||
else
|
||||
} else
|
||||
pr_err("failed to get event_update cpus\n");
|
||||
default:
|
||||
break;
|
||||
|
@ -289,15 +289,10 @@ static long hist_time(unsigned long htime)
|
||||
return htime;
|
||||
}
|
||||
|
||||
static void he_stat__add_period(struct he_stat *he_stat, u64 period,
|
||||
u64 weight, u64 ins_lat, u64 p_stage_cyc)
|
||||
static void he_stat__add_period(struct he_stat *he_stat, u64 period)
|
||||
{
|
||||
|
||||
he_stat->period += period;
|
||||
he_stat->weight += weight;
|
||||
he_stat->nr_events += 1;
|
||||
he_stat->ins_lat += ins_lat;
|
||||
he_stat->p_stage_cyc += p_stage_cyc;
|
||||
}
|
||||
|
||||
static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
|
||||
@ -308,9 +303,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
|
||||
dest->period_guest_sys += src->period_guest_sys;
|
||||
dest->period_guest_us += src->period_guest_us;
|
||||
dest->nr_events += src->nr_events;
|
||||
dest->weight += src->weight;
|
||||
dest->ins_lat += src->ins_lat;
|
||||
dest->p_stage_cyc += src->p_stage_cyc;
|
||||
}
|
||||
|
||||
static void he_stat__decay(struct he_stat *he_stat)
|
||||
@ -598,9 +590,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
|
||||
struct hist_entry *he;
|
||||
int64_t cmp;
|
||||
u64 period = entry->stat.period;
|
||||
u64 weight = entry->stat.weight;
|
||||
u64 ins_lat = entry->stat.ins_lat;
|
||||
u64 p_stage_cyc = entry->stat.p_stage_cyc;
|
||||
bool leftmost = true;
|
||||
|
||||
p = &hists->entries_in->rb_root.rb_node;
|
||||
@ -619,11 +608,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
|
||||
|
||||
if (!cmp) {
|
||||
if (sample_self) {
|
||||
he_stat__add_period(&he->stat, period, weight, ins_lat, p_stage_cyc);
|
||||
he_stat__add_period(&he->stat, period);
|
||||
hist_entry__add_callchain_period(he, period);
|
||||
}
|
||||
if (symbol_conf.cumulate_callchain)
|
||||
he_stat__add_period(he->stat_acc, period, weight, ins_lat, p_stage_cyc);
|
||||
he_stat__add_period(he->stat_acc, period);
|
||||
|
||||
/*
|
||||
* This mem info was allocated from sample__resolve_mem
|
||||
@ -733,9 +722,6 @@ __hists__add_entry(struct hists *hists,
|
||||
.stat = {
|
||||
.nr_events = 1,
|
||||
.period = sample->period,
|
||||
.weight = sample->weight,
|
||||
.ins_lat = sample->ins_lat,
|
||||
.p_stage_cyc = sample->p_stage_cyc,
|
||||
},
|
||||
.parent = sym_parent,
|
||||
.filtered = symbol__parent_filter(sym_parent) | al->filtered,
|
||||
@ -748,6 +734,9 @@ __hists__add_entry(struct hists *hists,
|
||||
.raw_size = sample->raw_size,
|
||||
.ops = ops,
|
||||
.time = hist_time(sample->time),
|
||||
.weight = sample->weight,
|
||||
.ins_lat = sample->ins_lat,
|
||||
.p_stage_cyc = sample->p_stage_cyc,
|
||||
}, *he = hists__findnew_entry(hists, &entry, al, sample_self);
|
||||
|
||||
if (!hists->has_callchains && he && he->callchain_size != 0)
|
||||
|
@ -369,7 +369,6 @@ enum {
|
||||
};
|
||||
|
||||
void perf_hpp__init(void);
|
||||
void perf_hpp__column_unregister(struct perf_hpp_fmt *format);
|
||||
void perf_hpp__cancel_cumulate(void);
|
||||
void perf_hpp__setup_output_field(struct perf_hpp_list *list);
|
||||
void perf_hpp__reset_output_field(struct perf_hpp_list *list);
|
||||
|
@ -402,8 +402,10 @@ static int add_event_tool(struct list_head *list, int *idx,
|
||||
if (!evsel)
|
||||
return -ENOMEM;
|
||||
evsel->tool_event = tool_event;
|
||||
if (tool_event == PERF_TOOL_DURATION_TIME)
|
||||
evsel->unit = "ns";
|
||||
if (tool_event == PERF_TOOL_DURATION_TIME) {
|
||||
free((char *)evsel->unit);
|
||||
evsel->unit = strdup("ns");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1630,7 +1632,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
|
||||
if (parse_state->fake_pmu)
|
||||
return 0;
|
||||
|
||||
evsel->unit = info.unit;
|
||||
free((char *)evsel->unit);
|
||||
evsel->unit = strdup(info.unit);
|
||||
evsel->scale = info.scale;
|
||||
evsel->per_pkg = info.per_pkg;
|
||||
evsel->snapshot = info.snapshot;
|
||||
|
@ -1325,88 +1325,68 @@ struct sort_entry sort_mispredict = {
|
||||
.se_width_idx = HISTC_MISPREDICT,
|
||||
};
|
||||
|
||||
static u64 he_weight(struct hist_entry *he)
|
||||
{
|
||||
return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
sort__weight_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
return he_weight(left) - he_weight(right);
|
||||
return left->weight - right->weight;
|
||||
}
|
||||
|
||||
static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
|
||||
return repsep_snprintf(bf, size, "%-*llu", width, he->weight);
|
||||
}
|
||||
|
||||
struct sort_entry sort_local_weight = {
|
||||
.se_header = "Local Weight",
|
||||
.se_cmp = sort__local_weight_cmp,
|
||||
.se_cmp = sort__weight_cmp,
|
||||
.se_snprintf = hist_entry__local_weight_snprintf,
|
||||
.se_width_idx = HISTC_LOCAL_WEIGHT,
|
||||
};
|
||||
|
||||
static int64_t
|
||||
sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
return left->stat.weight - right->stat.weight;
|
||||
}
|
||||
|
||||
static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
|
||||
return repsep_snprintf(bf, size, "%-*llu", width,
|
||||
he->weight * he->stat.nr_events);
|
||||
}
|
||||
|
||||
struct sort_entry sort_global_weight = {
|
||||
.se_header = "Weight",
|
||||
.se_cmp = sort__global_weight_cmp,
|
||||
.se_cmp = sort__weight_cmp,
|
||||
.se_snprintf = hist_entry__global_weight_snprintf,
|
||||
.se_width_idx = HISTC_GLOBAL_WEIGHT,
|
||||
};
|
||||
|
||||
static u64 he_ins_lat(struct hist_entry *he)
|
||||
{
|
||||
return he->stat.nr_events ? he->stat.ins_lat / he->stat.nr_events : 0;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
sort__local_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
sort__ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
return he_ins_lat(left) - he_ins_lat(right);
|
||||
return left->ins_lat - right->ins_lat;
|
||||
}
|
||||
|
||||
static int hist_entry__local_ins_lat_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_snprintf(bf, size, "%-*u", width, he_ins_lat(he));
|
||||
return repsep_snprintf(bf, size, "%-*u", width, he->ins_lat);
|
||||
}
|
||||
|
||||
struct sort_entry sort_local_ins_lat = {
|
||||
.se_header = "Local INSTR Latency",
|
||||
.se_cmp = sort__local_ins_lat_cmp,
|
||||
.se_cmp = sort__ins_lat_cmp,
|
||||
.se_snprintf = hist_entry__local_ins_lat_snprintf,
|
||||
.se_width_idx = HISTC_LOCAL_INS_LAT,
|
||||
};
|
||||
|
||||
static int64_t
|
||||
sort__global_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
return left->stat.ins_lat - right->stat.ins_lat;
|
||||
}
|
||||
|
||||
static int hist_entry__global_ins_lat_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_snprintf(bf, size, "%-*u", width, he->stat.ins_lat);
|
||||
return repsep_snprintf(bf, size, "%-*u", width,
|
||||
he->ins_lat * he->stat.nr_events);
|
||||
}
|
||||
|
||||
struct sort_entry sort_global_ins_lat = {
|
||||
.se_header = "INSTR Latency",
|
||||
.se_cmp = sort__global_ins_lat_cmp,
|
||||
.se_cmp = sort__ins_lat_cmp,
|
||||
.se_snprintf = hist_entry__global_ins_lat_snprintf,
|
||||
.se_width_idx = HISTC_GLOBAL_INS_LAT,
|
||||
};
|
||||
@ -1414,13 +1394,13 @@ struct sort_entry sort_global_ins_lat = {
|
||||
static int64_t
|
||||
sort__global_p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right)
|
||||
{
|
||||
return left->stat.p_stage_cyc - right->stat.p_stage_cyc;
|
||||
return left->p_stage_cyc - right->p_stage_cyc;
|
||||
}
|
||||
|
||||
static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf,
|
||||
size_t size, unsigned int width)
|
||||
{
|
||||
return repsep_snprintf(bf, size, "%-*u", width, he->stat.p_stage_cyc);
|
||||
return repsep_snprintf(bf, size, "%-*u", width, he->p_stage_cyc);
|
||||
}
|
||||
|
||||
struct sort_entry sort_p_stage_cyc = {
|
||||
|
@ -49,9 +49,6 @@ struct he_stat {
|
||||
u64 period_us;
|
||||
u64 period_guest_sys;
|
||||
u64 period_guest_us;
|
||||
u64 weight;
|
||||
u64 ins_lat;
|
||||
u64 p_stage_cyc;
|
||||
u32 nr_events;
|
||||
};
|
||||
|
||||
@ -109,6 +106,9 @@ struct hist_entry {
|
||||
s32 socket;
|
||||
s32 cpu;
|
||||
u64 code_page_size;
|
||||
u64 weight;
|
||||
u64 ins_lat;
|
||||
u64 p_stage_cyc;
|
||||
u8 cpumode;
|
||||
u8 depth;
|
||||
|
||||
|
@ -379,32 +379,32 @@ fetch_kernel_version(unsigned int *puint, char *str,
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *perf_tip(const char *dirpath)
|
||||
int perf_tip(char **strp, const char *dirpath)
|
||||
{
|
||||
struct strlist *tips;
|
||||
struct str_node *node;
|
||||
char *tip = NULL;
|
||||
struct strlist_config conf = {
|
||||
.dirname = dirpath,
|
||||
.file_only = true,
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
*strp = NULL;
|
||||
tips = strlist__new("tips.txt", &conf);
|
||||
if (tips == NULL)
|
||||
return errno == ENOENT ? NULL :
|
||||
"Tip: check path of tips.txt or get more memory! ;-p";
|
||||
return -errno;
|
||||
|
||||
if (strlist__nr_entries(tips) == 0)
|
||||
goto out;
|
||||
|
||||
node = strlist__entry(tips, random() % strlist__nr_entries(tips));
|
||||
if (asprintf(&tip, "Tip: %s", node->s) < 0)
|
||||
tip = (char *)"Tip: get more memory! ;-)";
|
||||
if (asprintf(strp, "Tip: %s", node->s) < 0)
|
||||
ret = -ENOMEM;
|
||||
|
||||
out:
|
||||
strlist__delete(tips);
|
||||
|
||||
return tip;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *perf_exe(char *buf, int len)
|
||||
|
@ -39,7 +39,7 @@ int fetch_kernel_version(unsigned int *puint,
|
||||
#define KVER_FMT "%d.%d.%d"
|
||||
#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
|
||||
|
||||
const char *perf_tip(const char *dirpath);
|
||||
int perf_tip(char **strp, const char *dirpath);
|
||||
|
||||
#ifndef HAVE_SCHED_GETCPU_SUPPORT
|
||||
int sched_getcpu(void);
|
||||
|
Loading…
Reference in New Issue
Block a user