Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 191230
b: refs/heads/master
c: b5a80b7
h: refs/heads/master
v: v3
  • Loading branch information
Ingo Molnar committed Apr 15, 2010
1 parent 77c1fb9 commit 4df844d
Show file tree
Hide file tree
Showing 40 changed files with 1,271 additions and 179 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f6c903f5856ffa75ae19dcee4dbb5093e320d45c
refs/heads/master: b5a80b7e91d6c067339e4d81a0176a835e9bf910
60 changes: 30 additions & 30 deletions trunk/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -4313,36 +4313,6 @@ static const struct pmu perf_ops_task_clock = {
.read = task_clock_perf_event_read,
};

#ifdef CONFIG_EVENT_TRACING

void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
int entry_size, struct pt_regs *regs)
{
struct perf_sample_data data;
struct perf_raw_record raw = {
.size = entry_size,
.data = record,
};

perf_sample_data_init(&data, addr);
data.raw = &raw;

/* Trace events already protected against recursion */
do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1,
&data, regs);
}
EXPORT_SYMBOL_GPL(perf_tp_event);

static int perf_tp_event_match(struct perf_event *event,
struct perf_sample_data *data)
{
void *record = data->raw->data;

if (likely(!event->filter) || filter_match_preds(event->filter, record))
return 1;
return 0;
}

static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
{
struct swevent_hlist *hlist;
Expand Down Expand Up @@ -4442,6 +4412,36 @@ static int swevent_hlist_get(struct perf_event *event)
return err;
}

#ifdef CONFIG_EVENT_TRACING

void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
int entry_size, struct pt_regs *regs)
{
struct perf_sample_data data;
struct perf_raw_record raw = {
.size = entry_size,
.data = record,
};

perf_sample_data_init(&data, addr);
data.raw = &raw;

/* Trace events already protected against recursion */
do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1,
&data, regs);
}
EXPORT_SYMBOL_GPL(perf_tp_event);

static int perf_tp_event_match(struct perf_event *event,
struct perf_sample_data *data)
{
void *record = data->raw->data;

if (likely(!event->filter) || filter_match_preds(event->filter, record))
return 1;
return 0;
}

static void tp_perf_event_destroy(struct perf_event *event)
{
perf_trace_disable(event->attr.config);
Expand Down
4 changes: 2 additions & 2 deletions trunk/tools/perf/Documentation/perf-record.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ OPTIONS

-f::
--force::
Overwrite existing data file.
Overwrite existing data file. (deprecated)

-c::
--count=::
Expand Down Expand Up @@ -101,7 +101,7 @@ OPTIONS

-R::
--raw-samples::
Collect raw sample records from all opened counters (typically for tracepoint counters).
Collect raw sample records from all opened counters (default for tracepoint counters).

SEE ALSO
--------
Expand Down
144 changes: 108 additions & 36 deletions trunk/tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,23 @@
#include <unistd.h>
#include <sched.h>

enum write_mode_t {
WRITE_FORCE,
WRITE_APPEND
};

static int *fd[MAX_NR_CPUS][MAX_COUNTERS];

static unsigned int user_interval = UINT_MAX;
static long default_interval = 0;

static int nr_cpus = 0;
static unsigned int page_size;
static unsigned int mmap_pages = 128;
static unsigned int user_freq = UINT_MAX;
static int freq = 1000;
static int output;
static int pipe_output = 0;
static const char *output_name = "perf.data";
static int group = 0;
static unsigned int realtime_prio = 0;
Expand All @@ -47,8 +55,7 @@ static pid_t *all_tids = NULL;
static int thread_num = 0;
static pid_t child_pid = -1;
static bool inherit = true;
static bool force = false;
static bool append_file = false;
static enum write_mode_t write_mode = WRITE_FORCE;
static bool call_graph = false;
static bool inherit_stat = false;
static bool no_samples = false;
Expand Down Expand Up @@ -103,6 +110,11 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
pc->data_tail = tail;
}

static void advance_output(size_t size)
{
bytes_written += size;
}

static void write_output(void *buf, size_t size)
{
while (size) {
Expand Down Expand Up @@ -251,10 +263,19 @@ static void create_counter(int counter, int cpu)
if (nr_counters > 1)
attr->sample_type |= PERF_SAMPLE_ID;

if (freq) {
attr->sample_type |= PERF_SAMPLE_PERIOD;
attr->freq = 1;
attr->sample_freq = freq;
/*
* We default some events to a 1 default interval. But keep
* it a weak assumption overridable by the user.
*/
if (!attr->sample_period || (user_freq != UINT_MAX &&
user_interval != UINT_MAX)) {
if (freq) {
attr->sample_type |= PERF_SAMPLE_PERIOD;
attr->freq = 1;
attr->sample_freq = freq;
} else {
attr->sample_period = default_interval;
}
}

if (no_samples)
Expand Down Expand Up @@ -420,10 +441,19 @@ static int process_buildids(void)

static void atexit_header(void)
{
session->header.data_size += bytes_written;
if (!pipe_output) {
session->header.data_size += bytes_written;

process_buildids();
perf_header__write(&session->header, output, true);
} else {
int err;

process_buildids();
perf_header__write(&session->header, output, true);
err = event__synthesize_build_ids(process_synthesized_event,
session);
if (err < 0)
pr_err("Couldn't synthesize build ids.\n");
}
}

static int __cmd_record(int argc, const char **argv)
Expand All @@ -449,45 +479,44 @@ static int __cmd_record(int argc, const char **argv)
exit(-1);
}

if (!stat(output_name, &st) && st.st_size) {
if (!force) {
if (!append_file) {
pr_err("Error, output file %s exists, use -A "
"to append or -f to overwrite.\n",
output_name);
exit(-1);
}
} else {
if (!strcmp(output_name, "-"))
pipe_output = 1;
else if (!stat(output_name, &st) && st.st_size) {
if (write_mode == WRITE_FORCE) {
char oldname[PATH_MAX];
snprintf(oldname, sizeof(oldname), "%s.old",
output_name);
unlink(oldname);
rename(output_name, oldname);
}
} else {
append_file = false;
} else if (write_mode == WRITE_APPEND) {
write_mode = WRITE_FORCE;
}

flags = O_CREAT|O_RDWR;
if (append_file)
if (write_mode == WRITE_APPEND)
file_new = 0;
else
flags |= O_TRUNC;

output = open(output_name, flags, S_IRUSR|S_IWUSR);
if (pipe_output)
output = STDOUT_FILENO;
else
output = open(output_name, flags, S_IRUSR | S_IWUSR);
if (output < 0) {
perror("failed to create output file");
exit(-1);
}

session = perf_session__new(output_name, O_WRONLY, force);
session = perf_session__new(output_name, O_WRONLY,
write_mode == WRITE_FORCE);
if (session == NULL) {
pr_err("Not enough memory for reading perf file header\n");
return -1;
}

if (!file_new) {
err = perf_header__read(&session->header, output);
err = perf_header__read(session, output);
if (err < 0)
return err;
}
Expand All @@ -513,6 +542,8 @@ static int __cmd_record(int argc, const char **argv)
}

if (!child_pid) {
if (pipe_output)
dup2(2, 1);
close(child_ready_pipe[0]);
close(go_pipe[1]);
fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
Expand Down Expand Up @@ -564,14 +595,46 @@ static int __cmd_record(int argc, const char **argv)
open_counters(cpumap[i]);
}

if (file_new) {
if (pipe_output) {
err = perf_header__write_pipe(output);
if (err < 0)
return err;
} else if (file_new) {
err = perf_header__write(&session->header, output, false);
if (err < 0)
return err;
}

post_processing_offset = lseek(output, 0, SEEK_CUR);

if (pipe_output) {
err = event__synthesize_attrs(&session->header,
process_synthesized_event,
session);
if (err < 0) {
pr_err("Couldn't synthesize attrs.\n");
return err;
}

err = event__synthesize_event_types(process_synthesized_event,
session);
if (err < 0) {
pr_err("Couldn't synthesize event_types.\n");
return err;
}

err = event__synthesize_tracing_data(output, attrs,
nr_counters,
process_synthesized_event,
session);
if (err <= 0) {
pr_err("Couldn't record tracing data.\n");
return err;
}

advance_output(err);
}

err = event__synthesize_kernel_mmap(process_synthesized_event,
session, "_text");
if (err < 0)
Expand Down Expand Up @@ -667,6 +730,8 @@ static const char * const record_usage[] = {
NULL
};

static bool force, append_file;

static const struct option options[] = {
OPT_CALLBACK('e', "event", NULL, "event",
"event selector. use 'perf list' to list available events",
Expand All @@ -688,14 +753,14 @@ static const struct option options[] = {
OPT_INTEGER('C', "profile_cpu", &profile_cpu,
"CPU to profile on"),
OPT_BOOLEAN('f', "force", &force,
"overwrite existing data file"),
OPT_LONG('c', "count", &default_interval,
"overwrite existing data file (deprecated)"),
OPT_LONG('c', "count", &user_interval,
"event period to sample"),
OPT_STRING('o', "output", &output_name, "file",
"output file name"),
OPT_BOOLEAN('i', "inherit", &inherit,
"child tasks inherit counters"),
OPT_INTEGER('F', "freq", &freq,
OPT_INTEGER('F', "freq", &user_freq,
"profile at this frequency"),
OPT_INTEGER('m', "mmap-pages", &mmap_pages,
"number of mmap data pages"),
Expand All @@ -716,7 +781,6 @@ static const struct option options[] = {

int cmd_record(int argc, const char **argv, const char *prefix __used)
{
int counter;
int i,j;

argc = parse_options(argc, argv, options, record_usage,
Expand All @@ -725,6 +789,16 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
!system_wide && profile_cpu == -1)
usage_with_options(record_usage, options);

if (force && append_file) {
fprintf(stderr, "Can't overwrite and append at the same time."
" You need to choose between -f and -A");
usage_with_options(record_usage, options);
} else if (append_file) {
write_mode = WRITE_APPEND;
} else {
write_mode = WRITE_FORCE;
}

symbol__init();

if (!nr_counters) {
Expand Down Expand Up @@ -764,6 +838,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
if (!event_array)
return -ENOMEM;

if (user_interval != UINT_MAX)
default_interval = user_interval;
if (user_freq != UINT_MAX)
freq = user_freq;

/*
* User specified count overrides default frequency.
*/
Expand All @@ -776,12 +855,5 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
exit(EXIT_FAILURE);
}

for (counter = 0; counter < nr_counters; counter++) {
if (attrs[counter].sample_period)
continue;

attrs[counter].sample_period = default_interval;
}

return __cmd_record(argc, argv);
}
Loading

0 comments on commit 4df844d

Please sign in to comment.