Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Thomas Gleixner: - fix for do_div() abuse on x86 - locking fix in perf core - a pile of (build) fixes and cleanups in perf tools * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (27 commits) perf/x86: Fix incorrect use of do_div() in NMI warning perf: Fix perf_lock_task_context() vs RCU perf: Remove WARN_ON_ONCE() check in __perf_event_enable() for valid scenario perf: Clone child context from parent context pmu perf script: Fix broken include in Context.xs perf tools: Fix -ldw/-lelf link test when static linking perf tools: Revert regression in configuration of Python support perf tools: Fix perf version generation perf stat: Fix per-socket output bug for uncore events perf symbols: Fix vdso list searching perf evsel: Fix missing increment in sample parsing perf tools: Update symbol_conf.nr_events when processing attribute events perf tools: Fix new_term() missing free on error path perf tools: Fix parse_events_terms() segfault on error path perf evsel: Fix count parameter to read call in event_format__new perf tools: fix a typo of a Power7 event name perf tools: Fix -x/--exclude-other option for report command perf evlist: Enhance perf_evlist__start_workload() perf record: Remove -f/--force option perf record: Remove -A/--append option ...
This commit is contained in:
commit
560ae37178
34 changed files with 154 additions and 163 deletions
|
@ -29,7 +29,7 @@ Description: Generic performance monitoring events
|
||||||
|
|
||||||
What: /sys/devices/cpu/events/PM_1PLUS_PPC_CMPL
|
What: /sys/devices/cpu/events/PM_1PLUS_PPC_CMPL
|
||||||
/sys/devices/cpu/events/PM_BRU_FIN
|
/sys/devices/cpu/events/PM_BRU_FIN
|
||||||
/sys/devices/cpu/events/PM_BRU_MPRED
|
/sys/devices/cpu/events/PM_BR_MPRED
|
||||||
/sys/devices/cpu/events/PM_CMPLU_STALL
|
/sys/devices/cpu/events/PM_CMPLU_STALL
|
||||||
/sys/devices/cpu/events/PM_CMPLU_STALL_BRU
|
/sys/devices/cpu/events/PM_CMPLU_STALL_BRU
|
||||||
/sys/devices/cpu/events/PM_CMPLU_STALL_DCACHE_MISS
|
/sys/devices/cpu/events/PM_CMPLU_STALL_DCACHE_MISS
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
#define PME_PM_LD_REF_L1 0xc880
|
#define PME_PM_LD_REF_L1 0xc880
|
||||||
#define PME_PM_LD_MISS_L1 0x400f0
|
#define PME_PM_LD_MISS_L1 0x400f0
|
||||||
#define PME_PM_BRU_FIN 0x10068
|
#define PME_PM_BRU_FIN 0x10068
|
||||||
#define PME_PM_BRU_MPRED 0x400f6
|
#define PME_PM_BR_MPRED 0x400f6
|
||||||
|
|
||||||
#define PME_PM_CMPLU_STALL_FXU 0x20014
|
#define PME_PM_CMPLU_STALL_FXU 0x20014
|
||||||
#define PME_PM_CMPLU_STALL_DIV 0x40014
|
#define PME_PM_CMPLU_STALL_DIV 0x40014
|
||||||
|
@ -349,7 +349,7 @@ static int power7_generic_events[] = {
|
||||||
[PERF_COUNT_HW_CACHE_REFERENCES] = PME_PM_LD_REF_L1,
|
[PERF_COUNT_HW_CACHE_REFERENCES] = PME_PM_LD_REF_L1,
|
||||||
[PERF_COUNT_HW_CACHE_MISSES] = PME_PM_LD_MISS_L1,
|
[PERF_COUNT_HW_CACHE_MISSES] = PME_PM_LD_MISS_L1,
|
||||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PME_PM_BRU_FIN,
|
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PME_PM_BRU_FIN,
|
||||||
[PERF_COUNT_HW_BRANCH_MISSES] = PME_PM_BRU_MPRED,
|
[PERF_COUNT_HW_BRANCH_MISSES] = PME_PM_BR_MPRED,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define C(x) PERF_COUNT_HW_CACHE_##x
|
#define C(x) PERF_COUNT_HW_CACHE_##x
|
||||||
|
@ -405,7 +405,7 @@ GENERIC_EVENT_ATTR(instructions, INST_CMPL);
|
||||||
GENERIC_EVENT_ATTR(cache-references, LD_REF_L1);
|
GENERIC_EVENT_ATTR(cache-references, LD_REF_L1);
|
||||||
GENERIC_EVENT_ATTR(cache-misses, LD_MISS_L1);
|
GENERIC_EVENT_ATTR(cache-misses, LD_MISS_L1);
|
||||||
GENERIC_EVENT_ATTR(branch-instructions, BRU_FIN);
|
GENERIC_EVENT_ATTR(branch-instructions, BRU_FIN);
|
||||||
GENERIC_EVENT_ATTR(branch-misses, BRU_MPRED);
|
GENERIC_EVENT_ATTR(branch-misses, BR_MPRED);
|
||||||
|
|
||||||
POWER_EVENT_ATTR(CYC, CYC);
|
POWER_EVENT_ATTR(CYC, CYC);
|
||||||
POWER_EVENT_ATTR(GCT_NOSLOT_CYC, GCT_NOSLOT_CYC);
|
POWER_EVENT_ATTR(GCT_NOSLOT_CYC, GCT_NOSLOT_CYC);
|
||||||
|
@ -414,7 +414,7 @@ POWER_EVENT_ATTR(INST_CMPL, INST_CMPL);
|
||||||
POWER_EVENT_ATTR(LD_REF_L1, LD_REF_L1);
|
POWER_EVENT_ATTR(LD_REF_L1, LD_REF_L1);
|
||||||
POWER_EVENT_ATTR(LD_MISS_L1, LD_MISS_L1);
|
POWER_EVENT_ATTR(LD_MISS_L1, LD_MISS_L1);
|
||||||
POWER_EVENT_ATTR(BRU_FIN, BRU_FIN)
|
POWER_EVENT_ATTR(BRU_FIN, BRU_FIN)
|
||||||
POWER_EVENT_ATTR(BRU_MPRED, BRU_MPRED);
|
POWER_EVENT_ATTR(BR_MPRED, BR_MPRED);
|
||||||
|
|
||||||
POWER_EVENT_ATTR(CMPLU_STALL_FXU, CMPLU_STALL_FXU);
|
POWER_EVENT_ATTR(CMPLU_STALL_FXU, CMPLU_STALL_FXU);
|
||||||
POWER_EVENT_ATTR(CMPLU_STALL_DIV, CMPLU_STALL_DIV);
|
POWER_EVENT_ATTR(CMPLU_STALL_DIV, CMPLU_STALL_DIV);
|
||||||
|
@ -449,7 +449,7 @@ static struct attribute *power7_events_attr[] = {
|
||||||
GENERIC_EVENT_PTR(LD_REF_L1),
|
GENERIC_EVENT_PTR(LD_REF_L1),
|
||||||
GENERIC_EVENT_PTR(LD_MISS_L1),
|
GENERIC_EVENT_PTR(LD_MISS_L1),
|
||||||
GENERIC_EVENT_PTR(BRU_FIN),
|
GENERIC_EVENT_PTR(BRU_FIN),
|
||||||
GENERIC_EVENT_PTR(BRU_MPRED),
|
GENERIC_EVENT_PTR(BR_MPRED),
|
||||||
|
|
||||||
POWER_EVENT_PTR(CYC),
|
POWER_EVENT_PTR(CYC),
|
||||||
POWER_EVENT_PTR(GCT_NOSLOT_CYC),
|
POWER_EVENT_PTR(GCT_NOSLOT_CYC),
|
||||||
|
@ -458,7 +458,7 @@ static struct attribute *power7_events_attr[] = {
|
||||||
POWER_EVENT_PTR(LD_REF_L1),
|
POWER_EVENT_PTR(LD_REF_L1),
|
||||||
POWER_EVENT_PTR(LD_MISS_L1),
|
POWER_EVENT_PTR(LD_MISS_L1),
|
||||||
POWER_EVENT_PTR(BRU_FIN),
|
POWER_EVENT_PTR(BRU_FIN),
|
||||||
POWER_EVENT_PTR(BRU_MPRED),
|
POWER_EVENT_PTR(BR_MPRED),
|
||||||
|
|
||||||
POWER_EVENT_PTR(CMPLU_STALL_FXU),
|
POWER_EVENT_PTR(CMPLU_STALL_FXU),
|
||||||
POWER_EVENT_PTR(CMPLU_STALL_DIV),
|
POWER_EVENT_PTR(CMPLU_STALL_DIV),
|
||||||
|
|
|
@ -111,7 +111,7 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2
|
||||||
*/
|
*/
|
||||||
list_for_each_entry_rcu(a, &desc->head, list) {
|
list_for_each_entry_rcu(a, &desc->head, list) {
|
||||||
u64 before, delta, whole_msecs;
|
u64 before, delta, whole_msecs;
|
||||||
int decimal_msecs, thishandled;
|
int remainder_ns, decimal_msecs, thishandled;
|
||||||
|
|
||||||
before = local_clock();
|
before = local_clock();
|
||||||
thishandled = a->handler(type, regs);
|
thishandled = a->handler(type, regs);
|
||||||
|
@ -123,8 +123,9 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
nmi_longest_ns = delta;
|
nmi_longest_ns = delta;
|
||||||
whole_msecs = do_div(delta, (1000 * 1000));
|
whole_msecs = delta;
|
||||||
decimal_msecs = do_div(delta, 1000) % 1000;
|
remainder_ns = do_div(whole_msecs, (1000 * 1000));
|
||||||
|
decimal_msecs = remainder_ns / 1000;
|
||||||
printk_ratelimited(KERN_INFO
|
printk_ratelimited(KERN_INFO
|
||||||
"INFO: NMI handler (%ps) took too long to run: "
|
"INFO: NMI handler (%ps) took too long to run: "
|
||||||
"%lld.%03d msecs\n", a->handler, whole_msecs,
|
"%lld.%03d msecs\n", a->handler, whole_msecs,
|
||||||
|
|
|
@ -947,8 +947,18 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
|
||||||
{
|
{
|
||||||
struct perf_event_context *ctx;
|
struct perf_event_context *ctx;
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
retry:
|
retry:
|
||||||
|
/*
|
||||||
|
* One of the few rules of preemptible RCU is that one cannot do
|
||||||
|
* rcu_read_unlock() while holding a scheduler (or nested) lock when
|
||||||
|
* part of the read side critical section was preemptible -- see
|
||||||
|
* rcu_read_unlock_special().
|
||||||
|
*
|
||||||
|
* Since ctx->lock nests under rq->lock we must ensure the entire read
|
||||||
|
* side critical section is non-preemptible.
|
||||||
|
*/
|
||||||
|
preempt_disable();
|
||||||
|
rcu_read_lock();
|
||||||
ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
|
ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
/*
|
/*
|
||||||
|
@ -964,6 +974,8 @@ retry:
|
||||||
raw_spin_lock_irqsave(&ctx->lock, *flags);
|
raw_spin_lock_irqsave(&ctx->lock, *flags);
|
||||||
if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
|
if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
|
||||||
raw_spin_unlock_irqrestore(&ctx->lock, *flags);
|
raw_spin_unlock_irqrestore(&ctx->lock, *flags);
|
||||||
|
rcu_read_unlock();
|
||||||
|
preempt_enable();
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,6 +985,7 @@ retry:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
preempt_enable();
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1950,7 +1963,16 @@ static int __perf_event_enable(void *info)
|
||||||
struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
|
struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!ctx->is_active))
|
/*
|
||||||
|
* There's a time window between 'ctx->is_active' check
|
||||||
|
* in perf_event_enable function and this place having:
|
||||||
|
* - IRQs on
|
||||||
|
* - ctx->lock unlocked
|
||||||
|
*
|
||||||
|
* where the task could be killed and 'ctx' deactivated
|
||||||
|
* by perf_event_exit_task.
|
||||||
|
*/
|
||||||
|
if (!ctx->is_active)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
raw_spin_lock(&ctx->lock);
|
raw_spin_lock(&ctx->lock);
|
||||||
|
@ -7465,7 +7487,7 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
|
||||||
* child.
|
* child.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
child_ctx = alloc_perf_context(event->pmu, child);
|
child_ctx = alloc_perf_context(parent_ctx->pmu, child);
|
||||||
if (!child_ctx)
|
if (!child_ctx)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,21 @@ include ../../scripts/Makefile.include
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC = $(CROSS_COMPILE)gcc
|
||||||
AR = $(CROSS_COMPILE)ar
|
AR = $(CROSS_COMPILE)ar
|
||||||
|
|
||||||
|
# Makefiles suck: This macro sets a default value of $(2) for the
|
||||||
|
# variable named by $(1), unless the variable has been set by
|
||||||
|
# environment or command line. This is necessary for CC and AR
|
||||||
|
# because make sets default values, so the simpler ?= approach
|
||||||
|
# won't work as expected.
|
||||||
|
define allow-override
|
||||||
|
$(if $(or $(findstring environment,$(origin $(1))),\
|
||||||
|
$(findstring command line,$(origin $(1)))),,\
|
||||||
|
$(eval $(1) = $(2)))
|
||||||
|
endef
|
||||||
|
|
||||||
|
# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
|
||||||
|
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
|
||||||
|
$(call allow-override,AR,$(CROSS_COMPILE)ar)
|
||||||
|
|
||||||
# guard against environment variables
|
# guard against environment variables
|
||||||
LIB_H=
|
LIB_H=
|
||||||
LIB_OBJS=
|
LIB_OBJS=
|
||||||
|
@ -14,7 +29,7 @@ LIB_OBJS += $(OUTPUT)debugfs.o
|
||||||
LIBFILE = liblk.a
|
LIBFILE = liblk.a
|
||||||
|
|
||||||
CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC
|
CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC
|
||||||
EXTLIBS = -lpthread -lrt -lelf -lm
|
EXTLIBS = -lelf -lpthread -lrt -lm
|
||||||
ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
|
ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
|
||||||
ALL_LDFLAGS = $(LDFLAGS)
|
ALL_LDFLAGS = $(LDFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
|
include ../../scripts/Makefile.include
|
||||||
include ../config/utilities.mak
|
include ../config/utilities.mak
|
||||||
|
|
||||||
OUTPUT := ./
|
|
||||||
ifeq ("$(origin O)", "command line")
|
|
||||||
ifneq ($(O),)
|
|
||||||
OUTPUT := $(O)/
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
MAN1_TXT= \
|
MAN1_TXT= \
|
||||||
$(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
|
$(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
|
||||||
$(wildcard perf-*.txt)) \
|
$(wildcard perf-*.txt)) \
|
||||||
|
@ -150,7 +144,7 @@ NO_SUBDIR = :
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(findstring $(MAKEFLAGS),s),s)
|
ifneq ($(findstring $(MAKEFLAGS),s),s)
|
||||||
ifndef V
|
ifneq ($(V),1)
|
||||||
QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@;
|
QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@;
|
||||||
QUIET_XMLTO = @echo ' ' XMLTO $@;
|
QUIET_XMLTO = @echo ' ' XMLTO $@;
|
||||||
QUIET_DB2TEXI = @echo ' ' DB2TEXI $@;
|
QUIET_DB2TEXI = @echo ' ' DB2TEXI $@;
|
||||||
|
@ -277,7 +271,7 @@ $(MAN_HTML): $(OUTPUT)%.html : %.txt
|
||||||
|
|
||||||
$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
|
$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
|
||||||
$(QUIET_XMLTO)$(RM) $@ && \
|
$(QUIET_XMLTO)$(RM) $@ && \
|
||||||
$(XMLTO) -o $(OUTPUT) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
|
$(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
|
||||||
|
|
||||||
$(OUTPUT)%.xml : %.txt
|
$(OUTPUT)%.xml : %.txt
|
||||||
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
|
||||||
|
|
|
@ -66,7 +66,7 @@ Furthermore, these tracepoints can be used to sample the workload as
|
||||||
well. For example the page allocations done by a 'git gc' can be
|
well. For example the page allocations done by a 'git gc' can be
|
||||||
captured the following way:
|
captured the following way:
|
||||||
|
|
||||||
titan:~/git> perf record -f -e kmem:mm_page_alloc -c 1 ./git gc
|
titan:~/git> perf record -e kmem:mm_page_alloc -c 1 ./git gc
|
||||||
Counting objects: 1148, done.
|
Counting objects: 1148, done.
|
||||||
Delta compression using up to 2 threads.
|
Delta compression using up to 2 threads.
|
||||||
Compressing objects: 100% (450/450), done.
|
Compressing objects: 100% (450/450), done.
|
||||||
|
@ -120,7 +120,7 @@ Furthermore, call-graph sampling can be done too, of page
|
||||||
allocations - to see precisely what kind of page allocations there
|
allocations - to see precisely what kind of page allocations there
|
||||||
are:
|
are:
|
||||||
|
|
||||||
titan:~/git> perf record -f -g -e kmem:mm_page_alloc -c 1 ./git gc
|
titan:~/git> perf record -g -e kmem:mm_page_alloc -c 1 ./git gc
|
||||||
Counting objects: 1148, done.
|
Counting objects: 1148, done.
|
||||||
Delta compression using up to 2 threads.
|
Delta compression using up to 2 threads.
|
||||||
Compressing objects: 100% (450/450), done.
|
Compressing objects: 100% (450/450), done.
|
||||||
|
|
|
@ -65,16 +65,10 @@ OPTIONS
|
||||||
-r::
|
-r::
|
||||||
--realtime=::
|
--realtime=::
|
||||||
Collect data with this RT SCHED_FIFO priority.
|
Collect data with this RT SCHED_FIFO priority.
|
||||||
|
|
||||||
-D::
|
-D::
|
||||||
--no-delay::
|
--no-delay::
|
||||||
Collect data without buffering.
|
Collect data without buffering.
|
||||||
-A::
|
|
||||||
--append::
|
|
||||||
Append to the output file to do incremental profiling.
|
|
||||||
|
|
||||||
-f::
|
|
||||||
--force::
|
|
||||||
Overwrite existing data file. (deprecated)
|
|
||||||
|
|
||||||
-c::
|
-c::
|
||||||
--count=::
|
--count=::
|
||||||
|
|
|
@ -121,17 +121,16 @@ SCRIPT_SH += perf-archive.sh
|
||||||
grep-libs = $(filter -l%,$(1))
|
grep-libs = $(filter -l%,$(1))
|
||||||
strip-libs = $(filter-out -l%,$(1))
|
strip-libs = $(filter-out -l%,$(1))
|
||||||
|
|
||||||
LK_PATH=$(LK_DIR)
|
|
||||||
|
|
||||||
ifneq ($(OUTPUT),)
|
ifneq ($(OUTPUT),)
|
||||||
TE_PATH=$(OUTPUT)
|
TE_PATH=$(OUTPUT)
|
||||||
ifneq ($(subdir),)
|
ifneq ($(subdir),)
|
||||||
LK_PATH=$(OUTPUT)$(LK_DIR)
|
LK_PATH=$(objtree)/lib/lk/
|
||||||
else
|
else
|
||||||
LK_PATH=$(OUTPUT)
|
LK_PATH=$(OUTPUT)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
TE_PATH=$(TRACE_EVENT_DIR)
|
TE_PATH=$(TRACE_EVENT_DIR)
|
||||||
|
LK_PATH=$(LK_DIR)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
|
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
|
||||||
|
|
|
@ -111,11 +111,11 @@ static double timeval2double(struct timeval *ts)
|
||||||
static void alloc_mem(void **dst, void **src, size_t length)
|
static void alloc_mem(void **dst, void **src, size_t length)
|
||||||
{
|
{
|
||||||
*dst = zalloc(length);
|
*dst = zalloc(length);
|
||||||
if (!dst)
|
if (!*dst)
|
||||||
die("memory allocation failed - maybe length is too large?\n");
|
die("memory allocation failed - maybe length is too large?\n");
|
||||||
|
|
||||||
*src = zalloc(length);
|
*src = zalloc(length);
|
||||||
if (!src)
|
if (!*src)
|
||||||
die("memory allocation failed - maybe length is too large?\n");
|
die("memory allocation failed - maybe length is too large?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ static double timeval2double(struct timeval *ts)
|
||||||
static void alloc_mem(void **dst, size_t length)
|
static void alloc_mem(void **dst, size_t length)
|
||||||
{
|
{
|
||||||
*dst = zalloc(length);
|
*dst = zalloc(length);
|
||||||
if (!dst)
|
if (!*dst)
|
||||||
die("memory allocation failed - maybe length is too large?\n");
|
die("memory allocation failed - maybe length is too large?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -607,7 +607,6 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
input_new = "perf.data.guest";
|
input_new = "perf.data.guest";
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol_conf.exclude_other = false;
|
|
||||||
if (symbol__init() < 0)
|
if (symbol__init() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
@ -708,7 +708,7 @@ static int parse_line_opt(const struct option *opt __maybe_unused,
|
||||||
static int __cmd_record(int argc, const char **argv)
|
static int __cmd_record(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
const char * const record_args[] = {
|
const char * const record_args[] = {
|
||||||
"record", "-a", "-R", "-f", "-c", "1",
|
"record", "-a", "-R", "-c", "1",
|
||||||
"-e", "kmem:kmalloc",
|
"-e", "kmem:kmalloc",
|
||||||
"-e", "kmem:kmalloc_node",
|
"-e", "kmem:kmalloc_node",
|
||||||
"-e", "kmem:kfree",
|
"-e", "kmem:kfree",
|
||||||
|
|
|
@ -878,7 +878,7 @@ static int __cmd_report(void)
|
||||||
static int __cmd_record(int argc, const char **argv)
|
static int __cmd_record(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
const char *record_args[] = {
|
const char *record_args[] = {
|
||||||
"record", "-R", "-f", "-m", "1024", "-c", "1",
|
"record", "-R", "-m", "1024", "-c", "1",
|
||||||
};
|
};
|
||||||
unsigned int rec_argc, i, j;
|
unsigned int rec_argc, i, j;
|
||||||
const char **rec_argv;
|
const char **rec_argv;
|
||||||
|
|
|
@ -61,11 +61,6 @@ static void __handle_on_exit_funcs(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum write_mode_t {
|
|
||||||
WRITE_FORCE,
|
|
||||||
WRITE_APPEND
|
|
||||||
};
|
|
||||||
|
|
||||||
struct perf_record {
|
struct perf_record {
|
||||||
struct perf_tool tool;
|
struct perf_tool tool;
|
||||||
struct perf_record_opts opts;
|
struct perf_record_opts opts;
|
||||||
|
@ -77,12 +72,8 @@ struct perf_record {
|
||||||
int output;
|
int output;
|
||||||
unsigned int page_size;
|
unsigned int page_size;
|
||||||
int realtime_prio;
|
int realtime_prio;
|
||||||
enum write_mode_t write_mode;
|
|
||||||
bool no_buildid;
|
bool no_buildid;
|
||||||
bool no_buildid_cache;
|
bool no_buildid_cache;
|
||||||
bool force;
|
|
||||||
bool file_new;
|
|
||||||
bool append_file;
|
|
||||||
long samples;
|
long samples;
|
||||||
off_t post_processing_offset;
|
off_t post_processing_offset;
|
||||||
};
|
};
|
||||||
|
@ -200,25 +191,6 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
|
||||||
signal(signr, SIG_DFL);
|
signal(signr, SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool perf_evlist__equal(struct perf_evlist *evlist,
|
|
||||||
struct perf_evlist *other)
|
|
||||||
{
|
|
||||||
struct perf_evsel *pos, *pair;
|
|
||||||
|
|
||||||
if (evlist->nr_entries != other->nr_entries)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
pair = perf_evlist__first(other);
|
|
||||||
|
|
||||||
list_for_each_entry(pos, &evlist->entries, node) {
|
|
||||||
if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
|
|
||||||
return false;
|
|
||||||
pair = perf_evsel__next(pair);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int perf_record__open(struct perf_record *rec)
|
static int perf_record__open(struct perf_record *rec)
|
||||||
{
|
{
|
||||||
char msg[512];
|
char msg[512];
|
||||||
|
@ -273,16 +245,7 @@ try_again:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec->file_new)
|
session->evlist = evlist;
|
||||||
session->evlist = evlist;
|
|
||||||
else {
|
|
||||||
if (!perf_evlist__equal(session->evlist, evlist)) {
|
|
||||||
fprintf(stderr, "incompatible append\n");
|
|
||||||
rc = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
perf_session__set_id_hdr_size(session);
|
perf_session__set_id_hdr_size(session);
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -415,23 +378,15 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||||
if (!strcmp(output_name, "-"))
|
if (!strcmp(output_name, "-"))
|
||||||
opts->pipe_output = true;
|
opts->pipe_output = true;
|
||||||
else if (!stat(output_name, &st) && st.st_size) {
|
else if (!stat(output_name, &st) && st.st_size) {
|
||||||
if (rec->write_mode == WRITE_FORCE) {
|
char oldname[PATH_MAX];
|
||||||
char oldname[PATH_MAX];
|
snprintf(oldname, sizeof(oldname), "%s.old",
|
||||||
snprintf(oldname, sizeof(oldname), "%s.old",
|
output_name);
|
||||||
output_name);
|
unlink(oldname);
|
||||||
unlink(oldname);
|
rename(output_name, oldname);
|
||||||
rename(output_name, oldname);
|
|
||||||
}
|
|
||||||
} else if (rec->write_mode == WRITE_APPEND) {
|
|
||||||
rec->write_mode = WRITE_FORCE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = O_CREAT|O_RDWR;
|
flags = O_CREAT|O_RDWR|O_TRUNC;
|
||||||
if (rec->write_mode == WRITE_APPEND)
|
|
||||||
rec->file_new = 0;
|
|
||||||
else
|
|
||||||
flags |= O_TRUNC;
|
|
||||||
|
|
||||||
if (opts->pipe_output)
|
if (opts->pipe_output)
|
||||||
output = STDOUT_FILENO;
|
output = STDOUT_FILENO;
|
||||||
|
@ -445,7 +400,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||||
rec->output = output;
|
rec->output = output;
|
||||||
|
|
||||||
session = perf_session__new(output_name, O_WRONLY,
|
session = perf_session__new(output_name, O_WRONLY,
|
||||||
rec->write_mode == WRITE_FORCE, false, NULL);
|
true, false, NULL);
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
pr_err("Not enough memory for reading perf file header\n");
|
pr_err("Not enough memory for reading perf file header\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -465,12 +420,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||||
if (!rec->opts.branch_stack)
|
if (!rec->opts.branch_stack)
|
||||||
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
|
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
|
||||||
|
|
||||||
if (!rec->file_new) {
|
|
||||||
err = perf_session__read_header(session, output);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_delete_session;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forks) {
|
if (forks) {
|
||||||
err = perf_evlist__prepare_workload(evsel_list, &opts->target,
|
err = perf_evlist__prepare_workload(evsel_list, &opts->target,
|
||||||
argv, opts->pipe_output,
|
argv, opts->pipe_output,
|
||||||
|
@ -498,7 +447,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||||
err = perf_header__write_pipe(output);
|
err = perf_header__write_pipe(output);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_delete_session;
|
goto out_delete_session;
|
||||||
} else if (rec->file_new) {
|
} else {
|
||||||
err = perf_session__write_header(session, evsel_list,
|
err = perf_session__write_header(session, evsel_list,
|
||||||
output, false);
|
output, false);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -869,8 +818,6 @@ static struct perf_record record = {
|
||||||
.uses_mmap = true,
|
.uses_mmap = true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.write_mode = WRITE_FORCE,
|
|
||||||
.file_new = true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
|
#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
|
||||||
|
@ -906,12 +853,8 @@ const struct option record_options[] = {
|
||||||
"collect raw sample records from all opened counters"),
|
"collect raw sample records from all opened counters"),
|
||||||
OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
|
OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
|
||||||
"system-wide collection from all CPUs"),
|
"system-wide collection from all CPUs"),
|
||||||
OPT_BOOLEAN('A', "append", &record.append_file,
|
|
||||||
"append to the output file to do incremental profiling"),
|
|
||||||
OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
|
OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
|
||||||
"list of cpus to monitor"),
|
"list of cpus to monitor"),
|
||||||
OPT_BOOLEAN('f', "force", &record.force,
|
|
||||||
"overwrite existing data file (deprecated)"),
|
|
||||||
OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
|
OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
|
||||||
OPT_STRING('o', "output", &record.output_name, "file",
|
OPT_STRING('o', "output", &record.output_name, "file",
|
||||||
"output file name"),
|
"output file name"),
|
||||||
|
@ -977,16 +920,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
if (!argc && perf_target__none(&rec->opts.target))
|
if (!argc && perf_target__none(&rec->opts.target))
|
||||||
usage_with_options(record_usage, record_options);
|
usage_with_options(record_usage, record_options);
|
||||||
|
|
||||||
if (rec->force && rec->append_file) {
|
|
||||||
ui__error("Can't overwrite and append at the same time."
|
|
||||||
" You need to choose between -f and -A");
|
|
||||||
usage_with_options(record_usage, record_options);
|
|
||||||
} else if (rec->append_file) {
|
|
||||||
rec->write_mode = WRITE_APPEND;
|
|
||||||
} else {
|
|
||||||
rec->write_mode = WRITE_FORCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nr_cgroups && !rec->opts.target.system_wide) {
|
if (nr_cgroups && !rec->opts.target.system_wide) {
|
||||||
ui__error("cgroup monitoring only available in"
|
ui__error("cgroup monitoring only available in"
|
||||||
" system-wide mode\n");
|
" system-wide mode\n");
|
||||||
|
|
|
@ -939,8 +939,7 @@ repeat:
|
||||||
*/
|
*/
|
||||||
if (!strstr(sort_order, "parent"))
|
if (!strstr(sort_order, "parent"))
|
||||||
sort_parent.elide = 1;
|
sort_parent.elide = 1;
|
||||||
} else
|
}
|
||||||
symbol_conf.exclude_other = false;
|
|
||||||
|
|
||||||
if (argc) {
|
if (argc) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1632,7 +1632,6 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
"record",
|
"record",
|
||||||
"-a",
|
"-a",
|
||||||
"-R",
|
"-R",
|
||||||
"-f",
|
|
||||||
"-m", "1024",
|
"-m", "1024",
|
||||||
"-c", "1",
|
"-c", "1",
|
||||||
"-e", "sched:sched_switch",
|
"-e", "sched:sched_switch",
|
||||||
|
|
|
@ -87,7 +87,7 @@ static int run_count = 1;
|
||||||
static bool no_inherit = false;
|
static bool no_inherit = false;
|
||||||
static bool scale = true;
|
static bool scale = true;
|
||||||
static enum aggr_mode aggr_mode = AGGR_GLOBAL;
|
static enum aggr_mode aggr_mode = AGGR_GLOBAL;
|
||||||
static pid_t child_pid = -1;
|
static volatile pid_t child_pid = -1;
|
||||||
static bool null_run = false;
|
static bool null_run = false;
|
||||||
static int detailed_run = 0;
|
static int detailed_run = 0;
|
||||||
static bool big_num = true;
|
static bool big_num = true;
|
||||||
|
@ -924,7 +924,7 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
|
||||||
static void print_aggr(char *prefix)
|
static void print_aggr(char *prefix)
|
||||||
{
|
{
|
||||||
struct perf_evsel *counter;
|
struct perf_evsel *counter;
|
||||||
int cpu, s, s2, id, nr;
|
int cpu, cpu2, s, s2, id, nr;
|
||||||
u64 ena, run, val;
|
u64 ena, run, val;
|
||||||
|
|
||||||
if (!(aggr_map || aggr_get_id))
|
if (!(aggr_map || aggr_get_id))
|
||||||
|
@ -936,7 +936,8 @@ static void print_aggr(char *prefix)
|
||||||
val = ena = run = 0;
|
val = ena = run = 0;
|
||||||
nr = 0;
|
nr = 0;
|
||||||
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
|
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
|
||||||
s2 = aggr_get_id(evsel_list->cpus, cpu);
|
cpu2 = perf_evsel__cpus(counter)->map[cpu];
|
||||||
|
s2 = aggr_get_id(evsel_list->cpus, cpu2);
|
||||||
if (s2 != id)
|
if (s2 != id)
|
||||||
continue;
|
continue;
|
||||||
val += counter->counts->cpu[cpu].val;
|
val += counter->counts->cpu[cpu].val;
|
||||||
|
@ -948,7 +949,7 @@ static void print_aggr(char *prefix)
|
||||||
fprintf(output, "%s", prefix);
|
fprintf(output, "%s", prefix);
|
||||||
|
|
||||||
if (run == 0 || ena == 0) {
|
if (run == 0 || ena == 0) {
|
||||||
aggr_printout(counter, cpu, nr);
|
aggr_printout(counter, id, nr);
|
||||||
|
|
||||||
fprintf(output, "%*s%s%*s",
|
fprintf(output, "%*s%s%*s",
|
||||||
csv_output ? 0 : 18,
|
csv_output ? 0 : 18,
|
||||||
|
@ -1148,13 +1149,34 @@ static void skip_signal(int signo)
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
signr = signo;
|
signr = signo;
|
||||||
|
/*
|
||||||
|
* render child_pid harmless
|
||||||
|
* won't send SIGTERM to a random
|
||||||
|
* process in case of race condition
|
||||||
|
* and fast PID recycling
|
||||||
|
*/
|
||||||
|
child_pid = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sig_atexit(void)
|
static void sig_atexit(void)
|
||||||
{
|
{
|
||||||
|
sigset_t set, oset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* avoid race condition with SIGCHLD handler
|
||||||
|
* in skip_signal() which is modifying child_pid
|
||||||
|
* goal is to avoid send SIGTERM to a random
|
||||||
|
* process
|
||||||
|
*/
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigaddset(&set, SIGCHLD);
|
||||||
|
sigprocmask(SIG_BLOCK, &set, &oset);
|
||||||
|
|
||||||
if (child_pid != -1)
|
if (child_pid != -1)
|
||||||
kill(child_pid, SIGTERM);
|
kill(child_pid, SIGTERM);
|
||||||
|
|
||||||
|
sigprocmask(SIG_SETMASK, &oset, NULL);
|
||||||
|
|
||||||
if (signr == -1)
|
if (signr == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1005,7 +1005,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
#ifdef SUPPORT_OLD_POWER_EVENTS
|
#ifdef SUPPORT_OLD_POWER_EVENTS
|
||||||
const char * const record_old_args[] = {
|
const char * const record_old_args[] = {
|
||||||
"record", "-a", "-R", "-f", "-c", "1",
|
"record", "-a", "-R", "-c", "1",
|
||||||
"-e", "power:power_start",
|
"-e", "power:power_start",
|
||||||
"-e", "power:power_end",
|
"-e", "power:power_end",
|
||||||
"-e", "power:power_frequency",
|
"-e", "power:power_frequency",
|
||||||
|
@ -1014,7 +1014,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
const char * const record_new_args[] = {
|
const char * const record_new_args[] = {
|
||||||
"record", "-a", "-R", "-f", "-c", "1",
|
"record", "-a", "-R", "-c", "1",
|
||||||
"-e", "power:cpu_frequency",
|
"-e", "power:cpu_frequency",
|
||||||
"-e", "power:cpu_idle",
|
"-e", "power:cpu_idle",
|
||||||
"-e", "sched:sched_wakeup",
|
"-e", "sched:sched_wakeup",
|
||||||
|
|
|
@ -1130,8 +1130,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
if (top.evlist == NULL)
|
if (top.evlist == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
symbol_conf.exclude_other = false;
|
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, top_usage, 0);
|
argc = parse_options(argc, argv, options, top_usage, 0);
|
||||||
if (argc)
|
if (argc)
|
||||||
usage_with_options(top_usage, options);
|
usage_with_options(top_usage, options);
|
||||||
|
|
|
@ -39,7 +39,7 @@ src-perf := $(srctree)/tools/perf
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(obj-perf),)
|
ifeq ($(obj-perf),)
|
||||||
obj-perf := $(objtree)
|
obj-perf := $(OUTPUT)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(obj-perf),)
|
ifneq ($(obj-perf),)
|
||||||
|
@ -85,7 +85,7 @@ CFLAGS += -Wall
|
||||||
CFLAGS += -Wextra
|
CFLAGS += -Wextra
|
||||||
CFLAGS += -std=gnu99
|
CFLAGS += -std=gnu99
|
||||||
|
|
||||||
EXTLIBS = -lpthread -lrt -lelf -lm
|
EXTLIBS = -lelf -lpthread -lrt -lm
|
||||||
|
|
||||||
ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
|
ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
|
||||||
CFLAGS += -fstack-protector-all
|
CFLAGS += -fstack-protector-all
|
||||||
|
@ -165,7 +165,7 @@ else
|
||||||
LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
|
LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
|
||||||
endif
|
endif
|
||||||
|
|
||||||
FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS)
|
FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lz -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS)
|
||||||
ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y)
|
ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y)
|
||||||
msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
|
msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
|
||||||
NO_DWARF := 1
|
NO_DWARF := 1
|
||||||
|
|
|
@ -173,7 +173,7 @@ _ge-abspath = $(if $(is-executable),$(1))
|
||||||
# Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
|
# Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
|
||||||
#
|
#
|
||||||
define get-executable-or-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
|
endef
|
||||||
_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
|
_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
|
||||||
_gea_warn = $(warning The path '$(1)' is not executable.)
|
_gea_warn = $(warning The path '$(1)' is not executable.)
|
||||||
|
@ -181,7 +181,7 @@ _gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
|
||||||
|
|
||||||
# try-cc
|
# try-cc
|
||||||
# Usage: option = $(call try-cc, source-to-build, cc-options, msg)
|
# Usage: option = $(call try-cc, source-to-build, cc-options, msg)
|
||||||
ifndef V
|
ifneq ($(V),1)
|
||||||
TRY_CC_OUTPUT= > /dev/null 2>&1
|
TRY_CC_OUTPUT= > /dev/null 2>&1
|
||||||
endif
|
endif
|
||||||
TRY_CC_MSG=echo " CHK $(3)" 1>&2;
|
TRY_CC_MSG=echo " CHK $(3)" 1>&2;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "perl.h"
|
#include "perl.h"
|
||||||
#include "XSUB.h"
|
#include "XSUB.h"
|
||||||
#include "../../../perf.h"
|
#include "../../../perf.h"
|
||||||
#include "../../../util/script-event.h"
|
#include "../../../util/trace-event.h"
|
||||||
|
|
||||||
MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context
|
MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context
|
||||||
PROTOTYPES: ENABLE
|
PROTOTYPES: ENABLE
|
||||||
|
|
|
@ -13,13 +13,22 @@ LF='
|
||||||
# First check if there is a .git to get the version from git describe
|
# First check if there is a .git to get the version from git describe
|
||||||
# otherwise try to get the version from the kernel Makefile
|
# otherwise try to get the version from the kernel Makefile
|
||||||
#
|
#
|
||||||
if test -d ../../.git -o -f ../../.git &&
|
CID=
|
||||||
VN=$(git tag 2>/dev/null | tail -1 | grep -E "v[0-9].[0-9]*")
|
TAG=
|
||||||
|
if test -d ../../.git -o -f ../../.git
|
||||||
then
|
then
|
||||||
VN=$(echo $VN"-g"$(git log -1 --abbrev=4 --pretty=format:"%h" HEAD))
|
TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null )
|
||||||
VN=$(echo "$VN" | sed -e 's/-/./g');
|
CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
|
||||||
else
|
fi
|
||||||
VN=$(MAKEFLAGS= make -sC ../.. kernelversion)
|
if test -z "$TAG"
|
||||||
|
then
|
||||||
|
TAG=$(MAKEFLAGS= make -sC ../.. kernelversion)
|
||||||
|
fi
|
||||||
|
VN="$TAG$CID"
|
||||||
|
if test -n "$CID"
|
||||||
|
then
|
||||||
|
# format version string, strip trailing zero of sublevel:
|
||||||
|
VN=$(echo "$VN" | sed -e 's/-/./g;s/\([0-9]*[.][0-9]*\)[.]0/\1/')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VN=$(expr "$VN" : v*'\(.*\)')
|
VN=$(expr "$VN" : v*'\(.*\)')
|
||||||
|
|
|
@ -513,10 +513,16 @@ void dsos__add(struct list_head *head, struct dso *dso)
|
||||||
list_add_tail(&dso->node, head);
|
list_add_tail(&dso->node, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dso *dsos__find(struct list_head *head, const char *name)
|
struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short)
|
||||||
{
|
{
|
||||||
struct dso *pos;
|
struct dso *pos;
|
||||||
|
|
||||||
|
if (cmp_short) {
|
||||||
|
list_for_each_entry(pos, head, node)
|
||||||
|
if (strcmp(pos->short_name, name) == 0)
|
||||||
|
return pos;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
list_for_each_entry(pos, head, node)
|
list_for_each_entry(pos, head, node)
|
||||||
if (strcmp(pos->long_name, name) == 0)
|
if (strcmp(pos->long_name, name) == 0)
|
||||||
return pos;
|
return pos;
|
||||||
|
@ -525,7 +531,7 @@ struct dso *dsos__find(struct list_head *head, const char *name)
|
||||||
|
|
||||||
struct dso *__dsos__findnew(struct list_head *head, const char *name)
|
struct dso *__dsos__findnew(struct list_head *head, const char *name)
|
||||||
{
|
{
|
||||||
struct dso *dso = dsos__find(head, name);
|
struct dso *dso = dsos__find(head, name, false);
|
||||||
|
|
||||||
if (!dso) {
|
if (!dso) {
|
||||||
dso = dso__new(name);
|
dso = dso__new(name);
|
||||||
|
|
|
@ -133,7 +133,8 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
|
||||||
const char *short_name, int dso_type);
|
const char *short_name, int dso_type);
|
||||||
|
|
||||||
void dsos__add(struct list_head *head, struct dso *dso);
|
void dsos__add(struct list_head *head, struct dso *dso);
|
||||||
struct dso *dsos__find(struct list_head *head, const char *name);
|
struct dso *dsos__find(struct list_head *head, const char *name,
|
||||||
|
bool cmp_short);
|
||||||
struct dso *__dsos__findnew(struct list_head *head, const char *name);
|
struct dso *__dsos__findnew(struct list_head *head, const char *name);
|
||||||
bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
|
bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
|
||||||
|
|
||||||
|
|
|
@ -821,6 +821,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
|
||||||
goto out_close_pipes;
|
goto out_close_pipes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC);
|
||||||
evlist->workload.cork_fd = go_pipe[1];
|
evlist->workload.cork_fd = go_pipe[1];
|
||||||
close(child_ready_pipe[0]);
|
close(child_ready_pipe[0]);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -837,10 +838,17 @@ out_close_ready_pipe:
|
||||||
int perf_evlist__start_workload(struct perf_evlist *evlist)
|
int perf_evlist__start_workload(struct perf_evlist *evlist)
|
||||||
{
|
{
|
||||||
if (evlist->workload.cork_fd > 0) {
|
if (evlist->workload.cork_fd > 0) {
|
||||||
|
char bf;
|
||||||
|
int ret;
|
||||||
/*
|
/*
|
||||||
* Remove the cork, let it rip!
|
* Remove the cork, let it rip!
|
||||||
*/
|
*/
|
||||||
return close(evlist->workload.cork_fd);
|
ret = write(evlist->workload.cork_fd, &bf, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
perror("enable to write to pipe");
|
||||||
|
|
||||||
|
close(evlist->workload.cork_fd);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -124,7 +124,7 @@ struct event_format *event_format__new(const char *sys, const char *name)
|
||||||
bf = nbf;
|
bf = nbf;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = read(fd, bf + size, BUFSIZ);
|
n = read(fd, bf + size, alloc_size - size);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
goto out_free_bf;
|
goto out_free_bf;
|
||||||
size += n;
|
size += n;
|
||||||
|
@ -1170,7 +1170,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
|
||||||
} else {
|
} else {
|
||||||
data->user_stack.data = (char *)array;
|
data->user_stack.data = (char *)array;
|
||||||
array += size / sizeof(*array);
|
array += size / sizeof(*array);
|
||||||
data->user_stack.size = *array;
|
data->user_stack.size = *array++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2303,29 +2303,18 @@ int perf_session__write_header(struct perf_session *session,
|
||||||
struct perf_file_header f_header;
|
struct perf_file_header f_header;
|
||||||
struct perf_file_attr f_attr;
|
struct perf_file_attr f_attr;
|
||||||
struct perf_header *header = &session->header;
|
struct perf_header *header = &session->header;
|
||||||
struct perf_evsel *evsel, *pair = NULL;
|
struct perf_evsel *evsel;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
lseek(fd, sizeof(f_header), SEEK_SET);
|
lseek(fd, sizeof(f_header), SEEK_SET);
|
||||||
|
|
||||||
if (session->evlist != evlist)
|
|
||||||
pair = perf_evlist__first(session->evlist);
|
|
||||||
|
|
||||||
list_for_each_entry(evsel, &evlist->entries, node) {
|
list_for_each_entry(evsel, &evlist->entries, node) {
|
||||||
evsel->id_offset = lseek(fd, 0, SEEK_CUR);
|
evsel->id_offset = lseek(fd, 0, SEEK_CUR);
|
||||||
err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
|
err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
out_err_write:
|
|
||||||
pr_debug("failed to write perf header\n");
|
pr_debug("failed to write perf header\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (session->evlist != evlist) {
|
|
||||||
err = do_write(fd, pair->id, pair->ids * sizeof(u64));
|
|
||||||
if (err < 0)
|
|
||||||
goto out_err_write;
|
|
||||||
evsel->ids += pair->ids;
|
|
||||||
pair = perf_evsel__next(pair);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header->attr_offset = lseek(fd, 0, SEEK_CUR);
|
header->attr_offset = lseek(fd, 0, SEEK_CUR);
|
||||||
|
@ -2967,6 +2956,8 @@ int perf_event__process_attr(union perf_event *event,
|
||||||
perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
|
perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
symbol_conf.nr_events = evlist->nr_entries;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -860,7 +860,8 @@ int parse_events_terms(struct list_head *terms, const char *str)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_events__free_terms(data.terms);
|
if (data.terms)
|
||||||
|
parse_events__free_terms(data.terms);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1183,6 +1184,7 @@ static int new_term(struct parse_events_term **_term, int type_val,
|
||||||
term->val.str = str;
|
term->val.str = str;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
free(term);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ int vmlinux_path__nr_entries;
|
||||||
char **vmlinux_path;
|
char **vmlinux_path;
|
||||||
|
|
||||||
struct symbol_conf symbol_conf = {
|
struct symbol_conf symbol_conf = {
|
||||||
.exclude_other = true,
|
|
||||||
.use_modules = true,
|
.use_modules = true,
|
||||||
.try_vmlinux_path = true,
|
.try_vmlinux_path = true,
|
||||||
.annotate_src = true,
|
.annotate_src = true,
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <sys/ttydefaults.h>
|
#include <sys/ttydefaults.h>
|
||||||
#include <lk/debugfs.h>
|
#include <lk/debugfs.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
extern const char *graph_line;
|
extern const char *graph_line;
|
||||||
extern const char *graph_dotted_line;
|
extern const char *graph_dotted_line;
|
||||||
|
@ -274,6 +275,5 @@ void dump_stack(void);
|
||||||
|
|
||||||
extern unsigned int page_size;
|
extern unsigned int page_size;
|
||||||
|
|
||||||
struct winsize;
|
|
||||||
void get_term_dimensions(struct winsize *ws);
|
void get_term_dimensions(struct winsize *ws);
|
||||||
#endif /* GIT_COMPAT_UTIL_H */
|
#endif /* GIT_COMPAT_UTIL_H */
|
||||||
|
|
|
@ -91,7 +91,7 @@ void vdso__exit(void)
|
||||||
|
|
||||||
struct dso *vdso__dso_findnew(struct list_head *head)
|
struct dso *vdso__dso_findnew(struct list_head *head)
|
||||||
{
|
{
|
||||||
struct dso *dso = dsos__find(head, VDSO__MAP_NAME);
|
struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true);
|
||||||
|
|
||||||
if (!dso) {
|
if (!dso) {
|
||||||
char *file;
|
char *file;
|
||||||
|
|
|
@ -59,7 +59,7 @@ QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
|
||||||
QUIET_SUBDIR1 =
|
QUIET_SUBDIR1 =
|
||||||
|
|
||||||
ifneq ($(findstring $(MAKEFLAGS),s),s)
|
ifneq ($(findstring $(MAKEFLAGS),s),s)
|
||||||
ifndef V
|
ifneq ($(V),1)
|
||||||
QUIET_CC = @echo ' ' CC $@;
|
QUIET_CC = @echo ' ' CC $@;
|
||||||
QUIET_AR = @echo ' ' AR $@;
|
QUIET_AR = @echo ' ' AR $@;
|
||||||
QUIET_LINK = @echo ' ' LINK $@;
|
QUIET_LINK = @echo ' ' LINK $@;
|
||||||
|
|
Loading…
Add table
Reference in a new issue