perf evlist: Close fds on destructor
[linux-2.6-microblaze.git] / tools / perf / util / evlist.c
index bbc746a..a083bdc 100644 (file)
@@ -7,7 +7,7 @@
  * Released under the GPL v2. (and only v2, not any later version)
  */
 #include "util.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include <poll.h>
 #include "cpumap.h"
 #include "thread_map.h"
@@ -101,14 +101,17 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
-       free(evlist->mmap);
-       free(evlist->pollfd);
-       evlist->mmap = NULL;
-       evlist->pollfd = NULL;
+       zfree(&evlist->mmap);
+       zfree(&evlist->pollfd);
 }
 
 void perf_evlist__delete(struct perf_evlist *evlist)
 {
+       perf_evlist__close(evlist);
+       cpu_map__delete(evlist->cpus);
+       thread_map__delete(evlist->threads);
+       evlist->cpus = NULL;
+       evlist->threads = NULL;
        perf_evlist__purge(evlist);
        perf_evlist__exit(evlist);
        free(evlist);
@@ -587,8 +590,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
        for (i = 0; i < evlist->nr_mmaps; i++)
                __perf_evlist__munmap(evlist, i);
 
-       free(evlist->mmap);
-       evlist->mmap = NULL;
+       zfree(&evlist->mmap);
 }
 
 static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
@@ -732,11 +734,13 @@ static long parse_pages_arg(const char *str, unsigned long min,
                        return -EINVAL;
        }
 
-       if ((pages == 0) && (min == 0)) {
+       if (pages == 0 && min == 0) {
                /* leave number of pages at 0 */
-       } else if (pages < (1UL << 31) && !is_power_of_2(pages)) {
+       } else if (!is_power_of_2(pages)) {
                /* round pages up to next power of 2 */
-               pages = next_pow2(pages);
+               pages = next_pow2_l(pages);
+               if (!pages)
+                       return -EINVAL;
                pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
                        pages * page_size, pages);
        }
@@ -754,7 +758,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
        unsigned long max = UINT_MAX;
        long pages;
 
-       if (max < SIZE_MAX / page_size)
+       if (max > SIZE_MAX / page_size)
                max = SIZE_MAX / page_size;
 
        pages = parse_pages_arg(str, 1, max);
@@ -819,11 +823,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
        if (evlist->threads == NULL)
                return -1;
 
-       if (target->force_per_cpu)
-               evlist->cpus = cpu_map__new(target->cpu_list);
-       else if (target__has_task(target))
-               evlist->cpus = cpu_map__dummy_new();
-       else if (!target__has_cpu(target) && !target->uses_mmap)
+       if (target__uses_dummy_map(target))
                evlist->cpus = cpu_map__dummy_new();
        else
                evlist->cpus = cpu_map__new(target->cpu_list);
@@ -838,14 +838,6 @@ out_delete_threads:
        return -1;
 }
 
-void perf_evlist__delete_maps(struct perf_evlist *evlist)
-{
-       cpu_map__delete(evlist->cpus);
-       thread_map__delete(evlist->threads);
-       evlist->cpus    = NULL;
-       evlist->threads = NULL;
-}
-
 int perf_evlist__apply_filters(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
@@ -1034,7 +1026,7 @@ out_err:
 
 int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
                                  const char *argv[], bool pipe_output,
-                                 bool want_signal)
+                                 void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
 {
        int child_ready_pipe[2], go_pipe[2];
        char bf;
@@ -1078,12 +1070,25 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
 
                execvp(argv[0], (char **)argv);
 
-               perror(argv[0]);
-               if (want_signal)
-                       kill(getppid(), SIGUSR1);
+               if (exec_error) {
+                       union sigval val;
+
+                       val.sival_int = errno;
+                       if (sigqueue(getppid(), SIGUSR1, val))
+                               perror(argv[0]);
+               } else
+                       perror(argv[0]);
                exit(-1);
        }
 
+       if (exec_error) {
+               struct sigaction act = {
+                       .sa_flags     = SA_SIGINFO,
+                       .sa_sigaction = exec_error,
+               };
+               sigaction(SIGUSR1, &act, NULL);
+       }
+
        if (target__none(target))
                evlist->threads->map[0] = evlist->workload.pid;
 
@@ -1193,8 +1198,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
                                    "Error:\t%s.\n"
                                    "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
 
-               if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value))
-                       break;
+               value = perf_event_paranoid();
 
                printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
 
@@ -1215,3 +1219,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
 
        return 0;
 }
+
+void perf_evlist__to_front(struct perf_evlist *evlist,
+                          struct perf_evsel *move_evsel)
+{
+       struct perf_evsel *evsel, *n;
+       LIST_HEAD(move);
+
+       if (move_evsel == perf_evlist__first(evlist))
+               return;
+
+       list_for_each_entry_safe(evsel, n, &evlist->entries, node) {
+               if (evsel->leader == move_evsel->leader)
+                       list_move_tail(&evsel->node, &move);
+       }
+
+       list_splice(&move, &evlist->entries);
+}