aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trace-plot-cpu.c32
-rw-r--r--trace-plot-task.c126
2 files changed, 143 insertions, 15 deletions
diff --git a/trace-plot-cpu.c b/trace-plot-cpu.c
index 09b1690..d6800ef 100644
--- a/trace-plot-cpu.c
+++ b/trace-plot-cpu.c
@@ -27,6 +27,7 @@ struct cpu_plot_info {
27 int cpu; 27 int cpu;
28 unsigned long long last_time; 28 unsigned long long last_time;
29 int last_pid; 29 int last_pid;
30 struct record *last_record;
30}; 31};
31 32
32static gint hash_pid(gint val) 33static gint hash_pid(gint val)
@@ -192,6 +193,7 @@ static void cpu_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
192 cpu = cpu_info->cpu; 193 cpu = cpu_info->cpu;
193 cpu_info->last_time = 0ULL; 194 cpu_info->last_time = 0ULL;
194 cpu_info->last_pid = -1; 195 cpu_info->last_pid = -1;
196 cpu_info->last_record = NULL;
195} 197}
196 198
197static int cpu_plot_event(struct graph_info *ginfo, 199static int cpu_plot_event(struct graph_info *ginfo,
@@ -200,6 +202,7 @@ static int cpu_plot_event(struct graph_info *ginfo,
200 struct plot_info *info) 202 struct plot_info *info)
201{ 203{
202 struct cpu_plot_info *cpu_info = plot->private; 204 struct cpu_plot_info *cpu_info = plot->private;
205 struct tracecmd_input *handle = ginfo->handle;
203 int sched_pid; 206 int sched_pid;
204 int orig_pid; 207 int orig_pid;
205 int is_sched_switch; 208 int is_sched_switch;
@@ -212,6 +215,11 @@ static int cpu_plot_event(struct graph_info *ginfo,
212 cpu = cpu_info->cpu; 215 cpu = cpu_info->cpu;
213 216
214 if (!record) { 217 if (!record) {
218 if (cpu_info->last_record) {
219 free_record(cpu_info->last_record);
220 cpu_info->last_record = NULL;
221 }
222
215 /* Finish a box if the last record was not idle */ 223 /* Finish a box if the last record was not idle */
216 if (cpu_info->last_pid > 0) { 224 if (cpu_info->last_pid > 0) {
217 info->box = TRUE; 225 info->box = TRUE;
@@ -222,6 +230,30 @@ static int cpu_plot_event(struct graph_info *ginfo,
222 return 0; 230 return 0;
223 } 231 }
224 232
233 /*
234 * If last record is NULL, then it may exist off the
235 * viewable range. Search to see if one exists.
236 */
237 if (!cpu_info->last_record) {
238 struct record *trecord;
239
240 trecord = tracecmd_read_prev(handle, record);
241 if (trecord) {
242 filter = filter_record(ginfo, trecord,
243 &orig_pid, &sched_pid,
244 &is_sched_switch);
245 cpu_info->last_pid = is_sched_switch ? sched_pid : orig_pid;
246 }
247 cpu_info->last_record = trecord;
248 /* We moved the cursor, put it back */
249 trecord = tracecmd_read_data(handle, record->cpu);
250 free_record(trecord);
251 }
252
253 free_record(cpu_info->last_record);
254 cpu_info->last_record = record;
255 tracecmd_record_ref(record);
256
225 cpu = cpu_info->cpu; 257 cpu = cpu_info->cpu;
226 258
227 filter = filter_record(ginfo, record, &orig_pid, &sched_pid, &is_sched_switch); 259 filter = filter_record(ginfo, record, &orig_pid, &sched_pid, &is_sched_switch);
diff --git a/trace-plot-task.c b/trace-plot-task.c
index c8d0905..aac771e 100644
--- a/trace-plot-task.c
+++ b/trace-plot-task.c
@@ -29,6 +29,7 @@
29struct task_plot_info { 29struct task_plot_info {
30 int pid; 30 int pid;
31 struct cpu_data *cpu_data; 31 struct cpu_data *cpu_data;
32 struct record **last_records;
32 unsigned long long last_time; 33 unsigned long long last_time;
33 unsigned long long wake_time; 34 unsigned long long wake_time;
34 unsigned long long display_wake_time; 35 unsigned long long display_wake_time;
@@ -104,26 +105,31 @@ static gboolean record_matches_pid(struct graph_info *ginfo,
104 return FALSE; 105 return FALSE;
105} 106}
106 107
107static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) 108static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time)
108{ 109{
109 struct record *record; 110 struct record *record;
110 int cpu;
111 111
112 for (cpu = 0; cpu < ginfo->cpus; cpu++) { 112 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
113 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
114 113
115 while ((record = tracecmd_read_data(ginfo->handle, cpu))) { 114 while ((record = tracecmd_read_data(ginfo->handle, cpu))) {
116 if (record->ts >= time) 115 if (record->ts >= time)
117 break; 116 break;
118 117
119 free_record(record); 118 free_record(record);
120 }
121 if (record) {
122 tracecmd_set_cursor(ginfo->handle, cpu, record->offset);
123 free_record(record);
124 } else
125 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
126 } 119 }
120 if (record) {
121 tracecmd_set_cursor(ginfo->handle, cpu, record->offset);
122 free_record(record);
123 } else
124 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
125}
126
127static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time)
128{
129 int cpu;
130
131 for (cpu = 0; cpu < ginfo->cpus; cpu++)
132 set_cpu_to_time(cpu, ginfo, time);
127} 133}
128 134
129static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, 135static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot,
@@ -315,6 +321,8 @@ static void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
315{ 321{
316 struct task_plot_info *task_info = plot->private; 322 struct task_plot_info *task_info = plot->private;
317 323
324 memset(task_info->last_records, 0, sizeof(struct record *) * ginfo->cpus);
325
318 task_info->last_time = 0ULL; 326 task_info->last_time = 0ULL;
319 task_info->last_cpu = -1; 327 task_info->last_cpu = -1;
320 task_info->wake_time = 0ULL; 328 task_info->wake_time = 0ULL;
@@ -327,16 +335,22 @@ static int task_plot_event(struct graph_info *ginfo,
327 struct plot_info *info) 335 struct plot_info *info)
328{ 336{
329 struct task_plot_info *task_info = plot->private; 337 struct task_plot_info *task_info = plot->private;
338 struct tracecmd_input *handle = ginfo->handle;
330 gboolean match; 339 gboolean match;
331 int sched_pid; 340 int sched_pid;
332 int rec_pid; 341 int rec_pid;
333 int is_wakeup; 342 int is_wakeup;
334 int is_sched; 343 int is_sched;
335 int pid; 344 int pid;
345 int cpu;
336 346
337 pid = task_info->pid; 347 pid = task_info->pid;
338 348
339 if (!record) { 349 if (!record) {
350 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
351 free_record(task_info->last_records[cpu]);
352 task_info->last_records[cpu] = NULL;
353 }
340 /* no more records, finish a box if one was started */ 354 /* no more records, finish a box if one was started */
341 if (task_info->last_cpu >= 0) { 355 if (task_info->last_cpu >= 0) {
342 info->box = TRUE; 356 info->box = TRUE;
@@ -350,14 +364,85 @@ static int task_plot_event(struct graph_info *ginfo,
350 match = record_matches_pid(ginfo, record, pid, &rec_pid, 364 match = record_matches_pid(ginfo, record, pid, &rec_pid,
351 &sched_pid, &is_sched, &is_wakeup); 365 &sched_pid, &is_sched, &is_wakeup);
352 366
353 if (!match && record->cpu != task_info->last_cpu) 367
368 if (!match && record->cpu != task_info->last_cpu) {
369 if (!task_info->last_records[record->cpu]) {
370 task_info->last_records[record->cpu] = record;
371 tracecmd_record_ref(record);
372 }
354 return 0; 373 return 0;
374 }
355 375
356 if (match) { 376 if (match) {
357 info->line = TRUE; 377 info->line = TRUE;
358 info->lcolor = hash_pid(rec_pid); 378 info->lcolor = hash_pid(rec_pid);
359 info->ltime = record->ts; 379 info->ltime = record->ts;
360 380
381 /*
382 * Is this our first match?
383 *
384 * If last record is NULL, then it may exist off the
385 * viewable range. Search to see if one exists, and if
386 * it is the record we want to match.
387 */
388 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
389 struct record *trecord, *t2record;
390 struct record *saved;
391 int this_cpu = record->cpu;
392 int tsched_pid;
393 int tpid;
394 int tis_wakeup;
395 int tis_sched;
396
397 if (task_info->last_records[cpu])
398 continue;
399
400 if (cpu == this_cpu) {
401 static int once;
402
403 trecord = tracecmd_read_prev(handle, record);
404 /* Set cpu cursor back to what it was */
405 saved = tracecmd_read_data(handle, cpu);
406 if (!once && saved->offset != record->offset) {
407 once++;
408 warning("failed to reset cursor!");
409 }
410 free_record(saved);
411 } else {
412 static int once;
413
414 saved = tracecmd_peek_data(handle, cpu);
415 set_cpu_to_time(cpu, ginfo, record->ts);
416 t2record = tracecmd_read_data(handle, cpu);
417 trecord = tracecmd_read_prev(handle, t2record);
418 free_record(t2record);
419 /* reset cursor back to what it was */
420 if (saved)
421 tracecmd_set_cursor(handle, cpu, saved->offset);
422 else {
423 saved = tracecmd_read_data(handle, cpu);
424 if (!once && saved) {
425 once++;
426 warning("failed to reset cursor to end!");
427 }
428 }
429 }
430 if (!trecord)
431 continue;
432
433 if (record_matches_pid(ginfo, trecord, pid, &tpid,
434 &tsched_pid, &tis_sched, &tis_wakeup) &&
435 !tis_wakeup &&
436 (!is_sched || (is_sched && sched_pid == pid))) {
437 task_info->last_records[cpu] = trecord;
438 task_info->last_cpu = trecord->cpu;
439 task_info->last_time = trecord->ts;
440 break;
441 }
442
443 free_record(trecord);
444 }
445
361 if (is_wakeup) { 446 if (is_wakeup) {
362 /* Wake up but not task */ 447 /* Wake up but not task */
363 info->ltime = hash_pid(rec_pid); 448 info->ltime = hash_pid(rec_pid);
@@ -424,6 +509,12 @@ static int task_plot_event(struct graph_info *ginfo,
424 return 1; 509 return 1;
425 } 510 }
426 511
512 cpu = record->cpu;
513
514 if (!task_info->last_records[cpu]) {
515 free_record(task_info->last_records[cpu]);
516 task_info->last_records[cpu] = record;
517 }
427 /* not a match, and on the last CPU, scheduled out? */ 518 /* not a match, and on the last CPU, scheduled out? */
428 if (task_info->last_cpu >= 0) { 519 if (task_info->last_cpu >= 0) {
429 info->box = TRUE; 520 info->box = TRUE;
@@ -622,6 +713,7 @@ void task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot)
622 713
623 trace_graph_plot_remove_all_recs(ginfo, plot); 714 trace_graph_plot_remove_all_recs(ginfo, plot);
624 715
716 free(task_info->last_records);
625 free(task_info); 717 free(task_info);
626} 718}
627 719
@@ -740,6 +832,8 @@ void graph_plot_init_tasks(struct graph_info *ginfo)
740 } 832 }
741 833
742 task_info = malloc_or_die(sizeof(*task_info)); 834 task_info = malloc_or_die(sizeof(*task_info));
835 task_info->last_records =
836 malloc_or_die(sizeof(struct record *) * ginfo->cpus);
743 task_info->pid = pid; 837 task_info->pid = pid;
744 838
745 snprintf(label, 100, "TASK %d", pid); 839 snprintf(label, 100, "TASK %d", pid);
@@ -756,6 +850,8 @@ void graph_plot_task(struct graph_info *ginfo, int pid, int pos)
756 int len; 850 int len;
757 851
758 task_info = malloc_or_die(sizeof(*task_info)); 852 task_info = malloc_or_die(sizeof(*task_info));
853 task_info->last_records =
854 malloc_or_die(sizeof(struct record *) * ginfo->cpus);
759 task_info->pid = pid; 855 task_info->pid = pid;
760 comm = pevent_data_comm_from_pid(ginfo->pevent, pid); 856 comm = pevent_data_comm_from_pid(ginfo->pevent, pid);
761 857