diff options
-rw-r--r-- | rt-graph.c | 9 | ||||
-rw-r--r-- | rt-graph.h | 6 | ||||
-rw-r--r-- | rt-plot-task.c | 170 | ||||
-rw-r--r-- | trace-graph.c | 2 |
4 files changed, 119 insertions, 68 deletions
@@ -57,9 +57,9 @@ static struct format_field* add_ts_hash(struct ts_list **events, gint eid, gint | |||
57 | * @epid: set to the event's task PID | 57 | * @epid: set to the event's task PID |
58 | * @rt_ts: set to the event's real-time timestamp | 58 | * @rt_ts: set to the event's real-time timestamp |
59 | */ | 59 | */ |
60 | void rt_graph_check_any(struct rt_graph_info *rtinfo, | 60 | int rt_graph_check_any(struct rt_graph_info *rtinfo, |
61 | struct pevent *pevent, struct record *record, | 61 | struct pevent *pevent, struct record *record, |
62 | gint *epid, unsigned long long *ts) | 62 | gint *epid, unsigned long long *ts) |
63 | { | 63 | { |
64 | guint key, eid; | 64 | guint key, eid; |
65 | struct format_field *field; | 65 | struct format_field *field; |
@@ -76,6 +76,7 @@ void rt_graph_check_any(struct rt_graph_info *rtinfo, | |||
76 | 76 | ||
77 | dprintf(3, "Read (%d) record for task %d at %llu\n", | 77 | dprintf(3, "Read (%d) record for task %d at %llu\n", |
78 | eid, *epid, *ts); | 78 | eid, *epid, *ts); |
79 | return 1; | ||
79 | } | 80 | } |
80 | 81 | ||
81 | /** | 82 | /** |
@@ -347,7 +348,7 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | |||
347 | } | 348 | } |
348 | 349 | ||
349 | /** | 350 | /** |
350 | * rt_graph_check_task_release - check for litmus_task_release record | 351 | * rt_graph_check_task_resume - check for litmus_task_resume record |
351 | * Return 1 and @pid if the record matches | 352 | * Return 1 and @pid if the record matches |
352 | */ | 353 | */ |
353 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | 354 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, |
@@ -63,9 +63,9 @@ struct ts_list { | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | /* Event parsers */ | 65 | /* Event parsers */ |
66 | void rt_graph_check_any(struct rt_graph_info *rtinfo, | 66 | int rt_graph_check_any(struct rt_graph_info *rtinfo, |
67 | struct pevent *pevent, struct record *record, | 67 | struct pevent *pevent, struct record *record, |
68 | gint *epid, unsigned long long *ts); | 68 | gint *pid, unsigned long long *ts); |
69 | int rt_graph_check_task_param(struct rt_graph_info *rtinfo, struct pevent *pevent, | 69 | int rt_graph_check_task_param(struct rt_graph_info *rtinfo, struct pevent *pevent, |
70 | struct record *record, gint *pid, | 70 | struct record *record, gint *pid, |
71 | unsigned long long *wcet, | 71 | unsigned long long *wcet, |
diff --git a/rt-plot-task.c b/rt-plot-task.c index 8ecbdbb..0b10d91 100644 --- a/rt-plot-task.c +++ b/rt-plot-task.c | |||
@@ -110,39 +110,23 @@ static gboolean record_matches_pid(struct graph_info *ginfo, | |||
110 | struct record *record, | 110 | struct record *record, |
111 | int match_pid) | 111 | int match_pid) |
112 | { | 112 | { |
113 | guint eid, pid; | 113 | gint dint, pid = 0, match = 0; |
114 | unsigned long long val; | 114 | unsigned long long dull; |
115 | struct format_field *pid_field = NULL; | 115 | struct rt_graph_info *rtg_info = &ginfo->rtinfo; |
116 | struct rt_graph_info *rtinfo = &ginfo->rtinfo; | 116 | |
117 | 117 | /* Must use check_* in case record has not been found yet, | |
118 | eid = pevent_data_type(ginfo->pevent, record); | 118 | * this macro was the best of many terrible options |
119 | if (eid == rtinfo->task_param_id) | 119 | */ |
120 | pid_field = rtinfo->param_pid_field; | 120 | #define MARGS rtg_info, ginfo->pevent, record, &pid |
121 | else if (eid == rtinfo->switch_to_id) | 121 | match = rt_graph_check_switch_to(MARGS, &dint, &dull) || |
122 | pid_field = rtinfo->switch_to_pid_field; | 122 | rt_graph_check_switch_away(MARGS, &dint, &dull) || |
123 | else if (eid == rtinfo->switch_away_id) | 123 | rt_graph_check_task_release(MARGS, &dint, &dull, &dull) || |
124 | pid_field = rtinfo->switch_away_pid_field; | 124 | rt_graph_check_task_completion(MARGS, &dint, &dull) || |
125 | else if (eid == rtinfo->task_release_id) | 125 | rt_graph_check_task_block(MARGS, &dull) || |
126 | pid_field = rtinfo->release_pid_field; | 126 | rt_graph_check_task_resume(MARGS, &dull) || |
127 | else if (eid == rtinfo->task_completion_id) | 127 | rt_graph_check_any(MARGS, &dull); |
128 | pid_field = rtinfo->completion_pid_field; | 128 | #undef MARGS |
129 | else if (eid == rtinfo->task_block_id) | 129 | return match && pid == match_pid; |
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 | } | 130 | } |
147 | 131 | ||
148 | struct record* | 132 | struct record* |
@@ -240,9 +224,6 @@ static int try_completion(struct graph_info *ginfo, | |||
240 | info->completion = TRUE; | 224 | info->completion = TRUE; |
241 | info->ctime = ts; | 225 | info->ctime = ts; |
242 | info->clabel = rtt_info->label; | 226 | info->clabel = rtt_info->label; |
243 | info->line = TRUE; | ||
244 | info->lcolor = hash_pid(record->cpu); | ||
245 | info->ltime = ts; | ||
246 | ret = 1; | 227 | ret = 1; |
247 | } | 228 | } |
248 | return ret; | 229 | return ret; |
@@ -361,6 +342,65 @@ static int try_other(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
361 | return ret; | 342 | return ret; |
362 | } | 343 | } |
363 | 344 | ||
345 | /* | ||
346 | * Return information for @time, returns @job, @release, @deadline, and @record. | ||
347 | * @job: Job number at this time | ||
348 | * @release: Job's release time | ||
349 | * @deadline: Job's deadline | ||
350 | * @record: Matching record | ||
351 | */ | ||
352 | static int get_time_info(struct graph_info *ginfo, | ||
353 | struct rt_task_info *rtt_info, | ||
354 | unsigned long long time, | ||
355 | int *out_job, | ||
356 | unsigned long long *out_release, | ||
357 | unsigned long long *out_deadline, | ||
358 | struct record **out_record) | ||
359 | |||
360 | { | ||
361 | int pid, job, match, found_job = 0; | ||
362 | unsigned long long release, deadline; | ||
363 | struct record *record, *last_record; | ||
364 | struct rt_graph_info *rtg_info = &ginfo->rtinfo; | ||
365 | |||
366 | /* Seek CPUs to first record after this time */ | ||
367 | *out_record = find_record(ginfo, rtt_info->base.pid, time); | ||
368 | if (!*out_record) | ||
369 | goto out; | ||
370 | |||
371 | last_record = *out_record; | ||
372 | last_record->ref_count++; | ||
373 | |||
374 | /* Read backwards for a release record */ | ||
375 | while ((record = tracecmd_read_prev(ginfo->handle, last_record))) { | ||
376 | match = rt_graph_check_task_release(rtg_info, ginfo->pevent, | ||
377 | record, &pid, &job, | ||
378 | &release, &deadline); | ||
379 | free_record(last_record); | ||
380 | last_record = record; | ||
381 | if (match && pid == rtt_info->base.pid && release <= time) { | ||
382 | found_job = TRUE; | ||
383 | break; | ||
384 | } | ||
385 | } | ||
386 | free_record(last_record); | ||
387 | |||
388 | if (found_job) { | ||
389 | *out_job = job; | ||
390 | *out_release = release; | ||
391 | *out_deadline = deadline; | ||
392 | } | ||
393 | out: | ||
394 | return found_job; | ||
395 | } | ||
396 | |||
397 | static inline int in_res(struct graph_info *ginfo, unsigned long long time, | ||
398 | unsigned long target) | ||
399 | { | ||
400 | return time > target - 2/ginfo->resolution && | ||
401 | time < target + 2/ginfo->resolution; | ||
402 | } | ||
403 | |||
364 | static int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | 404 | static int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, |
365 | struct record *record, struct plot_info *info) | 405 | struct record *record, struct plot_info *info) |
366 | { | 406 | { |
@@ -455,36 +495,46 @@ static int rt_task_plot_display_info(struct graph_info *ginfo, | |||
455 | struct trace_seq *s, | 495 | struct trace_seq *s, |
456 | unsigned long long time) | 496 | unsigned long long time) |
457 | { | 497 | { |
458 | int type; | 498 | const char *comm; |
499 | int show_dead, show_rel, pid, job, eid; | ||
459 | struct record *record; | 500 | struct record *record; |
460 | struct event_format *event; | 501 | struct event_format *event; |
461 | unsigned long sec, usec; | 502 | unsigned long usec, sec; |
503 | unsigned long long release, deadline, rts; | ||
462 | struct rt_task_info *rtt_info = plot->private; | 504 | struct rt_task_info *rtt_info = plot->private; |
463 | 505 | ||
464 | record = find_record(ginfo, rtt_info->base.pid, time); | 506 | get_time_info(ginfo, rtt_info, time, |
465 | if (!record) | 507 | &job, &release, &deadline, &record); |
466 | return 0; | 508 | show_rel = in_res(ginfo, release, time); |
509 | show_dead = in_res(ginfo, deadline, time); | ||
467 | 510 | ||
468 | /* Display only if the record's time is close enough */ | 511 | /* Show real-time data about time */ |
469 | if (get_rts(ginfo, record) > time - 2/ginfo->resolution && | 512 | pid = rtt_info->base.pid; |
470 | get_rts(ginfo, record) < time + 2/ginfo->resolution) { | 513 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); |
471 | 514 | trace_seq_printf(s, "%s - %d:%d\n", comm, pid, job); | |
472 | type = pevent_data_type(ginfo->pevent, record); | 515 | if (show_rel) |
473 | event = pevent_data_event_from_type(ginfo->pevent, type); | 516 | trace_seq_printf(s, "RELEASE\n"); |
474 | if (event) { | 517 | if (show_dead) |
475 | trace_seq_puts(s, event->name); | 518 | trace_seq_printf(s, "DEADLINE\n"); |
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 | 519 | ||
483 | /* Display a timestamp always */ | 520 | if (record) { |
484 | convert_nano(get_rts(ginfo, record), &sec, &usec); | 521 | rts = get_rts(ginfo, record); |
485 | trace_seq_printf(s, "%lu.%06lu CPU: %03d", | 522 | if (in_res(ginfo, rts, time)) { |
486 | sec, usec, record->cpu); | 523 | eid = pevent_data_type(ginfo->pevent, record); |
487 | free_record(record); | 524 | event = pevent_data_event_from_type(ginfo->pevent, eid); |
525 | if (event) { | ||
526 | trace_seq_puts(s, event->name); | ||
527 | trace_seq_putc(s, '\n'); | ||
528 | pevent_event_info(s, event, record); | ||
529 | trace_seq_putc(s, '\n'); | ||
530 | } else | ||
531 | trace_seq_printf(s, "UNKNOWN EVENT %d\n", eid); | ||
532 | } | ||
533 | convert_nano(get_rts(ginfo, record), &sec, &usec); | ||
534 | trace_seq_printf(s, "%lu.%06lu CPU: %03d", | ||
535 | sec, usec, record->cpu); | ||
536 | free_record(record); | ||
537 | } | ||
488 | 538 | ||
489 | return 1; | 539 | return 1; |
490 | } | 540 | } |
diff --git a/trace-graph.c b/trace-graph.c index 2cf7a95..f94ad50 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
@@ -76,7 +76,7 @@ static int convert_time_to_x(struct graph_info *ginfo, guint64 time) | |||
76 | return 0; | 76 | return 0; |
77 | return (time - ginfo->view_start_time) * ginfo->resolution; | 77 | return (time - ginfo->view_start_time) * ginfo->resolution; |
78 | } | 78 | } |
79 | 79 | r | |
80 | static guint64 convert_x_to_time(struct graph_info *ginfo, gint x) | 80 | static guint64 convert_x_to_time(struct graph_info *ginfo, gint x) |
81 | { | 81 | { |
82 | double d = x; | 82 | double d = x; |