aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-08 20:23:53 -0500
committerJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-08 20:23:53 -0500
commit11c9b6cac9c5cfb72ecaa88d6f5ab0c6cd0034ae (patch)
treec456d1d9b5aebcbe67042995dfe10f1d1e961512
parent8b715d53a1737e16f1c7c04b6c5b03feb1ebaed9 (diff)
rt-graph: rt cpus have all basic features implemented
-rw-r--r--rt-plot-cpu.c461
-rw-r--r--rt-plot-cpu.h20
-rw-r--r--rt-plot-task.c16
-rw-r--r--trace-graph.h6
4 files changed, 491 insertions, 12 deletions
diff --git a/rt-plot-cpu.c b/rt-plot-cpu.c
new file mode 100644
index 0000000..6884286
--- /dev/null
+++ b/rt-plot-cpu.c
@@ -0,0 +1,461 @@
1#include "trace-graph.h"
2#include "cpu.h"
3
4#define DEBUG_LEVEL 0
5#if DEBUG_LEVEL > 0
6#define dprintf(l, x...) \
7 do { \
8 if (l <= DEBUG_LEVEL) \
9 printf(x); \
10 } while (0)
11#else
12#define dprintf(l, x...) do { if (0) printf(x); } while (0)
13#endif
14
15static struct record*
16next_sa_record(struct graph_info *ginfo, struct rt_cpu_info *rtc_info,
17 unsigned long long time, int *out_pid)
18{
19 struct pevent *pevent;
20 struct record *ret = NULL, *record;
21 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
22 unsigned long long max_ts, dull;
23 int pid, dint, match;
24
25 max_ts = time + SEARCH_PERIODS * rtg_info->max_period;
26 pevent = ginfo->pevent;
27
28 set_cpu_to_rts(ginfo, time, rtc_info->cpu);
29
30 while ((record = tracecmd_read_data(ginfo->handle, rtc_info->cpu))) {
31 if (get_rts(ginfo, record) > max_ts) {
32 free_record(record);
33 break;
34 }
35 match = rt_graph_check_switch_away(rtg_info, pevent, record,
36 &pid, &dint, &dull);
37 if (match) {
38 ret = record;
39 *out_pid = pid;
40 break;
41 }
42 free_record(record);
43 }
44 return ret;
45}
46
47static struct record*
48find_record(struct graph_info *ginfo, int cpu, unsigned long long time)
49{
50 struct record *record = NULL;
51 set_cpu_to_rts(ginfo, time, cpu);
52
53 while ((record = tracecmd_read_data(ginfo->handle, cpu))) {
54 if (get_rts(ginfo, record) >= time)
55 break;
56 free_record(record);
57 }
58 return record;
59}
60
61
62static void update_pid(struct rt_cpu_info *rtc_info, int pid)
63{
64 rtc_info->fresh = FALSE;
65 if (pid != rtc_info->run_pid) {
66 rtc_info->run_pid = pid;
67 snprintf(rtc_info->label, LLABEL, "%d", rtc_info->run_pid);
68 }
69}
70
71static int
72try_switch_away(struct graph_info *ginfo, struct rt_cpu_info *rtc_info,
73 struct record *record, struct plot_info *info)
74{
75 int job, pid, match;
76 unsigned long long ts;
77
78 match = rt_graph_check_switch_away(&ginfo->rtg_info, ginfo->pevent,
79 record, &pid, &job, &ts);
80 if (match) {
81 update_pid(rtc_info, pid);
82 if (rtc_info->run_time && rtc_info->run_time < ts) {
83 info->box = TRUE;
84 info->bcolor = hash_pid(rtc_info->run_pid);
85 info->bfill = TRUE;
86 info->bstart = rtc_info->run_time;
87 info->bend = ts;
88 info->blabel = rtc_info->label;
89 }
90 rtc_info->run_pid = 0;
91 rtc_info->run_time = 0Ull;
92 }
93 return match;
94}
95
96static int
97try_switch_to(struct graph_info *ginfo, struct rt_cpu_info *rtc_info,
98 struct record *record, struct plot_info *info)
99{
100 int job, pid, match;
101 unsigned long long ts;
102
103 match = rt_graph_check_switch_to(&ginfo->rtg_info, ginfo->pevent,
104 record, &pid, &job, &ts);
105 if (match) {
106 update_pid(rtc_info, pid);
107 rtc_info->run_time = ts;
108 }
109 return match;
110}
111
112static int
113try_completion(struct graph_info *ginfo, struct rt_cpu_info *rtc_info,
114 struct record *record, struct plot_info *info)
115{
116 int pid, job, match;
117 unsigned long long ts;
118
119 match = rt_graph_check_task_completion(&ginfo->rtg_info, ginfo->pevent,
120 record, &pid, &job, &ts);
121 if (match) {
122 info->completion = TRUE;
123 info->ctime = ts;
124 }
125 return match;
126}
127
128static void do_plot_end(struct graph_info *ginfo, struct rt_cpu_info *rtc_info,
129 struct plot_info *info)
130{
131 int pid;
132 struct record *record;
133
134 if (rtc_info->run_time && rtc_info->run_pid) {
135 info->box = TRUE;
136 info->bcolor = hash_pid(rtc_info->run_pid);
137 info->bfill = TRUE;
138 info->bstart = rtc_info->run_time;
139 info->bend = ginfo->view_end_time;
140 info->blabel = rtc_info->label;
141 rtc_info->fresh = FALSE;
142 } else if (rtc_info->fresh) {
143 record = next_sa_record(ginfo, rtc_info,
144 ginfo->view_end_time,
145 &pid);
146 if (record) {
147 update_pid(rtc_info, pid);
148 info->box = TRUE;
149 info->bcolor = hash_pid(pid);
150 info->bfill = TRUE;
151 info->blabel = rtc_info->label;
152 info->bstart = ginfo->view_start_time;
153 info->bend = ginfo->view_end_time;
154 rtc_info->fresh = FALSE;
155 }
156 free_record(record);
157 }
158}
159
160static int rt_cpu_plot_match_time(struct graph_info *ginfo,
161 struct graph_plot *plot,
162 unsigned long long time)
163{
164 int ret = 0;
165 struct rt_cpu_info *rtc_info = plot->private;
166 struct record = find_record(ginfo, rtc_info->cpu, time);
167
168 if (record && get_rts(ginfo, record) == time)
169 ret = 1;
170 free_record(record);
171
172 return ret;
173}
174
175static void rt_cpu_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
176 unsigned long long time)
177{
178 struct rt_cpu_info *rtc_info = plot->private;
179
180 rtc_info->run_time = time;
181 rtc_info->run_pid = 0;
182 rtc_info->fresh = TRUE;
183}
184
185static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot,
186 struct record *record, struct plot_info *info)
187{
188 int pid, eid, match;
189 unsigned long long ts;
190 struct rt_cpu_info *rtc_info = plot->private;
191 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
192 const char *comm;
193
194 if (!record) {
195 do_plot_end(ginfo, rtc_info, info);
196 return 0;
197 }
198
199 if (record->cpu != rtc_info->cpu)
200 return 0;
201
202 match = try_switch_away(ginfo, rtc_info, record, info) ||
203 try_switch_to(ginfo, rtc_info, record, info) ||
204 try_completion(ginfo, rtc_info, record, info) ||
205 trace_graph_check_sched_switch(ginfo, record,
206 &pid, &comm);
207 if (!match) {
208 rt_graph_check_any(rtg_info, ginfo->pevent, record,
209 &pid, &eid, &ts);
210 info->line = TRUE;
211 info->lcolor = hash_pid(pid);
212 info->ltime = ts;
213 }
214 return 1;
215}
216
217static int
218rt_cpu_plot_display_last_event(struct graph_info *ginfo, struct graph_plot *plot,
219 struct trace_seq *s, unsigned long long time)
220{
221 struct rt_cpu_info *rtc_info = plot->private;
222 struct event_format *event;
223 struct record *record;
224 unsigned long long offset;
225 int eid, cpu;
226
227 cpu = rtc_info->cpu;
228 record = tracecmd_peek_data(ginfo->handle, cpu);
229 if (record)
230 offset = record->offset;
231
232 record = find_record(ginfo, cpu, time);
233
234 if (offset)
235 tracecmd_set_cursor(ginfo->handle, cpu, offset);
236 if (!record)
237 return 0;
238
239 eid = pevent_data_type(ginfo->pevent, record);
240 event = pevent_data_event_from_type(ginfo->pevent, eid);
241 if (event) {
242 trace_seq_puts(s, event->name);
243 trace_seq_printf(s, "\n"); /* Doesn't work otherwise */
244 } else
245 trace_seq_printf(s, "UNKNOWN EVENT %d\n", eid);
246 free_record(record);
247
248 return 1;
249}
250
251
252struct record*
253rt_cpu_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot,
254 unsigned long long time)
255{
256 struct rt_cpu_info *rtc_info = plot->private;
257 return find_record(ginfo, rtc_info->cpu, time);
258}
259
260static int get_time_info(struct graph_info *ginfo,
261 struct rt_cpu_info *rtc_info,
262 unsigned long long time,
263 int *out_pid, int *out_job,
264 struct record **out_record)
265{
266 struct record *record;
267 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
268 unsigned long long dull, max_ts;
269 int cpu, is_running, pid, job;
270
271 cpu = rtc_info->cpu;
272 *out_pid = *out_job = is_running = 0;
273
274 record = find_record(ginfo, cpu, time);
275 *out_record = record;
276 if (!record)
277 goto out;
278
279 max_ts = time + SEARCH_PERIODS * rtg_info->max_period;
280 do {
281 if (get_rts(ginfo, record) > max_ts)
282 break;
283
284#define ARG rtg_info, ginfo->pevent, record, &pid, &job, &dull
285 if (rt_graph_check_switch_to(ARG)) {
286 /* Nothing is running */
287 goto out;
288 } else if (rt_graph_check_switch_away(ARG)) {
289 is_running = 1;
290 *out_pid = pid;
291 *out_job = job;
292 goto out;
293 }
294 if (*out_record != record)
295 free_record(record);
296#undef ARG
297 } while ((record = tracecmd_read_data(ginfo->handle, cpu)));
298 out:
299 if (*out_record != record)
300 free_record(record);
301 return is_running;
302}
303
304static int
305rt_cpu_plot_display_info(struct graph_info *ginfo, struct graph_plot *plot,
306 struct trace_seq *s, unsigned long long time)
307{
308 struct rt_cpu_info *rtc_info = plot->private;
309 unsigned long long msec, nsec, rts;
310 int pid, eid, job, is_running;
311 struct record *record;
312 struct event_format *event;
313 const char *comm;
314
315 is_running = get_time_info(ginfo, rtc_info, time,
316 &pid, &job, &record);
317
318 if (is_running) {
319 comm = pevent_data_comm_from_pid(ginfo->pevent, pid);
320 trace_seq_printf(s, "%s-%d:%d\n", comm, pid, job);
321 }
322
323 if (record) {
324 rts = get_rts(ginfo, record);
325 if (in_res(ginfo, rts, time)) {
326 eid = pevent_data_type(ginfo->pevent, record);
327 event = pevent_data_event_from_type(ginfo->pevent, eid);
328 if (event) {
329 trace_seq_putc(s, '\n');
330 trace_seq_puts(s, event->name);
331 trace_seq_putc(s, '\n');
332 pevent_event_info(s, event, record);
333 } else
334 trace_seq_printf(s, "\nUNKNOWN EVENT %d\n", eid);
335 }
336 free_record(record);
337 }
338 trace_seq_putc(s, '\n');
339 nano_to_milli(time, &msec, &nsec);
340 trace_seq_printf(s, "%llu.%06llu ms CPU: %03d",
341 msec, nsec, rtc_info->cpu);
342
343 return 1;
344}
345
346static void rt_cpu_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot)
347{
348 struct rt_cpu_info *rtc_info = plot->private;
349
350 trace_graph_plot_remove_all_recs(ginfo, plot);
351 free(rtc_info->label);
352 free(rtc_info);
353}
354
355
356static const struct plot_callbacks rt_cpu_cb = {
357 .start = rt_cpu_plot_start,
358 .destroy = rt_cpu_plot_destroy,
359 .plot_event = rt_cpu_plot_event,
360 .display_last_event = rt_cpu_plot_display_last_event,
361 .display_info = rt_cpu_plot_display_info,
362 .match_time = rt_cpu_plot_match_time,
363 .find_record = rt_cpu_plot_find_record,
364};
365
366void rt_plot_cpus_update_callback(gboolean accept,
367 gboolean all_cpus,
368 guint64 *selected_cpu_mask,
369 gpointer data)
370{
371 struct graph_info *ginfo = data;
372 struct rt_cpu_info *rtc_info;
373 struct graph_plot *plot;
374 gboolean old_all_cpus;
375 guint64 *old_cpu_mask;
376 int i;
377
378 if (!accept)
379 return;
380
381 /* Get the current status */
382 rt_plot_cpus_plotted(ginfo, &old_all_cpus, &old_cpu_mask);
383
384 if (old_all_cpus == all_cpus ||
385 (selected_cpu_mask &&
386 cpus_equal(old_cpu_mask, selected_cpu_mask, ginfo->cpus))) {
387 /* Nothing to do */
388 g_free(old_cpu_mask);
389 return;
390 }
391
392 if (!all_cpus) {
393 /*
394 * Remove any plots not selected.
395 * Go backwards, since removing a plot shifts the
396 * array from current position back.
397 */
398 for (i = ginfo->plots - 1; i >= 0; i--) {
399 plot = ginfo->plot_array[i];
400 if (plot->type != PLOT_TYPE_CPU)
401 continue;
402 rtc_info = plot->private;
403 if (!cpu_isset(selected_cpu_mask, rtc_info->cpu))
404 trace_graph_plot_remove(ginfo, plot);
405 }
406 }
407
408 /* Now add any plots not set */
409 for (i = 0; i < ginfo->cpus; i++) {
410 if (!all_cpus && !cpu_isset(selected_cpu_mask, i))
411 continue;
412 if (cpu_isset(old_cpu_mask, i))
413 continue;
414 rt_plot_cpu(ginfo, i);
415 }
416
417 g_free(old_cpu_mask);
418
419 trace_graph_refresh(ginfo);
420}
421
422void rt_plot_cpus_plotted(struct graph_info *ginfo,
423 gboolean *all_cpus, guint64 **cpu_mask)
424{
425 struct rt_cpu_info *rtc_info;
426 struct graph_plot *plot;
427 int i;
428
429 *cpu_mask = g_new0(guint64, (ginfo->cpus >> 6) + 1);
430 g_assert(*cpu_mask);
431
432 for (i = 0; i < ginfo->plots; i++) {
433 plot = ginfo->plot_array[i];
434 if (plot->type != PLOT_TYPE_RT_CPU)
435 continue;
436 rtc_info = plot->private;
437 cpu_set(*cpu_mask, rtc_info->cpu);
438 }
439
440 *all_cpus = cpu_weight(*cpu_mask, ginfo->cpus) == ginfo->cpus ?
441 TRUE : FALSE;
442}
443
444
445void rt_plot_cpu(struct graph_info *ginfo, int cpu)
446{
447 struct rt_cpu_info *rtc_info;
448 struct graph_plot *plot;
449 char label[100];
450
451 rtc_info = malloc_or_die(sizeof(*rtc_info));
452 memset(rtc_info, 0, sizeof(*rtc_info));
453 rtc_info->cpu = cpu;
454 rtc_info->label = malloc_or_die(LLABEL);
455
456 snprintf(label, 100, "*CPU %d", cpu);
457
458 plot = trace_graph_plot_append(ginfo, label, PLOT_TYPE_RT_CPU,
459 TIME_TYPE_RT, &rt_cpu_cb, rtc_info);
460 trace_graph_plot_add_all_recs(ginfo, plot);
461}
diff --git a/rt-plot-cpu.h b/rt-plot-cpu.h
new file mode 100644
index 0000000..320bf53
--- /dev/null
+++ b/rt-plot-cpu.h
@@ -0,0 +1,20 @@
1#ifndef __RT_PLOT_CPU_H
2#define __RT_PLOT_CPU_H
3
4struct rt_cpu_info {
5 int cpu;
6 unsigned long long run_time;
7 int run_pid;
8 gboolean fresh;
9 char *label;
10};
11
12void rt_plot_cpu(struct graph_info *ginfo, int cpu);
13void rt_plot_cpus_plotted(struct graph_info *ginfo,
14 gboolean *all_cpus, guint64 **cpu_mask);
15void rt_plot_cpus_update_callback(gboolean accept,
16 gboolean all_cpus,
17 guint64 *selected_cpu_mask,
18 gpointer data);
19
20#endif
diff --git a/rt-plot-task.c b/rt-plot-task.c
index 48bcdde..f8d29ed 100644
--- a/rt-plot-task.c
+++ b/rt-plot-task.c
@@ -93,11 +93,8 @@ __find_record(struct graph_info *ginfo, gint pid, guint64 time, int display)
93 struct rt_graph_info *rtg_info = &ginfo->rtg_info; 93 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
94 94
95 set_cpus_to_rts(ginfo, time); 95 set_cpus_to_rts(ginfo, time);
96 do { 96 while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu))) {
97 free_record(record); 97 free_record(record);
98 record = tracecmd_read_next_data(ginfo->handle, &next_cpu);
99 if (!record)
100 return NULL;
101 match = record_matches_pid(ginfo, record, pid); 98 match = record_matches_pid(ginfo, record, pid);
102 if (display) { 99 if (display) {
103 eid = pevent_data_type(ginfo->pevent, record); 100 eid = pevent_data_type(ginfo->pevent, record);
@@ -109,7 +106,9 @@ __find_record(struct graph_info *ginfo, gint pid, guint64 time, int display)
109 eid == rtg_info->task_release_id); 106 eid == rtg_info->task_release_id);
110 } 107 }
111 ignored = ignored && eid == ginfo->event_sched_switch_id; 108 ignored = ignored && eid == ginfo->event_sched_switch_id;
112 } while (!(get_rts(ginfo, record) > time && match && !ignored)); 109 if (get_rts(ginfo, record) >= time && match && !ignored)
110 break;
111 };
113 112
114 return record; 113 return record;
115} 114}
@@ -593,13 +592,6 @@ static int rt_task_plot_display_last_event(struct graph_info *ginfo,
593 return 1; 592 return 1;
594} 593}
595 594
596static inline int in_res(struct graph_info *ginfo, unsigned long long time,
597 unsigned long target)
598{
599 return time > target - 2/ginfo->resolution &&
600 time < target + 2/ginfo->resolution;
601}
602
603static int rt_task_plot_display_info(struct graph_info *ginfo, 595static int rt_task_plot_display_info(struct graph_info *ginfo,
604 struct graph_plot *plot, 596 struct graph_plot *plot,
605 struct trace_seq *s, 597 struct trace_seq *s,
diff --git a/trace-graph.h b/trace-graph.h
index ffd7cf5..33bdde2 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -433,5 +433,11 @@ static inline int hash_cpu(int cpu)
433 return trace_hash(cpu); 433 return trace_hash(cpu);
434} 434}
435 435
436static inline int in_res(struct graph_info *ginfo, unsigned long long time,
437 unsigned long target)
438{
439 return time > target - 2/ginfo->resolution &&
440 time < target + 2/ginfo->resolution;
441}
436 442
437#endif /* _TRACE_GRAPH_H */ 443#endif /* _TRACE_GRAPH_H */