aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-timechart.c
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@infradead.org>2009-10-19 18:09:39 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-20 01:55:50 -0400
commitbbe2987bea26a684ff11d887dfc4cf39b22c27a2 (patch)
tree5d11557ced1a66ead7329a3728ba9b77154884bf /tools/perf/builtin-timechart.c
parentc258449bc9d286e2ee6546c9cdf911e96cbc126a (diff)
perf timechart: Add a process filter
During the Kernel Summit demo of perf/ftrace/timechart, there was a feature request to have a process filter for timechart so that you can zoom into one or a few processes that you are really interested in. This patch adds basic support for this feature, the -p (--process) option now can select a PID or a process name to be shown. Multiple -p options are allowed, and the combined set will be included in the output. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20091020070939.7d0fb8a7@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-timechart.c')
-rw-r--r--tools/perf/builtin-timechart.c105
1 files changed, 102 insertions, 3 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index e8a510d935e5..34fad57087f9 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -153,6 +153,17 @@ static struct wake_event *wake_events;
153 153
154struct sample_wrapper *all_samples; 154struct sample_wrapper *all_samples;
155 155
156
157struct process_filter;
158struct process_filter {
159 char *name;
160 int pid;
161 struct process_filter *next;
162};
163
164static struct process_filter *process_filter;
165
166
156static struct per_pid *find_create_pid(int pid) 167static struct per_pid *find_create_pid(int pid)
157{ 168{
158 struct per_pid *cursor = all_data; 169 struct per_pid *cursor = all_data;
@@ -763,11 +774,11 @@ static void draw_wakeups(void)
763 c = p->all; 774 c = p->all;
764 while (c) { 775 while (c) {
765 if (c->Y && c->start_time <= we->time && c->end_time >= we->time) { 776 if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
766 if (p->pid == we->waker) { 777 if (p->pid == we->waker && !from) {
767 from = c->Y; 778 from = c->Y;
768 task_from = strdup(c->comm); 779 task_from = strdup(c->comm);
769 } 780 }
770 if (p->pid == we->wakee) { 781 if (p->pid == we->wakee && !to) {
771 to = c->Y; 782 to = c->Y;
772 task_to = strdup(c->comm); 783 task_to = strdup(c->comm);
773 } 784 }
@@ -882,12 +893,89 @@ static void draw_process_bars(void)
882 } 893 }
883} 894}
884 895
896static void add_process_filter(const char *string)
897{
898 struct process_filter *filt;
899 int pid;
900
901 pid = strtoull(string, NULL, 10);
902 filt = malloc(sizeof(struct process_filter));
903 if (!filt)
904 return;
905
906 filt->name = strdup(string);
907 filt->pid = pid;
908 filt->next = process_filter;
909
910 process_filter = filt;
911}
912
913static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
914{
915 struct process_filter *filt;
916 if (!process_filter)
917 return 1;
918
919 filt = process_filter;
920 while (filt) {
921 if (filt->pid && p->pid == filt->pid)
922 return 1;
923 if (strcmp(filt->name, c->comm) == 0)
924 return 1;
925 filt = filt->next;
926 }
927 return 0;
928}
929
930static int determine_display_tasks_filtered(void)
931{
932 struct per_pid *p;
933 struct per_pidcomm *c;
934 int count = 0;
935
936 p = all_data;
937 while (p) {
938 p->display = 0;
939 if (p->start_time == 1)
940 p->start_time = first_time;
941
942 /* no exit marker, task kept running to the end */
943 if (p->end_time == 0)
944 p->end_time = last_time;
945
946 c = p->all;
947
948 while (c) {
949 c->display = 0;
950
951 if (c->start_time == 1)
952 c->start_time = first_time;
953
954 if (passes_filter(p, c)) {
955 c->display = 1;
956 p->display = 1;
957 count++;
958 }
959
960 if (c->end_time == 0)
961 c->end_time = last_time;
962
963 c = c->next;
964 }
965 p = p->next;
966 }
967 return count;
968}
969
885static int determine_display_tasks(u64 threshold) 970static int determine_display_tasks(u64 threshold)
886{ 971{
887 struct per_pid *p; 972 struct per_pid *p;
888 struct per_pidcomm *c; 973 struct per_pidcomm *c;
889 int count = 0; 974 int count = 0;
890 975
976 if (process_filter)
977 return determine_display_tasks_filtered();
978
891 p = all_data; 979 p = all_data;
892 while (p) { 980 while (p) {
893 p->display = 0; 981 p->display = 0;
@@ -1153,6 +1241,14 @@ static int __cmd_record(int argc, const char **argv)
1153 return cmd_record(i, rec_argv, NULL); 1241 return cmd_record(i, rec_argv, NULL);
1154} 1242}
1155 1243
1244static int
1245parse_process(const struct option *opt __used, const char *arg, int __used unset)
1246{
1247 if (arg)
1248 add_process_filter(arg);
1249 return 0;
1250}
1251
1156static const struct option options[] = { 1252static const struct option options[] = {
1157 OPT_STRING('i', "input", &input_name, "file", 1253 OPT_STRING('i', "input", &input_name, "file",
1158 "input file name"), 1254 "input file name"),
@@ -1160,8 +1256,11 @@ static const struct option options[] = {
1160 "output file name"), 1256 "output file name"),
1161 OPT_INTEGER('w', "width", &svg_page_width, 1257 OPT_INTEGER('w', "width", &svg_page_width,
1162 "page width"), 1258 "page width"),
1163 OPT_BOOLEAN('p', "power-only", &power_only, 1259 OPT_BOOLEAN('P', "power-only", &power_only,
1164 "output power data only"), 1260 "output power data only"),
1261 OPT_CALLBACK('p', "process", NULL, "process",
1262 "process selector. Pass a pid or process name.",
1263 parse_process),
1165 OPT_END() 1264 OPT_END()
1166}; 1265};
1167 1266