Skip to content

Commit

Permalink
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/acme/linux-2.6 into perf/core
  • Loading branch information
Ingo Molnar committed Mar 11, 2011
2 parents 4a0b166 + 1c0b04d commit 137ee20
Show file tree
Hide file tree
Showing 12 changed files with 317 additions and 447 deletions.
101 changes: 35 additions & 66 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include <sys/mman.h>

#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define SID(e, x, y) xyarray__entry(e->id, x, y)

enum write_mode_t {
WRITE_FORCE,
Expand All @@ -40,7 +39,6 @@ enum write_mode_t {

static u64 user_interval = ULLONG_MAX;
static u64 default_interval = 0;
static u64 sample_type;

static unsigned int page_size;
static unsigned int mmap_pages = 128;
Expand Down Expand Up @@ -160,54 +158,6 @@ static void sig_atexit(void)
kill(getpid(), signr);
}

static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
{
struct perf_header_attr *h_attr;

if (nr < session->header.attrs) {
h_attr = session->header.attr[nr];
} else {
h_attr = perf_header_attr__new(a);
if (h_attr != NULL)
if (perf_header__add_attr(&session->header, h_attr) < 0) {
perf_header_attr__delete(h_attr);
h_attr = NULL;
}
}

return h_attr;
}

static void create_counter(struct perf_evsel *evsel, int cpu)
{
struct perf_event_attr *attr = &evsel->attr;
struct perf_header_attr *h_attr;
struct perf_sample_id *sid;
int thread_index;

for (thread_index = 0; thread_index < evsel_list->threads->nr; thread_index++) {
h_attr = get_header_attr(attr, evsel->idx);
if (h_attr == NULL)
die("nomem\n");

if (!file_new) {
if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
fprintf(stderr, "incompatible append\n");
exit(-1);
}
}

sid = SID(evsel, cpu, thread_index);
if (perf_header_attr__add_id(h_attr, sid->id) < 0) {
pr_warning("Not enough memory to add id\n");
exit(-1);
}
}

if (!sample_type)
sample_type = attr->sample_type;
}

static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
{
struct perf_event_attr *attr = &evsel->attr;
Expand Down Expand Up @@ -278,10 +228,28 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
}
}

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 = list_entry(other->entries.next, struct perf_evsel, node);

list_for_each_entry(pos, &evlist->entries, node) {
if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
return false;
pair = list_entry(pair->node.next, struct perf_evsel, node);
}

return true;
}

static void open_counters(struct perf_evlist *evlist)
{
struct perf_evsel *pos;
int cpu;

list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr;
Expand Down Expand Up @@ -364,10 +332,16 @@ static void open_counters(struct perf_evlist *evlist)
if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
die("failed to mmap with %d (%s)\n", errno, strerror(errno));

for (cpu = 0; cpu < evsel_list->cpus->nr; ++cpu) {
list_for_each_entry(pos, &evlist->entries, node)
create_counter(pos, cpu);
}
if (file_new)
session->evlist = evlist;
else {
if (!perf_evlist__equal(session->evlist, evlist)) {
fprintf(stderr, "incompatible append\n");
exit(-1);
}
}

perf_session__update_sample_type(session);
}

static int process_buildids(void)
Expand All @@ -390,7 +364,7 @@ static void atexit_header(void)

if (!no_buildid)
process_buildids();
perf_header__write(&session->header, evsel_list, output, true);
perf_session__write_header(session, evsel_list, output, true);
perf_session__delete(session);
perf_evlist__delete(evsel_list);
symbol__exit();
Expand Down Expand Up @@ -524,7 +498,7 @@ static int __cmd_record(int argc, const char **argv)
perf_header__set_feat(&session->header, HEADER_BUILD_ID);

if (!file_new) {
err = perf_header__read(session, output);
err = perf_session__read_header(session, output);
if (err < 0)
goto out_delete_session;
}
Expand Down Expand Up @@ -588,8 +562,6 @@ static int __cmd_record(int argc, const char **argv)

open_counters(evsel_list);

perf_session__set_sample_type(session, sample_type);

/*
* perf_session__delete(session) will be called at atexit_header()
*/
Expand All @@ -600,20 +572,17 @@ static int __cmd_record(int argc, const char **argv)
if (err < 0)
return err;
} else if (file_new) {
err = perf_header__write(&session->header, evsel_list,
output, false);
err = perf_session__write_header(session, evsel_list,
output, false);
if (err < 0)
return err;
}

post_processing_offset = lseek(output, 0, SEEK_CUR);

perf_session__set_sample_id_all(session, sample_id_all_avail);

if (pipe_output) {
err = perf_event__synthesize_attrs(&session->header,
process_synthesized_event,
session);
err = perf_session__synthesize_attrs(session,
process_synthesized_event);
if (err < 0) {
pr_err("Couldn't synthesize attrs.\n");
return err;
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ static int perf_session__add_hist_entry(struct perf_session *session,
* FIXME: Propagate this back, but at least we're in a builtin,
* where exit() is allowed. ;-)
*/
ui__warning("Invalid %s file, contains samples with id not in "
"its header!\n", input_name);
ui__warning("Invalid %s file, contains samples with id %" PRIu64 " not in "
"its header!\n", input_name, sample->id);
exit_browser(0);
exit(1);
}
Expand Down
5 changes: 2 additions & 3 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,6 @@ static void start_counters(struct perf_evlist *evlist)
static int __cmd_top(void)
{
pthread_t thread;
struct perf_evsel *first;
int ret __used;
/*
* FIXME: perf_session__new should allow passing a O_MMAP, so that all this
Expand All @@ -900,8 +899,8 @@ static int __cmd_top(void)
perf_event__synthesize_threads(perf_event__process, session);

start_counters(top.evlist);
first = list_entry(top.evlist->entries.next, struct perf_evsel, node);
perf_session__set_sample_type(session, first->attr.sample_type);
session->evlist = top.evlist;
perf_session__update_sample_type(session);

/* Wait for a minimal set of events before starting the snapshot */
poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
Expand Down
26 changes: 17 additions & 9 deletions tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <linux/hash.h>

#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define SID(e, x, y) xyarray__entry(e->id, x, y)
#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)

void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
struct thread_map *threads)
Expand Down Expand Up @@ -106,8 +106,9 @@ void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
evlist->nr_fds++;
}

void perf_evlist__id_hash(struct perf_evlist *evlist, struct perf_evsel *evsel,
int cpu, int thread, u64 id)
static void perf_evlist__id_hash(struct perf_evlist *evlist,
struct perf_evsel *evsel,
int cpu, int thread, u64 id)
{
int hash;
struct perf_sample_id *sid = SID(evsel, cpu, thread);
Expand All @@ -118,9 +119,16 @@ void perf_evlist__id_hash(struct perf_evlist *evlist, struct perf_evsel *evsel,
hlist_add_head(&sid->node, &evlist->heads[hash]);
}

static int perf_evlist__id_hash_fd(struct perf_evlist *evlist,
struct perf_evsel *evsel,
int cpu, int thread, int fd)
void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
int cpu, int thread, u64 id)
{
perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
evsel->id[evsel->ids++] = id;
}

static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
struct perf_evsel *evsel,
int cpu, int thread, int fd)
{
u64 read_data[4] = { 0, };
int id_idx = 1; /* The first entry is the counter value */
Expand All @@ -134,7 +142,7 @@ static int perf_evlist__id_hash_fd(struct perf_evlist *evlist,
if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
++id_idx;

perf_evlist__id_hash(evlist, evsel, cpu, thread, read_data[id_idx]);
perf_evlist__id_add(evlist, evsel, cpu, thread, read_data[id_idx]);
return 0;
}

Expand Down Expand Up @@ -292,7 +300,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)

list_for_each_entry(evsel, &evlist->entries, node) {
if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
evsel->id == NULL &&
evsel->sample_id == NULL &&
perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0)
return -ENOMEM;

Expand All @@ -308,7 +316,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
goto out_unmap;

if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
perf_evlist__id_hash_fd(evlist, evsel, cpu, thread, fd) < 0)
perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
goto out_unmap;
}
}
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/util/evlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ void perf_evlist__delete(struct perf_evlist *evlist);
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
int perf_evlist__add_default(struct perf_evlist *evlist);

void perf_evlist__id_hash(struct perf_evlist *evlist, struct perf_evsel *evsel,
int cpu, int thread, u64 id);
void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
int cpu, int thread, u64 id);

int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
Expand Down
21 changes: 17 additions & 4 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,18 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)

int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
{
evsel->id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
return evsel->id != NULL ? 0 : -ENOMEM;
evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
if (evsel->sample_id == NULL)
return -ENOMEM;

evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
if (evsel->id == NULL) {
xyarray__delete(evsel->sample_id);
evsel->sample_id = NULL;
return -ENOMEM;
}

return 0;
}

int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
Expand All @@ -60,7 +70,9 @@ void perf_evsel__free_fd(struct perf_evsel *evsel)

void perf_evsel__free_id(struct perf_evsel *evsel)
{
xyarray__delete(evsel->id);
xyarray__delete(evsel->sample_id);
evsel->sample_id = NULL;
free(evsel->id);
evsel->id = NULL;
}

Expand All @@ -79,7 +91,8 @@ void perf_evsel__exit(struct perf_evsel *evsel)
{
assert(list_empty(&evsel->node));
xyarray__delete(evsel->fd);
xyarray__delete(evsel->id);
xyarray__delete(evsel->sample_id);
free(evsel->id);
}

void perf_evsel__delete(struct perf_evsel *evsel)
Expand Down
9 changes: 7 additions & 2 deletions tools/perf/util/evsel.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,17 @@ struct perf_evsel {
struct perf_event_attr attr;
char *filter;
struct xyarray *fd;
struct xyarray *id;
struct xyarray *sample_id;
u64 *id;
struct perf_counts *counts;
int idx;
int ids;
struct hists hists;
char *name;
void *priv;
union {
void *priv;
off_t id_offset;
};
struct cgroup_sel *cgrp;
};

Expand Down
Loading

0 comments on commit 137ee20

Please sign in to comment.