aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-timechart.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-timechart.c')
-rw-r--r--tools/perf/builtin-timechart.c146
1 files changed, 134 insertions, 12 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 702d8fe58fbc..0a2f22261c3a 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,21 +774,42 @@ 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 = 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 = c->comm; 783 task_to = strdup(c->comm);
773 } 784 }
774 } 785 }
775 c = c->next; 786 c = c->next;
776 } 787 }
788 c = p->all;
789 while (c) {
790 if (p->pid == we->waker && !from) {
791 from = c->Y;
792 task_from = strdup(c->comm);
793 }
794 if (p->pid == we->wakee && !to) {
795 to = c->Y;
796 task_to = strdup(c->comm);
797 }
798 c = c->next;
799 }
777 } 800 }
778 p = p->next; 801 p = p->next;
779 } 802 }
780 803
804 if (!task_from) {
805 task_from = malloc(40);
806 sprintf(task_from, "[%i]", we->waker);
807 }
808 if (!task_to) {
809 task_to = malloc(40);
810 sprintf(task_to, "[%i]", we->wakee);
811 }
812
781 if (we->waker == -1) 813 if (we->waker == -1)
782 svg_interrupt(we->time, to); 814 svg_interrupt(we->time, to);
783 else if (from && to && abs(from - to) == 1) 815 else if (from && to && abs(from - to) == 1)
@@ -785,6 +817,9 @@ static void draw_wakeups(void)
785 else 817 else
786 svg_partial_wakeline(we->time, from, task_from, to, task_to); 818 svg_partial_wakeline(we->time, from, task_from, to, task_to);
787 we = we->next; 819 we = we->next;
820
821 free(task_from);
822 free(task_to);
788 } 823 }
789} 824}
790 825
@@ -858,12 +893,89 @@ static void draw_process_bars(void)
858 } 893 }
859} 894}
860 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
861static int determine_display_tasks(u64 threshold) 970static int determine_display_tasks(u64 threshold)
862{ 971{
863 struct per_pid *p; 972 struct per_pid *p;
864 struct per_pidcomm *c; 973 struct per_pidcomm *c;
865 int count = 0; 974 int count = 0;
866 975
976 if (process_filter)
977 return determine_display_tasks_filtered();
978
867 p = all_data; 979 p = all_data;
868 while (p) { 980 while (p) {
869 p->display = 0; 981 p->display = 0;
@@ -1050,12 +1162,10 @@ more:
1050 size = event->header.size; 1162 size = event->header.size;
1051 1163
1052 if (!size || process_event(event) < 0) { 1164 if (!size || process_event(event) < 0) {
1053 1165 pr_warning("%p [%p]: skipping unknown header type: %d\n",
1054 printf("%p [%p]: skipping unknown header type: %d\n", 1166 (void *)(offset + head),
1055 (void *)(offset + head), 1167 (void *)(long)(event->header.size),
1056 (void *)(long)(event->header.size), 1168 event->header.type);
1057 event->header.type);
1058
1059 /* 1169 /*
1060 * assume we lost track of the stream, check alignment, and 1170 * assume we lost track of the stream, check alignment, and
1061 * increment a single u64 in the hope to catch on again 'soon'. 1171 * increment a single u64 in the hope to catch on again 'soon'.
@@ -1088,7 +1198,8 @@ done:
1088 1198
1089 write_svg_file(output_name); 1199 write_svg_file(output_name);
1090 1200
1091 printf("Written %2.1f seconds of trace to %s.\n", (last_time - first_time) / 1000000000.0, output_name); 1201 pr_info("Written %2.1f seconds of trace to %s.\n",
1202 (last_time - first_time) / 1000000000.0, output_name);
1092 1203
1093 return rc; 1204 return rc;
1094} 1205}
@@ -1129,6 +1240,14 @@ static int __cmd_record(int argc, const char **argv)
1129 return cmd_record(i, rec_argv, NULL); 1240 return cmd_record(i, rec_argv, NULL);
1130} 1241}
1131 1242
1243static int
1244parse_process(const struct option *opt __used, const char *arg, int __used unset)
1245{
1246 if (arg)
1247 add_process_filter(arg);
1248 return 0;
1249}
1250
1132static const struct option options[] = { 1251static const struct option options[] = {
1133 OPT_STRING('i', "input", &input_name, "file", 1252 OPT_STRING('i', "input", &input_name, "file",
1134 "input file name"), 1253 "input file name"),
@@ -1136,8 +1255,11 @@ static const struct option options[] = {
1136 "output file name"), 1255 "output file name"),
1137 OPT_INTEGER('w', "width", &svg_page_width, 1256 OPT_INTEGER('w', "width", &svg_page_width,
1138 "page width"), 1257 "page width"),
1139 OPT_BOOLEAN('p', "power-only", &power_only, 1258 OPT_BOOLEAN('P', "power-only", &power_only,
1140 "output power data only"), 1259 "output power data only"),
1260 OPT_CALLBACK('p', "process", NULL, "process",
1261 "process selector. Pass a pid or process name.",
1262 parse_process),
1141 OPT_END() 1263 OPT_END()
1142}; 1264};
1143 1265