mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	perf record: Read and inject LOST_SAMPLES events
When there are lost samples, it can read the number of PERF_FORMAT_LOST and convert it to PERF_RECORD_LOST_SAMPLES and write to the data file at the end. Reviewed-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: https://lore.kernel.org/r/20220901195739.668604-4-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
		
							parent
							
								
									e17f343c3b
								
							
						
					
					
						commit
						e3a23261ad
					
				
					 1 changed files with 64 additions and 0 deletions
				
			
		| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "util/build-id.h"
 | 
					#include "util/build-id.h"
 | 
				
			||||||
#include <subcmd/parse-options.h>
 | 
					#include <subcmd/parse-options.h>
 | 
				
			||||||
 | 
					#include <internal/xyarray.h>
 | 
				
			||||||
#include "util/parse-events.h"
 | 
					#include "util/parse-events.h"
 | 
				
			||||||
#include "util/config.h"
 | 
					#include "util/config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1852,6 +1853,68 @@ record__switch_output(struct record *rec, bool at_exit)
 | 
				
			||||||
	return fd;
 | 
						return fd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __record__read_lost_samples(struct record *rec, struct evsel *evsel,
 | 
				
			||||||
 | 
										struct perf_record_lost_samples *lost,
 | 
				
			||||||
 | 
										int cpu_idx, int thread_idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct perf_counts_values count;
 | 
				
			||||||
 | 
						struct perf_sample_id *sid;
 | 
				
			||||||
 | 
						struct perf_sample sample = {};
 | 
				
			||||||
 | 
						int id_hdr_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (perf_evsel__read(&evsel->core, cpu_idx, thread_idx, &count) < 0) {
 | 
				
			||||||
 | 
							pr_err("read LOST count failed\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (count.lost == 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lost->lost = count.lost;
 | 
				
			||||||
 | 
						if (evsel->core.ids) {
 | 
				
			||||||
 | 
							sid = xyarray__entry(evsel->core.sample_id, cpu_idx, thread_idx);
 | 
				
			||||||
 | 
							sample.id = sid->id;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						id_hdr_size = perf_event__synthesize_id_sample((void *)(lost + 1),
 | 
				
			||||||
 | 
											       evsel->core.attr.sample_type, &sample);
 | 
				
			||||||
 | 
						lost->header.size = sizeof(*lost) + id_hdr_size;
 | 
				
			||||||
 | 
						record__write(rec, NULL, lost, lost->header.size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void record__read_lost_samples(struct record *rec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct perf_session *session = rec->session;
 | 
				
			||||||
 | 
						struct perf_record_lost_samples *lost;
 | 
				
			||||||
 | 
						struct evsel *evsel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lost = zalloc(PERF_SAMPLE_MAX_SIZE);
 | 
				
			||||||
 | 
						if (lost == NULL) {
 | 
				
			||||||
 | 
							pr_debug("Memory allocation failed\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lost->header.type = PERF_RECORD_LOST_SAMPLES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						evlist__for_each_entry(session->evlist, evsel) {
 | 
				
			||||||
 | 
							struct xyarray *xy = evsel->core.sample_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (xyarray__max_x(evsel->core.fd) != xyarray__max_x(xy) ||
 | 
				
			||||||
 | 
							    xyarray__max_y(evsel->core.fd) != xyarray__max_y(xy)) {
 | 
				
			||||||
 | 
								pr_debug("Unmatched FD vs. sample ID: skip reading LOST count\n");
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (int x = 0; x < xyarray__max_x(xy); x++) {
 | 
				
			||||||
 | 
								for (int y = 0; y < xyarray__max_y(xy); y++) {
 | 
				
			||||||
 | 
									__record__read_lost_samples(rec, evsel, lost, x, y);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(lost);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static volatile int workload_exec_errno;
 | 
					static volatile int workload_exec_errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -2714,6 +2777,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 | 
				
			||||||
	if (rec->off_cpu)
 | 
						if (rec->off_cpu)
 | 
				
			||||||
		rec->bytes_written += off_cpu_write(rec->session);
 | 
							rec->bytes_written += off_cpu_write(rec->session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						record__read_lost_samples(rec);
 | 
				
			||||||
	record__synthesize(rec, true);
 | 
						record__synthesize(rec, true);
 | 
				
			||||||
	/* this will be recalculated during process_buildids() */
 | 
						/* this will be recalculated during process_buildids() */
 | 
				
			||||||
	rec->samples = 0;
 | 
						rec->samples = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue