Merge tag 'driver-core-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / tools / perf / util / synthetic-events.c
index 0cc9986..b698046 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/perf_event.h>
 #include <asm/bug.h>
 #include <perf/evsel.h>
-#include <internal/cpumap.h>
 #include <perf/cpumap.h>
 #include <internal/lib.h> // page_size
 #include <internal/threadmap.h>
@@ -70,13 +69,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 +101,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 +141,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 +162,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 +192,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)
@@ -691,6 +703,11 @@ int perf_event__synthesize_modules(struct perf_tool *tool, perf_event__handler_t
        return rc;
 }
 
+static int filter_task(const struct dirent *dirent)
+{
+       return isdigit(dirent->d_name[0]);
+}
+
 static int __event__synthesize_thread(union perf_event *comm_event,
                                      union perf_event *mmap_event,
                                      union perf_event *fork_event,
@@ -699,10 +716,10 @@ static int __event__synthesize_thread(union perf_event *comm_event,
                                      struct perf_tool *tool, struct machine *machine, bool mmap_data)
 {
        char filename[PATH_MAX];
-       DIR *tasks;
-       struct dirent *dirent;
+       struct dirent **dirent;
        pid_t tgid, ppid;
        int rc = 0;
+       int i, n;
 
        /* special case: only send one comm event using passed in pid */
        if (!full) {
@@ -734,23 +751,22 @@ static int __event__synthesize_thread(union perf_event *comm_event,
        snprintf(filename, sizeof(filename), "%s/proc/%d/task",
                 machine->root_dir, pid);
 
-       tasks = opendir(filename);
-       if (tasks == NULL) {
-               pr_debug("couldn't open %s\n", filename);
-               return 0;
-       }
+       n = scandir(filename, &dirent, filter_task, alphasort);
+       if (n < 0)
+               return n;
 
-       while ((dirent = readdir(tasks)) != NULL) {
+       for (i = 0; i < n; i++) {
                char *end;
                pid_t _pid;
+               bool kernel_thread;
 
-               _pid = strtol(dirent->d_name, &end, 10);
+               _pid = strtol(dirent[i]->d_name, &end, 10);
                if (*end)
                        continue;
 
                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 +784,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);
@@ -777,7 +793,10 @@ static int __event__synthesize_thread(union perf_event *comm_event,
                }
        }
 
-       closedir(tasks);
+       for (i = 0; i < n; i++)
+               zfree(&dirent[i]);
+       free(dirent);
+
        return rc;
 }
 
@@ -962,7 +981,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
                return 0;
 
        snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
-       n = scandir(proc_path, &dirent, 0, alphasort);
+       n = scandir(proc_path, &dirent, filter_task, alphasort);
        if (n < 0)
                return err;
 
@@ -1448,7 +1467,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
                }
        }
 
-       if (type & PERF_SAMPLE_WEIGHT)
+       if (type & PERF_SAMPLE_WEIGHT_TYPE)
                result += sizeof(u64);
 
        if (type & PERF_SAMPLE_DATA_SRC)
@@ -1487,6 +1506,12 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
        return result;
 }
 
+void __weak arch_perf_synthesize_sample_weight(const struct perf_sample *data,
+                                              __u64 *array, u64 type __maybe_unused)
+{
+       *array = data->weight;
+}
+
 int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format,
                                  const struct perf_sample *sample)
 {
@@ -1622,8 +1647,8 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_fo
                }
        }
 
-       if (type & PERF_SAMPLE_WEIGHT) {
-               *array = sample->weight;
+       if (type & PERF_SAMPLE_WEIGHT_TYPE) {
+               arch_perf_synthesize_sample_weight(sample, array, type);
                array++;
        }