diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-05-11 02:13:55 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-05-11 02:13:55 -0400 |
commit | 5dcefda0fd87fefa440abc9b9d3f1089229f8911 (patch) | |
tree | f19697dc461b40e277109fbba659d614892bb0d2 /tools/perf/util | |
parent | c4f400e837713f677de94390c57e7dc7567e0286 (diff) | |
parent | 5a5626b1b4bf8467891c9297ffda979db97ed5ec (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Fixes and improvements for perf/core:
- perf_target: abstraction for --uid, --pid, --tid, --cpu, --all-cpus handling,
eliminating code duplicated in the tools, having constraints that apply to
all of them, from Namhyung Kim
- Fixes for handling fallback to cpu-clock on PPC, from David Ahern
- Fix for processing events with unknown size, from Jiri Olsa
- Compilation fix on 32-bit, from Jiri Olsa
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/cache.h | 24 | ||||
-rw-r--r-- | tools/perf/util/debug.c | 1 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 16 | ||||
-rw-r--r-- | tools/perf/util/evlist.h | 4 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 9 | ||||
-rw-r--r-- | tools/perf/util/header.c | 17 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 2 | ||||
-rw-r--r-- | tools/perf/util/session.c | 30 | ||||
-rw-r--r-- | tools/perf/util/target.c | 142 | ||||
-rw-r--r-- | tools/perf/util/target.h | 64 | ||||
-rw-r--r-- | tools/perf/util/top.c | 19 | ||||
-rw-r--r-- | tools/perf/util/top.h | 6 | ||||
-rw-r--r-- | tools/perf/util/usage.c | 38 | ||||
-rw-r--r-- | tools/perf/util/util.h | 3 |
14 files changed, 268 insertions, 107 deletions
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 8dd224df3e54..cff18c617d13 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -33,7 +33,7 @@ extern int pager_use_color; | |||
33 | 33 | ||
34 | extern int use_browser; | 34 | extern int use_browser; |
35 | 35 | ||
36 | #ifdef NO_NEWT_SUPPORT | 36 | #if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) |
37 | static inline void setup_browser(bool fallback_to_pager) | 37 | static inline void setup_browser(bool fallback_to_pager) |
38 | { | 38 | { |
39 | if (fallback_to_pager) | 39 | if (fallback_to_pager) |
@@ -43,19 +43,29 @@ static inline void exit_browser(bool wait_for_ok __used) {} | |||
43 | #else | 43 | #else |
44 | void setup_browser(bool fallback_to_pager); | 44 | void setup_browser(bool fallback_to_pager); |
45 | void exit_browser(bool wait_for_ok); | 45 | void exit_browser(bool wait_for_ok); |
46 | |||
47 | #ifdef NO_NEWT_SUPPORT | ||
48 | static inline int ui__init(void) | ||
49 | { | ||
50 | return -1; | ||
51 | } | ||
52 | static inline void ui__exit(bool wait_for_ok __used) {} | ||
53 | #else | ||
54 | int ui__init(void); | ||
55 | void ui__exit(bool wait_for_ok); | ||
46 | #endif | 56 | #endif |
47 | 57 | ||
48 | #ifdef NO_GTK2_SUPPORT | 58 | #ifdef NO_GTK2_SUPPORT |
49 | static inline void perf_gtk_setup_browser(int argc __used, const char *argv[] __used, bool fallback_to_pager) | 59 | static inline int perf_gtk__init(void) |
50 | { | 60 | { |
51 | if (fallback_to_pager) | 61 | return -1; |
52 | setup_pager(); | ||
53 | } | 62 | } |
54 | static inline void perf_gtk_exit_browser(bool wait_for_ok __used) {} | 63 | static inline void perf_gtk__exit(bool wait_for_ok __used) {} |
55 | #else | 64 | #else |
56 | void perf_gtk_setup_browser(int argc, const char *argv[], bool fallback_to_pager); | 65 | int perf_gtk__init(void); |
57 | void perf_gtk_exit_browser(bool wait_for_ok); | 66 | void perf_gtk__exit(bool wait_for_ok); |
58 | #endif | 67 | #endif |
68 | #endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ | ||
59 | 69 | ||
60 | char *alias_lookup(const char *alias); | 70 | char *alias_lookup(const char *alias); |
61 | int split_cmdline(char *cmdline, const char ***argv); | 71 | int split_cmdline(char *cmdline, const char ***argv); |
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 26817daa2961..efb1fce259a4 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "event.h" | 11 | #include "event.h" |
12 | #include "debug.h" | 12 | #include "debug.h" |
13 | #include "util.h" | 13 | #include "util.h" |
14 | #include "target.h" | ||
14 | 15 | ||
15 | int verbose; | 16 | int verbose; |
16 | bool dump_trace = false, quiet = false; | 17 | bool dump_trace = false, quiet = false; |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 1986d8051bd1..1201daf71719 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <poll.h> | 11 | #include <poll.h> |
12 | #include "cpumap.h" | 12 | #include "cpumap.h" |
13 | #include "thread_map.h" | 13 | #include "thread_map.h" |
14 | #include "target.h" | ||
14 | #include "evlist.h" | 15 | #include "evlist.h" |
15 | #include "evsel.h" | 16 | #include "evsel.h" |
16 | #include <unistd.h> | 17 | #include <unistd.h> |
@@ -599,18 +600,19 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, | |||
599 | return perf_evlist__mmap_per_cpu(evlist, prot, mask); | 600 | return perf_evlist__mmap_per_cpu(evlist, prot, mask); |
600 | } | 601 | } |
601 | 602 | ||
602 | int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid, | 603 | int perf_evlist__create_maps(struct perf_evlist *evlist, |
603 | const char *target_tid, uid_t uid, const char *cpu_list) | 604 | struct perf_target *target) |
604 | { | 605 | { |
605 | evlist->threads = thread_map__new_str(target_pid, target_tid, uid); | 606 | evlist->threads = thread_map__new_str(target->pid, target->tid, |
607 | target->uid); | ||
606 | 608 | ||
607 | if (evlist->threads == NULL) | 609 | if (evlist->threads == NULL) |
608 | return -1; | 610 | return -1; |
609 | 611 | ||
610 | if (uid != UINT_MAX || (cpu_list == NULL && target_tid)) | 612 | if (!perf_target__no_cpu(target)) |
611 | evlist->cpus = cpu_map__dummy_new(); | 613 | evlist->cpus = cpu_map__new(target->cpu_list); |
612 | else | 614 | else |
613 | evlist->cpus = cpu_map__new(cpu_list); | 615 | evlist->cpus = cpu_map__dummy_new(); |
614 | 616 | ||
615 | if (evlist->cpus == NULL) | 617 | if (evlist->cpus == NULL) |
616 | goto out_delete_threads; | 618 | goto out_delete_threads; |
@@ -827,7 +829,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, | |||
827 | exit(-1); | 829 | exit(-1); |
828 | } | 830 | } |
829 | 831 | ||
830 | if (!opts->system_wide && !opts->target_tid && !opts->target_pid) | 832 | if (perf_target__none(&opts->target)) |
831 | evlist->threads->map[0] = evlist->workload.pid; | 833 | evlist->threads->map[0] = evlist->workload.pid; |
832 | 834 | ||
833 | close(child_ready_pipe[1]); | 835 | close(child_ready_pipe[1]); |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 21f1c9e57f13..58abb63ac13a 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -106,8 +106,8 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist, | |||
106 | evlist->threads = threads; | 106 | evlist->threads = threads; |
107 | } | 107 | } |
108 | 108 | ||
109 | int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid, | 109 | int perf_evlist__create_maps(struct perf_evlist *evlist, |
110 | const char *tid, uid_t uid, const char *cpu_list); | 110 | struct perf_target *target); |
111 | void perf_evlist__delete_maps(struct perf_evlist *evlist); | 111 | void perf_evlist__delete_maps(struct perf_evlist *evlist); |
112 | int perf_evlist__set_filters(struct perf_evlist *evlist); | 112 | int perf_evlist__set_filters(struct perf_evlist *evlist); |
113 | 113 | ||
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8c13dbcb84b9..21eaab240396 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "util.h" | 14 | #include "util.h" |
15 | #include "cpumap.h" | 15 | #include "cpumap.h" |
16 | #include "thread_map.h" | 16 | #include "thread_map.h" |
17 | #include "target.h" | ||
17 | 18 | ||
18 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 19 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
19 | #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) | 20 | #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) |
@@ -106,15 +107,15 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, | |||
106 | if (opts->call_graph) | 107 | if (opts->call_graph) |
107 | attr->sample_type |= PERF_SAMPLE_CALLCHAIN; | 108 | attr->sample_type |= PERF_SAMPLE_CALLCHAIN; |
108 | 109 | ||
109 | if (opts->system_wide) | 110 | if (opts->target.system_wide) |
110 | attr->sample_type |= PERF_SAMPLE_CPU; | 111 | attr->sample_type |= PERF_SAMPLE_CPU; |
111 | 112 | ||
112 | if (opts->period) | 113 | if (opts->period) |
113 | attr->sample_type |= PERF_SAMPLE_PERIOD; | 114 | attr->sample_type |= PERF_SAMPLE_PERIOD; |
114 | 115 | ||
115 | if (!opts->sample_id_all_missing && | 116 | if (!opts->sample_id_all_missing && |
116 | (opts->sample_time || opts->system_wide || | 117 | (opts->sample_time || !opts->no_inherit || |
117 | !opts->no_inherit || opts->cpu_list)) | 118 | !perf_target__no_cpu(&opts->target))) |
118 | attr->sample_type |= PERF_SAMPLE_TIME; | 119 | attr->sample_type |= PERF_SAMPLE_TIME; |
119 | 120 | ||
120 | if (opts->raw_samples) { | 121 | if (opts->raw_samples) { |
@@ -135,7 +136,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, | |||
135 | attr->mmap = track; | 136 | attr->mmap = track; |
136 | attr->comm = track; | 137 | attr->comm = track; |
137 | 138 | ||
138 | if (!opts->target_pid && !opts->target_tid && !opts->system_wide && | 139 | if (perf_target__none(&opts->target) && |
139 | (!opts->group || evsel == first)) { | 140 | (!opts->group || evsel == first)) { |
140 | attr->disabled = 1; | 141 | attr->disabled = 1; |
141 | attr->enable_on_exec = 1; | 142 | attr->enable_on_exec = 1; |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4c7c2d73251f..6e618ba21382 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -31,21 +31,16 @@ static const char **header_argv; | |||
31 | 31 | ||
32 | int perf_header__push_event(u64 id, const char *name) | 32 | int perf_header__push_event(u64 id, const char *name) |
33 | { | 33 | { |
34 | struct perf_trace_event_type *nevents; | ||
35 | |||
34 | if (strlen(name) > MAX_EVENT_NAME) | 36 | if (strlen(name) > MAX_EVENT_NAME) |
35 | pr_warning("Event %s will be truncated\n", name); | 37 | pr_warning("Event %s will be truncated\n", name); |
36 | 38 | ||
37 | if (!events) { | 39 | nevents = realloc(events, (event_count + 1) * sizeof(*events)); |
38 | events = malloc(sizeof(struct perf_trace_event_type)); | 40 | if (nevents == NULL) |
39 | if (events == NULL) | 41 | return -ENOMEM; |
40 | return -ENOMEM; | 42 | events = nevents; |
41 | } else { | ||
42 | struct perf_trace_event_type *nevents; | ||
43 | 43 | ||
44 | nevents = realloc(events, (event_count + 1) * sizeof(*events)); | ||
45 | if (nevents == NULL) | ||
46 | return -ENOMEM; | ||
47 | events = nevents; | ||
48 | } | ||
49 | memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); | 44 | memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); |
50 | events[event_count].event_id = id; | 45 | events[event_count].event_id = id; |
51 | strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); | 46 | strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index ca069f893381..5cb002894a17 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -4,7 +4,9 @@ | |||
4 | * Parse symbolic events/counts passed in as options: | 4 | * Parse symbolic events/counts passed in as options: |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <stdbool.h> | ||
7 | #include "../../../include/linux/perf_event.h" | 8 | #include "../../../include/linux/perf_event.h" |
9 | #include "types.h" | ||
8 | 10 | ||
9 | struct list_head; | 11 | struct list_head; |
10 | struct perf_evsel; | 12 | struct perf_evsel; |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1efd3bee6336..4dcc8f3190cf 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -1108,16 +1108,10 @@ more: | |||
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) { | 1110 | if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) { |
1111 | dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", | 1111 | pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", |
1112 | head, event.header.size, event.header.type); | 1112 | head, event.header.size, event.header.type); |
1113 | /* | 1113 | err = -EINVAL; |
1114 | * assume we lost track of the stream, check alignment, and | 1114 | goto out_err; |
1115 | * increment a single u64 in the hope to catch on again 'soon'. | ||
1116 | */ | ||
1117 | if (unlikely(head & 7)) | ||
1118 | head &= ~7ULL; | ||
1119 | |||
1120 | size = 8; | ||
1121 | } | 1115 | } |
1122 | 1116 | ||
1123 | head += size; | 1117 | head += size; |
@@ -1226,17 +1220,11 @@ more: | |||
1226 | 1220 | ||
1227 | if (size == 0 || | 1221 | if (size == 0 || |
1228 | perf_session__process_event(session, event, tool, file_pos) < 0) { | 1222 | perf_session__process_event(session, event, tool, file_pos) < 0) { |
1229 | dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", | 1223 | pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", |
1230 | file_offset + head, event->header.size, | 1224 | file_offset + head, event->header.size, |
1231 | event->header.type); | 1225 | event->header.type); |
1232 | /* | 1226 | err = -EINVAL; |
1233 | * assume we lost track of the stream, check alignment, and | 1227 | goto out_err; |
1234 | * increment a single u64 in the hope to catch on again 'soon'. | ||
1235 | */ | ||
1236 | if (unlikely(head & 7)) | ||
1237 | head &= ~7ULL; | ||
1238 | |||
1239 | size = 8; | ||
1240 | } | 1228 | } |
1241 | 1229 | ||
1242 | head += size; | 1230 | head += size; |
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c new file mode 100644 index 000000000000..1064d5b148ad --- /dev/null +++ b/tools/perf/util/target.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Helper functions for handling target threads/cpus | ||
3 | * | ||
4 | * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com> | ||
5 | * | ||
6 | * Released under the GPL v2. | ||
7 | */ | ||
8 | |||
9 | #include "target.h" | ||
10 | #include "debug.h" | ||
11 | |||
12 | #include <pwd.h> | ||
13 | #include <string.h> | ||
14 | |||
15 | |||
16 | enum perf_target_errno perf_target__validate(struct perf_target *target) | ||
17 | { | ||
18 | enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS; | ||
19 | |||
20 | if (target->pid) | ||
21 | target->tid = target->pid; | ||
22 | |||
23 | /* CPU and PID are mutually exclusive */ | ||
24 | if (target->tid && target->cpu_list) { | ||
25 | target->cpu_list = NULL; | ||
26 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
27 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU; | ||
28 | } | ||
29 | |||
30 | /* UID and PID are mutually exclusive */ | ||
31 | if (target->tid && target->uid_str) { | ||
32 | target->uid_str = NULL; | ||
33 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
34 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID; | ||
35 | } | ||
36 | |||
37 | /* UID and CPU are mutually exclusive */ | ||
38 | if (target->uid_str && target->cpu_list) { | ||
39 | target->cpu_list = NULL; | ||
40 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
41 | ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU; | ||
42 | } | ||
43 | |||
44 | /* PID and SYSTEM are mutually exclusive */ | ||
45 | if (target->tid && target->system_wide) { | ||
46 | target->system_wide = false; | ||
47 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
48 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM; | ||
49 | } | ||
50 | |||
51 | /* UID and SYSTEM are mutually exclusive */ | ||
52 | if (target->uid_str && target->system_wide) { | ||
53 | target->system_wide = false; | ||
54 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
55 | ret = PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM; | ||
56 | } | ||
57 | |||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | enum perf_target_errno perf_target__parse_uid(struct perf_target *target) | ||
62 | { | ||
63 | struct passwd pwd, *result; | ||
64 | char buf[1024]; | ||
65 | const char *str = target->uid_str; | ||
66 | |||
67 | target->uid = UINT_MAX; | ||
68 | if (str == NULL) | ||
69 | return PERF_ERRNO_TARGET__SUCCESS; | ||
70 | |||
71 | /* Try user name first */ | ||
72 | getpwnam_r(str, &pwd, buf, sizeof(buf), &result); | ||
73 | |||
74 | if (result == NULL) { | ||
75 | /* | ||
76 | * The user name not found. Maybe it's a UID number. | ||
77 | */ | ||
78 | char *endptr; | ||
79 | int uid = strtol(str, &endptr, 10); | ||
80 | |||
81 | if (*endptr != '\0') | ||
82 | return PERF_ERRNO_TARGET__INVALID_UID; | ||
83 | |||
84 | getpwuid_r(uid, &pwd, buf, sizeof(buf), &result); | ||
85 | |||
86 | if (result == NULL) | ||
87 | return PERF_ERRNO_TARGET__USER_NOT_FOUND; | ||
88 | } | ||
89 | |||
90 | target->uid = result->pw_uid; | ||
91 | return PERF_ERRNO_TARGET__SUCCESS; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * This must have a same ordering as the enum perf_target_errno. | ||
96 | */ | ||
97 | static const char *perf_target__error_str[] = { | ||
98 | "PID/TID switch overriding CPU", | ||
99 | "PID/TID switch overriding UID", | ||
100 | "UID switch overriding CPU", | ||
101 | "PID/TID switch overriding SYSTEM", | ||
102 | "UID switch overriding SYSTEM", | ||
103 | "Invalid User: %s", | ||
104 | "Problems obtaining information for user %s", | ||
105 | }; | ||
106 | |||
107 | int perf_target__strerror(struct perf_target *target, int errnum, | ||
108 | char *buf, size_t buflen) | ||
109 | { | ||
110 | int idx; | ||
111 | const char *msg; | ||
112 | |||
113 | if (errnum >= 0) { | ||
114 | strerror_r(errnum, buf, buflen); | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | if (errnum < __PERF_ERRNO_TARGET__START || | ||
119 | errnum >= __PERF_ERRNO_TARGET__END) | ||
120 | return -1; | ||
121 | |||
122 | idx = errnum - __PERF_ERRNO_TARGET__START; | ||
123 | msg = perf_target__error_str[idx]; | ||
124 | |||
125 | switch (errnum) { | ||
126 | case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU | ||
127 | ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM: | ||
128 | snprintf(buf, buflen, "%s", msg); | ||
129 | break; | ||
130 | |||
131 | case PERF_ERRNO_TARGET__INVALID_UID: | ||
132 | case PERF_ERRNO_TARGET__USER_NOT_FOUND: | ||
133 | snprintf(buf, buflen, msg, target->uid_str); | ||
134 | break; | ||
135 | |||
136 | default: | ||
137 | /* cannot reach here */ | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h new file mode 100644 index 000000000000..127cff3f8ced --- /dev/null +++ b/tools/perf/util/target.h | |||
@@ -0,0 +1,64 @@ | |||
1 | #ifndef _PERF_TARGET_H | ||
2 | #define _PERF_TARGET_H | ||
3 | |||
4 | #include <stdbool.h> | ||
5 | #include <sys/types.h> | ||
6 | |||
7 | struct perf_target { | ||
8 | const char *pid; | ||
9 | const char *tid; | ||
10 | const char *cpu_list; | ||
11 | const char *uid_str; | ||
12 | uid_t uid; | ||
13 | bool system_wide; | ||
14 | }; | ||
15 | |||
16 | enum perf_target_errno { | ||
17 | PERF_ERRNO_TARGET__SUCCESS = 0, | ||
18 | |||
19 | /* | ||
20 | * Choose an arbitrary negative big number not to clash with standard | ||
21 | * errno since SUS requires the errno has distinct positive values. | ||
22 | * See 'Issue 6' in the link below. | ||
23 | * | ||
24 | * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html | ||
25 | */ | ||
26 | __PERF_ERRNO_TARGET__START = -10000, | ||
27 | |||
28 | |||
29 | /* for perf_target__validate() */ | ||
30 | PERF_ERRNO_TARGET__PID_OVERRIDE_CPU = __PERF_ERRNO_TARGET__START, | ||
31 | PERF_ERRNO_TARGET__PID_OVERRIDE_UID, | ||
32 | PERF_ERRNO_TARGET__UID_OVERRIDE_CPU, | ||
33 | PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM, | ||
34 | PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM, | ||
35 | |||
36 | /* for perf_target__parse_uid() */ | ||
37 | PERF_ERRNO_TARGET__INVALID_UID, | ||
38 | PERF_ERRNO_TARGET__USER_NOT_FOUND, | ||
39 | |||
40 | __PERF_ERRNO_TARGET__END, | ||
41 | }; | ||
42 | |||
43 | enum perf_target_errno perf_target__validate(struct perf_target *target); | ||
44 | enum perf_target_errno perf_target__parse_uid(struct perf_target *target); | ||
45 | |||
46 | int perf_target__strerror(struct perf_target *target, int errnum, char *buf, | ||
47 | size_t buflen); | ||
48 | |||
49 | static inline bool perf_target__no_task(struct perf_target *target) | ||
50 | { | ||
51 | return !target->pid && !target->tid && !target->uid_str; | ||
52 | } | ||
53 | |||
54 | static inline bool perf_target__no_cpu(struct perf_target *target) | ||
55 | { | ||
56 | return !target->system_wide && !target->cpu_list; | ||
57 | } | ||
58 | |||
59 | static inline bool perf_target__none(struct perf_target *target) | ||
60 | { | ||
61 | return perf_target__no_task(target) && perf_target__no_cpu(target); | ||
62 | } | ||
63 | |||
64 | #endif /* _PERF_TARGET_H */ | ||
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index 09fe579ccafb..abe0e8e95068 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c | |||
@@ -69,23 +69,24 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) | |||
69 | 69 | ||
70 | ret += SNPRINTF(bf + ret, size - ret, "], "); | 70 | ret += SNPRINTF(bf + ret, size - ret, "], "); |
71 | 71 | ||
72 | if (top->target_pid) | 72 | if (top->target.pid) |
73 | ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s", | 73 | ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s", |
74 | top->target_pid); | 74 | top->target.pid); |
75 | else if (top->target_tid) | 75 | else if (top->target.tid) |
76 | ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s", | 76 | ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s", |
77 | top->target_tid); | 77 | top->target.tid); |
78 | else if (top->uid_str != NULL) | 78 | else if (top->target.uid_str != NULL) |
79 | ret += SNPRINTF(bf + ret, size - ret, " (uid: %s", | 79 | ret += SNPRINTF(bf + ret, size - ret, " (uid: %s", |
80 | top->uid_str); | 80 | top->target.uid_str); |
81 | else | 81 | else |
82 | ret += SNPRINTF(bf + ret, size - ret, " (all"); | 82 | ret += SNPRINTF(bf + ret, size - ret, " (all"); |
83 | 83 | ||
84 | if (top->cpu_list) | 84 | if (top->target.cpu_list) |
85 | ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", | 85 | ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", |
86 | top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list); | 86 | top->evlist->cpus->nr > 1 ? "s" : "", |
87 | top->target.cpu_list); | ||
87 | else { | 88 | else { |
88 | if (top->target_tid) | 89 | if (top->target.tid) |
89 | ret += SNPRINTF(bf + ret, size - ret, ")"); | 90 | ret += SNPRINTF(bf + ret, size - ret, ")"); |
90 | else | 91 | else |
91 | ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", | 92 | ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", |
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index ce61cb2d1acf..33347ca89ee4 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h | |||
@@ -13,6 +13,7 @@ struct perf_session; | |||
13 | struct perf_top { | 13 | struct perf_top { |
14 | struct perf_tool tool; | 14 | struct perf_tool tool; |
15 | struct perf_evlist *evlist; | 15 | struct perf_evlist *evlist; |
16 | struct perf_target target; | ||
16 | /* | 17 | /* |
17 | * Symbols will be added here in perf_event__process_sample and will | 18 | * Symbols will be added here in perf_event__process_sample and will |
18 | * get out after decayed. | 19 | * get out after decayed. |
@@ -23,10 +24,7 @@ struct perf_top { | |||
23 | u64 guest_us_samples, guest_kernel_samples; | 24 | u64 guest_us_samples, guest_kernel_samples; |
24 | int print_entries, count_filter, delay_secs; | 25 | int print_entries, count_filter, delay_secs; |
25 | int freq; | 26 | int freq; |
26 | const char *target_pid, *target_tid; | ||
27 | uid_t uid; | ||
28 | bool hide_kernel_symbols, hide_user_symbols, zero; | 27 | bool hide_kernel_symbols, hide_user_symbols, zero; |
29 | bool system_wide; | ||
30 | bool use_tui, use_stdio; | 28 | bool use_tui, use_stdio; |
31 | bool sort_has_symbols; | 29 | bool sort_has_symbols; |
32 | bool dont_use_callchains; | 30 | bool dont_use_callchains; |
@@ -37,7 +35,6 @@ struct perf_top { | |||
37 | bool sample_id_all_missing; | 35 | bool sample_id_all_missing; |
38 | bool exclude_guest_missing; | 36 | bool exclude_guest_missing; |
39 | bool dump_symtab; | 37 | bool dump_symtab; |
40 | const char *cpu_list; | ||
41 | struct hist_entry *sym_filter_entry; | 38 | struct hist_entry *sym_filter_entry; |
42 | struct perf_evsel *sym_evsel; | 39 | struct perf_evsel *sym_evsel; |
43 | struct perf_session *session; | 40 | struct perf_session *session; |
@@ -47,7 +44,6 @@ struct perf_top { | |||
47 | int realtime_prio; | 44 | int realtime_prio; |
48 | int sym_pcnt_filter; | 45 | int sym_pcnt_filter; |
49 | const char *sym_filter; | 46 | const char *sym_filter; |
50 | const char *uid_str; | ||
51 | }; | 47 | }; |
52 | 48 | ||
53 | size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); | 49 | size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); |
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c index 52bb07c6442a..4007aca8e0ca 100644 --- a/tools/perf/util/usage.c +++ b/tools/perf/util/usage.c | |||
@@ -82,41 +82,3 @@ void warning(const char *warn, ...) | |||
82 | warn_routine(warn, params); | 82 | warn_routine(warn, params); |
83 | va_end(params); | 83 | va_end(params); |
84 | } | 84 | } |
85 | |||
86 | uid_t parse_target_uid(const char *str, const char *tid, const char *pid) | ||
87 | { | ||
88 | struct passwd pwd, *result; | ||
89 | char buf[1024]; | ||
90 | |||
91 | if (str == NULL) | ||
92 | return UINT_MAX; | ||
93 | |||
94 | /* UID and PID are mutually exclusive */ | ||
95 | if (tid || pid) { | ||
96 | ui__warning("PID/TID switch overriding UID\n"); | ||
97 | sleep(1); | ||
98 | return UINT_MAX; | ||
99 | } | ||
100 | |||
101 | getpwnam_r(str, &pwd, buf, sizeof(buf), &result); | ||
102 | |||
103 | if (result == NULL) { | ||
104 | char *endptr; | ||
105 | int uid = strtol(str, &endptr, 10); | ||
106 | |||
107 | if (*endptr != '\0') { | ||
108 | ui__error("Invalid user %s\n", str); | ||
109 | return UINT_MAX - 1; | ||
110 | } | ||
111 | |||
112 | getpwuid_r(uid, &pwd, buf, sizeof(buf), &result); | ||
113 | |||
114 | if (result == NULL) { | ||
115 | ui__error("Problems obtaining information for user %s\n", | ||
116 | str); | ||
117 | return UINT_MAX - 1; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | return result->pw_uid; | ||
122 | } | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 6121e24fefc0..2daaedb83d84 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -74,7 +74,6 @@ | |||
74 | #include <netinet/tcp.h> | 74 | #include <netinet/tcp.h> |
75 | #include <arpa/inet.h> | 75 | #include <arpa/inet.h> |
76 | #include <netdb.h> | 76 | #include <netdb.h> |
77 | #include <pwd.h> | ||
78 | #include <inttypes.h> | 77 | #include <inttypes.h> |
79 | #include "../../../include/linux/magic.h" | 78 | #include "../../../include/linux/magic.h" |
80 | #include "types.h" | 79 | #include "types.h" |
@@ -249,8 +248,6 @@ struct perf_event_attr; | |||
249 | 248 | ||
250 | void event_attr_init(struct perf_event_attr *attr); | 249 | void event_attr_init(struct perf_event_attr *attr); |
251 | 250 | ||
252 | uid_t parse_target_uid(const char *str, const char *tid, const char *pid); | ||
253 | |||
254 | #define _STR(x) #x | 251 | #define _STR(x) #x |
255 | #define STR(x) _STR(x) | 252 | #define STR(x) _STR(x) |
256 | 253 | ||