|
@@ -31,7 +31,7 @@ static struct {
|
|
|
|
|
|
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
|
|
|
|
|
-static int __perf_evsel__sample_size(u64 sample_type)
|
|
|
+int __perf_evsel__sample_size(u64 sample_type)
|
|
|
{
|
|
|
u64 mask = sample_type & PERF_SAMPLE_MASK;
|
|
|
int size = 0;
|
|
@@ -47,6 +47,72 @@ static int __perf_evsel__sample_size(u64 sample_type)
|
|
|
return size;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * __perf_evsel__calc_id_pos - calculate id_pos.
|
|
|
+ * @sample_type: sample type
|
|
|
+ *
|
|
|
+ * This function returns the position of the event id (PERF_SAMPLE_ID or
|
|
|
+ * PERF_SAMPLE_IDENTIFIER) in a sample event i.e. in the array of struct
|
|
|
+ * sample_event.
|
|
|
+ */
|
|
|
+static int __perf_evsel__calc_id_pos(u64 sample_type)
|
|
|
+{
|
|
|
+ int idx = 0;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_IDENTIFIER)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (!(sample_type & PERF_SAMPLE_ID))
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_IP)
|
|
|
+ idx += 1;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_TID)
|
|
|
+ idx += 1;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_TIME)
|
|
|
+ idx += 1;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_ADDR)
|
|
|
+ idx += 1;
|
|
|
+
|
|
|
+ return idx;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * __perf_evsel__calc_is_pos - calculate is_pos.
|
|
|
+ * @sample_type: sample type
|
|
|
+ *
|
|
|
+ * This function returns the position (counting backwards) of the event id
|
|
|
+ * (PERF_SAMPLE_ID or PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if
|
|
|
+ * sample_id_all is used there is an id sample appended to non-sample events.
|
|
|
+ */
|
|
|
+static int __perf_evsel__calc_is_pos(u64 sample_type)
|
|
|
+{
|
|
|
+ int idx = 1;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_IDENTIFIER)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ if (!(sample_type & PERF_SAMPLE_ID))
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_CPU)
|
|
|
+ idx += 1;
|
|
|
+
|
|
|
+ if (sample_type & PERF_SAMPLE_STREAM_ID)
|
|
|
+ idx += 1;
|
|
|
+
|
|
|
+ return idx;
|
|
|
+}
|
|
|
+
|
|
|
+void perf_evsel__calc_id_pos(struct perf_evsel *evsel)
|
|
|
+{
|
|
|
+ evsel->id_pos = __perf_evsel__calc_id_pos(evsel->attr.sample_type);
|
|
|
+ evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type);
|
|
|
+}
|
|
|
+
|
|
|
void hists__init(struct hists *hists)
|
|
|
{
|
|
|
memset(hists, 0, sizeof(*hists));
|
|
@@ -63,6 +129,7 @@ void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
|
|
|
if (!(evsel->attr.sample_type & bit)) {
|
|
|
evsel->attr.sample_type |= bit;
|
|
|
evsel->sample_size += sizeof(u64);
|
|
|
+ perf_evsel__calc_id_pos(evsel);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -72,12 +139,19 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
|
|
|
if (evsel->attr.sample_type & bit) {
|
|
|
evsel->attr.sample_type &= ~bit;
|
|
|
evsel->sample_size -= sizeof(u64);
|
|
|
+ perf_evsel__calc_id_pos(evsel);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void perf_evsel__set_sample_id(struct perf_evsel *evsel)
|
|
|
+void perf_evsel__set_sample_id(struct perf_evsel *evsel,
|
|
|
+ bool can_sample_identifier)
|
|
|
{
|
|
|
- perf_evsel__set_sample_bit(evsel, ID);
|
|
|
+ if (can_sample_identifier) {
|
|
|
+ perf_evsel__reset_sample_bit(evsel, ID);
|
|
|
+ perf_evsel__set_sample_bit(evsel, IDENTIFIER);
|
|
|
+ } else {
|
|
|
+ perf_evsel__set_sample_bit(evsel, ID);
|
|
|
+ }
|
|
|
evsel->attr.read_format |= PERF_FORMAT_ID;
|
|
|
}
|
|
|
|
|
@@ -90,6 +164,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
|
|
|
INIT_LIST_HEAD(&evsel->node);
|
|
|
hists__init(&evsel->hists);
|
|
|
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
|
|
|
+ perf_evsel__calc_id_pos(evsel);
|
|
|
}
|
|
|
|
|
|
struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
|
|
@@ -509,7 +584,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
|
|
|
* We need ID even in case of single event, because
|
|
|
* PERF_SAMPLE_READ process ID specific data.
|
|
|
*/
|
|
|
- perf_evsel__set_sample_id(evsel);
|
|
|
+ perf_evsel__set_sample_id(evsel, false);
|
|
|
|
|
|
/*
|
|
|
* Apply group format only if we belong to group
|
|
@@ -1088,6 +1163,11 @@ static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
|
|
|
array += ((event->header.size -
|
|
|
sizeof(event->header)) / sizeof(u64)) - 1;
|
|
|
|
|
|
+ if (type & PERF_SAMPLE_IDENTIFIER) {
|
|
|
+ sample->id = *array;
|
|
|
+ array--;
|
|
|
+ }
|
|
|
+
|
|
|
if (type & PERF_SAMPLE_CPU) {
|
|
|
u.val64 = *array;
|
|
|
if (swapped) {
|
|
@@ -1184,6 +1264,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
|
|
|
if (evsel->sample_size + sizeof(event->header) > event->header.size)
|
|
|
return -EFAULT;
|
|
|
|
|
|
+ data->id = -1ULL;
|
|
|
+ if (type & PERF_SAMPLE_IDENTIFIER) {
|
|
|
+ data->id = *array;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
if (type & PERF_SAMPLE_IP) {
|
|
|
data->ip = *array;
|
|
|
array++;
|
|
@@ -1214,7 +1300,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
|
|
|
array++;
|
|
|
}
|
|
|
|
|
|
- data->id = -1ULL;
|
|
|
if (type & PERF_SAMPLE_ID) {
|
|
|
data->id = *array;
|
|
|
array++;
|
|
@@ -1396,6 +1481,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
|
|
|
|
|
|
array = event->sample.array;
|
|
|
|
|
|
+ if (type & PERF_SAMPLE_IDENTIFIER) {
|
|
|
+ *array = sample->id;
|
|
|
+ array++;
|
|
|
+ }
|
|
|
+
|
|
|
if (type & PERF_SAMPLE_IP) {
|
|
|
*array = sample->ip;
|
|
|
array++;
|
|
@@ -1584,6 +1674,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
|
|
|
bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
|
|
|
bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
|
|
|
bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
|
|
|
+ bit_name(IDENTIFIER),
|
|
|
{ .name = NULL, }
|
|
|
};
|
|
|
#undef bit_name
|