diff options
Diffstat (limited to 'tools/lib/perf')
| -rw-r--r-- | tools/lib/perf/evsel.c | 79 | ||||
| -rw-r--r-- | tools/lib/perf/include/perf/event.h | 3 | ||||
| -rw-r--r-- | tools/lib/perf/include/perf/evsel.h | 4 | 
3 files changed, 83 insertions, 3 deletions
| diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c index 952f3520d5c2..8ce5bbd09666 100644 --- a/tools/lib/perf/evsel.c +++ b/tools/lib/perf/evsel.c @@ -305,6 +305,9 @@ int perf_evsel__read_size(struct perf_evsel *evsel)  	if (read_format & PERF_FORMAT_ID)  		entry += sizeof(u64); +	if (read_format & PERF_FORMAT_LOST) +		entry += sizeof(u64); +  	if (read_format & PERF_FORMAT_GROUP) {  		nr = evsel->nr_members;  		size += sizeof(u64); @@ -314,24 +317,98 @@ int perf_evsel__read_size(struct perf_evsel *evsel)  	return size;  } +/* This only reads values for the leader */ +static int perf_evsel__read_group(struct perf_evsel *evsel, int cpu_map_idx, +				  int thread, struct perf_counts_values *count) +{ +	size_t size = perf_evsel__read_size(evsel); +	int *fd = FD(evsel, cpu_map_idx, thread); +	u64 read_format = evsel->attr.read_format; +	u64 *data; +	int idx = 1; + +	if (fd == NULL || *fd < 0) +		return -EINVAL; + +	data = calloc(1, size); +	if (data == NULL) +		return -ENOMEM; + +	if (readn(*fd, data, size) <= 0) { +		free(data); +		return -errno; +	} + +	/* +	 * This reads only the leader event intentionally since we don't have +	 * perf counts values for sibling events. +	 */ +	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) +		count->ena = data[idx++]; +	if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) +		count->run = data[idx++]; + +	/* value is always available */ +	count->val = data[idx++]; +	if (read_format & PERF_FORMAT_ID) +		count->id = data[idx++]; +	if (read_format & PERF_FORMAT_LOST) +		count->lost = data[idx++]; + +	free(data); +	return 0; +} + +/* + * The perf read format is very flexible.  It needs to set the proper + * values according to the read format. + */ +static void perf_evsel__adjust_values(struct perf_evsel *evsel, u64 *buf, +				      struct perf_counts_values *count) +{ +	u64 read_format = evsel->attr.read_format; +	int n = 0; + +	count->val = buf[n++]; + +	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) +		count->ena = buf[n++]; + +	if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) +		count->run = buf[n++]; + +	if (read_format & PERF_FORMAT_ID) +		count->id = buf[n++]; + +	if (read_format & PERF_FORMAT_LOST) +		count->lost = buf[n++]; +} +  int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread,  		     struct perf_counts_values *count)  {  	size_t size = perf_evsel__read_size(evsel);  	int *fd = FD(evsel, cpu_map_idx, thread); +	u64 read_format = evsel->attr.read_format; +	struct perf_counts_values buf;  	memset(count, 0, sizeof(*count));  	if (fd == NULL || *fd < 0)  		return -EINVAL; +	if (read_format & PERF_FORMAT_GROUP) +		return perf_evsel__read_group(evsel, cpu_map_idx, thread, count); +  	if (MMAP(evsel, cpu_map_idx, thread) && +	    !(read_format & (PERF_FORMAT_ID | PERF_FORMAT_LOST)) &&  	    !perf_mmap__read_self(MMAP(evsel, cpu_map_idx, thread), count))  		return 0; -	if (readn(*fd, count->values, size) <= 0) +	if (readn(*fd, buf.values, size) <= 0)  		return -errno; +	perf_evsel__adjust_values(evsel, buf.values, count);  	return 0;  } diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index 57f54781f5ed..93bf93a59c99 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -77,7 +77,7 @@ struct perf_record_lost_samples {  };  /* - * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID + * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID | PERF_FORMAT_LOST   */  struct perf_record_read {  	struct perf_event_header header; @@ -86,6 +86,7 @@ struct perf_record_read {  	__u64			 time_enabled;  	__u64			 time_running;  	__u64			 id; +	__u64			 lost;  };  struct perf_record_throttle { diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h index 699c0ed97d34..6f92204075c2 100644 --- a/tools/lib/perf/include/perf/evsel.h +++ b/tools/lib/perf/include/perf/evsel.h @@ -18,8 +18,10 @@ struct perf_counts_values {  			uint64_t val;  			uint64_t ena;  			uint64_t run; +			uint64_t id; +			uint64_t lost;  		}; -		uint64_t values[3]; +		uint64_t values[5];  	};  }; |