diff options
Diffstat (limited to 'trace-plot-task.c')
-rw-r--r-- | trace-plot-task.c | 148 |
1 files changed, 72 insertions, 76 deletions
diff --git a/trace-plot-task.c b/trace-plot-task.c index 9ca97a3..e4ac13a 100644 --- a/trace-plot-task.c +++ b/trace-plot-task.c | |||
@@ -26,41 +26,7 @@ | |||
26 | #define RED 0xff | 26 | #define RED 0xff |
27 | #define GREEN (0xff<<16) | 27 | #define GREEN (0xff<<16) |
28 | 28 | ||
29 | struct task_plot_info { | 29 | gboolean is_running(struct graph_info *ginfo, struct record *record) |
30 | int pid; | ||
31 | struct cpu_data *cpu_data; | ||
32 | struct record **last_records; | ||
33 | unsigned long long last_time; | ||
34 | unsigned long long wake_time; | ||
35 | unsigned long long display_wake_time; | ||
36 | int wake_color; | ||
37 | int last_cpu; | ||
38 | }; | ||
39 | |||
40 | static void convert_nano(unsigned long long time, unsigned long *sec, | ||
41 | unsigned long *usec) | ||
42 | { | ||
43 | *sec = time / 1000000000ULL; | ||
44 | *usec = (time / 1000) % 1000000; | ||
45 | } | ||
46 | |||
47 | static gint hash_pid(gint val) | ||
48 | { | ||
49 | /* idle always gets black */ | ||
50 | if (!val) | ||
51 | return 0; | ||
52 | |||
53 | return trace_hash(val); | ||
54 | } | ||
55 | |||
56 | static int hash_cpu(int cpu) | ||
57 | { | ||
58 | cpu = (cpu << 3) + cpu * 21; | ||
59 | |||
60 | return trace_hash(cpu); | ||
61 | } | ||
62 | |||
63 | static gboolean is_running(struct graph_info *ginfo, struct record *record) | ||
64 | { | 30 | { |
65 | unsigned long long val; | 31 | unsigned long long val; |
66 | int id; | 32 | int id; |
@@ -73,7 +39,7 @@ static gboolean is_running(struct graph_info *ginfo, struct record *record) | |||
73 | return val ? FALSE : TRUE; | 39 | return val ? FALSE : TRUE; |
74 | } | 40 | } |
75 | 41 | ||
76 | static gboolean record_matches_pid(struct graph_info *ginfo, | 42 | gboolean record_matches_pid(struct graph_info *ginfo, |
77 | struct record *record, int match_pid, | 43 | struct record *record, int match_pid, |
78 | int *pid, int *sched_pid, | 44 | int *pid, int *sched_pid, |
79 | gboolean *is_sched, | 45 | gboolean *is_sched, |
@@ -107,7 +73,7 @@ static gboolean record_matches_pid(struct graph_info *ginfo, | |||
107 | return FALSE; | 73 | return FALSE; |
108 | } | 74 | } |
109 | 75 | ||
110 | static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time) | 76 | void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time) |
111 | { | 77 | { |
112 | struct record *record; | 78 | struct record *record; |
113 | 79 | ||
@@ -126,7 +92,7 @@ static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long lon | |||
126 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time); | 92 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time); |
127 | } | 93 | } |
128 | 94 | ||
129 | static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) | 95 | void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) |
130 | { | 96 | { |
131 | int cpu; | 97 | int cpu; |
132 | 98 | ||
@@ -134,7 +100,7 @@ static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) | |||
134 | set_cpu_to_time(cpu, ginfo, time); | 100 | set_cpu_to_time(cpu, ginfo, time); |
135 | } | 101 | } |
136 | 102 | ||
137 | static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, | 103 | int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, |
138 | unsigned long long time) | 104 | unsigned long long time) |
139 | { | 105 | { |
140 | struct task_plot_info *task_info = plot->private; | 106 | struct task_plot_info *task_info = plot->private; |
@@ -173,11 +139,7 @@ static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plo | |||
173 | return ret; | 139 | return ret; |
174 | } | 140 | } |
175 | 141 | ||
176 | struct offset_cache { | 142 | struct offset_cache *save_offsets(struct graph_info *ginfo) |
177 | guint64 *offsets; | ||
178 | }; | ||
179 | |||
180 | static struct offset_cache *save_offsets(struct graph_info *ginfo) | ||
181 | { | 143 | { |
182 | struct offset_cache *offsets; | 144 | struct offset_cache *offsets; |
183 | struct record *record; | 145 | struct record *record; |
@@ -196,7 +158,7 @@ static struct offset_cache *save_offsets(struct graph_info *ginfo) | |||
196 | return offsets; | 158 | return offsets; |
197 | } | 159 | } |
198 | 160 | ||
199 | static void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets) | 161 | void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets) |
200 | { | 162 | { |
201 | struct record *record; | 163 | struct record *record; |
202 | int cpu; | 164 | int cpu; |
@@ -215,7 +177,7 @@ static void restore_offsets(struct graph_info *ginfo, struct offset_cache *offse | |||
215 | free(offsets); | 177 | free(offsets); |
216 | } | 178 | } |
217 | 179 | ||
218 | static struct record * | 180 | struct record * |
219 | find_record(struct graph_info *ginfo, gint pid, guint64 time) | 181 | find_record(struct graph_info *ginfo, gint pid, guint64 time) |
220 | { | 182 | { |
221 | struct record *record = NULL; | 183 | struct record *record = NULL; |
@@ -245,7 +207,7 @@ find_record(struct graph_info *ginfo, gint pid, guint64 time) | |||
245 | return record; | 207 | return record; |
246 | } | 208 | } |
247 | 209 | ||
248 | static int task_plot_display_last_event(struct graph_info *ginfo, | 210 | int task_plot_display_last_event(struct graph_info *ginfo, |
249 | struct graph_plot *plot, | 211 | struct graph_plot *plot, |
250 | struct trace_seq *s, | 212 | struct trace_seq *s, |
251 | unsigned long long time) | 213 | unsigned long long time) |
@@ -318,7 +280,7 @@ static int task_plot_display_last_event(struct graph_info *ginfo, | |||
318 | return 1; | 280 | return 1; |
319 | } | 281 | } |
320 | 282 | ||
321 | static void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | 283 | void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, |
322 | unsigned long long time) | 284 | unsigned long long time) |
323 | { | 285 | { |
324 | struct task_plot_info *task_info = plot->private; | 286 | struct task_plot_info *task_info = plot->private; |
@@ -331,7 +293,7 @@ static void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | |||
331 | task_info->display_wake_time = 0ULL; | 293 | task_info->display_wake_time = 0ULL; |
332 | } | 294 | } |
333 | 295 | ||
334 | static void update_last_record(struct graph_info *ginfo, | 296 | void update_last_task_record(struct graph_info *ginfo, |
335 | struct task_plot_info *task_info, | 297 | struct task_plot_info *task_info, |
336 | struct record *record) | 298 | struct record *record) |
337 | { | 299 | { |
@@ -363,7 +325,7 @@ static void update_last_record(struct graph_info *ginfo, | |||
363 | continue; | 325 | continue; |
364 | 326 | ||
365 | if (cpu == this_cpu) { | 327 | if (cpu == this_cpu) { |
366 | static int once; | 328 | int once; |
367 | 329 | ||
368 | trecord = tracecmd_read_prev(handle, record); | 330 | trecord = tracecmd_read_prev(handle, record); |
369 | /* Set cpu cursor back to what it was */ | 331 | /* Set cpu cursor back to what it was */ |
@@ -374,7 +336,7 @@ static void update_last_record(struct graph_info *ginfo, | |||
374 | } | 336 | } |
375 | free_record(saved); | 337 | free_record(saved); |
376 | } else { | 338 | } else { |
377 | static int once; | 339 | int once; |
378 | 340 | ||
379 | saved = tracecmd_read_data(handle, cpu); | 341 | saved = tracecmd_read_data(handle, cpu); |
380 | set_cpu_to_time(cpu, ginfo, ts); | 342 | set_cpu_to_time(cpu, ginfo, ts); |
@@ -412,7 +374,7 @@ static void update_last_record(struct graph_info *ginfo, | |||
412 | } | 374 | } |
413 | } | 375 | } |
414 | 376 | ||
415 | static int task_plot_event(struct graph_info *ginfo, | 377 | int task_plot_event(struct graph_info *ginfo, |
416 | struct graph_plot *plot, | 378 | struct graph_plot *plot, |
417 | struct record *record, | 379 | struct record *record, |
418 | struct plot_info *info) | 380 | struct plot_info *info) |
@@ -429,7 +391,7 @@ static int task_plot_event(struct graph_info *ginfo, | |||
429 | pid = task_info->pid; | 391 | pid = task_info->pid; |
430 | 392 | ||
431 | if (!record) { | 393 | if (!record) { |
432 | update_last_record(ginfo, task_info, record); | 394 | update_last_task_record(ginfo, task_info, record); |
433 | /* no more records, finish a box if one was started */ | 395 | /* no more records, finish a box if one was started */ |
434 | if (task_info->last_cpu >= 0) { | 396 | if (task_info->last_cpu >= 0) { |
435 | info->box = TRUE; | 397 | info->box = TRUE; |
@@ -468,7 +430,7 @@ static int task_plot_event(struct graph_info *ginfo, | |||
468 | * viewable range. Search to see if one exists, and if | 430 | * viewable range. Search to see if one exists, and if |
469 | * it is the record we want to match. | 431 | * it is the record we want to match. |
470 | */ | 432 | */ |
471 | update_last_record(ginfo, task_info, record); | 433 | update_last_task_record(ginfo, task_info, record); |
472 | 434 | ||
473 | if (is_wakeup) { | 435 | if (is_wakeup) { |
474 | /* Wake up but not task */ | 436 | /* Wake up but not task */ |
@@ -555,7 +517,7 @@ static int task_plot_event(struct graph_info *ginfo, | |||
555 | } | 517 | } |
556 | 518 | ||
557 | 519 | ||
558 | static struct record * | 520 | struct record * |
559 | task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, | 521 | task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, |
560 | unsigned long long time) | 522 | unsigned long long time) |
561 | { | 523 | { |
@@ -569,7 +531,7 @@ task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, | |||
569 | 531 | ||
570 | #define MAX_SEARCH 20 | 532 | #define MAX_SEARCH 20 |
571 | 533 | ||
572 | static struct record * | 534 | struct record * |
573 | find_previous_record(struct graph_info *ginfo, struct record *start_record, | 535 | find_previous_record(struct graph_info *ginfo, struct record *start_record, |
574 | int pid, int cpu) | 536 | int pid, int cpu) |
575 | { | 537 | { |
@@ -609,7 +571,7 @@ find_previous_record(struct graph_info *ginfo, struct record *start_record, | |||
609 | return record; | 571 | return record; |
610 | } | 572 | } |
611 | 573 | ||
612 | static struct record * | 574 | struct record * |
613 | get_display_record(struct graph_info *ginfo, int pid, unsigned long long time) | 575 | get_display_record(struct graph_info *ginfo, int pid, unsigned long long time) |
614 | { | 576 | { |
615 | struct record *record; | 577 | struct record *record; |
@@ -752,16 +714,10 @@ static const struct plot_callbacks task_plot_cb = { | |||
752 | .destroy = task_plot_destroy | 714 | .destroy = task_plot_destroy |
753 | }; | 715 | }; |
754 | 716 | ||
755 | /** | 717 | |
756 | * graph_plot_task_plotted - return what tasks are plotted | 718 | void graph_tasks_plotted(struct graph_info *ginfo, |
757 | * @ginfo: the graph info structure | 719 | enum task_plot_type type, |
758 | * @plotted: returns an allocated array of gints holding the pids. | 720 | gint **plotted) |
759 | * the last pid is -1, NULL, if none are. | ||
760 | * | ||
761 | * @plotted must be freed with free() after this is called. | ||
762 | */ | ||
763 | void graph_plot_task_plotted(struct graph_info *ginfo, | ||
764 | gint **plotted) | ||
765 | { | 721 | { |
766 | struct task_plot_info *task_info; | 722 | struct task_plot_info *task_info; |
767 | struct graph_plot *plot; | 723 | struct graph_plot *plot; |
@@ -778,10 +734,26 @@ void graph_plot_task_plotted(struct graph_info *ginfo, | |||
778 | } | 734 | } |
779 | } | 735 | } |
780 | 736 | ||
781 | void graph_plot_task_update_callback(gboolean accept, | 737 | /** |
782 | gint *selected, | 738 | * graph_plot_task_plotted - return what tasks are plotted |
783 | gint *non_select, | 739 | * @ginfo: the graph info structure |
784 | gpointer data) | 740 | * @plotted: returns an allocated array of gints holding the pids. |
741 | * the last pid is -1, NULL, if none are. | ||
742 | * | ||
743 | * @plotted must be freed with free() after this is called. | ||
744 | */ | ||
745 | void graph_plot_task_plotted(struct graph_info *ginfo, | ||
746 | gint **plotted) | ||
747 | { | ||
748 | graph_tasks_plotted(ginfo, TASK_PLOT_LINUX, plotted); | ||
749 | } | ||
750 | |||
751 | void graph_tasks_update_callback(enum task_plot_type type, | ||
752 | plot_task_cb plot_cb, | ||
753 | gboolean accept, | ||
754 | gint *selected, | ||
755 | gint *non_select, | ||
756 | gpointer data) | ||
785 | { | 757 | { |
786 | struct graph_info *ginfo = data; | 758 | struct graph_info *ginfo = data; |
787 | struct task_plot_info *task_info; | 759 | struct task_plot_info *task_info; |
@@ -809,12 +781,16 @@ void graph_plot_task_update_callback(gboolean accept, | |||
809 | plot = ginfo->plot_array[i]; | 781 | plot = ginfo->plot_array[i]; |
810 | if (plot->type != PLOT_TYPE_TASK) | 782 | if (plot->type != PLOT_TYPE_TASK) |
811 | continue; | 783 | continue; |
784 | |||
785 | task_info = plot->private; | ||
786 | if (task_info->type != type) | ||
787 | continue; | ||
788 | |||
812 | /* If non are selected, then remove all */ | 789 | /* If non are selected, then remove all */ |
813 | if (!select_size) { | 790 | if (!select_size) { |
814 | trace_graph_plot_remove(ginfo, plot); | 791 | trace_graph_plot_remove(ginfo, plot); |
815 | continue; | 792 | continue; |
816 | } | 793 | } |
817 | task_info = plot->private; | ||
818 | ptr = bsearch(&task_info->pid, selected, select_size, | 794 | ptr = bsearch(&task_info->pid, selected, select_size, |
819 | sizeof(gint), id_cmp); | 795 | sizeof(gint), id_cmp); |
820 | if (ptr) { | 796 | if (ptr) { |
@@ -834,11 +810,20 @@ void graph_plot_task_update_callback(gboolean accept, | |||
834 | 810 | ||
835 | /* Now add any plots that need to be added */ | 811 | /* Now add any plots that need to be added */ |
836 | for (i = 0; i < select_size; i++) | 812 | for (i = 0; i < select_size; i++) |
837 | graph_plot_task(ginfo, selected[i], ginfo->plots); | 813 | plot_cb(ginfo, selected[i], ginfo->plots); |
838 | 814 | ||
839 | trace_graph_refresh(ginfo); | 815 | trace_graph_refresh(ginfo); |
840 | } | 816 | } |
841 | 817 | ||
818 | void graph_plot_task_update_callback(gboolean accept, | ||
819 | gint *selected, | ||
820 | gint *non_select, | ||
821 | gpointer data) | ||
822 | { | ||
823 | graph_tasks_update_callback(TASK_PLOT_LINUX, graph_plot_task, | ||
824 | accept, selected, non_select, data); | ||
825 | } | ||
826 | |||
842 | void graph_plot_init_tasks(struct graph_info *ginfo) | 827 | void graph_plot_init_tasks(struct graph_info *ginfo) |
843 | { | 828 | { |
844 | struct task_plot_info *task_info; | 829 | struct task_plot_info *task_info; |
@@ -866,6 +851,17 @@ void graph_plot_init_tasks(struct graph_info *ginfo) | |||
866 | &task_plot_cb, task_info); | 851 | &task_plot_cb, task_info); |
867 | } | 852 | } |
868 | 853 | ||
854 | void init_task_plot_info(struct graph_info *ginfo, | ||
855 | struct task_plot_info *task_info, | ||
856 | enum task_plot_type type, | ||
857 | int pid) | ||
858 | { | ||
859 | task_info->last_records = | ||
860 | malloc_or_die(sizeof(struct record *) * ginfo->cpus); | ||
861 | task_info->pid = pid; | ||
862 | task_info->type = type; | ||
863 | } | ||
864 | |||
869 | void graph_plot_task(struct graph_info *ginfo, int pid, int pos) | 865 | void graph_plot_task(struct graph_info *ginfo, int pid, int pos) |
870 | { | 866 | { |
871 | struct task_plot_info *task_info; | 867 | struct task_plot_info *task_info; |
@@ -875,9 +871,9 @@ void graph_plot_task(struct graph_info *ginfo, int pid, int pos) | |||
875 | int len; | 871 | int len; |
876 | 872 | ||
877 | task_info = malloc_or_die(sizeof(*task_info)); | 873 | task_info = malloc_or_die(sizeof(*task_info)); |
878 | task_info->last_records = | 874 | |
879 | malloc_or_die(sizeof(struct record *) * ginfo->cpus); | 875 | init_task_plot_info(ginfo, task_info, TASK_PLOT_LINUX, pid); |
880 | task_info->pid = pid; | 876 | |
881 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); | 877 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); |
882 | 878 | ||
883 | len = strlen(comm) + 100; | 879 | len = strlen(comm) + 100; |