aboutsummaryrefslogtreecommitdiffstats
path: root/trace-plot-task.c
diff options
context:
space:
mode:
Diffstat (limited to 'trace-plot-task.c')
-rw-r--r--trace-plot-task.c166
1 files changed, 142 insertions, 24 deletions
diff --git a/trace-plot-task.c b/trace-plot-task.c
index c8d0905..794b889 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;
@@ -54,7 +55,9 @@ static gint hash_pid(gint val)
54 55
55static int hash_cpu(int cpu) 56static int hash_cpu(int cpu)
56{ 57{
57 return trace_hash(cpu + 124); 58 cpu = (cpu << 3) + cpu * 21;
59
60 return trace_hash(cpu);
58} 61}
59 62
60static gboolean is_running(struct graph_info *ginfo, struct record *record) 63static gboolean is_running(struct graph_info *ginfo, struct record *record)
@@ -104,26 +107,31 @@ static gboolean record_matches_pid(struct graph_info *ginfo,
104 return FALSE; 107 return FALSE;
105} 108}
106 109
107static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) 110static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time)
108{ 111{
109 struct record *record; 112 struct record *record;
110 int cpu;
111 113
112 for (cpu = 0; cpu < ginfo->cpus; cpu++) { 114 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
113 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
114 115
115 while ((record = tracecmd_read_data(ginfo->handle, cpu))) { 116 while ((record = tracecmd_read_data(ginfo->handle, cpu))) {
116 if (record->ts >= time) 117 if (record->ts >= time)
117 break; 118 break;
118 119
119 free_record(record); 120 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 } 121 }
122 if (record) {
123 tracecmd_set_cursor(ginfo->handle, cpu, record->offset);
124 free_record(record);
125 } else
126 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
127}
128
129static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time)
130{
131 int cpu;
132
133 for (cpu = 0; cpu < ginfo->cpus; cpu++)
134 set_cpu_to_time(cpu, ginfo, time);
127} 135}
128 136
129static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, 137static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot,
@@ -315,12 +323,92 @@ static void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
315{ 323{
316 struct task_plot_info *task_info = plot->private; 324 struct task_plot_info *task_info = plot->private;
317 325
326 memset(task_info->last_records, 0, sizeof(struct record *) * ginfo->cpus);
327
318 task_info->last_time = 0ULL; 328 task_info->last_time = 0ULL;
319 task_info->last_cpu = -1; 329 task_info->last_cpu = -1;
320 task_info->wake_time = 0ULL; 330 task_info->wake_time = 0ULL;
321 task_info->display_wake_time = 0ULL; 331 task_info->display_wake_time = 0ULL;
322} 332}
323 333
334static void update_last_record(struct graph_info *ginfo,
335 struct task_plot_info *task_info,
336 struct record *record)
337{
338 struct tracecmd_input *handle = ginfo->handle;
339 struct record *trecord, *t2record;
340 struct record *saved;
341 unsigned long long ts;
342 int sched_pid;
343 int pid;
344 int rec_pid;
345 int is_wakeup;
346 int is_sched;
347 int this_cpu;
348 int cpu;
349
350 pid = task_info->pid;
351
352 if (record) {
353 ts = record->ts;
354 this_cpu = record->cpu;
355 } else {
356 ts = ginfo->view_end_time;
357 this_cpu = -1;
358 }
359
360 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
361
362 if (task_info->last_records[cpu])
363 continue;
364
365 if (cpu == this_cpu) {
366 static int once;
367
368 trecord = tracecmd_read_prev(handle, record);
369 /* Set cpu cursor back to what it was */
370 saved = tracecmd_read_data(handle, cpu);
371 if (!once && saved->offset != record->offset) {
372 once++;
373 warning("failed to reset cursor!");
374 }
375 free_record(saved);
376 } else {
377 static int once;
378
379 saved = tracecmd_peek_data(handle, cpu);
380 set_cpu_to_time(cpu, ginfo, ts);
381 t2record = tracecmd_read_data(handle, cpu);
382 trecord = tracecmd_read_prev(handle, t2record);
383 free_record(t2record);
384 /* reset cursor back to what it was */
385 if (saved)
386 tracecmd_set_cursor(handle, cpu, saved->offset);
387 else {
388 saved = tracecmd_read_data(handle, cpu);
389 if (!once && saved) {
390 once++;
391 warning("failed to reset cursor to end!");
392 }
393 }
394 }
395 if (!trecord)
396 continue;
397
398 if (record_matches_pid(ginfo, trecord, pid, &rec_pid,
399 &sched_pid, &is_sched, &is_wakeup) &&
400 !is_wakeup &&
401 (!is_sched || (is_sched && sched_pid == pid))) {
402 task_info->last_records[cpu] = trecord;
403 task_info->last_cpu = trecord->cpu;
404 task_info->last_time = trecord->ts;
405 break;
406 }
407
408 free_record(trecord);
409 }
410}
411
324static int task_plot_event(struct graph_info *ginfo, 412static int task_plot_event(struct graph_info *ginfo,
325 struct graph_plot *plot, 413 struct graph_plot *plot,
326 struct record *record, 414 struct record *record,
@@ -333,10 +421,12 @@ static int task_plot_event(struct graph_info *ginfo,
333 int is_wakeup; 421 int is_wakeup;
334 int is_sched; 422 int is_sched;
335 int pid; 423 int pid;
424 int cpu;
336 425
337 pid = task_info->pid; 426 pid = task_info->pid;
338 427
339 if (!record) { 428 if (!record) {
429 update_last_record(ginfo, task_info, record);
340 /* no more records, finish a box if one was started */ 430 /* no more records, finish a box if one was started */
341 if (task_info->last_cpu >= 0) { 431 if (task_info->last_cpu >= 0) {
342 info->box = TRUE; 432 info->box = TRUE;
@@ -344,20 +434,39 @@ static int task_plot_event(struct graph_info *ginfo,
344 info->bend = ginfo->view_end_time; 434 info->bend = ginfo->view_end_time;
345 info->bcolor = hash_cpu(task_info->last_cpu); 435 info->bcolor = hash_cpu(task_info->last_cpu);
346 } 436 }
437 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
438 free_record(task_info->last_records[cpu]);
439 task_info->last_records[cpu] = NULL;
440 }
347 return 0; 441 return 0;
348 } 442 }
349 443
350 match = record_matches_pid(ginfo, record, pid, &rec_pid, 444 match = record_matches_pid(ginfo, record, pid, &rec_pid,
351 &sched_pid, &is_sched, &is_wakeup); 445 &sched_pid, &is_sched, &is_wakeup);
352 446
353 if (!match && record->cpu != task_info->last_cpu) 447
448 if (!match && record->cpu != task_info->last_cpu) {
449 if (!task_info->last_records[record->cpu]) {
450 task_info->last_records[record->cpu] = record;
451 tracecmd_record_ref(record);
452 }
354 return 0; 453 return 0;
454 }
355 455
356 if (match) { 456 if (match) {
357 info->line = TRUE; 457 info->line = TRUE;
358 info->lcolor = hash_pid(rec_pid); 458 info->lcolor = hash_pid(rec_pid);
359 info->ltime = record->ts; 459 info->ltime = record->ts;
360 460
461 /*
462 * Is this our first match?
463 *
464 * If last record is NULL, then it may exist off the
465 * viewable range. Search to see if one exists, and if
466 * it is the record we want to match.
467 */
468 update_last_record(ginfo, task_info, record);
469
361 if (is_wakeup) { 470 if (is_wakeup) {
362 /* Wake up but not task */ 471 /* Wake up but not task */
363 info->ltime = hash_pid(rec_pid); 472 info->ltime = hash_pid(rec_pid);
@@ -424,6 +533,12 @@ static int task_plot_event(struct graph_info *ginfo,
424 return 1; 533 return 1;
425 } 534 }
426 535
536 cpu = record->cpu;
537
538 if (!task_info->last_records[cpu]) {
539 free_record(task_info->last_records[cpu]);
540 task_info->last_records[cpu] = record;
541 }
427 /* not a match, and on the last CPU, scheduled out? */ 542 /* not a match, and on the last CPU, scheduled out? */
428 if (task_info->last_cpu >= 0) { 543 if (task_info->last_cpu >= 0) {
429 info->box = TRUE; 544 info->box = TRUE;
@@ -571,7 +686,9 @@ int task_plot_display_info(struct graph_info *ginfo,
571 struct pevent *pevent; 686 struct pevent *pevent;
572 unsigned long sec, usec; 687 unsigned long sec, usec;
573 const char *comm; 688 const char *comm;
689 int cpu;
574 int type; 690 int type;
691 int sched_pid = -1;
575 int pid; 692 int pid;
576 693
577 pid = task_info->pid; 694 pid = task_info->pid;
@@ -582,7 +699,7 @@ int task_plot_display_info(struct graph_info *ginfo,
582 pevent = ginfo->pevent; 699 pevent = ginfo->pevent;
583 700
584 pid = pevent_data_pid(ginfo->pevent, record); 701 pid = pevent_data_pid(ginfo->pevent, record);
585 comm = pevent_data_comm_from_pid(ginfo->pevent, pid); 702 cpu = record->cpu;
586 703
587 convert_nano(record->ts, &sec, &usec); 704 convert_nano(record->ts, &sec, &usec);
588 705
@@ -600,16 +717,12 @@ int task_plot_display_info(struct graph_info *ginfo,
600 trace_seq_putc(s, '\n'); 717 trace_seq_putc(s, '\n');
601 } else 718 } else
602 trace_seq_printf(s, "UNKNOW EVENT %d\n", type); 719 trace_seq_printf(s, "UNKNOW EVENT %d\n", type);
603 } else {
604 if (record->ts < time)
605 trace_graph_check_sched_switch(ginfo, record, &pid, &comm);
606 } 720 }
721 trace_graph_check_sched_switch(ginfo, record, &sched_pid, &comm);
607 722
608 trace_seq_printf(s, "%lu.%06lu", sec, usec); 723 trace_seq_printf(s, "%lu.%06lu", sec, usec);
609 if (pid) 724 if (pid == task_info->pid || sched_pid == task_info->pid)
610 trace_seq_printf(s, " %s-%d", comm, pid); 725 trace_seq_printf(s, " CPU: %03d", cpu);
611 else
612 trace_seq_puts(s, " <idle>");
613 726
614 free_record(record); 727 free_record(record);
615 728
@@ -622,6 +735,7 @@ void task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot)
622 735
623 trace_graph_plot_remove_all_recs(ginfo, plot); 736 trace_graph_plot_remove_all_recs(ginfo, plot);
624 737
738 free(task_info->last_records);
625 free(task_info); 739 free(task_info);
626} 740}
627 741
@@ -740,6 +854,8 @@ void graph_plot_init_tasks(struct graph_info *ginfo)
740 } 854 }
741 855
742 task_info = malloc_or_die(sizeof(*task_info)); 856 task_info = malloc_or_die(sizeof(*task_info));
857 task_info->last_records =
858 malloc_or_die(sizeof(struct record *) * ginfo->cpus);
743 task_info->pid = pid; 859 task_info->pid = pid;
744 860
745 snprintf(label, 100, "TASK %d", pid); 861 snprintf(label, 100, "TASK %d", pid);
@@ -756,6 +872,8 @@ void graph_plot_task(struct graph_info *ginfo, int pid, int pos)
756 int len; 872 int len;
757 873
758 task_info = malloc_or_die(sizeof(*task_info)); 874 task_info = malloc_or_die(sizeof(*task_info));
875 task_info->last_records =
876 malloc_or_die(sizeof(struct record *) * ginfo->cpus);
759 task_info->pid = pid; 877 task_info->pid = pid;
760 comm = pevent_data_comm_from_pid(ginfo->pevent, pid); 878 comm = pevent_data_comm_from_pid(ginfo->pevent, pid);
761 879