perf tools: Move event synthesizing routines to separate .c file

For better grouping, in time we may end up making most of these static,
i.e. generalizing the 'perf record' synthesizing code so that based on
the target it can do the right thing and call the needed synthesizers.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lkml.kernel.org/n/tip-s9zxxhk40s95pjng9panet16@git.kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 5cac8ea3
......@@ -1181,15 +1181,6 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
static void snapshot_sig_handler(int sig);
static void alarm_sig_handler(int sig);
int __weak
perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
struct perf_tool *tool __maybe_unused,
perf_event__handler_t process __maybe_unused,
struct machine *machine __maybe_unused)
{
return 0;
}
static const struct perf_event_mmap_page *
perf_evlist__pick_pc(struct evlist *evlist)
{
......
......@@ -86,6 +86,7 @@ perf-y += stat-display.o
perf-y += record.o
perf-y += srcline.o
perf-y += srccode.o
perf-y += synthetic-events.o
perf-y += data.o
perf-y += tsc.o
perf-y += cloexec.o
......
......@@ -35,6 +35,7 @@
#include "thread.h"
#include "thread-stack.h"
#include <tools/libc_compat.h>
#include "util/synthetic-events.h"
#define MAX_TIMESTAMP (~0ULL)
......
This diff is collapsed.
......@@ -40,7 +40,6 @@
#include "trace-event.h"
#include "stat.h"
#include "string2.h"
#include "util/synthetic-events.h"
#include "memswap.h"
#include "util.h"
#include "../perf-sys.h"
......@@ -2421,283 +2420,6 @@ int perf_evsel__parse_sample_timestamp(struct evsel *evsel,
return 0;
}
size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
u64 read_format)
{
size_t sz, result = sizeof(struct perf_record_sample);
if (type & PERF_SAMPLE_IDENTIFIER)
result += sizeof(u64);
if (type & PERF_SAMPLE_IP)
result += sizeof(u64);
if (type & PERF_SAMPLE_TID)
result += sizeof(u64);
if (type & PERF_SAMPLE_TIME)
result += sizeof(u64);
if (type & PERF_SAMPLE_ADDR)
result += sizeof(u64);
if (type & PERF_SAMPLE_ID)
result += sizeof(u64);
if (type & PERF_SAMPLE_STREAM_ID)
result += sizeof(u64);
if (type & PERF_SAMPLE_CPU)
result += sizeof(u64);
if (type & PERF_SAMPLE_PERIOD)
result += sizeof(u64);
if (type & PERF_SAMPLE_READ) {
result += sizeof(u64);
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
result += sizeof(u64);
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
result += sizeof(u64);
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
if (read_format & PERF_FORMAT_GROUP) {
sz = sample->read.group.nr *
sizeof(struct sample_read_value);
result += sz;
} else {
result += sizeof(u64);
}
}
if (type & PERF_SAMPLE_CALLCHAIN) {
sz = (sample->callchain->nr + 1) * sizeof(u64);
result += sz;
}
if (type & PERF_SAMPLE_RAW) {
result += sizeof(u32);
result += sample->raw_size;
}
if (type & PERF_SAMPLE_BRANCH_STACK) {
sz = sample->branch_stack->nr * sizeof(struct branch_entry);
sz += sizeof(u64);
result += sz;
}
if (type & PERF_SAMPLE_REGS_USER) {
if (sample->user_regs.abi) {
result += sizeof(u64);
sz = hweight64(sample->user_regs.mask) * sizeof(u64);
result += sz;
} else {
result += sizeof(u64);
}
}
if (type & PERF_SAMPLE_STACK_USER) {
sz = sample->user_stack.size;
result += sizeof(u64);
if (sz) {
result += sz;
result += sizeof(u64);
}
}
if (type & PERF_SAMPLE_WEIGHT)
result += sizeof(u64);
if (type & PERF_SAMPLE_DATA_SRC)
result += sizeof(u64);
if (type & PERF_SAMPLE_TRANSACTION)
result += sizeof(u64);
if (type & PERF_SAMPLE_REGS_INTR) {
if (sample->intr_regs.abi) {
result += sizeof(u64);
sz = hweight64(sample->intr_regs.mask) * sizeof(u64);
result += sz;
} else {
result += sizeof(u64);
}
}
if (type & PERF_SAMPLE_PHYS_ADDR)
result += sizeof(u64);
return result;
}
int perf_event__synthesize_sample(union perf_event *event, u64 type,
u64 read_format,
const struct perf_sample *sample)
{
__u64 *array;
size_t sz;
/*
* used for cross-endian analysis. See git commit 65014ab3
* for why this goofiness is needed.
*/
union u64_swap u;
array = event->sample.array;
if (type & PERF_SAMPLE_IDENTIFIER) {
*array = sample->id;
array++;
}
if (type & PERF_SAMPLE_IP) {
*array = sample->ip;
array++;
}
if (type & PERF_SAMPLE_TID) {
u.val32[0] = sample->pid;
u.val32[1] = sample->tid;
*array = u.val64;
array++;
}
if (type & PERF_SAMPLE_TIME) {
*array = sample->time;
array++;
}
if (type & PERF_SAMPLE_ADDR) {
*array = sample->addr;
array++;
}
if (type & PERF_SAMPLE_ID) {
*array = sample->id;
array++;
}
if (type & PERF_SAMPLE_STREAM_ID) {
*array = sample->stream_id;
array++;
}
if (type & PERF_SAMPLE_CPU) {
u.val32[0] = sample->cpu;
u.val32[1] = 0;
*array = u.val64;
array++;
}
if (type & PERF_SAMPLE_PERIOD) {
*array = sample->period;
array++;
}
if (type & PERF_SAMPLE_READ) {
if (read_format & PERF_FORMAT_GROUP)
*array = sample->read.group.nr;
else
*array = sample->read.one.value;
array++;
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
*array = sample->read.time_enabled;
array++;
}
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
*array = sample->read.time_running;
array++;
}
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
if (read_format & PERF_FORMAT_GROUP) {
sz = sample->read.group.nr *
sizeof(struct sample_read_value);
memcpy(array, sample->read.group.values, sz);
array = (void *)array + sz;
} else {
*array = sample->read.one.id;
array++;
}
}
if (type & PERF_SAMPLE_CALLCHAIN) {
sz = (sample->callchain->nr + 1) * sizeof(u64);
memcpy(array, sample->callchain, sz);
array = (void *)array + sz;
}
if (type & PERF_SAMPLE_RAW) {
u.val32[0] = sample->raw_size;
*array = u.val64;
array = (void *)array + sizeof(u32);
memcpy(array, sample->raw_data, sample->raw_size);
array = (void *)array + sample->raw_size;
}
if (type & PERF_SAMPLE_BRANCH_STACK) {
sz = sample->branch_stack->nr * sizeof(struct branch_entry);
sz += sizeof(u64);
memcpy(array, sample->branch_stack, sz);
array = (void *)array + sz;
}
if (type & PERF_SAMPLE_REGS_USER) {
if (sample->user_regs.abi) {
*array++ = sample->user_regs.abi;
sz = hweight64(sample->user_regs.mask) * sizeof(u64);
memcpy(array, sample->user_regs.regs, sz);
array = (void *)array + sz;
} else {
*array++ = 0;
}
}
if (type & PERF_SAMPLE_STACK_USER) {
sz = sample->user_stack.size;
*array++ = sz;
if (sz) {
memcpy(array, sample->user_stack.data, sz);
array = (void *)array + sz;
*array++ = sz;
}
}
if (type & PERF_SAMPLE_WEIGHT) {
*array = sample->weight;
array++;
}
if (type & PERF_SAMPLE_DATA_SRC) {
*array = sample->data_src;
array++;
}
if (type & PERF_SAMPLE_TRANSACTION) {
*array = sample->transaction;
array++;
}
if (type & PERF_SAMPLE_REGS_INTR) {
if (sample->intr_regs.abi) {
*array++ = sample->intr_regs.abi;
sz = hweight64(sample->intr_regs.mask) * sizeof(u64);
memcpy(array, sample->intr_regs.regs, sz);
array = (void *)array + sz;
} else {
*array++ = 0;
}
}
if (type & PERF_SAMPLE_PHYS_ADDR) {
*array = sample->phys_addr;
array++;
}
return 0;
}
struct tep_format_field *perf_evsel__field(struct evsel *evsel, const char *name)
{
return tep_find_field(evsel->tp_format, name);
......
This diff is collapsed.
......@@ -92,6 +92,24 @@ struct perf_header {
struct perf_env env;
};
struct feat_fd {
struct perf_header *ph;
int fd;
void *buf; /* Either buf != NULL or fd >= 0 */
ssize_t offset;
size_t size;
struct evsel *events;
};
struct perf_header_feature_ops {
int (*write)(struct feat_fd *ff, struct evlist *evlist);
void (*print)(struct feat_fd *ff, FILE *fp);
int (*process)(struct feat_fd *ff, void *data);
const char *name;
bool full_only;
bool synthesize;
};
struct evlist;
struct perf_session;
struct perf_tool;
......
......@@ -20,7 +20,6 @@
#include "symbol.h"
#include "sort.h"
#include "strlist.h"
#include "util/synthetic-events.h"
#include "target.h"
#include "thread.h"
#include "util.h"
......@@ -2610,30 +2609,6 @@ int machines__for_each_thread(struct machines *machines,
return rc;
}
int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
struct target *target, struct perf_thread_map *threads,
perf_event__handler_t process, bool data_mmap,
unsigned int nr_threads_synthesize)
{
if (target__has_task(target))
return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap);
else if (target__has_cpu(target))
return perf_event__synthesize_threads(tool, process,
machine, data_mmap,
nr_threads_synthesize);
/* command specified */
return 0;
}
int machine__synthesize_threads(struct machine *machine, struct target *target,
struct perf_thread_map *threads, bool data_mmap,
unsigned int nr_threads_synthesize)
{
return __machine__synthesize_threads(machine, NULL, target, threads,
perf_event__process, data_mmap,
nr_threads_synthesize);
}
pid_t machine__get_current_tid(struct machine *machine, int cpu)
{
int nr_cpus = min(machine->env->nr_cpus_online, MAX_NR_CPUS);
......
......@@ -17,8 +17,26 @@
#include <string.h>
#include <unistd.h>
#include <asm/bug.h>
#include <linux/kernel.h>
#include <linux/zalloc.h>
static const char *perf_ns__names[] = {
[NET_NS_INDEX] = "net",
[UTS_NS_INDEX] = "uts",
[IPC_NS_INDEX] = "ipc",
[PID_NS_INDEX] = "pid",
[USER_NS_INDEX] = "user",
[MNT_NS_INDEX] = "mnt",
[CGROUP_NS_INDEX] = "cgroup",
};
const char *perf_ns__name(unsigned int id)
{
if (id >= ARRAY_SIZE(perf_ns__names))
return "UNKNOWN";
return perf_ns__names[id];
}
struct namespaces *namespaces__new(struct perf_record_namespaces *event)
{
struct namespaces *namespaces;
......
......@@ -66,4 +66,6 @@ static inline void __nsinfo__zput(struct nsinfo **nsip)
#define nsinfo__zput(nsi) __nsinfo__zput(&nsi)
const char *perf_ns__name(unsigned int id);
#endif /* __PERF_NAMESPACES_H */
......@@ -29,7 +29,6 @@
#include "thread-stack.h"
#include "sample-raw.h"
#include "stat.h"
#include "util/synthetic-events.h"
#include "util.h"
#include "ui/progress.h"
#include "../perf.h"
......@@ -2413,73 +2412,3 @@ int perf_event__process_id_index(struct perf_session *session,
}
return 0;
}
int perf_event__synthesize_id_index(struct perf_tool *tool,
perf_event__handler_t process,
struct evlist *evlist,
struct machine *machine)
{
union perf_event *ev;
struct evsel *evsel;
size_t nr = 0, i = 0, sz, max_nr, n;
int err;
pr_debug2("Synthesizing id index\n");
max_nr = (UINT16_MAX - sizeof(struct perf_record_id_index)) /
sizeof(struct id_index_entry);
evlist__for_each_entry(evlist, evsel)
nr += evsel->ids;
n = nr > max_nr ? max_nr : nr;
sz = sizeof(struct perf_record_id_index) + n * sizeof(struct id_index_entry);
ev = zalloc(sz);
if (!ev)
return -ENOMEM;
ev->id_index.header.type = PERF_RECORD_ID_INDEX;
ev->id_index.header.size = sz;
ev->id_index.nr = n;
evlist__for_each_entry(evlist, evsel) {
u32 j;
for (j = 0; j < evsel->ids; j++) {
struct id_index_entry *e;
struct perf_sample_id *sid;
if (i >= n) {
err = process(tool, ev, NULL, machine);
if (err)
goto out_err;
nr -= n;
i = 0;
}
e = &ev->id_index.entries[i++];
e->id = evsel->id[j];
sid = perf_evlist__id2sid(evlist, e->id);
if (!sid) {
free(ev);
return -ENOENT;
}
e->idx = sid->idx;
e->cpu = sid->cpu;
e->tid = sid->tid;
}
}
sz = sizeof(struct perf_record_id_index) + nr * sizeof(struct id_index_entry);
ev->id_index.header.size = sz;
ev->id_index.nr = nr;
err = process(tool, ev, NULL, machine);
out_err:
free(ev);
return err;
}
......@@ -12,7 +12,6 @@
#include "target.h"
#include "evlist.h"
#include "evsel.h"
#include "util/synthetic-events.h"
#include "thread_map.h"
#include <linux/zalloc.h>
......@@ -495,45 +494,3 @@ int create_perf_stat_counter(struct evsel *evsel,
return perf_evsel__open_per_thread(evsel, evsel->core.threads);
}
int perf_event__synthesize_stat_events(struct perf_stat_config *config,
struct perf_tool *tool,
struct evlist *evlist,
perf_event__handler_t process,
bool attrs)
{
int err;
if (attrs) {
err = perf_event__synthesize_attrs(tool, evlist, process);
if (err < 0) {
pr_err("Couldn't synthesize attrs.\n");
return err;
}
}
err = perf_event__synthesize_extra_attr(tool, evlist, process,
attrs);
err = perf_event__synthesize_thread_map2(tool, evlist->core.threads,
process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize thread map.\n");
return err;
}
err = perf_event__synthesize_cpu_map(tool, evlist->core.cpus,
process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize thread map.\n");
return err;
}
err = perf_event__synthesize_stat_config(tool, config, process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize config.\n");
return err;
}
return 0;
}
This diff is collapsed.
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