aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-08-30 16:28:06 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-08-30 16:28:06 -0400
commit129f97bd91c3f971ee4c3d09264efca1384bd9b6 (patch)
tree6b060a9c33337f3013015b43db0333d75abb5eda
parent15bbd1e788af29d06b3fb64cefd0e2e3cdd64a8b (diff)
Fixed performance / memory leak of mouse hovering
-rw-r--r--kernel-shark.c6
-rw-r--r--rt-plot-container.c2
-rw-r--r--rt-plot-task.c17
-rw-r--r--rt-plot.c379
-rw-r--r--rt-plot.h23
-rw-r--r--trace-graph.c11
-rw-r--r--trace-input.c5
7 files changed, 325 insertions, 118 deletions
diff --git a/kernel-shark.c b/kernel-shark.c
index d921040..5961e30 100644
--- a/kernel-shark.c
+++ b/kernel-shark.c
@@ -303,7 +303,9 @@ int kernelshark_load_file(struct shark_info *info, const char *file)
303 display_warnings = 0; 303 display_warnings = 0;
304 pr_stat("\nLoading file %s", file); 304 pr_stat("\nLoading file %s", file);
305 trace_dialog_register_alt_warning(alt_warn); 305 trace_dialog_register_alt_warning(alt_warn);
306 printf("load\n");
306 handle = tracecmd_open(file); 307 handle = tracecmd_open(file);
308 printf("loaded %d\n", handle);
307 trace_dialog_register_alt_warning(NULL); 309 trace_dialog_register_alt_warning(NULL);
308 if (display_warnings) { 310 if (display_warnings) {
309 errno = 0; 311 errno = 0;
@@ -313,6 +315,7 @@ int kernelshark_load_file(struct shark_info *info, const char *file)
313 if (!handle) 315 if (!handle)
314 return -1; 316 return -1;
315 317
318 printf("loaded good\n");
316 tracecmd_close(info->handle); 319 tracecmd_close(info->handle);
317 info->handle = handle; 320 info->handle = handle;
318 trace_graph_load_handle(info->ginfo, handle); 321 trace_graph_load_handle(info->ginfo, handle);
@@ -1850,12 +1853,15 @@ void kernel_shark(int argc, char **argv)
1850 break; 1853 break;
1851 case 'c': 1854 case 'c':
1852 clean = 1; 1855 clean = 1;
1856 break;
1853 default: 1857 default:
1854 /* assume the other options are for gtk */ 1858 /* assume the other options are for gtk */
1855 break; 1859 break;
1856 } 1860 }
1857 } 1861 }
1858 1862
1863
1864
1859 if ((argc - optind) >= 1) { 1865 if ((argc - optind) >= 1) {
1860 if (input_file) 1866 if (input_file)
1861 usage(basename(argv[0])); 1867 usage(basename(argv[0]));
diff --git a/rt-plot-container.c b/rt-plot-container.c
index cb814fa..94f78ee 100644
--- a/rt-plot-container.c
+++ b/rt-plot-container.c
@@ -40,7 +40,7 @@ int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt,
40 *out_release = *out_deadline = *out_job = *out_tid = 0; 40 *out_release = *out_deadline = *out_job = *out_tid = 0;
41 41
42 /* Get current job info for server task */ 42 /* Get current job info for server task */
43 get_previous_release(ginfo, sid, time, 43 get_previous_release(ginfo, rt, sid, time,
44 out_job, out_release, out_deadline); 44 out_job, out_release, out_deadline);
45 45
46 /* Need to reset back to current location */ 46 /* Need to reset back to current location */
diff --git a/rt-plot-task.c b/rt-plot-task.c
index 77a517b..6e0013d 100644
--- a/rt-plot-task.c
+++ b/rt-plot-task.c
@@ -1,5 +1,6 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <string.h> 2#include <string.h>
3#include <stdlib.h>
3#include "trace-graph.h" 4#include "trace-graph.h"
4#include "trace-filter.h" 5#include "trace-filter.h"
5 6
@@ -133,7 +134,7 @@ static int get_time_info(struct graph_info *ginfo,
133 goto out; 134 goto out;
134 } 135 }
135 136
136 get_previous_release(ginfo, rtt_info->pid, time, 137 get_previous_release(ginfo, &rtt_info->common, rtt_info->pid, time,
137 out_job, out_release, out_deadline); 138 out_job, out_release, out_deadline);
138 out: 139 out:
139 return 1; 140 return 1;
@@ -492,7 +493,7 @@ rt_task_plot_write_header(struct rt_plot_common *rt,
492 const char *comm; 493 const char *comm;
493 int pid, job = -1, found; 494 int pid, job = -1, found;
494 struct record *record; 495 struct record *record;
495 unsigned long long release, deadline; 496 unsigned long long release = 0, deadline = 0;
496 struct rt_task_info *rtt_info = (struct rt_task_info*)rt; 497 struct rt_task_info *rtt_info = (struct rt_task_info*)rt;
497 498
498 found = get_time_info(ginfo, rtt_info, time, 499 found = get_time_info(ginfo, rtt_info, time,
@@ -502,7 +503,11 @@ rt_task_plot_write_header(struct rt_plot_common *rt,
502 503
503 pid = rtt_info->pid; 504 pid = rtt_info->pid;
504 comm = pevent_data_comm_from_pid(ginfo->pevent, pid); 505 comm = pevent_data_comm_from_pid(ginfo->pevent, pid);
505 trace_seq_printf(s, "%s-%d:%d\n", comm, pid, job); 506 trace_seq_printf(s, "%s-%d", comm, pid);
507 if (job != -1) {
508 trace_seq_printf(s, ":%d", job);
509 }
510 trace_seq_putc(s, '\n');
506 511
507 if (in_res(ginfo, deadline, time)) { 512 if (in_res(ginfo, deadline, time)) {
508 trace_seq_printf(s, "\nlitmus_deadline\n" 513 trace_seq_printf(s, "\nlitmus_deadline\n"
@@ -514,6 +519,11 @@ rt_task_plot_write_header(struct rt_plot_common *rt,
514 "release(job(%d,%d)): %llu\n", 519 "release(job(%d,%d)): %llu\n",
515 pid, job, release); 520 pid, job, release);
516 } 521 }
522
523 if (deadline != 0 && deadline < time) {
524 trace_seq_printf(s, "\nTARDY\n");
525 }
526
517 out: 527 out:
518 return record; 528 return record;
519} 529}
@@ -634,6 +644,7 @@ void rt_plot_task(struct graph_info *ginfo, int pid, int pos)
634 if (!params) 644 if (!params)
635 die ("RT task %d added without RT params!\n", pid); 645 die ("RT task %d added without RT params!\n", pid);
636 rtt_info = malloc_or_die(sizeof(*rtt_info)); 646 rtt_info = malloc_or_die(sizeof(*rtt_info));
647 memset(rtt_info, 0, sizeof(*rtt_info));
637 rtt_info->pid = pid; 648 rtt_info->pid = pid;
638 rtt_info->label = malloc_or_die(LLABEL); 649 rtt_info->label = malloc_or_die(LLABEL);
639 rtt_info->block_label = malloc_or_die(LLABEL); 650 rtt_info->block_label = malloc_or_die(LLABEL);
diff --git a/rt-plot.c b/rt-plot.c
index a2f5cfe..dd7535e 100644
--- a/rt-plot.c
+++ b/rt-plot.c
@@ -1,5 +1,170 @@
1#include <gtk/gtk.h> 1#include <gtk/gtk.h>
2#include <string.h>
2#include "trace-graph.h" 3#include "trace-graph.h"
4#include "list.h"
5
6
7struct record_list {
8 struct record_list *next;
9 struct record *record;
10};
11
12/*
13 * Insert @record into @list, storing the record in @node.
14 */
15void insert_record(struct graph_info *ginfo, struct record_list *list,
16 struct record *record, struct record_list *node,
17 int reverse)
18{
19 if (node->next)
20 die("Node is in use!");
21 if (!record) {
22 printf("No record\n");
23 return;
24 }
25
26 node->record = record;
27
28 struct record_list *pos = list;
29
30 while (pos->next) {
31 unsigned long long next_rts = get_rts(ginfo, pos->next->record);
32 if (( reverse && !next_rts > get_rts(ginfo, record)) ||
33 (!reverse && next_rts < get_rts(ginfo, record))){
34 break;
35 }
36 pos = pos->next;
37 }
38
39 node->next = pos->next;
40 pos->next = node;
41}
42
43
44/*
45 * Remove the first record in @list and put into @node.
46 */
47int pop_record(struct graph_info *ginfo, struct record_list *list,
48 struct record_list **node)
49{
50 if (!list->next)
51 return 0;
52
53 *node = list->next;
54 list->next = list->next->next;
55 (*node)->next = 0;
56
57 return 1;
58}
59
60
61/* For communication between get_previous_release and its iterator */
62struct prev_release_args {
63 unsigned long long min_ts;
64 struct rt_plot_common *common;
65 unsigned long long time;
66 int match_tid;
67 unsigned int *out_job;
68 unsigned long long *out_release;
69 unsigned long long *out_deadline;
70};
71
72
73static int
74prev_release_iterator(struct graph_info *ginfo, struct record *rec, void *data)
75{
76 int tid, is_release, job;
77 unsigned long long release, deadline;
78 struct prev_release_args *args = data;
79
80 if (get_rts(ginfo, rec) < args->min_ts) {
81 args->common->last_job.release = get_rts(ginfo, rec);
82 args->common->last_job.deadline = args->time;
83 return 0;
84 }
85
86#define ARG ginfo, rec, &tid, &job, &release, &deadline
87 is_release = rt_graph_check_task_release(ARG) ||
88 rt_graph_check_server_release(ARG);
89#undef ARG
90
91 if (is_release && args->match_tid == tid && release <= args->time) {
92 *(args->out_job) = job;
93 *(args->out_release) = release;
94 *(args->out_deadline) = deadline;
95
96 /* Cache to minimize work later */
97 args->common->last_job.no = job;
98 args->common->last_job.release = release;
99 args->common->last_job.deadline = deadline;
100 args->common->last_job.start = get_rts(ginfo, rec);
101 args->common->last_job.end = args->time;
102 return 0;
103 } else {
104 return 1;
105 }
106}
107
108
109/* For communication between find_prev_display_record and its iterator */
110struct prev_display_args {
111 struct rt_plot_common *common;
112 struct record *result;
113 unsigned long long min_ts;
114};
115
116
117static int
118prev_display_iterator(struct graph_info *ginfo, struct record *record, void *data)
119{
120 int eid, ignored;
121 struct prev_display_args *args = data;
122
123 if (get_rts(ginfo, record) < args->min_ts) {
124 return 0;
125 }
126
127 eid = pevent_data_type(ginfo->pevent, record);
128 ignored = (eid == ginfo->event_sched_switch_id);
129
130 if (!ignored) {
131 ignored = args->common->is_drawn(ginfo, eid);
132 }
133
134 if (!ignored && args->common->record_matches(args->common, ginfo, record)) {
135 args->result = record;
136 ++record->ref_count;
137 printf("success!\n");
138 return 0;
139 } else {
140 return 1;
141 }
142}
143
144
145/*
146 * Return first displayed record before @time, abandoning search after @range.
147 */
148static struct record*
149find_prev_display_record(struct graph_info *ginfo, struct rt_plot_common *rt_info,
150 unsigned long long time, unsigned long long range)
151{
152 int eid, ignored, match, cpu;
153 struct record *prev, *next, *res = NULL;
154 struct prev_display_args args = {rt_info, NULL, 0};
155
156 if (range) {
157 args.min_ts = time - range;
158 } else {
159 args.min_ts = time - max_rt_search(ginfo);
160 }
161
162 set_cpus_to_rts(ginfo, time);
163 iterate(ginfo, 1, prev_display_iterator, &args);
164
165 return args.result;
166}
167
3 168
4/** 169/**
5 * Return first relevant record after @time. 170 * Return first relevant record after @time.
@@ -10,7 +175,7 @@ __find_rt_record(struct graph_info *ginfo, struct rt_plot_common *rt_info,
10 guint64 time, int display, unsigned long long range) 175 guint64 time, int display, unsigned long long range)
11{ 176{
12 int next_cpu, match, eid, ignored; 177 int next_cpu, match, eid, ignored;
13 struct record *record; 178 struct record *record = NULL;
14 179
15 set_cpus_to_rts(ginfo, time); 180 set_cpus_to_rts(ginfo, time);
16 while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu))) { 181 while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu))) {
@@ -71,49 +236,6 @@ rt_plot_display_last_event(struct graph_info *ginfo, struct graph_plot *plot,
71 return 1; 236 return 1;
72} 237}
73 238
74/*
75 * Return first displayed record before @time, abandoning search after @range.
76 */
77static struct record*
78find_prev_display_record(struct graph_info *ginfo, struct rt_plot_common *rt_info,
79 unsigned long long time, unsigned long long range)
80{
81 int eid, ignored, match, cpu;
82 struct record *prev, *res = NULL;
83 unsigned long long min_ts;
84
85 if (range)
86 min_ts = time - range;
87 else
88 min_ts = time - max_rt_search(ginfo);
89
90 set_cpus_to_rts(ginfo, time);
91
92 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
93 prev = tracecmd_peek_data(ginfo->handle, cpu);
94 while ((prev = tracecmd_read_prev(ginfo->handle, prev)) &&
95 get_rts(ginfo, prev) > min_ts) {
96 eid = pevent_data_type(ginfo->pevent, prev);
97 ignored = (eid == ginfo->event_sched_switch_id);
98 if (!ignored) {
99 ignored = rt_info->is_drawn(ginfo, eid);
100 }
101 match = !ignored &&
102 rt_info->record_matches(rt_info, ginfo, prev);
103 if (match) {
104 if (!res ||
105 get_rts(ginfo, prev) > get_rts(ginfo, res)) {
106 free_record(res);
107 res = prev;
108 }
109 break;
110 }
111 free_record(prev);
112 }
113 }
114 return res;
115}
116
117/** 239/**
118 * rt_plot_display_info - write information about @time into @s 240 * rt_plot_display_info - write information about @time into @s
119 */ 241 */
@@ -128,14 +250,22 @@ rt_plot_display_info(struct graph_info *ginfo, struct graph_plot *plot,
128 long long pdiff, rdiff; 250 long long pdiff, rdiff;
129 int eid; 251 int eid;
130 252
253 /* printf("\nBegin display\n"); */
254
131 /* Write plot-specific data */ 255 /* Write plot-specific data */
132 data_record = rt_info->write_header(rt_info, ginfo, s, time); 256 data_record = rt_info->write_header(rt_info, ginfo, s, time);
257 /* printf("Data record: "); print_record(data_record); */
133 258
134 /* Select closest relevant record */ 259 /* Select closest relevant record */
135 range = 2 / ginfo->resolution; 260 range = 2 / ginfo->resolution;
136 261
262
137 record = __find_rt_record(ginfo, rt_info, time, 1, range); 263 record = __find_rt_record(ginfo, rt_info, time, 1, range);
138 prev_record = find_prev_display_record(ginfo, rt_info, time, range); 264 prev_record = find_prev_display_record(ginfo, rt_info, time, range);
265 //prev_record = NULL;
266
267 /* printf("Next: "); print_record(record); */
268 /* printf("Prev: "); print_record(prev_record); */
139 269
140 if (!record) { 270 if (!record) {
141 record = prev_record; 271 record = prev_record;
@@ -144,34 +274,42 @@ rt_plot_display_info(struct graph_info *ginfo, struct graph_plot *plot,
144 rtime = get_rts(ginfo, record); 274 rtime = get_rts(ginfo, record);
145 pdiff = (ptime < time) ? time - ptime : ptime - time; 275 pdiff = (ptime < time) ? time - ptime : ptime - time;
146 rdiff = (rtime < time) ? time - rtime : rtime - time; 276 rdiff = (rtime < time) ? time - rtime : rtime - time;
147 record = (pdiff < rdiff) ? prev_record : record; 277 if (pdiff < rdiff) {
278 free_record(record);
279 record = prev_record;
280 } else {
281 free_record(prev_record);
282 }
148 } 283 }
149 284
150 /* Write event info */ 285 /* Write event info */
151 if (record) { 286 if (record) {
152 rts = get_rts(ginfo, record); 287 /* rts = get_rts(ginfo, record); */
153 eid = pevent_data_type(ginfo->pevent, record); 288 /* eid = pevent_data_type(ginfo->pevent, record); */
154 289
155 if (in_res(ginfo, rts, time)) { 290 /* if (in_res(ginfo, rts, time)) { */
156 event = pevent_data_event_from_type(ginfo->pevent, eid); 291 /* event = pevent_data_event_from_type(ginfo->pevent, eid); */
157 if (event) { 292 /* if (event) { */
158 trace_seq_putc(s, '\n'); 293 /* trace_seq_putc(s, '\n'); */
159 trace_seq_puts(s, event->name); 294 /* trace_seq_puts(s, event->name); */
160 trace_seq_putc(s, '\n'); 295 /* trace_seq_putc(s, '\n'); */
161 pevent_event_info(s, event, record); 296 /* pevent_event_info(s, event, record); */
162 } else 297 /* } else */
163 trace_seq_printf(s, "\nUNKNOWN EVENT %d\n", eid); 298 /* trace_seq_printf(s, "\nUNKNOWN EVENT %d\n", eid); */
164 } 299 /* } */
165 free_record(record); 300 free_record(record);
301 /* printf("Freed record: "); print_record(record); */
166 } 302 }
167 303
168 /* Metadata */ 304 /* Metadata */
169 trace_seq_putc(s, '\n'); 305 trace_seq_putc(s, '\n');
170 nano_to_milli(time, &msec, &nsec); 306 nano_to_milli(time, &msec, &nsec);
171 trace_seq_printf(s, "%llu.%06llu ms", msec, nsec); 307 trace_seq_printf(s, "%llu.%06llu ms", msec, nsec);
308
172 if (data_record) { 309 if (data_record) {
173 trace_seq_printf(s, " CPU: %03d", data_record->cpu); 310 trace_seq_printf(s, " CPU: %03d", data_record->cpu);
174 free_record(data_record); 311 free_record(data_record);
312 /* printf("Freed data: "); print_record(data_record); */
175 } 313 }
176 314
177 return 1; 315 return 1;
@@ -360,6 +498,64 @@ int is_task_running(struct graph_info *ginfo,
360 return running; 498 return running;
361} 499}
362 500
501void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data)
502{
503 int proceed, cpu;
504 struct record *next, *prev;
505 struct record_list list;
506 struct record_list *nodes, *node;
507
508 nodes = malloc_or_die(sizeof(*nodes) * ginfo->cpus);
509 memset(nodes, 0, sizeof(*nodes) * ginfo->cpus);
510 memset(&list, 0, sizeof(list));
511
512 /* Maintains a list of the next record on each cpu, sorted by
513 * timestamp. Start with the first record on each cpu.
514 */
515 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
516 next = tracecmd_peek_data(ginfo->handle, cpu);
517 if (next) {
518 if (reverse) {
519 prev = next;
520 next = tracecmd_read_prev(ginfo->handle, prev);
521 if (prev != next && prev->data) {
522 free_record(prev);
523 }
524 }
525 insert_record(ginfo, &list, next, &nodes[cpu], reverse);
526 }
527 }
528
529 /* Read sequentially from all cpus */
530 while (pop_record(ginfo, &list, &node)) {
531 next = node->record;
532
533 proceed = cb(ginfo, next, data);
534
535 if (!proceed) {
536 free_record(next);
537 break;
538 }
539
540 prev = next;
541
542 if (!reverse) {
543 next = tracecmd_read_data(ginfo->handle, next->cpu);
544 } else {
545 next = tracecmd_read_prev(ginfo->handle, next);
546 }
547
548 free_record(prev);
549
550 insert_record(ginfo, &list, next, node, reverse);
551 }
552
553 while (pop_record(ginfo, &list, &node)) {
554 free_record(node->record);
555 }
556}
557
558
363/** 559/**
364 * Find the information for the last release of @match_tid on @cpu before @time. 560 * Find the information for the last release of @match_tid on @cpu before @time.
365 * 561 *
@@ -369,63 +565,26 @@ int is_task_running(struct graph_info *ginfo,
369 * Returns release record and @out_job, @out_release, and @out_deadline if a 565 * Returns release record and @out_job, @out_release, and @out_deadline if a
370 * release was found for @tid before @time. 566 * release was found for @tid before @time.
371 */ 567 */
372void get_previous_release(struct graph_info *ginfo, int match_tid, 568void get_previous_release(struct graph_info *ginfo, struct rt_plot_common *common,
569 int match_tid,
373 unsigned long long time, 570 unsigned long long time,
374 int *out_job, 571 int *out_job,
375 unsigned long long *out_release, 572 unsigned long long *out_release,
376 unsigned long long *out_deadline) 573 unsigned long long *out_deadline)
377{ 574{
378 int tid, cpu, match, job; 575 struct prev_release_args args = {
379 unsigned long long release, deadline, min_ts; 576 (time - max_rt_search(ginfo)), common, time, match_tid,
380 struct record *last_rec = NULL, *rec, *ret = NULL; 577 out_job, out_release, out_deadline};
381 578
382 *out_job = -2; 579 /* Use cached job info, if possible */
383 580 if (time >= common->last_job.start &&
384 min_ts = time - max_rt_search(ginfo); 581 time <= common->last_job.end) {
385 582 *out_job = common->last_job.no;
386 /* The release record could have occurred on any CPU. Search all */ 583 *out_release = common->last_job.release;
387 for (cpu = 0; cpu < ginfo->cpus; cpu++) { 584 *out_deadline = common->last_job.deadline;
388 set_cpu_to_rts(ginfo, time, cpu); 585 return;
389 last_rec = tracecmd_peek_data(ginfo->handle, cpu);
390
391 /* Require a record to start with */
392 if (!last_rec) {
393 goto loop_end;
394 }
395 last_rec->ref_count++;
396
397 while ((rec = tracecmd_read_prev(ginfo->handle, last_rec))) {
398 if (get_rts(ginfo, rec) < min_ts) {
399 free_record(rec);
400
401 goto loop_end;
402 }
403
404#define ARG ginfo, rec, &tid, &job, &release, &deadline
405 match = rt_graph_check_task_release(ARG) ||
406 rt_graph_check_server_release(ARG);
407#undef ARG
408
409 free_record(last_rec);
410 last_rec = rec;
411
412 /* Only consider releases before the current time */
413 if (match && tid == match_tid && release <= time) {
414 /* Return the lastest release */
415 if (!ret || *out_job < job) {
416 free_record(ret);
417 ret = rec;
418 *out_job = job;
419 *out_release = release;
420 *out_deadline = deadline;
421 }
422 last_rec = NULL;
423 goto loop_end;
424 }
425 }
426 loop_end:
427 free_record(last_rec);
428 } 586 }
429 587
430 free_record(ret); 588 set_cpus_to_rts(ginfo, time);
589 iterate(ginfo, 1, prev_release_iterator, &args);
431} 590}
diff --git a/rt-plot.h b/rt-plot.h
index e84bbf9..ef609bb 100644
--- a/rt-plot.h
+++ b/rt-plot.h
@@ -16,12 +16,29 @@ typedef struct record* (*write_header_cb)(struct rt_plot_common *rt,
16 struct graph_info *ginfo, 16 struct graph_info *ginfo,
17 struct trace_seq *s, 17 struct trace_seq *s,
18 unsigned long long time); 18 unsigned long long time);
19typedef int (*iterate_cb)(struct graph_info *ginfo, struct record *record, void *data);
20
21struct job_info {
22 unsigned long long release;
23 unsigned long long deadline;
24 unsigned long long start;
25 unsigned long long end;
26 unsigned long long no;
27};
28
29
19struct rt_plot_common { 30struct rt_plot_common {
20 record_matches_cb record_matches; 31 record_matches_cb record_matches;
21 is_drawn_cb is_drawn; 32 is_drawn_cb is_drawn;
22 write_header_cb write_header; 33 write_header_cb write_header;
34
35 /* Cache the current job info. Used in mouseovers to avoid recalulating
36 * job information when the mouse does not cross job boundaries.
37 */
38 struct job_info last_job;
23}; 39};
24 40
41
25int 42int
26rt_plot_display_last_event(struct graph_info *ginfo, struct graph_plot *plot, 43rt_plot_display_last_event(struct graph_info *ginfo, struct graph_plot *plot,
27 struct trace_seq *s, unsigned long long time); 44 struct trace_seq *s, unsigned long long time);
@@ -60,9 +77,13 @@ void set_cpus_to_rts(struct graph_info *ginfo,
60int is_task_running(struct graph_info *ginfo, 77int is_task_running(struct graph_info *ginfo,
61 unsigned long long time, 78 unsigned long long time,
62 int pid); 79 int pid);
63void get_previous_release(struct graph_info *ginfo, int tid, 80void get_previous_release(struct graph_info *ginfo, struct rt_plot_common *common,
81 int tid,
64 unsigned long long time, int *job, 82 unsigned long long time, int *job,
65 unsigned long long *release, 83 unsigned long long *release,
66 unsigned long long *deadline); 84 unsigned long long *deadline);
67 85
86void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data);
87
88
68#endif 89#endif
diff --git a/trace-graph.c b/trace-graph.c
index f9bd4af..f843e26 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -1863,7 +1863,6 @@ static void draw_plot(struct graph_info *ginfo, struct graph_plot *plot,
1863static void draw_hashed_plots(struct graph_info *ginfo) 1863static void draw_hashed_plots(struct graph_info *ginfo)
1864{ 1864{
1865 gint cpu, pid; 1865 gint cpu, pid;
1866 gboolean started;
1867 struct record *record; 1866 struct record *record;
1868 struct plot_hash *hash; 1867 struct plot_hash *hash;
1869 struct plot_list *list; 1868 struct plot_list *list;
@@ -1882,7 +1881,7 @@ static void draw_hashed_plots(struct graph_info *ginfo)
1882 1881
1883 // TODO: hack to clean up until first release, make unhacky 1882 // TODO: hack to clean up until first release, make unhacky
1884 if (ginfo->rtg_info.clean_records && 1883 if (ginfo->rtg_info.clean_records &&
1885 ginfo->rtg_info.start_time == 0) { 1884 (ginfo->rtg_info.start_time == 0 || ginfo->view_start_time < ginfo->rtg_info.start_time)) {
1886 unsigned long long dull, rel = 0; 1885 unsigned long long dull, rel = 0;
1887 char *dchar; 1886 char *dchar;
1888 int dint; 1887 int dint;
@@ -1964,6 +1963,8 @@ static void draw_plots(struct graph_info *ginfo, gint new_width)
1964 set_color(ginfo->draw, plot->gc, plot->last_color); 1963 set_color(ginfo->draw, plot->gc, plot->last_color);
1965 } 1964 }
1966 1965
1966 printf("we here1\n");
1967
1967 trace_set_cursor(GDK_WATCH); 1968 trace_set_cursor(GDK_WATCH);
1968 /* Shortcut if we don't have any task plots */ 1969 /* Shortcut if we don't have any task plots */
1969 if (!ginfo->nr_task_hash && !ginfo->all_recs) { 1970 if (!ginfo->nr_task_hash && !ginfo->all_recs) {
@@ -1991,6 +1992,8 @@ static void draw_plots(struct graph_info *ginfo, gint new_width)
1991 goto out; 1992 goto out;
1992 } 1993 }
1993 1994
1995 printf("we here\n");
1996
1994 draw_hashed_plots(ginfo); 1997 draw_hashed_plots(ginfo);
1995 1998
1996out: 1999out:
@@ -2097,8 +2100,10 @@ static void draw_timeline(struct graph_info *ginfo, gint width)
2097static void draw_info(struct graph_info *ginfo, 2100static void draw_info(struct graph_info *ginfo,
2098 gint new_width) 2101 gint new_width)
2099{ 2102{
2103 printf("we going?\n");
2100 if (!ginfo->handle) 2104 if (!ginfo->handle)
2101 return; 2105 return;
2106 printf("we gone\n");
2102 2107
2103 ginfo->resolution = (gdouble)new_width / (gdouble)(ginfo->view_end_time - 2108 ginfo->resolution = (gdouble)new_width / (gdouble)(ginfo->view_end_time -
2104 ginfo->view_start_time); 2109 ginfo->view_start_time);
@@ -2107,6 +2112,7 @@ static void draw_info(struct graph_info *ginfo,
2107 2112
2108 draw_timeline(ginfo, new_width); 2113 draw_timeline(ginfo, new_width);
2109 2114
2115 printf("drawing plots\n");
2110 draw_plots(ginfo, new_width); 2116 draw_plots(ginfo, new_width);
2111 2117
2112 ginfo->read_comms = FALSE; 2118 ginfo->read_comms = FALSE;
@@ -2324,6 +2330,7 @@ static void redraw_pixmap_backend(struct graph_info *ginfo)
2324 if (old_pix) 2330 if (old_pix)
2325 g_object_unref(old_pix); 2331 g_object_unref(old_pix);
2326 2332
2333
2327 if (ginfo->hadj_value) { 2334 if (ginfo->hadj_value) {
2328// gtk_adjustment_set_lower(ginfo->hadj, -100.0); 2335// gtk_adjustment_set_lower(ginfo->hadj, -100.0);
2329 gtk_adjustment_set_value(ginfo->hadj, ginfo->hadj_value); 2336 gtk_adjustment_set_value(ginfo->hadj, ginfo->hadj_value);
diff --git a/trace-input.c b/trace-input.c
index 5b01386..48dafe9 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -719,8 +719,11 @@ void free_record(struct record *record)
719 if (!record) 719 if (!record)
720 return; 720 return;
721 721
722 if (!record->ref_count) 722 if (!record->ref_count) {
723 struct record *rec = NULL;
724 rec->ref_count = 2;
723 die("record ref count is zero!"); 725 die("record ref count is zero!");
726 }
724 727
725 record->ref_count--; 728 record->ref_count--;
726 729