Commit 5242519b authored by Ingo Molnar's avatar Ingo Molnar

perf stat: Convert to Git option parsing

Remove getopt usage and use Git's much more advanced and more compact
command option library.

Extend the event parser library with the extensions that were in
perf-stat before.

Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 8ad8db37
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include "util/util.h" #include "util/util.h"
#include "util/parse-options.h" #include "util/parse-options.h"
#include "util/parse-events.h" #include "util/parse-events.h"
#include "util/exec_cmd.h"
#include <sched.h> #include <sched.h>
...@@ -400,7 +399,7 @@ static const char * const record_usage[] = { ...@@ -400,7 +399,7 @@ static const char * const record_usage[] = {
static char events_help_msg[EVENTS_HELP_MAX]; static char events_help_msg[EVENTS_HELP_MAX];
const struct option options[] = { static const struct option options[] = {
OPT_CALLBACK('e', "event", NULL, "event", OPT_CALLBACK('e', "event", NULL, "event",
events_help_msg, parse_events), events_help_msg, parse_events),
OPT_INTEGER('c', "count", &default_interval, OPT_INTEGER('c', "count", &default_interval,
......
This diff is collapsed.
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
int nr_counters; int nr_counters;
__u64 event_id[MAX_COUNTERS] = { }; __u64 event_id[MAX_COUNTERS] = { };
int event_mask[MAX_COUNTERS];
struct event_symbol { struct event_symbol {
__u64 event; __u64 event;
...@@ -37,6 +38,64 @@ static struct event_symbol event_symbols[] = { ...@@ -37,6 +38,64 @@ static struct event_symbol event_symbols[] = {
{EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "migrations", }, {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "migrations", },
}; };
#define __PERF_COUNTER_FIELD(config, name) \
((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
static char *hw_event_names[] = {
"CPU cycles",
"instructions",
"cache references",
"cache misses",
"branches",
"branch misses",
"bus cycles",
};
static char *sw_event_names[] = {
"cpu clock ticks",
"task clock ticks",
"pagefaults",
"context switches",
"CPU migrations",
"minor faults",
"major faults",
};
char *event_name(int ctr)
{
__u64 config = event_id[ctr];
int type = PERF_COUNTER_TYPE(config);
int id = PERF_COUNTER_ID(config);
static char buf[32];
if (PERF_COUNTER_RAW(config)) {
sprintf(buf, "raw 0x%llx", PERF_COUNTER_CONFIG(config));
return buf;
}
switch (type) {
case PERF_TYPE_HARDWARE:
if (id < PERF_HW_EVENTS_MAX)
return hw_event_names[id];
return "unknown-hardware";
case PERF_TYPE_SOFTWARE:
if (id < PERF_SW_EVENTS_MAX)
return sw_event_names[id];
return "unknown-software";
default:
break;
}
return "unknown";
}
/* /*
* Each event can have multiple symbolic names. * Each event can have multiple symbolic names.
* Symbolic names are (almost) exactly matched. * Symbolic names are (almost) exactly matched.
...@@ -46,12 +105,23 @@ static __u64 match_event_symbols(const char *str) ...@@ -46,12 +105,23 @@ static __u64 match_event_symbols(const char *str)
__u64 config, id; __u64 config, id;
int type; int type;
unsigned int i; unsigned int i;
char mask_str[4];
if (sscanf(str, "r%llx", &config) == 1) if (sscanf(str, "r%llx", &config) == 1)
return config | PERF_COUNTER_RAW_MASK; return config | PERF_COUNTER_RAW_MASK;
if (sscanf(str, "%d:%llu", &type, &id) == 2) switch (sscanf(str, "%d:%llu:%2s", &type, &id, mask_str)) {
return EID(type, id); case 3:
if (strchr(mask_str, 'k'))
event_mask[nr_counters] |= EVENT_MASK_USER;
if (strchr(mask_str, 'u'))
event_mask[nr_counters] |= EVENT_MASK_KERNEL;
case 2:
return EID(type, id);
default:
break;
}
for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
if (!strncmp(str, event_symbols[i].symbol, if (!strncmp(str, event_symbols[i].symbol,
...@@ -86,14 +156,6 @@ int parse_events(const struct option *opt, const char *str, int unset) ...@@ -86,14 +156,6 @@ int parse_events(const struct option *opt, const char *str, int unset)
return 0; return 0;
} }
#define __PERF_COUNTER_FIELD(config, name) \
((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
/* /*
* Create the help text for the event symbols: * Create the help text for the event symbols:
*/ */
......
/*
* Parse symbolic events/counts passed in as options:
*/
extern int nr_counters; extern int nr_counters;
extern __u64 event_id[MAX_COUNTERS]; extern __u64 event_id[MAX_COUNTERS];
extern int event_mask[MAX_COUNTERS];
#define EVENT_MASK_KERNEL 1
#define EVENT_MASK_USER 2
extern char *event_name(int ctr);
extern int parse_events(const struct option *opt, const char *str, int unset); extern int parse_events(const struct option *opt, const char *str, int unset);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment