Commit aaf045f7 authored by Steven Rostedt's avatar Steven Rostedt Committed by Frederic Weisbecker

perf: Have perf use the new libtraceevent.a library

The event parsing code in perf was originally copied from trace-cmd
but never was kept up-to-date with the changes that was done there.
The trace-cmd libtraceevent.a code is much more mature than what is
currently in perf.

This updates the code to use wrappers to handle the calls to the
new event parsing code. The new code requires a handle to be pass
around, which removes the global event variables and allows
more than one event structure to be read from different files
(and different machines).

But perf still has the old global events and the code throughout
perf does not yet have a nice way to pass around a handle.
A global 'pevent' has been made for perf and the old calls have
been created as wrappers to the new event parsing code that uses
the global pevent.

With this change, perf can later incorporate the pevent handle into
the perf structures and allow more than one file to be read and
compared, that contains different events.
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent 668fe01f
......@@ -149,7 +149,7 @@ endif
### --- END CONFIGURATION SECTION ---
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(EVENT_PARSE_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =
# Guard against environment variables
......@@ -179,7 +179,15 @@ $(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
EVENT_PARSE_DIR = ../lib/traceevent/
LIBTRACEEVENT = $(OUTPUT)$(EVENT_PARSE_DIR)libtraceevent.a
ifeq ("$(origin O)", "command line")
EP_PATH=$(OUTPUT)/
else
EP_PATH=$(EVENT_PARSE_DIR)/
endif
LIBPARSEVENT = $(EP_PATH)libtraceevent.a
EP_LIB := -L$(EP_PATH) -ltraceevent
#
# Single 'perf' binary right now:
......@@ -295,7 +303,6 @@ LIB_H += util/hist.h
LIB_H += util/thread.h
LIB_H += util/thread_map.h
LIB_H += util/trace-event.h
LIB_H += util/trace-parse-events.h
LIB_H += util/probe-finder.h
LIB_H += util/dwarf-aux.h
LIB_H += util/probe-event.h
......@@ -358,7 +365,6 @@ LIB_OBJS += $(OUTPUT)util/pmu-bison.o
LIB_OBJS += $(OUTPUT)util/trace-event-read.o
LIB_OBJS += $(OUTPUT)util/trace-event-info.o
LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
LIB_OBJS += $(OUTPUT)util/trace-parse-events.o
LIB_OBJS += $(OUTPUT)util/svghelper.o
LIB_OBJS += $(OUTPUT)util/sort.o
LIB_OBJS += $(OUTPUT)util/hist.o
......@@ -402,7 +408,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
BUILTIN_OBJS += $(OUTPUT)builtin-test.o
BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
PERFLIBS = $(LIB_FILE)
PERFLIBS = $(LIB_FILE) $(LIBPARSEVENT)
# Files needed for the python binding, perf.so
# pyrf is just an internal name needed for all those wrappers.
......@@ -699,7 +705,7 @@ $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
$(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) $(LIBTRACEEVENT)
$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \
$(BUILTIN_OBJS) $(LIBS) -o $@
......@@ -806,7 +812,7 @@ $(LIB_FILE): $(LIB_OBJS)
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
# libparsevent.a
$(LIBTRACEEVENT):
$(LIBPARSEVENT):
make -C $(EVENT_PARSE_DIR) $(COMMAND_O) libtraceevent.a
help:
......
......@@ -192,7 +192,7 @@ static void insert_caller_stat(unsigned long call_site,
}
static void process_alloc_event(void *data,
struct event *event,
struct event_format *event,
int cpu,
u64 timestamp __used,
struct thread *thread __used,
......@@ -253,7 +253,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr,
}
static void process_free_event(void *data,
struct event *event,
struct event_format *event,
int cpu,
u64 timestamp __used,
struct thread *thread __used)
......@@ -281,7 +281,7 @@ static void process_free_event(void *data,
static void process_raw_event(union perf_event *raw_event __used, void *data,
int cpu, u64 timestamp, struct thread *thread)
{
struct event *event;
struct event_format *event;
int type;
type = trace_parse_common_type(data);
......
......@@ -356,25 +356,25 @@ struct trace_release_event {
struct trace_lock_handler {
void (*acquire_event)(struct trace_acquire_event *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*acquired_event)(struct trace_acquired_event *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*contended_event)(struct trace_contended_event *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*release_event)(struct trace_release_event *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
......@@ -416,7 +416,7 @@ enum acquire_flags {
static void
report_lock_acquire_event(struct trace_acquire_event *acquire_event,
struct event *__event __used,
struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -480,7 +480,7 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
static void
report_lock_acquired_event(struct trace_acquired_event *acquired_event,
struct event *__event __used,
struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -536,7 +536,7 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event,
static void
report_lock_contended_event(struct trace_contended_event *contended_event,
struct event *__event __used,
struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -583,7 +583,7 @@ report_lock_contended_event(struct trace_contended_event *contended_event,
static void
report_lock_release_event(struct trace_release_event *release_event,
struct event *__event __used,
struct event_format *__event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -647,7 +647,7 @@ static struct trace_lock_handler *trace_handler;
static void
process_lock_acquire_event(void *data,
struct event *event __used,
struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -666,7 +666,7 @@ process_lock_acquire_event(void *data,
static void
process_lock_acquired_event(void *data,
struct event *event __used,
struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -684,7 +684,7 @@ process_lock_acquired_event(void *data,
static void
process_lock_contended_event(void *data,
struct event *event __used,
struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -702,7 +702,7 @@ process_lock_contended_event(void *data,
static void
process_lock_release_event(void *data,
struct event *event __used,
struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -721,7 +721,7 @@ process_lock_release_event(void *data,
static void
process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
{
struct event *event;
struct event_format *event;
int type;
type = trace_parse_common_type(data);
......
......@@ -728,34 +728,34 @@ struct trace_migrate_task_event {
struct trace_sched_handler {
void (*switch_event)(struct trace_switch_event *,
struct machine *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*runtime_event)(struct trace_runtime_event *,
struct machine *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*wakeup_event)(struct trace_wakeup_event *,
struct machine *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*fork_event)(struct trace_fork_event *,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
void (*migrate_task_event)(struct trace_migrate_task_event *,
struct machine *machine,
struct event *,
struct event_format *,
int cpu,
u64 timestamp,
struct thread *thread);
......@@ -765,7 +765,7 @@ struct trace_sched_handler {
static void
replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
struct machine *machine __used,
struct event *event,
struct event_format *event,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -792,7 +792,7 @@ static u64 cpu_last_switched[MAX_CPUS];
static void
replay_switch_event(struct trace_switch_event *switch_event,
struct machine *machine __used,
struct event *event,
struct event_format *event,
int cpu,
u64 timestamp,
struct thread *thread __used)
......@@ -835,7 +835,7 @@ replay_switch_event(struct trace_switch_event *switch_event,
static void
replay_fork_event(struct trace_fork_event *fork_event,
struct event *event,
struct event_format *event,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -944,7 +944,7 @@ static void thread_atoms_insert(struct thread *thread)
static void
latency_fork_event(struct trace_fork_event *fork_event __used,
struct event *event __used,
struct event_format *event __used,
int cpu __used,
u64 timestamp __used,
struct thread *thread __used)
......@@ -1026,7 +1026,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
static void
latency_switch_event(struct trace_switch_event *switch_event,
struct machine *machine,
struct event *event __used,
struct event_format *event __used,
int cpu,
u64 timestamp,
struct thread *thread __used)
......@@ -1079,7 +1079,7 @@ latency_switch_event(struct trace_switch_event *switch_event,
static void
latency_runtime_event(struct trace_runtime_event *runtime_event,
struct machine *machine,
struct event *event __used,
struct event_format *event __used,
int cpu,
u64 timestamp,
struct thread *this_thread __used)
......@@ -1102,7 +1102,7 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
static void
latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
struct machine *machine,
struct event *__event __used,
struct event_format *__event __used,
int cpu __used,
u64 timestamp,
struct thread *thread __used)
......@@ -1150,7 +1150,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
static void
latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
struct machine *machine,
struct event *__event __used,
struct event_format *__event __used,
int cpu __used,
u64 timestamp,
struct thread *thread __used)
......@@ -1361,7 +1361,7 @@ static struct trace_sched_handler *trace_handler;
static void
process_sched_wakeup_event(struct perf_tool *tool __used,
struct event *event,
struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
......@@ -1398,7 +1398,7 @@ static char next_shortname2 = '0';
static void
map_switch_event(struct trace_switch_event *switch_event,
struct machine *machine,
struct event *event __used,
struct event_format *event __used,
int this_cpu,
u64 timestamp,
struct thread *thread __used)
......@@ -1476,7 +1476,7 @@ map_switch_event(struct trace_switch_event *switch_event,
static void
process_sched_switch_event(struct perf_tool *tool __used,
struct event *event,
struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
......@@ -1512,7 +1512,7 @@ process_sched_switch_event(struct perf_tool *tool __used,
static void
process_sched_runtime_event(struct perf_tool *tool __used,
struct event *event,
struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
......@@ -1532,7 +1532,7 @@ process_sched_runtime_event(struct perf_tool *tool __used,
static void
process_sched_fork_event(struct perf_tool *tool __used,
struct event *event,
struct event_format *event,
struct perf_sample *sample,
struct machine *machine __used,
struct thread *thread)
......@@ -1554,7 +1554,7 @@ process_sched_fork_event(struct perf_tool *tool __used,
static void
process_sched_exit_event(struct perf_tool *tool __used,
struct event *event,
struct event_format *event,
struct perf_sample *sample __used,
struct machine *machine __used,
struct thread *thread __used)
......@@ -1565,7 +1565,7 @@ process_sched_exit_event(struct perf_tool *tool __used,
static void
process_sched_migrate_task_event(struct perf_tool *tool __used,
struct event *event,
struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread)
......@@ -1586,7 +1586,7 @@ process_sched_migrate_task_event(struct perf_tool *tool __used,
sample->time, thread);
}
typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event,
typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event_format *event,
struct perf_sample *sample,
struct machine *machine,
struct thread *thread);
......
......@@ -261,7 +261,7 @@ static void print_sample_start(struct perf_sample *sample,
struct perf_event_attr *attr)
{
int type;
struct event *event;
struct event_format *event;
const char *evname = NULL;
unsigned long secs;
unsigned long usecs;
......
......@@ -37,7 +37,7 @@ PyMODINIT_FUNC initperf_trace_context(void);
#define FTRACE_MAX_EVENT \
((1 << (sizeof(unsigned short) * 8)) - 1)
struct event *events[FTRACE_MAX_EVENT];
struct event_format *events[FTRACE_MAX_EVENT];
#define MAX_FIELDS 64
#define N_COMMON_FIELDS 7
......@@ -136,7 +136,7 @@ static void define_field(enum print_arg_type field_type,
Py_DECREF(t);
}
static void define_event_symbols(struct event *event,
static void define_event_symbols(struct event_format *event,
const char *ev_name,
struct print_arg *args)
{
......@@ -178,6 +178,10 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->op.right);
break;
default:
/* gcc warns for these? */
case PRINT_BSTRING:
case PRINT_DYNAMIC_ARRAY:
case PRINT_FUNC:
/* we should warn... */
return;
}
......@@ -186,10 +190,10 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->next);
}
static inline struct event *find_cache_event(int type)
static inline struct event_format *find_cache_event(int type)
{
static char ev_name[256];
struct event *event;
struct event_format *event;
if (events[type])
return events[type];
......@@ -216,7 +220,7 @@ static void python_process_event(union perf_event *pevent __unused,
struct format_field *field;
unsigned long long val;
unsigned long s, ns;
struct event *event;
struct event_format *event;
unsigned n = 0;
int type;
int pid;
......@@ -436,7 +440,7 @@ static int python_stop_script(void)
static int python_generate_script(const char *outfile)
{
struct event *event = NULL;
struct event_format *event = NULL;
struct format_field *f;
char fname[PATH_MAX];
int not_first, count;
......
......@@ -68,7 +68,7 @@ struct events {
};
void *malloc_or_die(unsigned int size)
static void *malloc_or_die(unsigned int size)
{
void *data;
......@@ -448,6 +448,8 @@ static void tracing_data_header(void)
else
buf[0] = 0;
read_trace_init(buf[0], buf[0]);
write_or_die(buf, 1);
/* save size of long */
......
/*
* Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "../perf.h"
#include "util.h"
#include "trace-event.h"
int common_pc(struct scripting_context *context)
int header_page_size_size;
int header_page_ts_size;
int header_page_data_offset;
struct pevent *perf_pevent;
static struct pevent *pevent;
bool latency_format;
int read_trace_init(int file_bigendian, int host_bigendian)
{
return parse_common_pc(context->event_data);
if (pevent)
return 0;
perf_pevent = pevent_alloc();
pevent = perf_pevent;
pevent_set_file_bigendian(pevent, file_bigendian);
pevent_set_host_bigendian(pevent, host_bigendian);
return 0;
}
int common_flags(struct scripting_context *context)
static int get_common_field(struct scripting_context *context,
int *offset, int *size, const char *type)
{
return parse_common_flags(context->event_data);
struct event_format *event;
struct format_field *field;
if (!*size) {
if (!pevent->events)
return 0;
event = pevent->events[0];
field = pevent_find_common_field(event, type);
if (!field)
return 0;
*offset = field->offset;
*size = field->size;
}
return pevent_read_number(pevent, context->event_data + *offset, *size);
}
int common_lock_depth(struct scripting_context *context)
{
return parse_common_lock_depth(context->event_data);
static int offset;
static int size;
int ret;
ret = get_common_field(context, &size, &offset,
"common_lock_depth");
if (ret < 0)
return -1;
return ret;
}
int common_flags(struct scripting_context *context)
{
static int offset;
static int size;
int ret;
ret = get_common_field(context, &size, &offset,
"common_flags");
if (ret < 0)
return -1;
return ret;
}
int common_pc(struct scripting_context *context)
{
static int offset;
static int size;
int ret;
ret = get_common_field(context, &size, &offset,
"common_preempt_count");
if (ret < 0)
return -1;
return ret;
}
unsigned long long
raw_field_value(struct event_format *event, const char *name, void *data)
{
struct format_field *field;
unsigned long long val;
field = pevent_find_any_field(event, name);
if (!field)
return 0ULL;
pevent_read_number_field(field, data, &val);
return val;
}
void *raw_field_ptr(struct event_format *event, const char *name, void *data)
{
struct format_field *field;
field = pevent_find_any_field(event, name);
if (!field)
return NULL;
if (field->flags & FIELD_IS_DYNAMIC) {
int offset;
offset = *(int *)(data + field->offset);
offset &= 0xffff;
return data + offset;
}
return data + field->offset;
}
int trace_parse_common_type(void *data)
{
struct record record;
record.data = data;
return pevent_data_type(pevent, &record);
}
int trace_parse_common_pid(void *data)
{
struct record record;
record.data = data;
return pevent_data_pid(pevent, &record);
}
unsigned long long read_size(void *ptr, int size)
{
return pevent_read_number(pevent, ptr, size);
}
struct event_format *trace_find_event(int type)
{
return pevent_find_event(pevent, type);
}
void print_trace_event(int cpu, void *data, int size)
{
struct event_format *event;
struct record record;
struct trace_seq s;
int type;
type = trace_parse_common_type(data);
event = trace_find_event(type);
if (!event) {
warning("ug! no event found for type %d", type);
return;
}
memset(&record, 0, sizeof(record));
record.cpu = cpu;
record.size = size;
record.data = data;
trace_seq_init(&s);
pevent_print_event(pevent, &s, &record);
trace_seq_do_printf(&s);
printf("\n");
}
void print_event(int cpu, void *data, int size, unsigned long long nsecs,
char *comm)
{
struct record record;
struct trace_seq s;
int pid;
pevent->latency_format = latency_format;
record.ts = nsecs;
record.cpu = cpu;
record.size = size;
record.data = data;
pid = pevent_data_pid(pevent, &record);
if (!pevent_pid_is_registered(pevent, pid))
pevent_register_comm(pevent, comm, pid);
trace_seq_init(&s);
pevent_print_event(pevent, &s, &record);
trace_seq_do_printf(&s);
printf("\n");
}
void parse_proc_kallsyms(char *file, unsigned int size __unused)
{
unsigned long long addr;
char *func;
char *line;
char *next = NULL;
char *addr_str;
char *mod;
char ch;
line = strtok_r(file, "\n", &next);
while (line) {
mod = NULL;
sscanf(line, "%as %c %as\t[%as",
(float *)(void *)&addr_str, /* workaround gcc warning */
&ch, (float *)(void *)&func, (float *)(void *)&mod);
addr = strtoull(addr_str, NULL, 16);
free(addr_str);
/* truncate the extra ']' */
if (mod)
mod[strlen(mod) - 1] = 0;
pevent_register_function(pevent, func, addr, mod);
free(func);
free(mod);
line = strtok_r(NULL, "\n", &next);
}
}
void parse_ftrace_printk(char *file, unsigned int size __unused)
{
unsigned long long addr;
char *printk;
char *line;
char *next = NULL;
char *addr_str;
char *fmt;
line = strtok_r(file, "\n", &next);
while (line) {
addr_str = strtok_r(line, ":", &fmt);
if (!addr_str) {
warning("printk format with empty entry");
break;
}
addr = strtoull(addr_str, NULL, 16);
/* fmt still has a space, skip it */
printk = strdup(fmt+1);
line = strtok_r(NULL, "\n", &next);
pevent_register_print_string(pevent, printk, addr);
}
}
int parse_ftrace_file(char *buf, unsigned long size)
{
return pevent_parse_event(pevent, buf, size, "ftrace");
}
int parse_event_file(char *buf, unsigned long size, char *sys)
{
return pevent_parse_event(pevent, buf, size, sys);
}
struct event_format *trace_find_next_event(struct event_format *event)
{
static int idx;
if (!pevent->events)
return NULL;
if (!event) {
idx = 0;
return pevent->events[0];
}
if (idx < pevent->nr_events && event == pevent->events[idx]) {
idx++;
if (idx == pevent->nr_events)
return NULL;
return pevent->events[idx];
}
for (idx = 1; idx < pevent->nr_events; idx++) {
if (event == pevent->events[idx - 1])
return pevent->events[idx];
}
return NULL;
}
struct flag {
const char *name;
unsigned long long value;
};
static const struct flag flags[] = {
{ "HI_SOFTIRQ", 0 },
{ "TIMER_SOFTIRQ", 1 },
{ "NET_TX_SOFTIRQ", 2 },
{ "NET_RX_SOFTIRQ", 3 },
{ "BLOCK_SOFTIRQ", 4 },
{ "BLOCK_IOPOLL_SOFTIRQ", 5 },
{ "TASKLET_SOFTIRQ", 6 },
{ "SCHED_SOFTIRQ", 7 },
{ "HRTIMER_SOFTIRQ", 8 },
{ "RCU_SOFTIRQ", 9 },
{ "HRTIMER_NORESTART", 0 },
{ "HRTIMER_RESTART", 1 },
};
unsigned long long eval_flag(const char *flag)
{
int i;
/*
* Some flags in the format files do not get converted.
* If the flag is not numeric, see if it is something that
* we already know about.
*/
if (isdigit(flag[0]))
return strtoull(flag, NULL, 0);
for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
if (strcmp(flags[i].name, flag) == 0)
return flags[i].value;
return 0;
}
......@@ -52,6 +52,16 @@ static unsigned long page_size;
static ssize_t calc_data_size;
static bool repipe;
static void *malloc_or_die(int size)
{
void *ret;
ret = malloc(size);
if (!ret)
die("malloc");
return ret;
}
static int do_read(int fd, void *buf, int size)
{
int rsize = size;
......@@ -109,7 +119,7 @@ static unsigned int read4(void)
unsigned int data;
read_or_die(&data, 4);
return __data2host4(data);
return __data2host4(perf_pevent, data);
}
static unsigned long long read8(void)
......@@ -117,7 +127,7 @@ static unsigned long long read8(void)
unsigned long long data;
read_or_die(&data, 8);
return __data2host8(data);
return __data2host8(perf_pevent, data);
}
static char *read_string(void)
......@@ -389,15 +399,15 @@ struct record *trace_peek_data(int cpu)
/* FIXME: handle header page */
if (header_page_ts_size != 8)
die("expected a long long type for timestamp");
cpu_data[cpu].timestamp = data2host8(ptr);
cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr);
ptr += 8;
switch (header_page_size_size) {
case 4:
cpu_data[cpu].page_size = data2host4(ptr);
cpu_data[cpu].page_size = data2host4(perf_pevent, ptr);
ptr += 4;
break;
case 8:
cpu_data[cpu].page_size = data2host8(ptr);
cpu_data[cpu].page_size = data2host8(perf_pevent, ptr);
ptr += 8;
break;
default:
......@@ -414,7 +424,7 @@ struct record *trace_peek_data(int cpu)
return trace_peek_data(cpu);
}
type_len_ts = data2host4(ptr);
type_len_ts = data2host4(perf_pevent, ptr);
ptr += 4;
type_len = type_len4host(type_len_ts);
......@@ -424,14 +434,14 @@ struct record *trace_peek_data(int cpu)
case RINGBUF_TYPE_PADDING:
if (!delta)
die("error, hit unexpected end of page");
length = data2host4(ptr);
length = data2host4(perf_pevent, ptr);
ptr += 4;
length *= 4;
ptr += length;
goto read_again;
case RINGBUF_TYPE_TIME_EXTEND:
extend = data2host4(ptr);
extend = data2host4(perf_pevent, ptr);
ptr += 4;
extend <<= TS_SHIFT;
extend += delta;
......@@ -442,7 +452,7 @@ struct record *trace_peek_data(int cpu)
ptr += 12;
break;
case 0:
length = data2host4(ptr);
length = data2host4(perf_pevent, ptr);
ptr += 4;
die("here! length=%d", length);
break;
......@@ -509,6 +519,8 @@ ssize_t trace_report(int fd, bool __repipe)
file_bigendian = buf[0];
host_bigendian = bigendian();
read_trace_init(file_bigendian, host_bigendian);
read_or_die(buf, 1);
long_size = buf[0];
......@@ -526,11 +538,11 @@ ssize_t trace_report(int fd, bool __repipe)
repipe = false;
if (show_funcs) {
print_funcs();
pevent_print_funcs(perf_pevent);
return size;
}
if (show_printk) {
print_printk();
pevent_print_printk(perf_pevent);
return size;
}
......
......@@ -2,7 +2,7 @@
#define _PERF_UTIL_TRACE_EVENT_H
#include "parse-events.h"
#include "trace-parse-events.h"
#include "event-parse.h"
#include "session.h"
struct machine;
......@@ -10,6 +10,54 @@ struct perf_sample;
union perf_event;
struct thread;
extern int header_page_size_size;
extern int header_page_ts_size;
extern int header_page_data_offset;
extern bool latency_format;
extern struct pevent *perf_pevent;
enum {
RINGBUF_TYPE_PADDING = 29,
RINGBUF_TYPE_TIME_EXTEND = 30,
RINGBUF_TYPE_TIME_STAMP = 31,
};
#ifndef TS_SHIFT
#define TS_SHIFT 27
#endif
int bigendian(void);
int read_trace_init(int file_bigendian, int host_bigendian);
void print_trace_event(int cpu, void *data, int size);
void print_event(int cpu, void *data, int size, unsigned long long nsecs,
char *comm);
int parse_ftrace_file(char *buf, unsigned long size);
int parse_event_file(char *buf, unsigned long size, char *sys);
struct record *trace_peek_data(int cpu);
struct event_format *trace_find_event(int type);
unsigned long long
raw_field_value(struct event_format *event, const char *name, void *data);
void *raw_field_ptr(struct event_format *event, const char *name, void *data);
void parse_proc_kallsyms(char *file, unsigned int size __unused);
void parse_ftrace_printk(char *file, unsigned int size __unused);
ssize_t trace_report(int fd, bool repipe);
int trace_parse_common_type(void *data);
int trace_parse_common_pid(void *data);
struct event_format *trace_find_next_event(struct event_format *event);
unsigned long long read_size(void *ptr, int size);
unsigned long long eval_flag(const char *flag);
struct record *trace_read_data(int cpu);
int read_tracing_data(int fd, struct list_head *pattrs);
struct tracing_data {
......
This diff is collapsed.
#ifndef __PERF_TRACE_EVENTS_H
#define __PERF_TRACE_EVENTS_H
#include <stdbool.h>
#include <unistd.h>
#define __unused __attribute__((unused))
#ifndef PAGE_MASK
#define PAGE_MASK (page_size - 1)
#endif
enum {
RINGBUF_TYPE_PADDING = 29,
RINGBUF_TYPE_TIME_EXTEND = 30,
RINGBUF_TYPE_TIME_STAMP = 31,
};
#ifndef TS_SHIFT
#define TS_SHIFT 27
#endif
#define NSECS_PER_SEC 1000000000ULL
#define NSECS_PER_USEC 1000ULL
enum format_flags {
FIELD_IS_ARRAY = 1,
FIELD_IS_POINTER = 2,
FIELD_IS_SIGNED = 4,
FIELD_IS_STRING = 8,
FIELD_IS_DYNAMIC = 16,
FIELD_IS_FLAG = 32,
FIELD_IS_SYMBOLIC = 64,
};
struct format_field {
struct format_field *next;
char *type;
char *name;
int offset;
int size;
unsigned long flags;
};
struct format {
int nr_common;
int nr_fields;
struct format_field *common_fields;
struct format_field *fields;
};
struct print_arg_atom {
char *atom;
};
struct print_arg_string {
char *string;
int offset;
};
struct print_arg_field {
char *name;
struct format_field *field;
};
struct print_flag_sym {
struct print_flag_sym *next;
char *value;
char *str;
};
struct print_arg_typecast {
char *type;
struct print_arg *item;
};
struct print_arg_flags {
struct print_arg *field;
char *delim;
struct print_flag_sym *flags;
};
struct print_arg_symbol {
struct print_arg *field;
struct print_flag_sym *symbols;
};
struct print_arg;
struct print_arg_op {
char *op;
int prio;
struct print_arg *left;
struct print_arg *right;
};
struct print_arg_func {
char *name;
struct print_arg *args;
};
enum print_arg_type {
PRINT_NULL,
PRINT_ATOM,
PRINT_FIELD,
PRINT_FLAGS,
PRINT_SYMBOL,
PRINT_TYPE,
PRINT_STRING,
PRINT_OP,
};
struct print_arg {
struct print_arg *next;
enum print_arg_type type;
union {
struct print_arg_atom atom;
struct print_arg_field field;
struct print_arg_typecast typecast;
struct print_arg_flags flags;
struct print_arg_symbol symbol;
struct print_arg_func func;
struct print_arg_string string;
struct print_arg_op op;
};
};
struct print_fmt {
char *format;
struct print_arg *args;
};
struct event {
struct event *next;
char *name;
int id;
int flags;
struct format format;
struct print_fmt print_fmt;
char *system;
};
enum {
EVENT_FL_ISFTRACE = 0x01,
EVENT_FL_ISPRINT = 0x02,
EVENT_FL_ISBPRINT = 0x04,
EVENT_FL_ISFUNC = 0x08,
EVENT_FL_ISFUNCENT = 0x10,
EVENT_FL_ISFUNCRET = 0x20,
EVENT_FL_FAILED = 0x80000000
};
struct record {
unsigned long long ts;
int size;
void *data;
};
struct record *trace_peek_data(int cpu);
struct record *trace_read_data(int cpu);
void parse_set_info(int nr_cpus, int long_sz);
ssize_t trace_report(int fd, bool repipe);
void *malloc_or_die(unsigned int size);
void parse_cmdlines(char *file, int size);
void parse_proc_kallsyms(char *file, unsigned int size);
void parse_ftrace_printk(char *file, unsigned int size);
void print_funcs(void);
void print_printk(void);
int parse_ftrace_file(char *buf, unsigned long size);
int parse_event_file(char *buf, unsigned long size, char *sys);
void print_trace_event(int cpu, void *data, int size);
extern int file_bigendian;
extern int host_bigendian;
int bigendian(void);
static inline unsigned short __data2host2(unsigned short data)
{
unsigned short swap;
if (host_bigendian == file_bigendian)
return data;
swap = ((data & 0xffULL) << 8) |
((data & (0xffULL << 8)) >> 8);
return swap;
}
static inline unsigned int __data2host4(unsigned int data)
{
unsigned int swap;
if (host_bigendian == file_bigendian)
return data;
swap = ((data & 0xffULL) << 24) |
((data & (0xffULL << 8)) << 8) |
((data & (0xffULL << 16)) >> 8) |
((data & (0xffULL << 24)) >> 24);
return swap;
}
static inline unsigned long long __data2host8(unsigned long long data)
{
unsigned long long swap;
if (host_bigendian == file_bigendian)
return data;
swap = ((data & 0xffULL) << 56) |
((data & (0xffULL << 8)) << 40) |
((data & (0xffULL << 16)) << 24) |
((data & (0xffULL << 24)) << 8) |
((data & (0xffULL << 32)) >> 8) |
((data & (0xffULL << 40)) >> 24) |
((data & (0xffULL << 48)) >> 40) |
((data & (0xffULL << 56)) >> 56);
return swap;
}
#define data2host2(ptr) __data2host2(*(unsigned short *)ptr)
#define data2host4(ptr) __data2host4(*(unsigned int *)ptr)
#define data2host8(ptr) ({ \
unsigned long long __val; \
\
memcpy(&__val, (ptr), sizeof(unsigned long long)); \
__data2host8(__val); \
})
extern int header_page_ts_offset;
extern int header_page_ts_size;
extern int header_page_size_offset;
extern int header_page_size_size;
extern int header_page_data_offset;
extern int header_page_data_size;
extern bool latency_format;
int trace_parse_common_type(void *data);
int trace_parse_common_pid(void *data);
int parse_common_pc(void *data);
int parse_common_flags(void *data);
int parse_common_lock_depth(void *data);
struct event *trace_find_event(int id);
struct event *trace_find_next_event(struct event *event);
unsigned long long read_size(void *ptr, int size);
unsigned long long
raw_field_value(struct event *event, const char *name, void *data);
void *raw_field_ptr(struct event *event, const char *name, void *data);
unsigned long long eval_flag(const char *flag);
/* taken from kernel/trace/trace.h */
enum trace_flag_type {
TRACE_FLAG_IRQS_OFF = 0x01,
TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
TRACE_FLAG_NEED_RESCHED = 0x04,
TRACE_FLAG_HARDIRQ = 0x08,
TRACE_FLAG_SOFTIRQ = 0x10,
};
#endif /* __PERF_TRACE_EVENTS_H */
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