[PATCH 23/31] perf, tools: Add support for generic transaction events to perf userspace
From: Andi Kleen
Date: Fri Sep 28 2012 - 00:37:39 EST
From: Andi Kleen <ak@xxxxxxxxxxxxxxx>
Add the generic transaction events with aliases to the parser, lexer
and the reverse map code.
Signed-off-by: Andi Kleen <ak@xxxxxxxxxxxxxxx>
---
tools/perf/util/evsel.c | 40 ++++++++++++++++++++++++++++++++++++++++
tools/perf/util/parse-events.c | 24 ++++++++++++++++++++++++
tools/perf/util/parse-events.l | 19 ++++++++++++++++++-
tools/perf/util/parse-events.y | 4 ++--
4 files changed, 84 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ff084b0..8790069 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -288,6 +288,42 @@ static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t
return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
}
+static const char *transaction_name[] = {
+ [PERF_COUNT_HW_TRANSACTION_START] = "transaction-start",
+ [PERF_COUNT_HW_TRANSACTION_COMMIT] = "transaction-commit",
+ [PERF_COUNT_HW_TRANSACTION_ABORT] = "transaction-abort",
+ [PERF_COUNT_HW_ELISION_START] = "elision-start",
+ [PERF_COUNT_HW_ELISION_COMMIT] = "elision-commit",
+ [PERF_COUNT_HW_ELISION_ABORT] = "elision-abort",
+};
+
+static const char *transaction_reason[] = {
+ [PERF_COUNT_HW_ABORT_ALL] = "all",
+ [PERF_COUNT_HW_ABORT_CONFLICT] = "conflict",
+ [PERF_COUNT_HW_ABORT_CAPACITY] = "capacity",
+};
+
+static int perf_evsel__transaction_name(struct perf_evsel *evsel, char *bf,
+ size_t size)
+{
+ u64 config = evsel->attr.config;
+ u8 name = config & 0xff, reason = (config >> 8) & 0xff;
+
+ if (name < PERF_COUNT_HW_TRANSACTION_MAX &&
+ reason < PERF_COUNT_HW_ABORT_MAX) {
+ const char *sep = "", *rtxt = "";
+ if (name == PERF_COUNT_HW_TRANSACTION_ABORT ||
+ name == PERF_COUNT_HW_ELISION_ABORT) {
+ sep = "-";
+ rtxt = transaction_reason[reason];
+ }
+ return scnprintf(bf, size, "%s%s%s", transaction_name[name],
+ sep, rtxt);
+ }
+
+ return scnprintf(bf, size, "invalid-transaction");
+}
+
static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
{
int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
@@ -326,6 +362,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
perf_evsel__bp_name(evsel, bf, sizeof(bf));
break;
+ case PERF_TYPE_HW_TRANSACTION:
+ perf_evsel__transaction_name(evsel, bf, sizeof(bf));
+ break;
+
default:
scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
break;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5668ca6..e24a490 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -110,6 +110,20 @@ static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
},
};
+static struct event_symbol event_symbols_txn[] = {
+ { .symbol = "transaction-start", .alias = "tx-start" },
+ { .symbol = "transaction-commit", .alias = "tx-commit" },
+ { .symbol = "transaction-abort-all", .alias = "tx-abort" },
+ { .symbol = "transaction-abort-capacity", .alias = "tx-capacity" },
+ { .symbol = "transaction-abort-conflict", .alias = "tx-conflict" },
+ { .symbol = "elision-start", .alias = "le-start" },
+ { .symbol = "elision-commit", .alias = "le-commit" },
+ { .symbol = "elision-abort-all", .alias = "le-abort" },
+ { .symbol = "elision-abort-capacity", .alias = "le-capacity" },
+ { .symbol = "elision-abort-conflict", .alias = "le-conflict" },
+
+};
+
#define __PERF_EVENT_FIELD(config, name) \
((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
@@ -232,6 +246,9 @@ const char *event_type(int type)
case PERF_TYPE_HW_CACHE:
return "hardware-cache";
+ case PERF_TYPE_HW_TRANSACTION:
+ return "hardware-transaction";
+
default:
break;
}
@@ -800,6 +817,7 @@ static const char * const event_type_descriptors[] = {
"Hardware cache event",
"Raw hardware event descriptor",
"Hardware breakpoint",
+ "Hardware transaction event",
};
/*
@@ -909,6 +927,9 @@ void print_events_type(u8 type)
{
if (type == PERF_TYPE_SOFTWARE)
__print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
+ else if (type == PERF_TYPE_HW_TRANSACTION)
+ __print_events_type(type, event_symbols_txn,
+ ARRAY_SIZE(event_symbols_txn));
else
__print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
}
@@ -984,6 +1005,9 @@ void print_events(const char *event_glob)
print_hwcache_events(event_glob);
+ print_symbol_events(event_glob, PERF_TYPE_HW_TRANSACTION,
+ event_symbols_txn, ARRAY_SIZE(event_symbols_txn));
+
if (event_glob != NULL)
return;
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 96ab100..2c9dd04 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -56,7 +56,8 @@ static int sym(yyscan_t scanner, int type, int config)
YYSTYPE *yylval = parse_events_get_lval(scanner);
yylval->num = (type << 16) + config;
- return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
+ return type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_TRANSACTION ?
+ PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
}
static int term(yyscan_t scanner, int type)
@@ -67,6 +68,11 @@ static int term(yyscan_t scanner, int type)
return PE_TERM;
}
+#define txn(t) sym(yyscanner, PERF_TYPE_HW_TRANSACTION, \
+ PERF_COUNT_HW_##t)
+#define txn_abort(t, a) sym(yyscanner, PERF_TYPE_HW_TRANSACTION, \
+ PERF_COUNT_HW_##t | ((PERF_COUNT_HW_ABORT_##a)<<8))
+
%}
%x mem
@@ -127,6 +133,17 @@ speculative-read|speculative-load |
refs|Reference|ops|access |
misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
+transaction-start|tx-start { return txn(TRANSACTION_START); }
+transaction-commit|tx-commit { return txn(TRANSACTION_COMMIT); }
+transaction-abort-all|tx-aborts? { return txn_abort(TRANSACTION_ABORT, ALL); }
+transaction-abort-conflict|tx-conflict { return txn_abort(TRANSACTION_ABORT, CONFLICT); }
+transaction-abort-capacity|tx-capacity { return txn_abort(TRANSACTION_ABORT, CAPACITY); }
+elision-start|le-start { return txn(ELISION_START); }
+elision-commit|le-commit { return txn(ELISION_COMMIT); }
+elision-abort-all|le-aborts? { return txn_abort(ELISION_ABORT, ALL); }
+elision-abort-conflict|le-conflict { return txn_abort(ELISION_ABORT, CONFLICT); }
+elision-abort-capacity|le-capacity { return txn_abort(ELISION_ABORT, CAPACITY); }
+
/*
* These are event config hardcoded term names to be specified
* within xxx/.../ syntax. So far we dont clash with other names,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 2bc5fbf..6485eb3 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -122,7 +122,7 @@ value_sym '/' event_config '/'
struct parse_events_data__events *data = _data;
struct list_head *list = NULL;
int type = $1 >> 16;
- int config = $1 & 255;
+ int config = $1 & 0xffff;
ABORT_ON(parse_events_add_numeric(&list, &data->idx,
type, config, $3));
@@ -135,7 +135,7 @@ value_sym sep_slash_dc
struct parse_events_data__events *data = _data;
struct list_head *list = NULL;
int type = $1 >> 16;
- int config = $1 & 255;
+ int config = $1 & 0xffff;
ABORT_ON(parse_events_add_numeric(&list, &data->idx,
type, config, NULL));
--
1.7.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/