Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Flush remaining samples w/o deferred callchains

It's possible that some kernel samples don't have matching deferred
callchain records when the profiling session was ended before the
threads came back to userspace. Let's flush the samples before
finish the session.

Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

+50
+50
tools/perf/util/session.c
··· 1295 1295 union perf_event *event; 1296 1296 }; 1297 1297 1298 + /* 1299 + * This is called when a deferred callchain record comes up. Find all matching 1300 + * samples, merge the callchains and process them. 1301 + */ 1298 1302 static int evlist__deliver_deferred_callchain(struct evlist *evlist, 1299 1303 const struct perf_tool *tool, 1300 1304 union perf_event *event, ··· 1338 1334 1339 1335 if (orig_sample.deferred_callchain) 1340 1336 free(orig_sample.callchain); 1337 + 1338 + list_del(&de->list); 1339 + free(de->event); 1340 + free(de); 1341 + 1342 + if (ret) 1343 + break; 1344 + } 1345 + return ret; 1346 + } 1347 + 1348 + /* 1349 + * This is called at the end of the data processing for the session. Flush the 1350 + * remaining samples as there's no hope for matching deferred callchains. 1351 + */ 1352 + static int session__flush_deferred_samples(struct perf_session *session, 1353 + const struct perf_tool *tool) 1354 + { 1355 + struct evlist *evlist = session->evlist; 1356 + struct machine *machine = &session->machines.host; 1357 + struct deferred_event *de, *tmp; 1358 + struct evsel *evsel; 1359 + int ret = 0; 1360 + 1361 + list_for_each_entry_safe(de, tmp, &evlist->deferred_samples, list) { 1362 + struct perf_sample sample; 1363 + 1364 + ret = evlist__parse_sample(evlist, de->event, &sample); 1365 + if (ret < 0) { 1366 + pr_err("failed to parse original sample\n"); 1367 + break; 1368 + } 1369 + 1370 + evsel = evlist__id2evsel(evlist, sample.id); 1371 + ret = evlist__deliver_sample(evlist, tool, de->event, 1372 + &sample, evsel, machine); 1341 1373 1342 1374 list_del(&de->list); 1343 1375 free(de->event); ··· 2080 2040 err = ordered_events__flush(oe, OE_FLUSH__FINAL); 2081 2041 if (err) 2082 2042 goto out_err; 2043 + err = session__flush_deferred_samples(session, tool); 2044 + if (err) 2045 + goto out_err; 2083 2046 err = auxtrace__flush_events(session, tool); 2084 2047 if (err) 2085 2048 goto out_err; ··· 2429 2386 err = auxtrace__flush_events(session, tool); 2430 2387 if (err) 2431 2388 goto out_err; 2389 + err = session__flush_deferred_samples(session, tool); 2390 + if (err) 2391 + goto out_err; 2432 2392 err = perf_session__flush_thread_stacks(session); 2433 2393 out_err: 2434 2394 ui_progress__finish(); ··· 2549 2503 } 2550 2504 2551 2505 ret = ordered_events__flush(&session->ordered_events, OE_FLUSH__FINAL); 2506 + if (ret) 2507 + goto out_err; 2508 + 2509 + ret = session__flush_deferred_samples(session, tool); 2552 2510 if (ret) 2553 2511 goto out_err; 2554 2512