summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-record.txt11
-rw-r--r--tools/perf/Documentation/perf-stat.txt11
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/bench/sched-pipe.c2
-rw-r--r--tools/perf/builtin-annotate.c14
-rw-r--r--tools/perf/builtin-record.c15
-rw-r--r--tools/perf/builtin-report.c7
-rw-r--r--tools/perf/builtin-sched.c12
-rw-r--r--tools/perf/builtin-stat.c40
-rw-r--r--tools/perf/builtin-top.c73
-rw-r--r--tools/perf/util/annotate.c137
-rw-r--r--tools/perf/util/annotate.h37
-rw-r--r--tools/perf/util/cgroup.c178
-rw-r--r--tools/perf/util/cgroup.h17
-rw-r--r--tools/perf/util/event.c19
-rw-r--r--tools/perf/util/event.h6
-rw-r--r--tools/perf/util/evsel.c16
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.c5
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/probe-finder.c165
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c3
-rw-r--r--tools/perf/util/symbol.c4
-rw-r--r--tools/perf/util/top.h10
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/perf/util/ui/browsers/annotate.c18
-rw-r--r--tools/perf/util/ui/browsers/map.c2
-rw-r--r--tools/power/x86/turbostat/turbostat.c200
29 files changed, 677 insertions, 338 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e032716..5a520f8 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -137,6 +137,17 @@ Do not update the builid cache. This saves some overhead in situations
where the information in the perf.data file (which includes buildids)
is sufficient.
+-G name,...::
+--cgroup name,...::
+monitor only in the container (cgroup) called "name". This option is available only
+in per-cpu mode. The cgroup filesystem must be mounted. All threads belonging to
+container "name" are monitored when they run on the monitored CPUs. Multiple cgroups
+can be provided. Each cgroup is applied to the corresponding event, i.e., first cgroup
+to first event, second cgroup to second event and so on. It is possible to provide
+an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
+corresponding events, i.e., they always refer to events defined earlier on the command
+line.
+
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index b6da7af..918cc38 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -83,6 +83,17 @@ This option is only valid in system-wide mode.
print counts using a CSV-style output to make it easy to import directly into
spreadsheets. Columns are separated by the string specified in SEP.
+-G name::
+--cgroup name::
+monitor only in the container (cgroup) called "name". This option is available only
+in per-cpu mode. The cgroup filesystem must be mounted. All threads belonging to
+container "name" are monitored when they run on the monitored CPUs. Multiple cgroups
+can be provided. Each cgroup is applied to the corresponding event, i.e., first cgroup
+to first event, second cgroup to second event and so on. It is possible to provide
+an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
+corresponding events, i.e., they always refer to events defined earlier on the command
+line.
+
EXAMPLES
--------
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index be3eb1d..bc4d9bf 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -326,7 +326,7 @@ grep-libs = $(filter -l%,$(1))
strip-libs = $(filter-out -l%,$(1))
$(OUTPUT)python/perf.so: $(PYRF_OBJS)
- @python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \
+ $(QUIET_GEN)python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \
--build-temp='$(OUTPUT)python/temp'
#
# No Perl scripts right now:
@@ -442,6 +442,7 @@ LIB_H += util/pstack.h
LIB_H += util/cpumap.h
LIB_H += util/top.h
LIB_H += $(ARCH_INCLUDE)
+LIB_H += util/cgroup.h
LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
@@ -496,6 +497,7 @@ LIB_OBJS += $(OUTPUT)util/probe-event.o
LIB_OBJS += $(OUTPUT)util/util.o
LIB_OBJS += $(OUTPUT)util/xyarray.o
LIB_OBJS += $(OUTPUT)util/cpumap.o
+LIB_OBJS += $(OUTPUT)util/cgroup.o
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index d9ab3ce..0c7454f 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -55,7 +55,7 @@ int bench_sched_pipe(int argc, const char **argv,
* discarding returned value of read(), write()
* causes error in building environment for perf
*/
- int ret, wait_stat;
+ int __used ret, wait_stat;
pid_t pid, retpid;
argc = parse_options(argc, argv, options,
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index ea6a116..4271829 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -62,7 +62,8 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
* All aggregated on the first sym_hist.
*/
struct annotation *notes = symbol__annotation(he->ms.sym);
- if (notes->histograms == NULL && symbol__alloc_hist(he->ms.sym, 1) < 0)
+ if (notes->src == NULL &&
+ symbol__alloc_hist(he->ms.sym, 1) < 0)
return -ENOMEM;
return hist_entry__inc_addr_samples(he, 0, al->addr);
@@ -77,7 +78,8 @@ static int process_sample_event(union perf_event *event,
{
struct addr_location al;
- if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
+ if (perf_event__preprocess_sample(event, session, &al, sample,
+ symbol__annotate_init) < 0) {
pr_warning("problem processing %d event, skipping it.\n",
event->header.type);
return -1;
@@ -111,7 +113,7 @@ static void hists__find_annotations(struct hists *self)
goto find_next;
notes = symbol__annotation(he->ms.sym);
- if (notes->histograms == NULL) {
+ if (notes->src == NULL) {
find_next:
if (key == KEY_LEFT)
nd = rb_prev(nd);
@@ -142,11 +144,11 @@ find_next:
nd = rb_next(nd);
/*
* Since we have a hist_entry per IP for the same
- * symbol, free he->ms.sym->histogram to signal we already
+ * symbol, free he->ms.sym->src to signal we already
* processed this symbol.
*/
- free(notes->histograms);
- notes->histograms = NULL;
+ free(notes->src);
+ notes->src = NULL;
}
}
}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 07f8d6d..a4aaadc 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -680,9 +680,9 @@ static int __cmd_record(int argc, const char **argv)
perf_event__synthesize_guest_os);
if (!system_wide)
- perf_event__synthesize_thread(target_tid,
- process_synthesized_event,
- session);
+ perf_event__synthesize_thread_map(evsel_list->threads,
+ process_synthesized_event,
+ session);
else
perf_event__synthesize_threads(process_synthesized_event,
session);
@@ -807,6 +807,9 @@ const struct option record_options[] = {
"do not update the buildid cache"),
OPT_BOOLEAN('B', "no-buildid", &no_buildid,
"do not collect buildids in perf.data"),
+ OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+ "monitor event in cgroup name only",
+ parse_cgroups),
OPT_END()
};
@@ -835,6 +838,12 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
write_mode = WRITE_FORCE;
}
+ if (nr_cgroups && !system_wide) {
+ fprintf(stderr, "cgroup monitoring only available in"
+ " system-wide mode\n");
+ usage_with_options(record_usage, record_options);
+ }
+
symbol__init();
if (no_buildid_cache || no_buildid)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index de06bf5..f9a99a1 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -44,6 +44,7 @@ static const char default_pretty_printing_style[] = "normal";
static const char *pretty_printing_style = default_pretty_printing_style;
static char callchain_default_opt[] = "fractal,0.5";
+static symbol_filter_t annotate_init;
static struct hists *perf_session__hists_findnew(struct perf_session *self,
u64 event_stream, u32 type,
@@ -123,7 +124,7 @@ static int perf_session__add_hist_entry(struct perf_session *session,
* All aggregated on the first sym_hist.
*/
struct annotation *notes = symbol__annotation(he->ms.sym);
- if (notes->histograms == NULL &&
+ if (notes->src == NULL &&
symbol__alloc_hist(he->ms.sym, 1) < 0)
err = -ENOMEM;
else
@@ -166,7 +167,8 @@ static int process_sample_event(union perf_event *event,
struct addr_location al;
struct perf_event_attr *attr;
- if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
+ if (perf_event__preprocess_sample(event, session, &al, sample,
+ annotate_init) < 0) {
fprintf(stderr, "problem processing %d event, skipping it.\n",
event->header.type);
return -1;
@@ -519,6 +521,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
*/
if (use_browser > 0) {
symbol_conf.priv_size = sizeof(struct annotation);
+ annotate_init = symbol__annotate_init;
/*
* For searching by name on the "Browse map details".
* providing it only in verbose mode not to bloat too
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index ae26211..a32f411 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -369,11 +369,6 @@ static void
process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
{
int ret = 0;
- u64 now;
- long long delta;
-
- now = get_nsecs();
- delta = start_time + atom->timestamp - now;
switch (atom->type) {
case SCHED_EVENT_RUN:
@@ -562,7 +557,7 @@ static void wait_for_tasks(void)
static void run_one_test(void)
{
- u64 T0, T1, delta, avg_delta, fluct, std_dev;
+ u64 T0, T1, delta, avg_delta, fluct;
T0 = get_nsecs();
wait_for_tasks();
@@ -578,7 +573,6 @@ static void run_one_test(void)
else
fluct = delta - avg_delta;
sum_fluct += fluct;
- std_dev = sum_fluct / nr_runs / sqrt(nr_runs);
if (!run_avg)
run_avg = delta;
run_avg = (run_avg*9 + delta)/10;
@@ -799,7 +793,7 @@ replay_switch_event(struct trace_switch_event *switch_event,
u64 timestamp,
struct thread *thread __used)
{
- struct task_desc *prev, *next;
+ struct task_desc *prev, __used *next;
u64 timestamp0;
s64 delta;
@@ -1404,7 +1398,7 @@ map_switch_event(struct trace_switch_event *switch_event,
u64 timestamp,
struct thread *thread __used)
{
- struct thread *sched_out, *sched_in;
+ struct thread *sched_out __used, *sched_in;
int new_shortname;
u64 timestamp0;
s64 delta;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 806a999..21c0252 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -390,6 +390,9 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
+ if (evsel->cgrp)
+ fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
+
if (csv_output)
return;
@@ -420,6 +423,9 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
+ if (evsel->cgrp)
+ fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
+
if (csv_output)
return;
@@ -460,9 +466,17 @@ static void print_counter_aggr(struct perf_evsel *counter)
int scaled = counter->counts->scaled;
if (scaled == -1) {
- fprintf(stderr, "%*s%s%-24s\n",
+ fprintf(stderr, "%*s%s%*s",
csv_output ? 0 : 18,
- "<not counted>", csv_sep, event_name(counter));
+ "<not counted>",
+ csv_sep,
+ csv_output ? 0 : -24,
+ event_name(counter));
+
+ if (counter->cgrp)
+ fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
+
+ fputc('\n', stderr);
return;
}
@@ -487,7 +501,6 @@ static void print_counter_aggr(struct perf_evsel *counter)
fprintf(stderr, " (scaled from %.2f%%)",
100 * avg_running / avg_enabled);
}
-
fprintf(stderr, "\n");
}
@@ -505,14 +518,18 @@ static void print_counter(struct perf_evsel *counter)
ena = counter->counts->cpu[cpu].ena;
run = counter->counts->cpu[cpu].run;
if (run == 0 || ena == 0) {
- fprintf(stderr, "CPU%*d%s%*s%s%-24s",
+ fprintf(stderr, "CPU%*d%s%*s%s%*s",
csv_output ? 0 : -4,
evsel_list->cpus->map[cpu], csv_sep,
csv_output ? 0 : 18,
"<not counted>", csv_sep,
+ csv_output ? 0 : -24,
event_name(counter));
- fprintf(stderr, "\n");
+ if (counter->cgrp)
+ fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
+
+ fputc('\n', stderr);
continue;
}
@@ -529,7 +546,7 @@ static void print_counter(struct perf_evsel *counter)
100.0 * run / ena);
}
}
- fprintf(stderr, "\n");
+ fputc('\n', stderr);
}
}
@@ -642,6 +659,9 @@ static const struct option options[] = {
"disable CPU count aggregation"),
OPT_STRING('x', "field-separator", &csv_sep, "separator",
"print counts with custom separator"),
+ OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+ "monitor event in cgroup name only",
+ parse_cgroups),
OPT_END()
};
@@ -682,9 +702,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
if (run_count <= 0)
usage_with_options(stat_usage, options);
- /* no_aggr is for system-wide only */
- if (no_aggr && !system_wide)
+ /* no_aggr, cgroup are for system-wide only */
+ if ((no_aggr || nr_cgroups) && !system_wide) {
+ fprintf(stderr, "both cgroup and no-aggregation "
+ "modes only available in system-wide mode\n");
+
usage_with_options(stat_usage, options);
+ }
/* Set attrs and nr_counters if no event is selected and !null_run */
if (!null_run && !evsel_list->nr_entries) {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 716118a..c9fd66d 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -139,7 +139,7 @@ static void sig_winch_handler(int sig __used)
static int parse_source(struct sym_entry *syme)
{
struct symbol *sym;
- struct sym_entry_source *source;
+ struct annotation *notes;
struct map *map;
int err = -1;
@@ -152,39 +152,35 @@ static int parse_source(struct sym_entry *syme)
/*
* We can't annotate with just /proc/kallsyms
*/
- if (map->dso->origin == DSO__ORIG_KERNEL)
+ if (map->dso->origin == DSO__ORIG_KERNEL) {
+ pr_err("Can't annotate %s: No vmlinux file was found in the "
+ "path\n", sym->name);
+ sleep(1);
return -1;
-
- if (syme->src == NULL) {
- syme->src = zalloc(sizeof(*source));
- if (syme->src == NULL)
- return -1;
- pthread_mutex_init(&syme->src->lock, NULL);
- INIT_LIST_HEAD(&syme->src->head);
}
- source = syme->src;
-
- if (symbol__annotation(sym)->histograms != NULL) {
- pthread_mutex_lock(&source->lock);
+ notes = symbol__annotation(sym);
+ if (notes->src != NULL) {
+ pthread_mutex_lock(&notes->lock);
goto out_assign;
}
- pthread_mutex_lock(&source->lock);
+ pthread_mutex_lock(&notes->lock);
if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
pr_err("Not enough memory for annotating '%s' symbol!\n",
sym->name);
+ sleep(1);
goto out_unlock;
}
- err = symbol__annotate(sym, syme->map, &source->head, 0);
+ err = symbol__annotate(sym, syme->map, 0);
if (err == 0) {
out_assign:
sym_filter_entry = syme;
}
out_unlock:
- pthread_mutex_unlock(&source->lock);
+ pthread_mutex_unlock(&notes->lock);
return err;
}
@@ -196,20 +192,27 @@ static void __zero_source_counters(struct sym_entry *syme)
static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
{
+ struct annotation *notes;
+ struct symbol *sym;
+
if (syme != sym_filter_entry)
return;
- if (pthread_mutex_trylock(&syme->src->lock))
+ sym = sym_entry__symbol(syme);
+ notes = symbol__annotation(sym);
+
+ if (pthread_mutex_trylock(&notes->lock))
return;
ip = syme->map->map_ip(syme->map, ip);
- symbol__inc_addr_samples(sym_entry__symbol(syme), syme->map, counter, ip);
+ symbol__inc_addr_samples(sym, syme->map, counter, ip);
- pthread_mutex_unlock(&syme->src->lock);
+ pthread_mutex_unlock(&notes->lock);
}
static void show_details(struct sym_entry *syme)
{
+ struct annotation *notes;
struct symbol *symbol;
int more;
@@ -217,24 +220,26 @@ static void show_details(struct sym_entry *syme)
return;
symbol = sym_entry__symbol(syme);
- if (!syme->src || symbol__annotation(symbol)->histograms == NULL)
- return;
+ notes = symbol__annotation(symbol);
+
+ pthread_mutex_lock(&notes->lock);
+
+ if (notes->src == NULL)
+ goto out_unlock;
printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
- pthread_mutex_lock(&syme->src->lock);
- more = symbol__annotate_printf(symbol, syme->map, &syme->src->head,
- top.sym_evsel->idx, 0, sym_pcnt_filter,
- top.print_entries);
+ more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx,
+ 0, sym_pcnt_filter, top.print_entries, 4);
if (top.zero)
symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
else
- symbol__annotate_decay_histogram(symbol, &syme->src->head,
- top.sym_evsel->idx);
- pthread_mutex_unlock(&syme->src->lock);
+ symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx);
if (more != 0)
printf("%d lines not displayed, maybe increase display entries [e]\n", more);
+out_unlock:
+ pthread_mutex_unlock(&notes->lock);
}
static const char CONSOLE_CLEAR[] = "";
@@ -372,10 +377,8 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
/* zero counters of active symbol */
if (syme) {
- pthread_mutex_lock(&syme->src->lock);
__zero_source_counters(syme);
*target = NULL;
- pthread_mutex_unlock(&syme->src->lock);
}
fprintf(stdout, "\n%s: ", msg);
@@ -554,10 +557,8 @@ static void handle_keypress(struct perf_session *session, int c)
else {
struct sym_entry *syme = sym_filter_entry;
- pthread_mutex_lock(&syme->src->lock);
sym_filter_entry = NULL;
__zero_source_counters(syme);
- pthread_mutex_unlock(&syme->src->lock);
}
break;
case 'U':
@@ -653,7 +654,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
syme = symbol__priv(sym);
syme->map = map;
- syme->src = NULL;
+ symbol__annotate_init(map, sym);
if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
/* schedule initial sym_filter_entry setup */
@@ -865,7 +866,7 @@ static int __cmd_top(void)
{
pthread_t thread;
struct perf_evsel *first;
- int ret;
+ int ret __used;
/*
* FIXME: perf_session__new should allow passing a O_MMAP, so that all this
* mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
@@ -875,8 +876,8 @@ static int __cmd_top(void)
return -ENOMEM;
if (top.target_tid != -1)
- perf_event__synthesize_thread(top.target_tid, perf_event__process,
- session);
+ perf_event__synthesize_thread_map(top.evlist->threads,
+ perf_event__process, session);
else
perf_event__synthesize_threads(perf_event__process, session);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 2973376..02976b8 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -14,25 +14,39 @@
#include "symbol.h"
#include "debug.h"
#include "annotate.h"
+#include <pthread.h>
-int symbol__alloc_hist(struct symbol *sym, int nevents)
+int symbol__annotate_init(struct map *map __used, struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
+ pthread_mutex_init(&notes->lock, NULL);
+ return 0;
+}
- notes->sizeof_sym_hist = (sizeof(*notes->histograms) +
+int symbol__alloc_hist(struct symbol *sym, int nevents)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
(sym->end - sym->start) * sizeof(u64));
- notes->histograms = calloc(nevents, notes->sizeof_sym_hist);
- notes->nr_histograms = nevents;
- return notes->histograms == NULL ? -1 : 0;
+
+ notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist);
+ if (notes->src == NULL)
+ return -1;
+ notes->src->sizeof_sym_hist = sizeof_sym_hist;
+ notes->src->nr_histograms = nevents;
+ INIT_LIST_HEAD(&notes->src->source);
+ return 0;
}
void symbol__annotate_zero_histograms(struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
- if (notes->histograms != NULL)
- memset(notes->histograms, 0,
- notes->nr_histograms * notes->sizeof_sym_hist);
+ pthread_mutex_lock(&notes->lock);
+ if (notes->src != NULL)
+ memset(notes->src->histograms, 0,
+ notes->src->nr_histograms * notes->src->sizeof_sym_hist);
+ pthread_mutex_unlock(&notes->lock);
}
int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
@@ -43,7 +57,7 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
struct sym_hist *h;
notes = symbol__annotation(sym);
- if (notes->histograms == NULL)
+ if (notes->src == NULL)
return -ENOMEM;
pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
@@ -95,10 +109,10 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
return NULL;
}
-static int objdump_line__print(struct objdump_line *oline,
- struct list_head *head, struct symbol *sym,
+static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
int evidx, u64 len, int min_pcnt,
- int printed, int max_lines)
+ int printed, int max_lines,
+ struct objdump_line *queue)
{
static const char *prev_line;
static const char *prev_color;
@@ -109,10 +123,12 @@ static int objdump_line__print(struct objdump_line *oline,
double percent = 0.0;
const char *color;
struct annotation *notes = symbol__annotation(sym);
- struct source_line *src_line = notes->src_line;
+ struct source_line *src_line = notes->src->lines;
struct sym_hist *h = annotation__histogram(notes, evidx);
s64 offset = oline->offset;
- struct objdump_line *next = objdump__get_next_ip_line(head, oline);
+ struct objdump_line *next;
+
+ next = objdump__get_next_ip_line(&notes->src->source, oline);
while (offset < (s64)len &&
(next == NULL || offset < next->offset)) {
@@ -132,9 +148,18 @@ static int objdump_line__print(struct objdump_line *oline,
if (percent < min_pcnt)
return -1;
- if (printed >= max_lines)
+ if (max_lines && printed >= max_lines)
return 1;
+ if (queue != NULL) {
+ list_for_each_entry_from(queue, &notes->src->source, node) {
+ if (queue == oline)
+ break;
+ objdump_line__print(queue, sym, evidx, len,
+ 0, 0, 1, NULL);
+ }
+ }
+
color = get_percent_color(percent);
/*
@@ -154,9 +179,12 @@ static int objdump_line__print(struct objdump_line *oline,
color_fprintf(stdout, color, " %7.2f", percent);
printf(" : ");
color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line);
- } else if (printed >= max_lines)
+ } else if (max_lines && printed >= max_lines)
return 1;
else {
+ if (queue)
+ return -1;
+
if (!*oline->line)
printf(" :\n");
else
@@ -166,9 +194,10 @@ static int objdump_line__print(struct objdump_line *oline,
return 0;
}
-static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE *file,
- struct list_head *head, size_t privsize)
+static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
+ FILE *file, size_t privsize)
{
+ struct annotation *notes = symbol__annotation(sym);
struct objdump_line *objdump_line;
char *line = NULL, *tmp, *tmp2, *c;
size_t line_len;
@@ -222,13 +251,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE
free(line);
return -1;
}
- objdump__add_line(head, objdump_line);
+ objdump__add_line(&notes->src->source, objdump_line);
return 0;
}
-int symbol__annotate(struct symbol *sym, struct map *map,
- struct list_head *head, size_t privsize)
+int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
{
struct dso *dso = map->dso;
char *filename = dso__build_id_filename(dso, NULL, 0);
@@ -236,7 +264,6 @@ int symbol__annotate(struct symbol *sym, struct map *map,
char command[PATH_MAX * 2];
FILE *file;
int err = 0;
- u64 len;
char symfs_filename[PATH_MAX];
if (filename) {
@@ -281,8 +308,6 @@ fallback:
filename, sym->name, map->unmap_ip(map, sym->start),
map->unmap_ip(map, sym->end));
- len = sym->end - sym->start;
-
pr_debug("annotating [%p] %30s : [%p] %30s\n",
dso, dso->long_name, sym, sym->name);
@@ -300,7 +325,7 @@ fallback:
goto out_free_filename;
while (!feof(file))
- if (symbol__parse_objdump_line(sym, map, file, head, privsize) < 0)
+ if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
break;
pclose(file);
@@ -333,14 +358,14 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
static void symbol__free_source_line(struct symbol *sym, int len)
{
struct annotation *notes = symbol__annotation(sym);
- struct source_line *src_line = notes->src_line;
+ struct source_line *src_line = notes->src->lines;
int i;
for (i = 0; i < len; i++)
free(src_line[i].path);
free(src_line);
- notes->src_line = NULL;
+ notes->src->lines = NULL;
}
/* Get the filename:line for the colored entries */
@@ -358,8 +383,8 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
if (!h->sum)
return 0;
- src_line = notes->src_line = calloc(len, sizeof(struct source_line));
- if (!notes->src_line)
+ src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
+ if (!notes->src->lines)
return -1;
start = map->unmap_ip(map, sym->start);
@@ -439,14 +464,15 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)
printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
}
-int symbol__annotate_printf(struct symbol *sym, struct map *map,
- struct list_head *head, int evidx, bool full_paths,
- int min_pcnt, int max_lines)
+int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
+ bool full_paths, int min_pcnt, int max_lines,
+ int context)
{
struct dso *dso = map->dso;
const char *filename = dso->long_name, *d_filename;
- struct objdump_line *pos;
- int printed = 2;
+ struct annotation *notes = symbol__annotation(sym);
+ struct objdump_line *pos, *queue = NULL;
+ int printed = 2, queue_len = 0;
int more = 0;
u64 len;
@@ -463,11 +489,21 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
if (verbose)
symbol__annotate_hits(sym, evidx);
- list_for_each_entry(pos, head, node) {
- switch (objdump_line__print(pos, head, sym, evidx, len, min_pcnt,
- printed, max_lines)) {
+ list_for_each_entry(pos, &notes->src->source, node) {
+ if (context && queue == NULL) {
+ queue = pos;
+ queue_len = 0;
+ }
+
+ switch (objdump_line__print(pos, sym, evidx, len, min_pcnt,
+ printed, max_lines, queue)) {
case 0:
++printed;
+ if (context) {
+ printed += queue_len;
+ queue = NULL;
+ queue_len = 0;
+ }
break;
case 1:
/* filtered by max_lines */
@@ -475,7 +511,16 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
break;
case -1:
default:
- /* filtered by min_pcnt */
+ /*
+ * Filtered by min_pcnt or non IP lines when
+ * context != 0
+ */
+ if (!context)
+ break;
+ if (queue_len == context)
+ queue = list_entry(queue->node.next, typeof(*queue), node);
+ else
+ ++queue_len;
break;
}
}
@@ -488,11 +533,10 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx);
- memset(h, 0, notes->sizeof_sym_hist);
+ memset(h, 0, notes->src->sizeof_sym_hist);
}
-void symbol__annotate_decay_histogram(struct symbol *sym,
- struct list_head *head, int evidx)
+void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
{
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx);
@@ -500,7 +544,7 @@ void symbol__annotate_decay_histogram(struct symbol *sym,
h->sum = 0;
- list_for_each_entry(pos, head, node) {
+ list_for_each_entry(pos, &notes->src->source, node) {
if (pos->offset != -1) {
h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
h->sum += h->addr[pos->offset];
@@ -525,10 +569,9 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
struct dso *dso = map->dso;
const char *filename = dso->long_name;
struct rb_root source_line = RB_ROOT;
- LIST_HEAD(head);
u64 len;
- if (symbol__annotate(sym, map, &head, 0) < 0)
+ if (symbol__annotate(sym, map, 0) < 0)
return -1;
len = sym->end - sym->start;
@@ -539,12 +582,12 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
print_summary(&source_line, filename);
}
- symbol__annotate_printf(sym, map, &head, evidx, full_paths,
- min_pcnt, max_lines);
+ symbol__annotate_printf(sym, map, evidx, full_paths,
+ min_pcnt, max_lines, 0);
if (print_lines)
symbol__free_source_line(sym, len);
- objdump_line_list__purge(&head);
+ objdump_line_list__purge(&symbol__annotation(sym)->src->source);
return 0;
}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index b1253aa..e848803 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -28,22 +28,29 @@ struct source_line {
char *path;
};
-/** struct annotation - symbols with hits have this attached as in sannotation
+/** struct annotated_source - symbols with hits have this attached as in sannotation
*
* @histogram: Array of addr hit histograms per event being monitored
- * @src_line: If 'print_lines' is specified, per source code line percentages
+ * @lines: If 'print_lines' is specified, per source code line percentages
+ * @source: source parsed from objdump -dS
*
- * src_line is allocated, percentages calculated and all sorted by percentage
+ * lines is allocated, percentages calculated and all sorted by percentage
* when the annotation is about to be presented, so the percentages are for
* one of the entries in the histogram array, i.e. for the event/counter being
* presented. It is deallocated right after symbol__{tui,tty,etc}_annotate
* returns.
*/
-struct annotation {
- struct source_line *src_line;
- struct sym_hist *histograms;
+struct annotated_source {
+ struct list_head source;
+ struct source_line *lines;
int nr_histograms;
int sizeof_sym_hist;
+ struct sym_hist histograms[0];
+};
+
+struct annotation {
+ pthread_mutex_t lock;
+ struct annotated_source *src;
};
struct sannotation {
@@ -53,7 +60,8 @@ struct sannotation {
static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
{
- return ((void *)notes->histograms) + (notes->sizeof_sym_hist * idx);
+ return (((void *)&notes->src->histograms) +
+ (notes->src->sizeof_sym_hist * idx));
}
static inline struct annotation *symbol__annotation(struct symbol *sym)
@@ -67,14 +75,13 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
int symbol__alloc_hist(struct symbol *sym, int nevents);
void symbol__annotate_zero_histograms(struct symbol *sym);
-int symbol__annotate(struct symbol *sym, struct map *map,
- struct list_head *head, size_t privsize);
-int symbol__annotate_printf(struct symbol *sym, struct map *map,
- struct list_head *head, int evidx, bool full_paths,
- int min_pcnt, int max_lines);
+int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
+int symbol__annotate_init(struct map *map __used, struct symbol *sym);
+int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
+ bool full_paths, int min_pcnt, int max_lines,
+ int context);
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
-void symbol__annotate_decay_histogram(struct symbol *sym,
- struct list_head *head, int evidx);
+void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
void objdump_line_list__purge(struct list_head *head);
int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
@@ -82,7 +89,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
int max_lines);
#ifdef NO_NEWT_SUPPORT
-static inline int symbol__tui_annotate(symbol *sym __used,
+static inline int symbol__tui_annotate(struct symbol *sym __used,
struct map *map __used, int evidx __used)
{
return 0;
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
new file mode 100644
index 0000000..9fea755
--- /dev/null
+++ b/tools/perf/util/cgroup.c
@@ -0,0 +1,178 @@
+#include "util.h"
+#include "../perf.h"
+#include "parse-options.h"
+#include "evsel.h"
+#include "cgroup.h"
+#include "debugfs.h" /* MAX_PATH, STR() */
+#include "evlist.h"
+
+int nr_cgroups;
+
+static int
+cgroupfs_find_mountpoint(char *buf, size_t maxlen)
+{
+ FILE *fp;
+ char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1];
+ char *token, *saved_ptr;
+ int found = 0;
+
+ fp = fopen("/proc/mounts", "r");
+ if (!fp)
+ return -1;
+
+ /*
+ * in order to handle split hierarchy, we need to scan /proc/mounts
+ * and inspect every cgroupfs mount point to find one that has
+ * perf_event subsystem
+ */
+ while (fscanf(fp, "%*s %"STR(MAX_PATH)"s %"STR(MAX_PATH)"s %"
+ STR(MAX_PATH)"s %*d %*d\n",
+ mountpoint, type, tokens) == 3) {
+
+ if (!strcmp(type, "cgroup")) {
+
+ token = strtok_r(tokens, ",", &saved_ptr);
+
+ while (token != NULL) {
+ if (!strcmp(token, "perf_event")) {
+ found = 1;
+ break;
+ }
+ token = strtok_r(NULL, ",", &saved_ptr);
+ }
+ }
+ if (found)
+ break;
+ }
+ fclose(fp);
+ if (!found)
+ return -1;
+
+ if (strlen(mountpoint) < maxlen) {
+ strcpy(buf, mountpoint);
+ return 0;
+ }
+ return -1;
+}
+
+static int open_cgroup(char *name)
+{
+ char path[MAX_PATH+1];
+ char mnt[MAX_PATH+1];
+ int fd;
+
+
+ if (cgroupfs_find_mountpoint(mnt, MAX_PATH+1))
+ return -1;
+
+ snprintf(path, MAX_PATH, "%s/%s", mnt, name);
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ fprintf(stderr, "no access to cgroup %s\n", path);
+
+ return fd;
+}
+
+static int add_cgroup(struct perf_evlist *evlist, char *str)
+{
+ struct perf_evsel *counter;
+ struct cgroup_sel *cgrp = NULL;
+ int n;
+ /*
+ * check if cgrp is already defined, if so we reuse it
+ */
+ list_for_each_entry(counter, &evlist->entries, node) {
+ cgrp = counter->cgrp;
+ if (!cgrp)
+ continue;
+ if (!strcmp(cgrp->name, str))
+ break;
+
+ cgrp = NULL;
+ }
+
+ if (!cgrp) {
+ cgrp = zalloc(sizeof(*cgrp));
+ if (!cgrp)
+ return -1;
+
+ cgrp->name = str;
+
+ cgrp->fd = open_cgroup(str);
+ if (cgrp->fd == -1) {
+ free(cgrp);
+ return -1;
+ }
+ }
+
+ /*
+ * find corresponding event
+ * if add cgroup N, then need to find event N
+ */
+ n = 0;
+ list_for_each_entry(counter, &evlist->entries, node) {
+ if (n == nr_cgroups)
+ goto found;
+ n++;
+ }
+ if (cgrp->refcnt == 0)
+ free(cgrp);
+
+ return -1;
+found:
+ cgrp->refcnt++;
+ counter->cgrp = cgrp;
+ return 0;
+}
+
+void close_cgroup(struct cgroup_sel *cgrp)
+{
+ if (!cgrp)
+ return;
+
+ /* XXX: not reentrant */
+ if (--cgrp->refcnt == 0) {
+ close(cgrp->fd);
+ free(cgrp->name);
+ free(cgrp);
+ }
+}
+
+int parse_cgroups(const struct option *opt __used, const char *str,
+ int unset __used)
+{
+ struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+ const char *p, *e, *eos = str + strlen(str);
+ char *s;
+ int ret;
+
+ if (list_empty(&evlist->entries)) {
+ fprintf(stderr, "must define events before cgroups\n");
+ return -1;
+ }
+
+ for (;;) {
+ p = strchr(str, ',');
+ e = p ? p : eos;
+
+ /* allow empty cgroups, i.e., skip */
+ if (e - str) {
+ /* termination added */
+ s = strndup(str, e - str);
+ if (!s)
+ return -1;
+ ret = add_cgroup(evlist, s);
+ if (ret) {
+ free(s);
+ return -1;
+ }
+ }
+ /* nr_cgroups is increased een for empty cgroups */
+ nr_cgroups++;
+ if (!p)
+ break;
+ str = p+1;
+ }
+ return 0;
+}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
new file mode 100644
index 0000000..89acd6d
--- /dev/null
+++ b/tools/perf/util/cgroup.h
@@ -0,0 +1,17 @@
+#ifndef __CGROUP_H__
+#define __CGROUP_H__
+
+struct option;
+
+struct cgroup_sel {
+ char *name;
+ int fd;
+ int refcnt;
+};
+
+
+extern int nr_cgroups; /* number of explicit cgroups defined */
+extern void close_cgroup(struct cgroup_sel *cgrp);
+extern int parse_cgroups(const struct option *opt, const char *str, int unset);
+
+#endif /* __CGROUP_H__ */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 731265f..fbf5754 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -6,6 +6,7 @@
#include "string.h"
#include "strlist.h"
#include "thread.h"
+#include "thread_map.h"
static const char *perf_event__names[] = {
[0] = "TOTAL",
@@ -265,11 +266,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,
process, session);
}
-int perf_event__synthesize_thread(pid_t pid, perf_event__handler_t process,
- struct perf_session *session)
+int perf_event__synthesize_thread_map(struct thread_map *threads,
+ perf_event__handler_t process,
+ struct perf_session *session)
{
union perf_event *comm_event, *mmap_event;
- int err = -1;
+ int err = -1, thread;
comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
if (comm_event == NULL)
@@ -279,8 +281,15 @@ int perf_event__synthesize_thread(pid_t pid, perf_event__handler_t process,
if (mmap_event == NULL)
goto out_free_comm;
- err = __event__synthesize_thread(comm_event, mmap_event, pid,
- process, session);
+ err = 0;
+ for (thread = 0; thread < threads->nr; ++thread) {
+ if (__event__synthesize_thread(comm_event, mmap_event,
+ threads->map[thread],
+ process, session)) {
+ err = -1;
+ break;
+ }
+ }
free(mmap_event);
out_free_comm:
free(comm_event);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index eecb422..9c35170 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -135,6 +135,7 @@ union perf_event {
void perf_event__print_totals(void);
struct perf_session;
+struct thread_map;
typedef int (*perf_event__handler_synth_t)(union perf_event *event,
struct perf_session *session);
@@ -142,8 +143,9 @@ typedef int (*perf_event__handler_t)(union perf_event *event,
struct perf_sample *sample,
struct perf_session *session);
-int perf_event__synthesize_thread(pid_t pid, perf_event__handler_t process,
- struct perf_session *session);
+int perf_event__synthesize_thread_map(struct thread_map *threads,
+ perf_event__handler_t process,
+ struct perf_session *session);
int perf_event__synthesize_threads(perf_event__handler_t process,
struct perf_session *session);
int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 211063e..c974e08 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -85,6 +85,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
void perf_evsel__delete(struct perf_evsel *evsel)
{
perf_evsel__exit(evsel);
+ close_cgroup(evsel->cgrp);
free(evsel);
}
@@ -163,21 +164,32 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
struct thread_map *threads, bool group, bool inherit)
{
int cpu, thread;
+ unsigned long flags = 0;
+ int pid = -1;
if (evsel->fd == NULL &&
perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
return -1;
+ if (evsel->cgrp) {
+ flags = PERF_FLAG_PID_CGROUP;
+ pid = evsel->cgrp->fd;
+ }
+
for (cpu = 0; cpu < cpus->nr; cpu++) {
int group_fd = -1;
evsel->attr.inherit = (cpus->map[cpu] < 0) && inherit;
for (thread = 0; thread < threads->nr; thread++) {
+
+ if (!evsel->cgrp)
+ pid = threads->map[thread];
+
FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
- threads->map[thread],
+ pid,
cpus->map[cpu],
- group_fd, 0);
+ group_fd, flags);
if (FD(evsel, cpu, thread) < 0)
goto out_close;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index eecdc3a..1d3d5a3 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -6,6 +6,7 @@
#include "../../../include/linux/perf_event.h"
#include "types.h"
#include "xyarray.h"
+#include "cgroup.h"
struct perf_counts_values {
union {
@@ -45,6 +46,7 @@ struct perf_evsel {
struct perf_counts *counts;
int idx;
void *priv;
+ struct cgroup_sel *cgrp;
};
struct cpu_map;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c0de5ec..72c124d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1145,7 +1145,7 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
{
union perf_event ev;
ssize_t size = 0, aligned_size = 0, padding;
- int err = 0;
+ int err __used = 0;
memset(&ev, 0, sizeof(ev));
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index bac5ab6..3f43723 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -955,10 +955,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
}
-int hist_entry__annotate(struct hist_entry *he, struct list_head *head,
- size_t privsize)
+int hist_entry__annotate(struct hist_entry *he, size_t privsize)
{
- return symbol__annotate(he->ms.sym, he->ms.map, head, privsize);
+ return symbol__annotate(he->ms.sym, he->ms.map, privsize);
}
void hists__inc_nr_events(struct hists *self, u32 type)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2c6cdae..37c7908 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -78,8 +78,7 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
bool show_displacement, FILE *fp);
int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
-int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
- size_t privsize);
+int hist_entry__annotate(struct hist_entry *self, size_t privsize);
void hists__filter_by_dso(struct hists *self, const struct dso *dso);
void hists__filter_by_thread(struct hists *self, const struct thread *thread);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 69215bf..fe461f6 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -33,6 +33,7 @@
#include <ctype.h>
#include <dwarf-regs.h>
+#include <linux/bitops.h>
#include "event.h"
#include "debug.h"
#include "util.h"
@@ -333,13 +334,23 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
return vr_die;
}
-static bool die_is_signed_type(Dwarf_Die *tp_die)
+static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
+ Dwarf_Word *result)
{
Dwarf_Attribute attr;
+
+ if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
+ dwarf_formudata(&attr, result) != 0)
+ return -ENOENT;
+
+ return 0;
+}
+
+static bool die_is_signed_type(Dwarf_Die *tp_die)
+{
Dwarf_Word ret;
- if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
- dwarf_formudata(&attr, &ret) != 0)
+ if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
return false;
return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
@@ -348,11 +359,29 @@ static bool die_is_signed_type(Dwarf_Die *tp_die)
static int die_get_byte_size(Dwarf_Die *tp_die)
{
- Dwarf_Attribute attr;
Dwarf_Word ret;
- if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
- dwarf_formudata(&attr, &ret) != 0)
+ if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret))
+ return 0;
+
+ return (int)ret;
+}
+
+static int die_get_bit_size(Dwarf_Die *tp_die)
+{
+ Dwarf_Word ret;
+
+ if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret))
+ return 0;
+
+ return (int)ret;
+}
+
+static int die_get_bit_offset(Dwarf_Die *tp_die)
+{
+ Dwarf_Word ret;
+
+ if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret))
return 0;
return (int)ret;
@@ -827,6 +856,8 @@ static_var:
return 0;
}
+#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long))
+
static int convert_variable_type(Dwarf_Die *vr_die,
struct probe_trace_arg *tvar,
const char *cast)
@@ -843,6 +874,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
return (tvar->type == NULL) ? -ENOMEM : 0;
}
+ if (die_get_bit_size(vr_die) != 0) {
+ /* This is a bitfield */
+ ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die),
+ die_get_bit_offset(vr_die),
+ BYTES_TO_BITS(die_get_byte_size(vr_die)));
+ goto formatted;
+ }
+
if (die_get_real_type(vr_die, &type) == NULL) {
pr_warning("Failed to get a type information of %s.\n",
dwarf_diename(vr_die));
@@ -887,29 +926,31 @@ static int convert_variable_type(Dwarf_Die *vr_die,
return (tvar->type == NULL) ? -ENOMEM : 0;
}
- ret = die_get_byte_size(&type) * 8;
- if (ret) {
- /* Check the bitwidth */
- if (ret > MAX_BASIC_TYPE_BITS) {
- pr_info("%s exceeds max-bitwidth."
- " Cut down to %d bits.\n",
- dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
- ret = MAX_BASIC_TYPE_BITS;
- }
+ ret = BYTES_TO_BITS(die_get_byte_size(&type));
+ if (!ret)
+ /* No size ... try to use default type */
+ return 0;
- ret = snprintf(buf, 16, "%c%d",
- die_is_signed_type(&type) ? 's' : 'u', ret);
- if (ret < 0 || ret >= 16) {
- if (ret >= 16)
- ret = -E2BIG;
- pr_warning("Failed to convert variable type: %s\n",
- strerror(-ret));
- return ret;
- }
- tvar->type = strdup(buf);
- if (tvar->type == NULL)
- return -ENOMEM;
+ /* Check the bitwidth */
+ if (ret > MAX_BASIC_TYPE_BITS) {
+ pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
+ dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
+ ret = MAX_BASIC_TYPE_BITS;
+ }
+ ret = snprintf(buf, 16, "%c%d",
+ die_is_signed_type(&type) ? 's' : 'u', ret);
+
+formatted:
+ if (ret < 0 || ret >= 16) {
+ if (ret >= 16)
+ ret = -E2BIG;
+ pr_warning("Failed to convert variable type: %s\n",
+ strerror(-ret));
+ return ret;
}
+ tvar->type = strdup(buf);
+ if (tvar->type == NULL)
+ return -ENOMEM;
return 0;
}
@@ -1234,51 +1275,38 @@ static int find_probe_point_by_line(struct probe_finder *pf)
static int find_lazy_match_lines(struct list_head *head,
const char *fname, const char *pat)
{
- char *fbuf, *p1, *p2;
- int fd, line, nlines = -1;
- struct stat st;
+ FILE *fp;
+ char *line = NULL;
+ size_t line_len;
+ ssize_t len;
+ int count = 0, linenum = 1;
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
+ fp = fopen(fname, "r");
+ if (!fp) {
+ pr_warning("Failed to open %s: %s\n", fname, strerror(errno));
return -errno;
}
- if (fstat(fd, &st) < 0) {
- pr_warning("Failed to get the size of %s: %s\n",
- fname, strerror(errno));
- nlines = -errno;
- goto out_close;
- }
-
- nlines = -ENOMEM;
- fbuf = malloc(st.st_size + 2);
- if (fbuf == NULL)
- goto out_close;
- if (read(fd, fbuf, st.st_size) < 0) {
- pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
- nlines = -errno;
- goto out_free_fbuf;
- }
- fbuf[st.st_size] = '\n'; /* Dummy line */
- fbuf[st.st_size + 1] = '\0';
- p1 = fbuf;
- line = 1;
- nlines = 0;
- while ((p2 = strchr(p1, '\n')) != NULL) {
- *p2 = '\0';
- if (strlazymatch(p1, pat)) {
- line_list__add_line(head, line);
- nlines++;
+ while ((len = getline(&line, &line_len, fp)) > 0) {
+
+ if (line[len - 1] == '\n')
+ line[len - 1] = '\0';
+
+ if (strlazymatch(line, pat)) {
+ line_list__add_line(head, linenum);
+ count++;
}
- line++;
- p1 = p2 + 1;
+ linenum++;
}
-out_free_fbuf:
- free(fbuf);
-out_close:
- close(fd);
- return nlines;
+
+ if (ferror(fp))
+ count = -errno;
+ free(line);
+ fclose(fp);
+
+ if (count == 0)
+ pr_debug("No matched lines found in %s.\n", fname);
+ return count;
}
static int probe_point_lazy_walker(const char *fname, int lineno,
@@ -1312,10 +1340,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
/* Matching lazy line pattern */
ret = find_lazy_match_lines(&pf->lcache, pf->fname,
pf->pev->point.lazy_line);
- if (ret == 0) {
- pr_debug("No matched lines found in %s.\n", pf->fname);
- return 0;
- } else if (ret < 0)
+ if (ret <= 0)
return ret;
}
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index c6d9933..2040b85 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -248,8 +248,7 @@ static void python_process_event(int cpu, void *data,
context = PyCObject_FromVoidPtr(scripting_context, NULL);
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
- PyTuple_SetItem(t, n++,
- PyCObject_FromVoidPtr(scripting_context, NULL));
+ PyTuple_SetItem(t, n++, context);
if (handler) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 7821d0e..3e193f8 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1525,8 +1525,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
symbol_conf.symfs, self->long_name);
break;
case DSO__ORIG_GUEST_KMODULE:
- if (map->groups && map->groups->machine)
- root_dir = map->groups->machine->root_dir;
+ if (map->groups && machine)
+ root_dir = machine->root_dir;
else
root_dir = "";
snprintf(name, size, "%s%s%s", symbol_conf.symfs,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index fe44afb..4f769f4 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -11,11 +11,6 @@
struct perf_evlist;
struct perf_evsel;
-struct sym_entry_source {
- struct list_head head;
- pthread_mutex_t lock;
-};
-
struct sym_entry {
struct rb_node rb_node;
struct list_head node;
@@ -24,7 +19,6 @@ struct sym_entry {
int skip;
u8 origin;
struct map *map;
- struct sym_entry_source *src;
unsigned long count[0];
};
@@ -46,8 +40,8 @@ struct perf_top {
u64 exact_samples;
u64 guest_us_samples, guest_kernel_samples;
int print_entries, count_filter, delay_secs;
- int display_weighted, freq, rb_entries;
- int sym_counter, target_pid, target_tid;
+ int display_weighted, freq, rb_entries, sym_counter;
+ pid_t target_pid, target_tid;
bool hide_kernel_symbols, hide_user_symbols, zero;
const char *cpu_list;
struct perf_evsel *sym_evsel;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 73a0222..d8e622d 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -153,7 +153,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
char *next = NULL;
char *addr_str;
char ch;
- int ret;
+ int ret __used;
int i;
line = strtok_r(file, "\n", &next);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 8d8a168..1aa3965 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -60,7 +60,6 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
}
static double objdump_line__calc_percent(struct objdump_line *self,
- struct list_head *head,
struct symbol *sym, int evidx)
{
double percent = 0.0;
@@ -69,11 +68,12 @@ static double objdump_line__calc_percent(struct objdump_line *self,
int len = sym->end - sym->start;
unsigned int hits = 0;
struct annotation *notes = symbol__annotation(sym);
- struct source_line *src_line = notes->src_line;
+ struct source_line *src_line = notes->src->lines;
struct sym_hist *h = annotation__histogram(notes, evidx);
s64 offset = self->offset;
- struct objdump_line *next = objdump__get_next_ip_line(head, self);
+ struct objdump_line *next;
+ next = objdump__get_next_ip_line(&notes->src->source, self);
while (offset < (s64)len &&
(next == NULL || offset < next->offset)) {
if (src_line) {
@@ -192,10 +192,10 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
{
struct objdump_line *pos, *n;
struct objdump_line_rb_node *rbpos;
- LIST_HEAD(head);
+ struct annotation *notes = symbol__annotation(sym);
struct annotate_browser browser = {
.b = {
- .entries = &head,
+ .entries = &notes->src->source,
.refresh = ui_browser__list_head_refresh,
.seek = ui_browser__list_head_seek,
.write = annotate_browser__write,
@@ -210,20 +210,20 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
if (map->dso->annotate_warned)
return -1;
- if (symbol__annotate(sym, map, &head, sizeof(*rbpos)) < 0) {
+ if (symbol__annotate(sym, map, sizeof(*rbpos)) < 0) {
ui__error_window(ui_helpline__last_msg);
return -1;
}
ui_helpline__push("Press <- or ESC to exit");
- list_for_each_entry(pos, &head, node) {
+ list_for_each_entry(pos, &notes->src->source, node) {
size_t line_len = strlen(pos->line);
if (browser.b.width < line_len)
browser.b.width = line_len;
rbpos = objdump_line__rb(pos);
rbpos->idx = browser.b.nr_entries++;
- rbpos->percent = objdump_line__calc_percent(pos, &head, sym, evidx);
+ rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
if (rbpos->percent < 0.01)
continue;
objdump__insert_line(&browser.entries, rbpos);
@@ -238,7 +238,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
browser.b.width += 18; /* Percentage */
ret = annotate_browser__run(&browser);
- list_for_each_entry_safe(pos, n, &head, node) {
+ list_for_each_entry_safe(pos, n, &notes->src->source, node) {
list_del(&pos->node);
objdump_line__free(pos);
}
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index e515836..8462bff 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -41,7 +41,7 @@ static int ui_entry__read(const char *title, char *bf, size_t size, int width)
out_free_form:
newtPopWindow();
newtFormDestroy(form);
- return 0;
+ return err;
}
struct map_browser {
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 4c6983d..362a0cb 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -72,7 +72,7 @@ int need_reinitialize;
int num_cpus;
-typedef struct per_cpu_counters {
+struct counters {
unsigned long long tsc; /* per thread */
unsigned long long aperf; /* per thread */
unsigned long long mperf; /* per thread */
@@ -88,13 +88,13 @@ typedef struct per_cpu_counters {
int pkg;
int core;
int cpu;
- struct per_cpu_counters *next;
-} PCC;
+ struct counters *next;
+};
-PCC *pcc_even;
-PCC *pcc_odd;
-PCC *pcc_delta;
-PCC *pcc_average;
+struct counters *cnt_even;
+struct counters *cnt_odd;
+struct counters *cnt_delta;
+struct counters *cnt_average;
struct timeval tv_even;
struct timeval tv_odd;
struct timeval tv_delta;
@@ -125,7 +125,7 @@ unsigned long long get_msr(int cpu, off_t offset)
return msr;
}
-void print_header()
+void print_header(void)
{
if (show_pkg)
fprintf(stderr, "pkg ");
@@ -160,39 +160,39 @@ void print_header()
putc('\n', stderr);
}
-void dump_pcc(PCC *pcc)
+void dump_cnt(struct counters *cnt)
{
- fprintf(stderr, "package: %d ", pcc->pkg);
- fprintf(stderr, "core:: %d ", pcc->core);
- fprintf(stderr, "CPU: %d ", pcc->cpu);
- fprintf(stderr, "TSC: %016llX\n", pcc->tsc);
- fprintf(stderr, "c3: %016llX\n", pcc->c3);
- fprintf(stderr, "c6: %016llX\n", pcc->c6);
- fprintf(stderr, "c7: %016llX\n", pcc->c7);
- fprintf(stderr, "aperf: %016llX\n", pcc->aperf);
- fprintf(stderr, "pc2: %016llX\n", pcc->pc2);
- fprintf(stderr, "pc3: %016llX\n", pcc->pc3);
- fprintf(stderr, "pc6: %016llX\n", pcc->pc6);
- fprintf(stderr, "pc7: %016llX\n", pcc->pc7);
- fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, pcc->extra_msr);
+ fprintf(stderr, "package: %d ", cnt->pkg);
+ fprintf(stderr, "core:: %d ", cnt->core);
+ fprintf(stderr, "CPU: %d ", cnt->cpu);
+ fprintf(stderr, "TSC: %016llX\n", cnt->tsc);
+ fprintf(stderr, "c3: %016llX\n", cnt->c3);
+ fprintf(stderr, "c6: %016llX\n", cnt->c6);
+ fprintf(stderr, "c7: %016llX\n", cnt->c7);
+ fprintf(stderr, "aperf: %016llX\n", cnt->aperf);
+ fprintf(stderr, "pc2: %016llX\n", cnt->pc2);
+ fprintf(stderr, "pc3: %016llX\n", cnt->pc3);
+ fprintf(stderr, "pc6: %016llX\n", cnt->pc6);
+ fprintf(stderr, "pc7: %016llX\n", cnt->pc7);
+ fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, cnt->extra_msr);
}
-void dump_list(PCC *pcc)
+void dump_list(struct counters *cnt)
{
- printf("dump_list 0x%p\n", pcc);
+ printf("dump_list 0x%p\n", cnt);
- for (; pcc; pcc = pcc->next)
- dump_pcc(pcc);
+ for (; cnt; cnt = cnt->next)
+ dump_cnt(cnt);
}
-void print_pcc(PCC *p)
+void print_cnt(struct counters *p)
{
double interval_float;
interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
/* topology columns, print blanks on 1st (average) line */
- if (p == pcc_average) {
+ if (p == cnt_average) {
if (show_pkg)
fprintf(stderr, " ");
if (show_core)
@@ -262,24 +262,24 @@ void print_pcc(PCC *p)
putc('\n', stderr);
}
-void print_counters(PCC *cnt)
+void print_counters(struct counters *counters)
{
- PCC *pcc;
+ struct counters *cnt;
print_header();
if (num_cpus > 1)
- print_pcc(pcc_average);
+ print_cnt(cnt_average);
- for (pcc = cnt; pcc != NULL; pcc = pcc->next)
- print_pcc(pcc);
+ for (cnt = counters; cnt != NULL; cnt = cnt->next)
+ print_cnt(cnt);
}
#define SUBTRACT_COUNTER(after, before, delta) (delta = (after - before), (before > after))
-
-int compute_delta(PCC *after, PCC *before, PCC *delta)
+int compute_delta(struct counters *after,
+ struct counters *before, struct counters *delta)
{
int errors = 0;
int perf_err = 0;
@@ -391,20 +391,20 @@ int compute_delta(PCC *after, PCC *before, PCC *delta)
delta->extra_msr = after->extra_msr;
if (errors) {
fprintf(stderr, "ERROR cpu%d before:\n", before->cpu);
- dump_pcc(before);
+ dump_cnt(before);
fprintf(stderr, "ERROR cpu%d after:\n", before->cpu);
- dump_pcc(after);
+ dump_cnt(after);
errors = 0;
}
}
return 0;
}
-void compute_average(PCC *delta, PCC *avg)
+void compute_average(struct counters *delta, struct counters *avg)
{
- PCC *sum;
+ struct counters *sum;
- sum = calloc(1, sizeof(PCC));
+ sum = calloc(1, sizeof(struct counters));
if (sum == NULL) {
perror("calloc sum");
exit(1);
@@ -438,35 +438,34 @@ void compute_average(PCC *delta, PCC *avg)
free(sum);
}
-void get_counters(PCC *pcc)
+void get_counters(struct counters *cnt)
{
- for ( ; pcc; pcc = pcc->next) {
- pcc->tsc = get_msr(pcc->cpu, MSR_TSC);
+ for ( ; cnt; cnt = cnt->next) {
+ cnt->tsc = get_msr(cnt->cpu, MSR_TSC);
if (do_nhm_cstates)
- pcc->c3 = get_msr(pcc->cpu, MSR_CORE_C3_RESIDENCY);
+ cnt->c3 = get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY);
if (do_nhm_cstates)
- pcc->c6 = get_msr(pcc->cpu, MSR_CORE_C6_RESIDENCY);
+ cnt->c6 = get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY);
if (do_snb_cstates)
- pcc->c7 = get_msr(pcc->cpu, MSR_CORE_C7_RESIDENCY);
+ cnt->c7 = get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY);
if (has_aperf)
- pcc->aperf = get_msr(pcc->cpu, MSR_APERF);
+ cnt->aperf = get_msr(cnt->cpu, MSR_APERF);
if (has_aperf)
- pcc->mperf = get_msr(pcc->cpu, MSR_MPERF);
+ cnt->mperf = get_msr(cnt->cpu, MSR_MPERF);
if (do_snb_cstates)
- pcc->pc2 = get_msr(pcc->cpu, MSR_PKG_C2_RESIDENCY);
+ cnt->pc2 = get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY);
if (do_nhm_cstates)
- pcc->pc3 = get_msr(pcc->cpu, MSR_PKG_C3_RESIDENCY);
+ cnt->pc3 = get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY);
if (do_nhm_cstates)
- pcc->pc6 = get_msr(pcc->cpu, MSR_PKG_C6_RESIDENCY);
+ cnt->pc6 = get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY);
if (do_snb_cstates)
- pcc->pc7 = get_msr(pcc->cpu, MSR_PKG_C7_RESIDENCY);
+ cnt->pc7 = get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY);
if (extra_msr_offset)
- pcc->extra_msr = get_msr(pcc->cpu, extra_msr_offset);
+ cnt->extra_msr = get_msr(cnt->cpu, extra_msr_offset);
}
}
-
-void print_nehalem_info()
+void print_nehalem_info(void)
{
unsigned long long msr;
unsigned int ratio;
@@ -514,38 +513,38 @@ void print_nehalem_info()
}
-void free_counter_list(PCC *list)
+void free_counter_list(struct counters *list)
{
- PCC *p;
+ struct counters *p;
for (p = list; p; ) {
- PCC *free_me;
+ struct counters *free_me;
free_me = p;
p = p->next;
free(free_me);
}
- return;
}
void free_all_counters(void)
{
- free_counter_list(pcc_even);
- pcc_even = NULL;
+ free_counter_list(cnt_even);
+ cnt_even = NULL;
- free_counter_list(pcc_odd);
- pcc_odd = NULL;
+ free_counter_list(cnt_odd);
+ cnt_odd = NULL;
- free_counter_list(pcc_delta);
- pcc_delta = NULL;
+ free_counter_list(cnt_delta);
+ cnt_delta = NULL;
- free_counter_list(pcc_average);
- pcc_average = NULL;
+ free_counter_list(cnt_average);
+ cnt_average = NULL;
}
-void insert_cpu_counters(PCC **list, PCC *new)
+void insert_counters(struct counters **list,
+ struct counters *new)
{
- PCC *prev;
+ struct counters *prev;
/*
* list was empty
@@ -594,18 +593,16 @@ void insert_cpu_counters(PCC **list, PCC *new)
*/
new->next = prev->next;
prev->next = new;
-
- return;
}
-void alloc_new_cpu_counters(int pkg, int core, int cpu)
+void alloc_new_counters(int pkg, int core, int cpu)
{
- PCC *new;
+ struct counters *new;
if (verbose > 1)
printf("pkg%d core%d, cpu%d\n", pkg, core, cpu);
- new = (PCC *)calloc(1, sizeof(PCC));
+ new = (struct counters *)calloc(1, sizeof(struct counters));
if (new == NULL) {
perror("calloc");
exit(1);
@@ -613,9 +610,10 @@ void alloc_new_cpu_counters(int pkg, int core, int cpu)
new->pkg = pkg;
new->core = core;
new->cpu = cpu;
- insert_cpu_counters(&pcc_odd, new);
+ insert_counters(&cnt_odd, new);
- new = (PCC *)calloc(1, sizeof(PCC));
+ new = (struct counters *)calloc(1,
+ sizeof(struct counters));
if (new == NULL) {
perror("calloc");
exit(1);
@@ -623,9 +621,9 @@ void alloc_new_cpu_counters(int pkg, int core, int cpu)
new->pkg = pkg;
new->core = core;
new->cpu = cpu;
- insert_cpu_counters(&pcc_even, new);
+ insert_counters(&cnt_even, new);
- new = (PCC *)calloc(1, sizeof(PCC));
+ new = (struct counters *)calloc(1, sizeof(struct counters));
if (new == NULL) {
perror("calloc");
exit(1);
@@ -633,9 +631,9 @@ void alloc_new_cpu_counters(int pkg, int core, int cpu)
new->pkg = pkg;
new->core = core;
new->cpu = cpu;
- insert_cpu_counters(&pcc_delta, new);
+ insert_counters(&cnt_delta, new);
- new = (PCC *)calloc(1, sizeof(PCC));
+ new = (struct counters *)calloc(1, sizeof(struct counters));
if (new == NULL) {
perror("calloc");
exit(1);
@@ -643,7 +641,7 @@ void alloc_new_cpu_counters(int pkg, int core, int cpu)
new->pkg = pkg;
new->core = core;
new->cpu = cpu;
- pcc_average = new;
+ cnt_average = new;
}
int get_physical_package_id(int cpu)
@@ -719,7 +717,7 @@ void re_initialize(void)
{
printf("turbostat: topology changed, re-initializing.\n");
free_all_counters();
- num_cpus = for_all_cpus(alloc_new_cpu_counters);
+ num_cpus = for_all_cpus(alloc_new_counters);
need_reinitialize = 0;
printf("num_cpus is now %d\n", num_cpus);
}
@@ -728,7 +726,7 @@ void dummy(int pkg, int core, int cpu) { return; }
/*
* check to see if a cpu came on-line
*/
-void verify_num_cpus()
+void verify_num_cpus(void)
{
int new_num_cpus;
@@ -740,14 +738,12 @@ void verify_num_cpus()
num_cpus, new_num_cpus);
need_reinitialize = 1;
}
-
- return;
}
void turbostat_loop()
{
restart:
- get_counters(pcc_even);
+ get_counters(cnt_even);
gettimeofday(&tv_even, (struct timezone *)NULL);
while (1) {
@@ -757,24 +753,24 @@ restart:
goto restart;
}
sleep(interval_sec);
- get_counters(pcc_odd);
+ get_counters(cnt_odd);
gettimeofday(&tv_odd, (struct timezone *)NULL);
- compute_delta(pcc_odd, pcc_even, pcc_delta);
+ compute_delta(cnt_odd, cnt_even, cnt_delta);
timersub(&tv_odd, &tv_even, &tv_delta);
- compute_average(pcc_delta, pcc_average);
- print_counters(pcc_delta);
+ compute_average(cnt_delta, cnt_average);
+ print_counters(cnt_delta);
if (need_reinitialize) {
re_initialize();
goto restart;
}
sleep(interval_sec);
- get_counters(pcc_even);
+ get_counters(cnt_even);
gettimeofday(&tv_even, (struct timezone *)NULL);
- compute_delta(pcc_even, pcc_odd, pcc_delta);
+ compute_delta(cnt_even, cnt_odd, cnt_delta);
timersub(&tv_even, &tv_odd, &tv_delta);
- compute_average(pcc_delta, pcc_average);
- print_counters(pcc_delta);
+ compute_average(cnt_delta, cnt_average);
+ print_counters(cnt_delta);
}
}
@@ -892,7 +888,7 @@ void check_cpuid()
* this check is valid for both Intel and AMD
*/
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007));
- has_invariant_tsc = edx && (1 << 8);
+ has_invariant_tsc = edx & (1 << 8);
if (!has_invariant_tsc) {
fprintf(stderr, "No invariant TSC\n");
@@ -905,7 +901,7 @@ void check_cpuid()
*/
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6));
- has_aperf = ecx && (1 << 0);
+ has_aperf = ecx & (1 << 0);
if (!has_aperf) {
fprintf(stderr, "No APERF MSR\n");
exit(1);
@@ -952,7 +948,7 @@ void turbostat_init()
check_dev_msr();
check_super_user();
- num_cpus = for_all_cpus(alloc_new_cpu_counters);
+ num_cpus = for_all_cpus(alloc_new_counters);
if (verbose)
print_nehalem_info();
@@ -962,7 +958,7 @@ int fork_it(char **argv)
{
int retval;
pid_t child_pid;
- get_counters(pcc_even);
+ get_counters(cnt_even);
gettimeofday(&tv_even, (struct timezone *)NULL);
child_pid = fork();
@@ -985,14 +981,14 @@ int fork_it(char **argv)
exit(1);
}
}
- get_counters(pcc_odd);
+ get_counters(cnt_odd);
gettimeofday(&tv_odd, (struct timezone *)NULL);
- retval = compute_delta(pcc_odd, pcc_even, pcc_delta);
+ retval = compute_delta(cnt_odd, cnt_even, cnt_delta);
timersub(&tv_odd, &tv_even, &tv_delta);
- compute_average(pcc_delta, pcc_average);
+ compute_average(cnt_delta, cnt_average);
if (!retval)
- print_counters(pcc_delta);
+ print_counters(cnt_delta);
fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);;
OpenPOWER on IntegriCloud