aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/synthetic-events.c
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2021-02-02 18:01:17 +0900
committerArnaldo Carvalho de Melo <acme@redhat.com>2021-02-03 13:10:44 -0300
commitc1b907953b2cd9ff130594e58c9114019926a217 (patch)
tree7548c18689123ca887e2c1a9179fcfdee12c6145 /tools/perf/util/synthetic-events.c
parentperf tools: Use /proc/<PID>/task/<TID>/status for PERF_RECORD_ event synthesis (diff)
downloadlinux-dev-c1b907953b2cd9ff130594e58c9114019926a217.tar.xz
linux-dev-c1b907953b2cd9ff130594e58c9114019926a217.zip
perf tools: Skip PERF_RECORD_MMAP event synthesis for kernel threads
To synthesize information to resolve sample IPs, it needs to scan task and mmap info from the /proc filesystem. For each process, it opens (and reads) status and maps file respectively. But as kernel threads don't have memory maps so we can skip the maps file. To find kernel threads, check "VmPeak:" line in /proc/<PID>/status file. It's about the peak virtual memory usage so only user-level tasks have that. Note that it's possible to miss the line due to partial reads. So we should double-check if it's a really kernel thread when there's no VmPeak line. Thus check "Threads:" line (which follows the VmPeak line whether or not it exists) to be sure it's read enough data - just in case of deeply nested pid namespaces or large number of supplementary groups are involved. This is for user process: $ head -40 /proc/1/status Name: systemd Umask: 0000 State: S (sleeping) Tgid: 1 Ngid: 0 Pid: 1 PPid: 0 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 256 Groups: NStgid: 1 NSpid: 1 NSpgid: 1 NSsid: 1 VmPeak: 234192 kB <-- here VmSize: 169964 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 29528 kB VmRSS: 6104 kB RssAnon: 2756 kB RssFile: 3348 kB RssShmem: 0 kB VmData: 19776 kB VmStk: 1036 kB VmExe: 784 kB VmLib: 9532 kB VmPTE: 116 kB VmSwap: 2400 kB HugetlbPages: 0 kB CoreDumping: 0 THP_enabled: 1 Threads: 1 <-- and here SigQ: 1/62808 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 7be3c0fe28014a03 SigIgn: 0000000000001000 And this is for kernel thread: $ head -20 /proc/2/status Name: kthreadd Umask: 0000 State: S (sleeping) Tgid: 2 Ngid: 0 Pid: 2 PPid: 0 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 64 Groups: NStgid: 2 NSpid: 2 NSpgid: 0 NSsid: 0 Threads: 1 <-- here SigQ: 1/62808 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 Signed-off-by: Namhyung Kim <namhyung@kernel.org> Acked-by: Jiri Olsa <jolsa@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: https://lore.kernel.org/r/20210202090118.2008551-3-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/synthetic-events.c')
-rw-r--r--tools/perf/util/synthetic-events.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
index 0cc998663b03..abea6885f94b 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -70,13 +70,13 @@ int perf_tool__process_synth_event(struct perf_tool *tool,
* the comm, tgid and ppid.
*/
static int perf_event__get_comm_ids(pid_t pid, pid_t tid, char *comm, size_t len,
- pid_t *tgid, pid_t *ppid)
+ pid_t *tgid, pid_t *ppid, bool *kernel)
{
char bf[4096];
int fd;
size_t size = 0;
ssize_t n;
- char *name, *tgids, *ppids;
+ char *name, *tgids, *ppids, *vmpeak, *threads;
*tgid = -1;
*ppid = -1;
@@ -102,8 +102,14 @@ static int perf_event__get_comm_ids(pid_t pid, pid_t tid, char *comm, size_t len
bf[n] = '\0';
name = strstr(bf, "Name:");
- tgids = strstr(bf, "Tgid:");
- ppids = strstr(bf, "PPid:");
+ tgids = strstr(name ?: bf, "Tgid:");
+ ppids = strstr(tgids ?: bf, "PPid:");
+ vmpeak = strstr(ppids ?: bf, "VmPeak:");
+
+ if (vmpeak)
+ threads = NULL;
+ else
+ threads = strstr(ppids ?: bf, "Threads:");
if (name) {
char *nl;
@@ -136,12 +142,17 @@ static int perf_event__get_comm_ids(pid_t pid, pid_t tid, char *comm, size_t len
pr_debug("PPid: string not found for pid %d\n", tid);
}
+ if (!vmpeak && threads)
+ *kernel = true;
+ else
+ *kernel = false;
+
return 0;
}
static int perf_event__prepare_comm(union perf_event *event, pid_t pid, pid_t tid,
struct machine *machine,
- pid_t *tgid, pid_t *ppid)
+ pid_t *tgid, pid_t *ppid, bool *kernel)
{
size_t size;
@@ -152,7 +163,7 @@ static int perf_event__prepare_comm(union perf_event *event, pid_t pid, pid_t ti
if (machine__is_host(machine)) {
if (perf_event__get_comm_ids(pid, tid, event->comm.comm,
sizeof(event->comm.comm),
- tgid, ppid) != 0) {
+ tgid, ppid, kernel) != 0) {
return -1;
}
} else {
@@ -182,8 +193,10 @@ pid_t perf_event__synthesize_comm(struct perf_tool *tool,
struct machine *machine)
{
pid_t tgid, ppid;
+ bool kernel_thread;
- if (perf_event__prepare_comm(event, 0, pid, machine, &tgid, &ppid) != 0)
+ if (perf_event__prepare_comm(event, 0, pid, machine, &tgid, &ppid,
+ &kernel_thread) != 0)
return -1;
if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
@@ -743,6 +756,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
while ((dirent = readdir(tasks)) != NULL) {
char *end;
pid_t _pid;
+ bool kernel_thread;
_pid = strtol(dirent->d_name, &end, 10);
if (*end)
@@ -750,7 +764,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
rc = -1;
if (perf_event__prepare_comm(comm_event, pid, _pid, machine,
- &tgid, &ppid) != 0)
+ &tgid, &ppid, &kernel_thread) != 0)
break;
if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
@@ -768,7 +782,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
break;
rc = 0;
- if (_pid == pid) {
+ if (_pid == pid && !kernel_thread) {
/* process the parent's maps too */
rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
process, machine, mmap_data);