aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-06 23:18:16 -0500
committerJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-06 23:18:16 -0500
commitb305fe1222b244f020e22c31b204375cf02b823e (patch)
tree17056362e995bbc732c9e2d00fa77d4f11ed0bfa
parent471b1045226249deacf12ad419b24d962bded880 (diff)
rt-graph: real-time plots display info popup
When you hover close enough to an events time, the event name will display. This time is based on _litmus_ time, not record time.
-rw-r--r--Documentation/structure.txt26
-rw-r--r--parse-events.h1
-rw-r--r--rt-graph.c1
-rw-r--r--rt-graph.h4
-rw-r--r--rt-plot-task.c215
-rw-r--r--trace-input.c2
-rw-r--r--trace-plot-task.c18
-rw-r--r--trace-plot-task.h12
8 files changed, 239 insertions, 40 deletions
diff --git a/Documentation/structure.txt b/Documentation/structure.txt
index adee54d..4060c51 100644
--- a/Documentation/structure.txt
+++ b/Documentation/structure.txt
@@ -99,6 +99,7 @@ struct trace-plot-task.c {
99 99
100 /* Return first record after time which is from our pid */ 100 /* Return first record after time which is from our pid */
101 find_record(ginfo, pid, time); 101 find_record(ginfo, pid, time);
102 - set_cpus_to_time
102 103
103 /* Updates last_whatevers in task info */ 104 /* Updates last_whatevers in task info */
104 update_last_record(ginfo, task_plot_info, record); 105 update_last_record(ginfo, task_plot_info, record);
@@ -107,6 +108,9 @@ struct trace-plot-task.c {
107 find_previous_record(ginfo, start_record, pid, cpu); 108 find_previous_record(ginfo, start_record, pid, cpu);
108 109
109 get_display_record(ginfo, pid, time); 110 get_display_record(ginfo, pid, time);
111 - find_record
112 - find_previous_record
113
110 114
111 /**** PUBLIC METHODS *****/ 115 /**** PUBLIC METHODS *****/
112 116
@@ -119,6 +123,19 @@ struct trace-plot-task.c {
119 /* Get record at time, print info */ 123 /* Get record at time, print info */
120 task_plot_display_last_event(info, plot, trace_seq s, time); 124 task_plot_display_last_event(info, plot, trace_seq s, time);
121 125
126 /* Just frontend for find_record */
127 task_plot_find_record(ginfo, plot, time);
128
129 /* Print out event info if in current resolution */
130 task_plot_display_info(ginfo, plot, sequence s, time);
131 - get_display_record
132 - find_record
133 - set_cpus_to_time
134 - find_previous_record
135
136 /* Free private info */
137 task_plot_destroy(info, plot);
138
122 /* Always draws a line of the color of the pid. Always. 139 /* Always draws a line of the color of the pid. Always.
123 * Then update_last_record. 140 * Then update_last_record.
124 * If record is null, times up, just finish our shit and return. 141 * If record is null, times up, just finish our shit and return.
@@ -141,15 +158,6 @@ struct trace-plot-task.c {
141 */ 158 */
142 task_plot_event(ginfo, plot,r ecord, info); 159 task_plot_event(ginfo, plot,r ecord, info);
143 160
144 /* Just frontend for find_record */
145 task_plot_find_record(ginfo, plot, time);
146
147 /* Print out event info if in current resolution */
148 task_plot_display_info(ginfo, plot, sequence s, time);
149
150 /* Free private info */
151 task_plot_destroy(info, plot);
152
153 161
154 /*** STATIC METHODS ***/ 162 /*** STATIC METHODS ***/
155 163
diff --git a/parse-events.h b/parse-events.h
index 56cef4a..83c7d79 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -42,6 +42,7 @@
42struct record { 42struct record {
43 unsigned long long ts; 43 unsigned long long ts;
44 unsigned long long offset; 44 unsigned long long offset;
45 unsigned long long cached_rts;
45 long long missed_events; /* buffer dropped events before */ 46 long long missed_events; /* buffer dropped events before */
46 int record_size; /* size of binary record */ 47 int record_size; /* size of binary record */
47 int size; /* size of data */ 48 int size; /* size of data */
diff --git a/rt-graph.c b/rt-graph.c
index 5b8c759..5f4d0b0 100644
--- a/rt-graph.c
+++ b/rt-graph.c
@@ -121,7 +121,6 @@ int rt_graph_check_task_param(struct rt_graph_info *rtinfo,
121 dprintf(3, "Read task_param (%d) record for task %d " 121 dprintf(3, "Read task_param (%d) record for task %d "
122 "(%llu, %llu)\n", id, *pid, *wcet, *period); 122 "(%llu, %llu)\n", id, *pid, *wcet, *period);
123 123
124 /* Only of these per task, so we can safely add new tasks now */
125 add_task_hash(rtinfo->tasks, *pid); 124 add_task_hash(rtinfo->tasks, *pid);
126 } 125 }
127 out: 126 out:
diff --git a/rt-graph.h b/rt-graph.h
index be9aa44..17247f6 100644
--- a/rt-graph.h
+++ b/rt-graph.h
@@ -7,7 +7,7 @@
7#include "rt-plot-task.h" 7#include "rt-plot-task.h"
8 8
9#define RT_TS_FIELD "__rt_ts" 9#define RT_TS_FIELD "__rt_ts"
10#define TS_HASH_SIZE 6 10#define TS_HASH_SIZE 12
11struct ts_list; 11struct ts_list;
12 12
13struct rt_graph_info { 13struct rt_graph_info {
@@ -52,7 +52,7 @@ struct rt_graph_info {
52 struct format_field *resume_pid_field; 52 struct format_field *resume_pid_field;
53 struct format_field *resume_ts_field; 53 struct format_field *resume_ts_field;
54 54
55 /* Cache of ts fields for new events */ 55 /* Cache of ts fields for non-litmus events */
56 struct ts_list *events[TS_HASH_SIZE]; 56 struct ts_list *events[TS_HASH_SIZE];
57}; 57};
58 58
diff --git a/rt-plot-task.c b/rt-plot-task.c
index 8be1888..8ecbdbb 100644
--- a/rt-plot-task.c
+++ b/rt-plot-task.c
@@ -13,7 +13,159 @@
13#define dprintf(l, x...) do { if (0) printf(x); } while (0) 13#define dprintf(l, x...) do { if (0) printf(x); } while (0)
14#endif 14#endif
15 15
16/* Ok to do it this way as long as it remains single threaded */ 16/*
17 * Extract timestamp from a record, attempting to use cache if possible
18 */
19static unsigned long long
20get_rts(struct graph_info *ginfo, struct record *record)
21{
22 gint epid;
23 unsigned long long ts;
24 if (!record->cached_rts) {
25 rt_graph_check_any(&ginfo->rtinfo, ginfo->pevent, record,
26 &epid, &ts);
27 record->cached_rts = ts;
28 } else
29 ts = record->cached_rts;
30 return ts;
31}
32
33/*
34 * Get the real-time timestamp of the next record at time
35 */
36static unsigned long long
37next_rts(struct graph_info *ginfo, int cpu, unsigned long long time)
38{
39 struct record *record;
40 unsigned long long ts;
41 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
42 record = tracecmd_read_data(ginfo->handle, cpu);
43 if (record) {
44 ts = get_rts(ginfo, record);
45 free_record(record);
46 return ts;
47 } else
48 return 0;
49}
50
51static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time)
52{
53 struct record *record;
54 unsigned long long rts, seek_time, last_seek;
55 long long diff;
56
57 rts = next_rts(ginfo, cpu, time);
58 diff = time - rts;
59
60 /* "Guess" a new target based on difference */
61 seek_time = time + diff;
62 rts = next_rts(ginfo, cpu, seek_time);
63 diff = time - rts;
64
65 /* Zero in in 1.5x the difference increments */
66 if (rts && diff > 0) {
67 /* rts time
68 * seek ?
69 * ---|---->>----|---
70 */
71 do {
72 last_seek = seek_time;
73 seek_time = seek_time + 1.5 * (time - rts);
74 rts = next_rts(ginfo, cpu, seek_time);
75 } while (rts < time);
76 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek);
77 seek_time = last_seek;
78 } else if (rts && diff < 0) {
79 /* time rts
80 * ? seek
81 * ---|----<<----|---
82 */
83 do {
84 seek_time = seek_time - 1.5 * (rts - time);
85 rts = next_rts(ginfo, cpu, seek_time);
86 } while (rts > time);
87 }
88
89 /* Get to first record at or after time */
90 while ((record = tracecmd_read_data(ginfo->handle, cpu))) {
91 if (get_rts(ginfo, record) >= time)
92 break;
93 free_record(record);
94 }
95 if (record) {
96 tracecmd_set_cursor(ginfo->handle, cpu, record->offset);
97 free_record(record);
98 } else
99 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time);
100}
101
102void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time)
103{
104 int cpu;
105 for (cpu = 0; cpu < ginfo->cpus; cpu++)
106 set_cpu_to_time(cpu, ginfo, time);
107}
108
109static gboolean record_matches_pid(struct graph_info *ginfo,
110 struct record *record,
111 int match_pid)
112{
113 guint eid, pid;
114 unsigned long long val;
115 struct format_field *pid_field = NULL;
116 struct rt_graph_info *rtinfo = &ginfo->rtinfo;
117
118 eid = pevent_data_type(ginfo->pevent, record);
119 if (eid == rtinfo->task_param_id)
120 pid_field = rtinfo->param_pid_field;
121 else if (eid == rtinfo->switch_to_id)
122 pid_field = rtinfo->switch_to_pid_field;
123 else if (eid == rtinfo->switch_away_id)
124 pid_field = rtinfo->switch_away_pid_field;
125 else if (eid == rtinfo->task_release_id)
126 pid_field = rtinfo->release_pid_field;
127 else if (eid == rtinfo->task_completion_id)
128 pid_field = rtinfo->completion_pid_field;
129 else if (eid == rtinfo->task_block_id)
130 pid_field = rtinfo->block_pid_field;
131 else if (eid == rtinfo->task_resume_id)
132 pid_field = rtinfo->resume_pid_field;
133
134 if (pid_field) {
135 pevent_read_number_field(rtinfo->param_pid_field,
136 record->data, &val);
137 pid = val;
138 } else {
139 pid = pevent_data_pid(ginfo->pevent, record);
140 }
141
142 if (pid == match_pid)
143 return TRUE;
144 else
145 return FALSE;
146}
147
148struct record*
149find_record(struct graph_info *ginfo, gint pid, guint64 time)
150{
151 int next_cpu, match;
152 struct record *record = NULL;
153
154 set_cpus_to_time(ginfo, time);
155 do {
156 free_record(record);
157 record = tracecmd_read_next_data(ginfo->handle, &next_cpu);
158 if (!record)
159 return NULL;
160 match = record_matches_pid(ginfo, record, pid);
161 } while (!(get_rts(ginfo, record) > time && match));
162
163 return record;
164}
165
166/*
167 * Update current job in @rtt_info, ensuring monotonic increase
168 */
17static void update_job(struct rt_task_info *rtt_info, int job) 169static void update_job(struct rt_task_info *rtt_info, int job)
18{ 170{
19 if (job < rtt_info->last_job) { 171 if (job < rtt_info->last_job) {
@@ -88,6 +240,9 @@ static int try_completion(struct graph_info *ginfo,
88 info->completion = TRUE; 240 info->completion = TRUE;
89 info->ctime = ts; 241 info->ctime = ts;
90 info->clabel = rtt_info->label; 242 info->clabel = rtt_info->label;
243 info->line = TRUE;
244 info->lcolor = hash_pid(record->cpu);
245 info->ltime = ts;
91 ret = 1; 246 ret = 1;
92 } 247 }
93 return ret; 248 return ret;
@@ -177,10 +332,6 @@ static int try_switch_to(struct graph_info *ginfo, struct rt_task_info *rtt_info
177 rtt_info->run_time = ts; 332 rtt_info->run_time = ts;
178 rtt_info->last_cpu = record->cpu; 333 rtt_info->last_cpu = record->cpu;
179 334
180 info->line = TRUE;
181 info->lcolor = hash_pid(record->cpu);
182 info->ltime = ts;
183
184 dprintf(3, "Switching to %d:%d at %llu on CPU %d\n", 335 dprintf(3, "Switching to %d:%d at %llu on CPU %d\n",
185 rtt_info->base.pid, rtt_info->last_job, 336 rtt_info->base.pid, rtt_info->last_job,
186 ts, rtt_info->last_cpu); 337 ts, rtt_info->last_cpu);
@@ -289,15 +440,65 @@ static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *pl
289 task_plot_destroy(ginfo, plot); 440 task_plot_destroy(ginfo, plot);
290} 441}
291 442
443static int rt_task_plot_display_last_event(struct graph_info *ginfo,
444 struct graph_plot *plot,
445 struct trace_seq *s,
446 unsigned long long time)
447{
448 trace_seq_printf(s, "Displaying last event at %llu\n",
449 time);
450 return 1;
451}
452
453static int rt_task_plot_display_info(struct graph_info *ginfo,
454 struct graph_plot *plot,
455 struct trace_seq *s,
456 unsigned long long time)
457{
458 int type;
459 struct record *record;
460 struct event_format *event;
461 unsigned long sec, usec;
462 struct rt_task_info *rtt_info = plot->private;
463
464 record = find_record(ginfo, rtt_info->base.pid, time);
465 if (!record)
466 return 0;
467
468 /* Display only if the record's time is close enough */
469 if (get_rts(ginfo, record) > time - 2/ginfo->resolution &&
470 get_rts(ginfo, record) < time + 2/ginfo->resolution) {
471
472 type = pevent_data_type(ginfo->pevent, record);
473 event = pevent_data_event_from_type(ginfo->pevent, type);
474 if (event) {
475 trace_seq_puts(s, event->name);
476 trace_seq_putc(s, '\n');
477 pevent_event_info(s, event, record);
478 trace_seq_putc(s, '\n');
479 } else
480 trace_seq_printf(s, "UNKNOWN EVENT %d\n", type);
481 }
482
483 /* Display a timestamp always */
484 convert_nano(get_rts(ginfo, record), &sec, &usec);
485 trace_seq_printf(s, "%lu.%06lu CPU: %03d",
486 sec, usec, record->cpu);
487 free_record(record);
488
489 return 1;
490}
491
292static const struct plot_callbacks rt_task_cb = { 492static const struct plot_callbacks rt_task_cb = {
293 .plot_event = rt_task_plot_event, 493 .plot_event = rt_task_plot_event,
294 .start = rt_task_plot_start, 494 .start = rt_task_plot_start,
295 .destroy = rt_task_plot_destroy, 495 .destroy = rt_task_plot_destroy,
296 496
497 .display_last_event = rt_task_plot_display_last_event,
498 .display_info = rt_task_plot_display_info,
499
297 .match_time = task_plot_match_time, 500 .match_time = task_plot_match_time,
298 .display_last_event = task_plot_display_last_event,
299 .find_record = task_plot_find_record, 501 .find_record = task_plot_find_record,
300 .display_info = task_plot_display_info,
301}; 502};
302 503
303void rt_plot_task_update_callback(gboolean accept, 504void rt_plot_task_update_callback(gboolean accept,
diff --git a/trace-input.c b/trace-input.c
index b6af1e6..5b01386 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -1625,6 +1625,7 @@ tracecmd_read_page_record(struct pevent *pevent, void *page, int size,
1625 record->cpu = 0; 1625 record->cpu = 0;
1626 record->data = ptr; 1626 record->data = ptr;
1627 record->ref_count = 1; 1627 record->ref_count = 1;
1628 record->cached_rts = 0ULL;
1628 1629
1629 return record; 1630 return record;
1630} 1631}
@@ -1745,6 +1746,7 @@ read_again:
1745 record->missed_events = missed_events; 1746 record->missed_events = missed_events;
1746 record->ref_count = 1; 1747 record->ref_count = 1;
1747 record->locked = 1; 1748 record->locked = 1;
1749 record->cached_rts = 0ULL;
1748 1750
1749 ptr += length; 1751 ptr += length;
1750 1752
diff --git a/trace-plot-task.c b/trace-plot-task.c
index 068fd91..abcdd89 100644
--- a/trace-plot-task.c
+++ b/trace-plot-task.c
@@ -39,11 +39,11 @@ gboolean is_running(struct graph_info *ginfo, struct record *record)
39 return val ? FALSE : TRUE; 39 return val ? FALSE : TRUE;
40} 40}
41 41
42gboolean record_matches_pid(struct graph_info *ginfo, 42static gboolean record_matches_pid(struct graph_info *ginfo,
43 struct record *record, int match_pid, 43 struct record *record, int match_pid,
44 int *pid, int *sched_pid, 44 int *pid, int *sched_pid,
45 gboolean *is_sched, 45 gboolean *is_sched,
46 gboolean *wakeup) 46 gboolean *wakeup)
47{ 47{
48 const char *comm; 48 const char *comm;
49 49
@@ -73,7 +73,7 @@ gboolean record_matches_pid(struct graph_info *ginfo,
73 return FALSE; 73 return FALSE;
74} 74}
75 75
76void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time) 76static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time)
77{ 77{
78 struct record *record; 78 struct record *record;
79 79
@@ -92,7 +92,7 @@ void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time)
92 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time); 92 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time);
93} 93}
94 94
95void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) 95static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time)
96{ 96{
97 int cpu; 97 int cpu;
98 98
@@ -177,7 +177,7 @@ void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets)
177 free(offsets); 177 free(offsets);
178} 178}
179 179
180struct record * 180static struct record *
181find_record(struct graph_info *ginfo, gint pid, guint64 time) 181find_record(struct graph_info *ginfo, gint pid, guint64 time)
182{ 182{
183 struct record *record = NULL; 183 struct record *record = NULL;
@@ -207,6 +207,7 @@ find_record(struct graph_info *ginfo, gint pid, guint64 time)
207 return record; 207 return record;
208} 208}
209 209
210
210int task_plot_display_last_event(struct graph_info *ginfo, 211int task_plot_display_last_event(struct graph_info *ginfo,
211 struct graph_plot *plot, 212 struct graph_plot *plot,
212 struct trace_seq *s, 213 struct trace_seq *s,
@@ -263,7 +264,6 @@ int task_plot_display_last_event(struct graph_info *ginfo,
263 pid); 264 pid);
264 } 265 }
265 } else { 266 } else {
266
267 /* Must have the record we want */ 267 /* Must have the record we want */
268 type = pevent_data_type(ginfo->pevent, record); 268 type = pevent_data_type(ginfo->pevent, record);
269 event = pevent_data_event_from_type(ginfo->pevent, type); 269 event = pevent_data_event_from_type(ginfo->pevent, type);
diff --git a/trace-plot-task.h b/trace-plot-task.h
index 78ff68f..e050512 100644
--- a/trace-plot-task.h
+++ b/trace-plot-task.h
@@ -41,9 +41,6 @@ struct task_plot_info {
41 41
42/* Querying records */ 42/* Querying records */
43gboolean is_running(struct graph_info *ginfo, struct record *record); 43gboolean is_running(struct graph_info *ginfo, struct record *record);
44/* gboolean record_matches_pid(struct graph_info *ginfo, struct record *record, */
45/* int match_pid, int *pid, int *sched_pid, */
46/* gboolean *is_sched, gboolean *wakeup); */
47 44
48/* State maintenance */ 45/* State maintenance */
49void update_last_task_record(struct graph_info *ginfo, struct task_plot_info *task_info, 46void update_last_task_record(struct graph_info *ginfo, struct task_plot_info *task_info,
@@ -51,20 +48,11 @@ void update_last_task_record(struct graph_info *ginfo, struct task_plot_info *ta
51 48
52/* Searching for records */ 49/* Searching for records */
53#define MAX_SEARCH 20 50#define MAX_SEARCH 20
54struct record *
55find_record(struct graph_info *ginfo, gint pid, guint64 time);
56struct record *find_previous_record(struct graph_info *ginfo, 51struct record *find_previous_record(struct graph_info *ginfo,
57 struct record *start_record, 52 struct record *start_record,
58 int pid, int cpu); 53 int pid, int cpu);
59struct record *get_display_record(struct graph_info *ginfo, int pid, 54struct record *get_display_record(struct graph_info *ginfo, int pid,
60 unsigned long long time); 55 unsigned long long time);
61gboolean record_matches_pid(struct graph_info *ginfo, struct record *record,
62 int match_pid, int *pid, int *sched_pid,
63 gboolean *is_sched, gboolean *wakeup);
64
65/* Seeking in data file */
66void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time);
67void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time);
68 56
69/* Saving / restoring state */ 57/* Saving / restoring state */
70struct offset_cache { 58struct offset_cache {