aboutsummaryrefslogtreecommitdiffstats
path: root/rt-graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'rt-graph.c')
-rw-r--r--rt-graph.c143
1 files changed, 130 insertions, 13 deletions
diff --git a/rt-graph.c b/rt-graph.c
index 3e9f248..d6b1847 100644
--- a/rt-graph.c
+++ b/rt-graph.c
@@ -1,7 +1,7 @@
1#include "rt-graph.h" 1#include "trace-graph.h"
2#include "trace-hash.h" 2#include "trace-hash.h"
3 3
4#define DEBUG_LEVEL 0 4#define DEBUG_LEVEL 4
5#if DEBUG_LEVEL > 0 5#if DEBUG_LEVEL > 0
6#define dprintf(l, x...) \ 6#define dprintf(l, x...) \
7 do { \ 7 do { \
@@ -17,6 +17,9 @@ static guint get_event_hash_key(gint eid)
17 return trace_hash(eid) % TS_HASH_SIZE; 17 return trace_hash(eid) % TS_HASH_SIZE;
18} 18}
19 19
20/*
21 * Returns cached field for @eid at @key.
22 */
20struct format_field* find_ts_hash(struct ts_list **events, 23struct format_field* find_ts_hash(struct ts_list **events,
21 gint key, gint eid) 24 gint key, gint eid)
22{ 25{
@@ -29,10 +32,11 @@ struct format_field* find_ts_hash(struct ts_list **events,
29} 32}
30 33
31/* 34/*
32 * Return format field for @eid, caching its location if this is the first try 35 * Return field for @eid at @key, caching if necessary.
33 */ 36 */
34static struct format_field* add_ts_hash(struct ts_list **events, gint eid, gint key, 37static struct format_field*
35 struct pevent *pevent, struct record *record) 38add_ts_hash(struct ts_list **events, gint eid, gint key,
39 struct pevent *pevent, struct record *record)
36{ 40{
37 struct ts_list *list; 41 struct ts_list *list;
38 struct format_field *field; 42 struct format_field *field;
@@ -59,16 +63,12 @@ static struct format_field* add_ts_hash(struct ts_list **events, gint eid, gint
59 */ 63 */
60int rt_graph_check_any(struct rt_graph_info *rtinfo, 64int rt_graph_check_any(struct rt_graph_info *rtinfo,
61 struct pevent *pevent, struct record *record, 65 struct pevent *pevent, struct record *record,
62 gint *epid, unsigned long long *ts) 66 gint *epid, gint *out_eid, unsigned long long *ts)
63{ 67{
64 guint key, eid; 68 guint key, eid;
65 struct format_field *field; 69 struct format_field *field;
66 70
67 eid = pevent_data_type(pevent, record); 71 eid = pevent_data_type(pevent, record);
68
69 if (eid == rtinfo->switch_away_id)
70 return 0;
71
72 key = get_event_hash_key(eid); 72 key = get_event_hash_key(eid);
73 field = find_ts_hash(rtinfo->events, key, eid); 73 field = find_ts_hash(rtinfo->events, key, eid);
74 74
@@ -80,6 +80,7 @@ int rt_graph_check_any(struct rt_graph_info *rtinfo,
80 80
81 dprintf(3, "Read (%d) record for task %d at %llu\n", 81 dprintf(3, "Read (%d) record for task %d at %llu\n",
82 eid, *epid, *ts); 82 eid, *epid, *ts);
83 *out_eid = eid;
83 return 1; 84 return 1;
84} 85}
85 86
@@ -222,7 +223,7 @@ int rt_graph_check_switch_away(struct rt_graph_info *rtinfo,
222 223
223/** 224/**
224 * rt_graph_check_task_release - check for litmus_task_release record 225 * rt_graph_check_task_release - check for litmus_task_release record
225 * Return 1 and @pid, @job, and @deadline if the record matches 226 * Return 1 and @pid, @job, @release, and @deadline if the record matches
226 */ 227 */
227int rt_graph_check_task_release(struct rt_graph_info *rtinfo, 228int rt_graph_check_task_release(struct rt_graph_info *rtinfo,
228 struct pevent *pevent, struct record *record, 229 struct pevent *pevent, struct record *record,
@@ -271,7 +272,7 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo,
271 272
272/** 273/**
273 * rt_graph_check_task_completion - check for litmus_task_completion record 274 * rt_graph_check_task_completion - check for litmus_task_completion record
274 * Return 1 and @pid, @job if the record matches 275 * Return 1 and @pid, @job, and @ts if the record matches
275 */ 276 */
276int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, 277int rt_graph_check_task_completion(struct rt_graph_info *rtinfo,
277 struct pevent *pevent, struct record *record, 278 struct pevent *pevent, struct record *record,
@@ -314,7 +315,7 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo,
314 315
315/** 316/**
316 * rt_graph_check_task_block - check for litmus_task_block record 317 * rt_graph_check_task_block - check for litmus_task_block record
317 * Return 1 and @pid if the record matches 318 * Return 1, @pid, and @ts if the record matches
318 */ 319 */
319int rt_graph_check_task_block(struct rt_graph_info *rtinfo, 320int rt_graph_check_task_block(struct rt_graph_info *rtinfo,
320 struct pevent *pevent, struct record *record, 321 struct pevent *pevent, struct record *record,
@@ -431,3 +432,119 @@ void init_rt_event_cache(struct rt_graph_info *rtinfo)
431 rtinfo->resume_pid_field = NULL; 432 rtinfo->resume_pid_field = NULL;
432 rtinfo->resume_ts_field = NULL; 433 rtinfo->resume_ts_field = NULL;
433} 434}
435
436/**
437 * get_rts - extract real-time timestamp from a record
438 *
439 * This will only have to extract the timestamp once; after the time
440 * is extracted it will be cached in the record itself.
441 */
442unsigned long long
443get_rts(struct graph_info *ginfo, struct record *record)
444{
445 gint epid, eid;
446 unsigned long long ts;
447 if (!record->cached_rts) {
448 rt_graph_check_any(&ginfo->rtinfo, ginfo->pevent, record,
449 &epid, &eid, &ts);
450 record->cached_rts = ts;
451 } else
452 ts = record->cached_rts;
453 return ts;
454}
455
456/**
457 * next_rts - find a real-time timestamp AROUND an FTRACE time
458 * @ginfo: Current state of the graph
459 * @cpu: CPU to search
460 * @ft_target: FTRACE time to seek towards
461 *
462 * Returns the RT time of a record CLOSELY BEFORE @ft_time.
463 */
464unsigned long long
465next_rts(struct graph_info *ginfo, int cpu, unsigned long long ft_target)
466{
467 struct record *record;
468 unsigned long long ts = 0ULL;
469 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, ft_target);
470 record = tracecmd_read_data(ginfo->handle, cpu);
471 if (record) {
472 ts = get_rts(ginfo, record);
473 free_record(record);
474 return ts;
475 } else
476 return 0;
477}
478
479/**
480 * set_cpu_to_rts - seek CPU to a time closely preceding a real-time timestamp
481 * @ginfo: Current state o the graph
482 * @cpu: The CPU to seek
483 * @rt_target: RT time to seek towards
484 *
485 * This seeks to a real-time timestamp, not the default ftrace timestamps.
486 * The @cpu seek location will be placed before the given time, but will
487 * not necessarily be placed _right_ before the time.
488 */
489void
490set_cpu_to_rts(struct graph_info *ginfo, unsigned long long rt_target, int cpu)
491{
492 struct record *record;
493 unsigned long long last_rts, rts, seek_time, last_seek;
494 long long diff;
495
496 rts = next_rts(ginfo, cpu, rt_target);
497 diff = rt_target - rts;
498
499 /* "Guess" a new target based on difference */
500 seek_time = rt_target + diff;
501 rts = next_rts(ginfo, cpu, seek_time);
502 diff = rt_target - rts;
503
504 /* Zero in in 1.5x the difference increments */
505 if (rts && diff > 0) {
506 /* rts rt_target
507 * seek ?
508 * ---|---->>----|---
509 */
510 do {
511 last_seek = seek_time;
512 last_rts = rts;
513 seek_time = seek_time + 1.5 * (rt_target - rts);
514 rts = next_rts(ginfo, cpu, seek_time);
515 } while (rts < rt_target && last_rts != rts);
516 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek);
517 seek_time = last_seek;
518 } else if (rts && diff < 0) {
519 /* rt_target rts
520 * ? seek
521 * ---|----<<----|---
522 */
523 do {
524 seek_time = seek_time - 1.5 * (rts - rt_target);
525 rts = next_rts(ginfo, cpu, seek_time);
526 } while (rts > rt_target);
527 }
528
529 /* Get to first record at or after time */
530 while ((record = tracecmd_read_data(ginfo->handle, cpu))) {
531 if (get_rts(ginfo, record) >= rt_target)
532 break;
533 free_record(record);
534 }
535 if (record) {
536 tracecmd_set_cursor(ginfo->handle, cpu, record->offset);
537 free_record(record);
538 } else
539 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time);
540}
541
542/**
543 * set_cpus_to_time - seek all cpus to real-time @rt_target
544 */
545void set_cpus_to_rts(struct graph_info *ginfo, unsigned long long rt_target)
546{
547 int cpu;
548 for (cpu = 0; cpu < ginfo->cpus; cpu++)
549 set_cpu_to_rts(ginfo, rt_target, cpu);
550}