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.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2019-09-18 16:08:52 -03:00
parent 5cac8ea3e6
commit 055c67ed39
13 changed files with 1928 additions and 1923 deletions

View File

@ -1181,15 +1181,6 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
static void snapshot_sig_handler(int sig); static void snapshot_sig_handler(int sig);
static void alarm_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 * static const struct perf_event_mmap_page *
perf_evlist__pick_pc(struct evlist *evlist) perf_evlist__pick_pc(struct evlist *evlist)
{ {

View File

@ -86,6 +86,7 @@ perf-y += stat-display.o
perf-y += record.o perf-y += record.o
perf-y += srcline.o perf-y += srcline.o
perf-y += srccode.o perf-y += srccode.o
perf-y += synthetic-events.o
perf-y += data.o perf-y += data.o
perf-y += tsc.o perf-y += tsc.o
perf-y += cloexec.o perf-y += cloexec.o

View File

@ -35,6 +35,7 @@
#include "thread.h" #include "thread.h"
#include "thread-stack.h" #include "thread-stack.h"
#include <tools/libc_compat.h> #include <tools/libc_compat.h>
#include "util/synthetic-events.h"
#define MAX_TIMESTAMP (~0ULL) #define MAX_TIMESTAMP (~0ULL)

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,6 @@
#include "trace-event.h" #include "trace-event.h"
#include "stat.h" #include "stat.h"
#include "string2.h" #include "string2.h"
#include "util/synthetic-events.h"
#include "memswap.h" #include "memswap.h"
#include "util.h" #include "util.h"
#include "../perf-sys.h" #include "../perf-sys.h"
@ -2421,283 +2420,6 @@ int perf_evsel__parse_sample_timestamp(struct evsel *evsel,
return 0; 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) struct tep_format_field *perf_evsel__field(struct evsel *evsel, const char *name)
{ {
return tep_find_field(evsel->tp_format, name); return tep_find_field(evsel->tp_format, name);

View File

@ -45,7 +45,6 @@
#include "util.h" // page_size, perf_exe() #include "util.h" // page_size, perf_exe()
#include "cputopo.h" #include "cputopo.h"
#include "bpf-event.h" #include "bpf-event.h"
#include "util/synthetic-events.h"
#include <linux/ctype.h> #include <linux/ctype.h>
#include <internal/lib.h> #include <internal/lib.h>
@ -72,15 +71,6 @@ struct perf_file_attr {
struct perf_file_section ids; struct perf_file_section ids;
}; };
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;
};
void perf_header__set_feat(struct perf_header *header, int feat) void perf_header__set_feat(struct perf_header *header, int feat)
{ {
set_bit(feat, header->adds_features); set_bit(feat, header->adds_features);
@ -2825,15 +2815,6 @@ static int process_compressed(struct feat_fd *ff,
return 0; return 0;
} }
struct 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;
};
#define FEAT_OPR(n, func, __full_only) \ #define FEAT_OPR(n, func, __full_only) \
[HEADER_##n] = { \ [HEADER_##n] = { \
.name = __stringify(n), \ .name = __stringify(n), \
@ -2860,8 +2841,10 @@ struct feature_ops {
#define process_branch_stack NULL #define process_branch_stack NULL
#define process_stat NULL #define process_stat NULL
// Only used in util/synthetic-events.c
const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE];
static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPN(TRACING_DATA, tracing_data, false), FEAT_OPN(TRACING_DATA, tracing_data, false),
FEAT_OPN(BUILD_ID, build_id, false), FEAT_OPN(BUILD_ID, build_id, false),
FEAT_OPR(HOSTNAME, hostname, false), FEAT_OPR(HOSTNAME, hostname, false),
@ -3658,105 +3641,6 @@ out_delete_evlist:
return -ENOMEM; return -ENOMEM;
} }
int perf_event__synthesize_attr(struct perf_tool *tool,
struct perf_event_attr *attr, u32 ids, u64 *id,
perf_event__handler_t process)
{
union perf_event *ev;
size_t size;
int err;
size = sizeof(struct perf_event_attr);
size = PERF_ALIGN(size, sizeof(u64));
size += sizeof(struct perf_event_header);
size += ids * sizeof(u64);
ev = zalloc(size);
if (ev == NULL)
return -ENOMEM;
ev->attr.attr = *attr;
memcpy(ev->attr.id, id, ids * sizeof(u64));
ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
ev->attr.header.size = (u16)size;
if (ev->attr.header.size == size)
err = process(tool, ev, NULL, NULL);
else
err = -E2BIG;
free(ev);
return err;
}
int perf_event__synthesize_features(struct perf_tool *tool,
struct perf_session *session,
struct evlist *evlist,
perf_event__handler_t process)
{
struct perf_header *header = &session->header;
struct feat_fd ff;
struct perf_record_header_feature *fe;
size_t sz, sz_hdr;
int feat, ret;
sz_hdr = sizeof(fe->header);
sz = sizeof(union perf_event);
/* get a nice alignment */
sz = PERF_ALIGN(sz, page_size);
memset(&ff, 0, sizeof(ff));
ff.buf = malloc(sz);
if (!ff.buf)
return -ENOMEM;
ff.size = sz - sz_hdr;
ff.ph = &session->header;
for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
if (!feat_ops[feat].synthesize) {
pr_debug("No record header feature for header :%d\n", feat);
continue;
}
ff.offset = sizeof(*fe);
ret = feat_ops[feat].write(&ff, evlist);
if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
pr_debug("Error writing feature\n");
continue;
}
/* ff.buf may have changed due to realloc in do_write() */
fe = ff.buf;
memset(fe, 0, sizeof(*fe));
fe->feat_id = feat;
fe->header.type = PERF_RECORD_HEADER_FEATURE;
fe->header.size = ff.offset;
ret = process(tool, ff.buf, NULL, NULL);
if (ret) {
free(ff.buf);
return ret;
}
}
/* Send HEADER_LAST_FEATURE mark. */
fe = ff.buf;
fe->feat_id = HEADER_LAST_FEATURE;
fe->header.type = PERF_RECORD_HEADER_FEATURE;
fe->header.size = sizeof(*fe);
ret = process(tool, ff.buf, NULL, NULL);
free(ff.buf);
return ret;
}
int perf_event__process_feature(struct perf_session *session, int perf_event__process_feature(struct perf_session *session,
union perf_event *event) union perf_event *event)
{ {
@ -3799,113 +3683,6 @@ int perf_event__process_feature(struct perf_session *session,
return 0; return 0;
} }
static struct perf_record_event_update *
event_update_event__new(size_t size, u64 type, u64 id)
{
struct perf_record_event_update *ev;
size += sizeof(*ev);
size = PERF_ALIGN(size, sizeof(u64));
ev = zalloc(size);
if (ev) {
ev->header.type = PERF_RECORD_EVENT_UPDATE;
ev->header.size = (u16)size;
ev->type = type;
ev->id = id;
}
return ev;
}
int
perf_event__synthesize_event_update_unit(struct perf_tool *tool,
struct evsel *evsel,
perf_event__handler_t process)
{
struct perf_record_event_update *ev;
size_t size = strlen(evsel->unit);
int err;
ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->id[0]);
if (ev == NULL)
return -ENOMEM;
strlcpy(ev->data, evsel->unit, size + 1);
err = process(tool, (union perf_event *)ev, NULL, NULL);
free(ev);
return err;
}
int
perf_event__synthesize_event_update_scale(struct perf_tool *tool,
struct evsel *evsel,
perf_event__handler_t process)
{
struct perf_record_event_update *ev;
struct perf_record_event_update_scale *ev_data;
int err;
ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
if (ev == NULL)
return -ENOMEM;
ev_data = (struct perf_record_event_update_scale *)ev->data;
ev_data->scale = evsel->scale;
err = process(tool, (union perf_event*) ev, NULL, NULL);
free(ev);
return err;
}
int
perf_event__synthesize_event_update_name(struct perf_tool *tool,
struct evsel *evsel,
perf_event__handler_t process)
{
struct perf_record_event_update *ev;
size_t len = strlen(evsel->name);
int err;
ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->id[0]);
if (ev == NULL)
return -ENOMEM;
strlcpy(ev->data, evsel->name, len + 1);
err = process(tool, (union perf_event*) ev, NULL, NULL);
free(ev);
return err;
}
int
perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
struct evsel *evsel,
perf_event__handler_t process)
{
size_t size = sizeof(struct perf_record_event_update);
struct perf_record_event_update *ev;
int max, err;
u16 type;
if (!evsel->core.own_cpus)
return 0;
ev = cpu_map_data__alloc(evsel->core.own_cpus, &size, &type, &max);
if (!ev)
return -ENOMEM;
ev->header.type = PERF_RECORD_EVENT_UPDATE;
ev->header.size = (u16)size;
ev->type = PERF_EVENT_UPDATE__CPUS;
ev->id = evsel->id[0];
cpu_map_data__synthesize((struct perf_record_cpu_map_data *)ev->data,
evsel->core.own_cpus,
type, max);
err = process(tool, (union perf_event*) ev, NULL, NULL);
free(ev);
return err;
}
size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
{ {
struct perf_record_event_update *ev = &event->event_update; struct perf_record_event_update *ev = &event->event_update;
@ -3945,93 +3722,6 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
return ret; return ret;
} }
int perf_event__synthesize_attrs(struct perf_tool *tool,
struct evlist *evlist,
perf_event__handler_t process)
{
struct evsel *evsel;
int err = 0;
evlist__for_each_entry(evlist, evsel) {
err = perf_event__synthesize_attr(tool, &evsel->core.attr, evsel->ids,
evsel->id, process);
if (err) {
pr_debug("failed to create perf header attribute\n");
return err;
}
}
return err;
}
static bool has_unit(struct evsel *counter)
{
return counter->unit && *counter->unit;
}
static bool has_scale(struct evsel *counter)
{
return counter->scale != 1;
}
int perf_event__synthesize_extra_attr(struct perf_tool *tool,
struct evlist *evsel_list,
perf_event__handler_t process,
bool is_pipe)
{
struct evsel *counter;
int err;
/*
* Synthesize other events stuff not carried within
* attr event - unit, scale, name
*/
evlist__for_each_entry(evsel_list, counter) {
if (!counter->supported)
continue;
/*
* Synthesize unit and scale only if it's defined.
*/
if (has_unit(counter)) {
err = perf_event__synthesize_event_update_unit(tool, counter, process);
if (err < 0) {
pr_err("Couldn't synthesize evsel unit.\n");
return err;
}
}
if (has_scale(counter)) {
err = perf_event__synthesize_event_update_scale(tool, counter, process);
if (err < 0) {
pr_err("Couldn't synthesize evsel counter.\n");
return err;
}
}
if (counter->core.own_cpus) {
err = perf_event__synthesize_event_update_cpus(tool, counter, process);
if (err < 0) {
pr_err("Couldn't synthesize evsel cpus.\n");
return err;
}
}
/*
* Name is needed only for pipe output,
* perf.data carries event names.
*/
if (is_pipe) {
err = perf_event__synthesize_event_update_name(tool, counter, process);
if (err < 0) {
pr_err("Couldn't synthesize evsel name.\n");
return err;
}
}
}
return 0;
}
int perf_event__process_attr(struct perf_tool *tool __maybe_unused, int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
union perf_event *event, union perf_event *event,
struct evlist **pevlist) struct evlist **pevlist)
@ -4116,55 +3806,6 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
return 0; return 0;
} }
int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
struct evlist *evlist,
perf_event__handler_t process)
{
union perf_event ev;
struct tracing_data *tdata;
ssize_t size = 0, aligned_size = 0, padding;
struct feat_fd ff;
int err __maybe_unused = 0;
/*
* We are going to store the size of the data followed
* by the data contents. Since the fd descriptor is a pipe,
* we cannot seek back to store the size of the data once
* we know it. Instead we:
*
* - write the tracing data to the temp file
* - get/write the data size to pipe
* - write the tracing data from the temp file
* to the pipe
*/
tdata = tracing_data_get(&evlist->core.entries, fd, true);
if (!tdata)
return -1;
memset(&ev, 0, sizeof(ev));
ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
size = tdata->size;
aligned_size = PERF_ALIGN(size, sizeof(u64));
padding = aligned_size - size;
ev.tracing_data.header.size = sizeof(ev.tracing_data);
ev.tracing_data.size = aligned_size;
process(tool, &ev, NULL, NULL);
/*
* The put function will copy all the tracing data
* stored in temp file to the pipe.
*/
tracing_data_put(tdata);
ff = (struct feat_fd){ .fd = fd };
if (write_padded(&ff, NULL, 0, padding))
return -1;
return aligned_size;
}
int perf_event__process_tracing_data(struct perf_session *session, int perf_event__process_tracing_data(struct perf_session *session,
union perf_event *event) union perf_event *event)
{ {
@ -4204,34 +3845,6 @@ int perf_event__process_tracing_data(struct perf_session *session,
return size_read + padding; return size_read + padding;
} }
int perf_event__synthesize_build_id(struct perf_tool *tool,
struct dso *pos, u16 misc,
perf_event__handler_t process,
struct machine *machine)
{
union perf_event ev;
size_t len;
int err = 0;
if (!pos->hit)
return err;
memset(&ev, 0, sizeof(ev));
len = pos->long_name_len + 1;
len = PERF_ALIGN(len, NAME_ALIGN);
memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
ev.build_id.header.misc = misc;
ev.build_id.pid = machine->pid;
ev.build_id.header.size = sizeof(ev.build_id) + len;
memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
err = process(tool, &ev, NULL, machine);
return err;
}
int perf_event__process_build_id(struct perf_session *session, int perf_event__process_build_id(struct perf_session *session,
union perf_event *event) union perf_event *event)
{ {

View File

@ -92,6 +92,24 @@ struct perf_header {
struct perf_env env; 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 evlist;
struct perf_session; struct perf_session;
struct perf_tool; struct perf_tool;

View File

@ -20,7 +20,6 @@
#include "symbol.h" #include "symbol.h"
#include "sort.h" #include "sort.h"
#include "strlist.h" #include "strlist.h"
#include "util/synthetic-events.h"
#include "target.h" #include "target.h"
#include "thread.h" #include "thread.h"
#include "util.h" #include "util.h"
@ -2610,30 +2609,6 @@ int machines__for_each_thread(struct machines *machines,
return rc; 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) pid_t machine__get_current_tid(struct machine *machine, int cpu)
{ {
int nr_cpus = min(machine->env->nr_cpus_online, MAX_NR_CPUS); int nr_cpus = min(machine->env->nr_cpus_online, MAX_NR_CPUS);

View File

@ -17,8 +17,26 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <asm/bug.h> #include <asm/bug.h>
#include <linux/kernel.h>
#include <linux/zalloc.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__new(struct perf_record_namespaces *event)
{ {
struct namespaces *namespaces; struct namespaces *namespaces;

View File

@ -66,4 +66,6 @@ static inline void __nsinfo__zput(struct nsinfo **nsip)
#define nsinfo__zput(nsi) __nsinfo__zput(&nsi) #define nsinfo__zput(nsi) __nsinfo__zput(&nsi)
const char *perf_ns__name(unsigned int id);
#endif /* __PERF_NAMESPACES_H */ #endif /* __PERF_NAMESPACES_H */

View File

@ -29,7 +29,6 @@
#include "thread-stack.h" #include "thread-stack.h"
#include "sample-raw.h" #include "sample-raw.h"
#include "stat.h" #include "stat.h"
#include "util/synthetic-events.h"
#include "util.h" #include "util.h"
#include "ui/progress.h" #include "ui/progress.h"
#include "../perf.h" #include "../perf.h"
@ -2413,73 +2412,3 @@ int perf_event__process_id_index(struct perf_session *session,
} }
return 0; 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;
}

View File

@ -12,7 +12,6 @@
#include "target.h" #include "target.h"
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
#include "util/synthetic-events.h"
#include "thread_map.h" #include "thread_map.h"
#include <linux/zalloc.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); 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;
}

File diff suppressed because it is too large Load Diff