Commit 560ae371 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 4fa109b1 baf64b85
...@@ -29,7 +29,7 @@ Description: Generic performance monitoring events ...@@ -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 @@ ...@@ -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[] = { ...@@ -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); ...@@ -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); ...@@ -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[] = { ...@@ -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[] = { ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) ...@@ -964,6 +974,8 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
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 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) ...@@ -973,6 +985,7 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
} }
} }
rcu_read_unlock(); rcu_read_unlock();
preempt_enable();
return ctx; return ctx;
} }
...@@ -1950,7 +1963,16 @@ static int __perf_event_enable(void *info) ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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)
......
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 = : ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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) ...@@ -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 @@ static int perf_record__open(struct perf_record *rec) ...@@ -273,16 +245,7 @@ static int perf_record__open(struct perf_record *rec)
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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[] = { ...@@ -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) ...@@ -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 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -939,8 +939,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
*/ */
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) ...@@ -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; ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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)) ...@@ -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)) ...@@ -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 @@ ...@@ -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=' ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, ...@@ -837,10 +838,17 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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; ...@@ -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 @@ ...@@ -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); ...@@ -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) ...@@ -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 ...@@ -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 $@;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment