aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-06 16:10:41 -0500
committerJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-06 16:10:41 -0500
commit471b1045226249deacf12ad419b24d962bded880 (patch)
treeda61dd2c1d1942421cee3b812d4853bb47392b34
parentbb3a47fd55929bbeef0a6dfdef1017391d5b7425 (diff)
rt-graph: real-time plots now draw other events
Vertical lines mark events which were run either with the tasks pid or ran on the task's cpu while it is executing.
-rw-r--r--parse-events.h1
-rw-r--r--rt-graph.c172
-rw-r--r--rt-graph.h46
-rw-r--r--rt-plot-task.c201
-rw-r--r--rt-plot-task.h6
5 files changed, 265 insertions, 161 deletions
diff --git a/parse-events.h b/parse-events.h
index 67e7886..56cef4a 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -406,6 +406,7 @@ struct pevent {
406 406
407 /* cache */ 407 /* cache */
408 struct event_format *last_event; 408 struct event_format *last_event;
409
409}; 410};
410 411
411/* Can be overridden */ 412/* Can be overridden */
diff --git a/rt-graph.c b/rt-graph.c
index 06fb6ab..5b8c759 100644
--- a/rt-graph.c
+++ b/rt-graph.c
@@ -1,7 +1,7 @@
1#include "rt-graph.h" 1#include "rt-graph.h"
2#include "trace-hash.h" 2#include "trace-hash.h"
3 3
4#define DEBUG_LEVEL 1 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 { \
@@ -12,6 +12,72 @@
12#define dprintf(l, x...) do { if (0) printf(x); } while (0) 12#define dprintf(l, x...) do { if (0) printf(x); } while (0)
13#endif 13#endif
14 14
15static guint get_event_hash_key(gint eid)
16{
17 return trace_hash(eid) % TS_HASH_SIZE;
18}
19
20struct format_field* find_ts_hash(struct ts_list **events,
21 gint key, gint eid)
22{
23 struct ts_list *list;
24 for (list = events[key]; list; list = list->next) {
25 if (list->eid == eid)
26 return list->ts_field;
27 }
28 return NULL;
29}
30
31/*
32 * Return format field for @eid, caching its location if this is the first try
33 */
34static struct format_field* add_ts_hash(struct ts_list **events, gint eid, gint key,
35 struct pevent *pevent, struct record *record)
36{
37 struct ts_list *list;
38 struct format_field *field;
39 struct event_format *event;
40
41 event = pevent_find_event(pevent, eid);
42 if (!event)
43 die("Could not find event %d for record!\n", eid);
44 field = pevent_find_field(event, RT_TS_FIELD);
45
46 list = malloc_or_die(sizeof(*list));
47 list->eid = eid;
48 list->next = events[key];
49 list->ts_field = field;
50 events[key] = list;
51
52 return field;
53}
54
55/**
56 * rt_graph_check_any - parse timestamp of any record
57 * @epid: set to the event's task PID
58 * @rt_ts: set to the event's real-time timestamp
59 */
60void rt_graph_check_any(struct rt_graph_info *rtinfo,
61 struct pevent *pevent, struct record *record,
62 gint *epid, unsigned long long *ts)
63{
64 guint key, eid;
65 struct format_field *field;
66
67 eid = pevent_data_type(pevent, record);
68 key = get_event_hash_key(eid);
69 field = find_ts_hash(rtinfo->events, key, eid);
70
71 if (!field)
72 field = add_ts_hash(rtinfo->events, eid, key, pevent, record);
73
74 *epid = pevent_data_pid(pevent, record);
75 pevent_read_number_field(field, record->data, ts);
76
77 dprintf(3, "Read (%d) record for task %d at %llu\n",
78 eid, *epid, *ts);
79}
80
15/** 81/**
16 * rt_graph_check_task_param - check for litmus_task_param record 82 * rt_graph_check_task_param - check for litmus_task_param record
17 * Return 1 and @pid, @wcet, and @period if the record matches 83 * Return 1 and @pid, @wcet, and @period if the record matches
@@ -63,88 +129,88 @@ int rt_graph_check_task_param(struct rt_graph_info *rtinfo,
63} 129}
64 130
65/** 131/**
66 * rt_graph_check_task_switch_to - check for litmus_task_switch_to record 132 * rt_graph_check_switch_to - check for litmus_switch_to record
67 * Return 1 and @pid, @job, and @when if the record matches 133 * Return 1 and @pid, @job, and @ts if the record matches
68 */ 134 */
69int rt_graph_check_task_switch_to(struct rt_graph_info *rtinfo, 135int rt_graph_check_switch_to(struct rt_graph_info *rtinfo,
70 struct pevent *pevent, struct record *record, 136 struct pevent *pevent, struct record *record,
71 gint *pid, gint *job, 137 gint *pid, gint *job,
72 unsigned long long *when) 138 unsigned long long *ts)
73{ 139{
74 struct event_format *event; 140 struct event_format *event;
75 unsigned long long val; 141 unsigned long long val;
76 gint id; 142 gint id;
77 int ret = 0; 143 int ret = 0;
78 144
79 if (rtinfo->task_switch_to_id < 0) { 145 if (rtinfo->switch_to_id < 0) {
80 event = pevent_find_event_by_name(pevent, "litmus", 146 event = pevent_find_event_by_name(pevent, "litmus",
81 "litmus_task_switch_to"); 147 "litmus_switch_to");
82 if (!event) 148 if (!event)
83 goto out; 149 goto out;
84 rtinfo->task_switch_to_id = event->id; 150 rtinfo->switch_to_id = event->id;
85 dprintf(2, "Found task_switch_to id %d\n", event->id); 151 dprintf(2, "Found switch_to id %d\n", event->id);
86 rtinfo->switch_to_pid_field = pevent_find_field(event, "pid"); 152 rtinfo->switch_to_pid_field = pevent_find_field(event, "pid");
87 rtinfo->switch_to_job_field = pevent_find_field(event, "job"); 153 rtinfo->switch_to_job_field = pevent_find_field(event, "job");
88 rtinfo->switch_to_when_field = pevent_find_field(event, "when"); 154 rtinfo->switch_to_ts_field = pevent_find_field(event, RT_TS_FIELD);
89 } 155 }
90 156
91 id = pevent_data_type(pevent, record); 157 id = pevent_data_type(pevent, record);
92 if (id == rtinfo->task_switch_to_id) { 158 if (id == rtinfo->switch_to_id) {
93 pevent_read_number_field(rtinfo->switch_to_pid_field, 159 pevent_read_number_field(rtinfo->switch_to_pid_field,
94 record->data, &val); 160 record->data, &val);
95 *pid = val; 161 *pid = val;
96 pevent_read_number_field(rtinfo->switch_to_job_field, 162 pevent_read_number_field(rtinfo->switch_to_job_field,
97 record->data, &val); 163 record->data, &val);
98 *job = val; 164 *job = val;
99 pevent_read_number_field(rtinfo->switch_to_when_field, 165 pevent_read_number_field(rtinfo->switch_to_ts_field,
100 record->data, when); 166 record->data, ts);
101 ret = 1; 167 ret = 1;
102 dprintf(3, "Read task_switch_to (%d) record for job %d:%d, " 168 dprintf(3, "Read switch_to (%d) record for job %d:%d, "
103 "when: %llu\n", id, *pid, *job, *when); 169 "ts: %llu\n", id, *pid, *job, *ts);
104 } 170 }
105 out: 171 out:
106 return ret; 172 return ret;
107} 173}
108 174
109/** 175/**
110 * rt_graph_check_task_switch_away - check for litmus_task_switch_away record 176 * rt_graph_check_switch_away - check for litmus_switch_away record
111 * Return 1 and @pid, @job, and @when if the record matches 177 * Return 1 and @pid, @job, and @ts if the record matches
112 */ 178 */
113int rt_graph_check_task_switch_away(struct rt_graph_info *rtinfo, 179int rt_graph_check_switch_away(struct rt_graph_info *rtinfo,
114 struct pevent *pevent, struct record *record, 180 struct pevent *pevent, struct record *record,
115 gint *pid, gint *job, 181 gint *pid, gint *job,
116 unsigned long long *when) 182 unsigned long long *ts)
117{ 183{
118 struct event_format *event; 184 struct event_format *event;
119 unsigned long long val; 185 unsigned long long val;
120 gint id; 186 gint id;
121 int ret = 0; 187 int ret = 0;
122 188
123 if (rtinfo->task_switch_away_id < 0) { 189 if (rtinfo->switch_away_id < 0) {
124 event = pevent_find_event_by_name(pevent, "litmus", 190 event = pevent_find_event_by_name(pevent, "litmus",
125 "litmus_task_switch_away"); 191 "litmus_switch_away");
126 if (!event) 192 if (!event)
127 goto out; 193 goto out;
128 rtinfo->task_switch_away_id = event->id; 194 rtinfo->switch_away_id = event->id;
129 dprintf(2, "Found task_switch_away id %d\n", event->id); 195 dprintf(2, "Found switch_away id %d\n", event->id);
130 rtinfo->switch_away_pid_field = pevent_find_field(event, "pid"); 196 rtinfo->switch_away_pid_field = pevent_find_field(event, "pid");
131 rtinfo->switch_away_job_field = pevent_find_field(event, "job"); 197 rtinfo->switch_away_job_field = pevent_find_field(event, "job");
132 rtinfo->switch_away_when_field = pevent_find_field(event, "when"); 198 rtinfo->switch_away_ts_field = pevent_find_field(event, RT_TS_FIELD);
133 } 199 }
134 200
135 id = pevent_data_type(pevent, record); 201 id = pevent_data_type(pevent, record);
136 if (id == rtinfo->task_switch_away_id) { 202 if (id == rtinfo->switch_away_id) {
137 pevent_read_number_field(rtinfo->switch_away_pid_field, 203 pevent_read_number_field(rtinfo->switch_away_pid_field,
138 record->data, &val); 204 record->data, &val);
139 *pid = val; 205 *pid = val;
140 pevent_read_number_field(rtinfo->switch_away_job_field, 206 pevent_read_number_field(rtinfo->switch_away_job_field,
141 record->data, &val); 207 record->data, &val);
142 *job = val; 208 *job = val;
143 pevent_read_number_field(rtinfo->switch_away_when_field, 209 pevent_read_number_field(rtinfo->switch_away_ts_field,
144 record->data, when); 210 record->data, ts);
145 ret = 1; 211 ret = 1;
146 dprintf(3, "Read task_switch_away (%d) record for job %d:%d, " 212 dprintf(3, "Read switch_away (%d) record for job %d:%d, "
147 "when: %llu\n", id, *pid, *job, *when); 213 "ts: %llu\n", id, *pid, *job, *ts);
148 } 214 }
149 out: 215 out:
150 return ret; 216 return ret;
@@ -156,7 +222,8 @@ int rt_graph_check_task_switch_away(struct rt_graph_info *rtinfo,
156 */ 222 */
157int rt_graph_check_task_release(struct rt_graph_info *rtinfo, 223int rt_graph_check_task_release(struct rt_graph_info *rtinfo,
158 struct pevent *pevent, struct record *record, 224 struct pevent *pevent, struct record *record,
159 gint *pid, gint *job, unsigned long long *release, 225 gint *pid, gint *job,
226 unsigned long long *release,
160 unsigned long long *deadline) 227 unsigned long long *deadline)
161{ 228{
162 struct event_format *event; 229 struct event_format *event;
@@ -191,7 +258,8 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo,
191 record->data, deadline); 258 record->data, deadline);
192 ret = 1; 259 ret = 1;
193 dprintf(3, "Read task_release (%d) record for job %d:%d, " 260 dprintf(3, "Read task_release (%d) record for job %d:%d, "
194 "dead: %llu\n", id, *pid, *job, *deadline); 261 "release: %llu, dead: %llu\n", id, *pid, *job, *release,
262 *deadline);
195 } 263 }
196 out: 264 out:
197 return ret; 265 return ret;
@@ -203,7 +271,7 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo,
203 */ 271 */
204int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, 272int rt_graph_check_task_completion(struct rt_graph_info *rtinfo,
205 struct pevent *pevent, struct record *record, 273 struct pevent *pevent, struct record *record,
206 gint *pid, gint *job, unsigned long long *when) 274 gint *pid, gint *job, unsigned long long *ts)
207{ 275{
208 struct event_format *event; 276 struct event_format *event;
209 unsigned long long val; 277 unsigned long long val;
@@ -219,7 +287,7 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo,
219 dprintf(2, "Found task_completion id %d\n", event->id); 287 dprintf(2, "Found task_completion id %d\n", event->id);
220 rtinfo->completion_pid_field = pevent_find_field(event, "pid"); 288 rtinfo->completion_pid_field = pevent_find_field(event, "pid");
221 rtinfo->completion_job_field = pevent_find_field(event, "job"); 289 rtinfo->completion_job_field = pevent_find_field(event, "job");
222 rtinfo->completion_when_field = pevent_find_field(event, "when"); 290 rtinfo->completion_ts_field = pevent_find_field(event, RT_TS_FIELD);
223 } 291 }
224 292
225 id = pevent_data_type(pevent, record); 293 id = pevent_data_type(pevent, record);
@@ -230,11 +298,11 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo,
230 pevent_read_number_field(rtinfo->completion_job_field, 298 pevent_read_number_field(rtinfo->completion_job_field,
231 record->data, &val); 299 record->data, &val);
232 *job = val; 300 *job = val;
233 pevent_read_number_field(rtinfo->completion_when_field, 301 pevent_read_number_field(rtinfo->completion_ts_field,
234 record->data, when); 302 record->data, ts);
235 ret = 1; 303 ret = 1;
236 dprintf(3, "Read task_completion (%d) record for job %d:%d\n", 304 dprintf(3, "Read task_completion (%d) record for job %d:%d "
237 id, *pid, *job); 305 "ts: %llu\n", id, *pid, *job, *ts);
238 } 306 }
239 out: 307 out:
240 return ret; 308 return ret;
@@ -246,7 +314,7 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo,
246 */ 314 */
247int rt_graph_check_task_block(struct rt_graph_info *rtinfo, 315int rt_graph_check_task_block(struct rt_graph_info *rtinfo,
248 struct pevent *pevent, struct record *record, 316 struct pevent *pevent, struct record *record,
249 gint *pid, unsigned long long *when) 317 gint *pid, unsigned long long *ts)
250{ 318{
251 struct event_format *event; 319 struct event_format *event;
252 unsigned long long val; 320 unsigned long long val;
@@ -261,7 +329,7 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo,
261 dprintf(2, "Found task_block id %d\n", event->id); 329 dprintf(2, "Found task_block id %d\n", event->id);
262 rtinfo->task_block_id = event->id; 330 rtinfo->task_block_id = event->id;
263 rtinfo->block_pid_field = pevent_find_field(event, "pid"); 331 rtinfo->block_pid_field = pevent_find_field(event, "pid");
264 rtinfo->block_when_field = pevent_find_field(event, "when"); 332 rtinfo->block_ts_field = pevent_find_field(event, RT_TS_FIELD);
265 } 333 }
266 334
267 id = pevent_data_type(pevent, record); 335 id = pevent_data_type(pevent, record);
@@ -269,8 +337,8 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo,
269 pevent_read_number_field(rtinfo->block_pid_field, 337 pevent_read_number_field(rtinfo->block_pid_field,
270 record->data, &val); 338 record->data, &val);
271 *pid = val; 339 *pid = val;
272 pevent_read_number_field(rtinfo->block_when_field, 340 pevent_read_number_field(rtinfo->block_ts_field,
273 record->data, when); 341 record->data, ts);
274 ret = 1; 342 ret = 1;
275 dprintf(3, "Read task_block (%d) record for task %d\n", 343 dprintf(3, "Read task_block (%d) record for task %d\n",
276 id, *pid); 344 id, *pid);
@@ -285,7 +353,7 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo,
285 */ 353 */
286int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, 354int rt_graph_check_task_resume(struct rt_graph_info *rtinfo,
287 struct pevent *pevent, struct record *record, 355 struct pevent *pevent, struct record *record,
288 gint *pid, unsigned long long *when) 356 gint *pid, unsigned long long *ts)
289{ 357{
290 struct event_format *event; 358 struct event_format *event;
291 unsigned long long val; 359 unsigned long long val;
@@ -300,7 +368,7 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo,
300 dprintf(2, "Found task_resume id %d\n", event->id); 368 dprintf(2, "Found task_resume id %d\n", event->id);
301 rtinfo->task_resume_id = event->id; 369 rtinfo->task_resume_id = event->id;
302 rtinfo->resume_pid_field = pevent_find_field(event, "pid"); 370 rtinfo->resume_pid_field = pevent_find_field(event, "pid");
303 rtinfo->resume_when_field = pevent_find_field(event, "when"); 371 rtinfo->resume_ts_field = pevent_find_field(event, RT_TS_FIELD);
304 } 372 }
305 373
306 id = pevent_data_type(pevent, record); 374 id = pevent_data_type(pevent, record);
@@ -308,8 +376,8 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo,
308 pevent_read_number_field(rtinfo->resume_pid_field, 376 pevent_read_number_field(rtinfo->resume_pid_field,
309 record->data, &val); 377 record->data, &val);
310 *pid = val; 378 *pid = val;
311 pevent_read_number_field(rtinfo->resume_when_field, 379 pevent_read_number_field(rtinfo->resume_ts_field,
312 record->data, when); 380 record->data, ts);
313 ret = 1; 381 ret = 1;
314 dprintf(3, "Read task_resume (%d) record for task %d\n", 382 dprintf(3, "Read task_resume (%d) record for task %d\n",
315 id, *pid); 383 id, *pid);
@@ -325,8 +393,8 @@ void init_rt_event_cache(struct rt_graph_info *rtinfo)
325{ 393{
326 dprintf(1, "Initializing RT event cache\n"); 394 dprintf(1, "Initializing RT event cache\n");
327 rtinfo->task_param_id = -1; 395 rtinfo->task_param_id = -1;
328 rtinfo->task_switch_to_id = -1; 396 rtinfo->switch_to_id = -1;
329 rtinfo->task_switch_away = -1; 397 rtinfo->switch_away_id = -1;
330 rtinfo->task_release_id = -1; 398 rtinfo->task_release_id = -1;
331 rtinfo->task_completion_id = -1; 399 rtinfo->task_completion_id = -1;
332 rtinfo->task_block_id = -1; 400 rtinfo->task_block_id = -1;
@@ -338,11 +406,11 @@ void init_rt_event_cache(struct rt_graph_info *rtinfo)
338 406
339 rtinfo->switch_to_pid_field = NULL; 407 rtinfo->switch_to_pid_field = NULL;
340 rtinfo->switch_to_job_field = NULL; 408 rtinfo->switch_to_job_field = NULL;
341 rtinfo->switch_to_when_field = NULL; 409 rtinfo->switch_to_ts_field = NULL;
342 410
343 rtinfo->switch_away_pid_field = NULL; 411 rtinfo->switch_away_pid_field = NULL;
344 rtinfo->switch_away_job_field = NULL; 412 rtinfo->switch_away_job_field = NULL;
345 rtinfo->switch_away_when_field = NULL; 413 rtinfo->switch_away_ts_field = NULL;
346 414
347 rtinfo->release_pid_field = NULL; 415 rtinfo->release_pid_field = NULL;
348 rtinfo->release_job_field = NULL; 416 rtinfo->release_job_field = NULL;
@@ -351,11 +419,11 @@ void init_rt_event_cache(struct rt_graph_info *rtinfo)
351 419
352 rtinfo->completion_pid_field = NULL; 420 rtinfo->completion_pid_field = NULL;
353 rtinfo->completion_job_field = NULL; 421 rtinfo->completion_job_field = NULL;
354 rtinfo->completion_when_field = NULL; 422 rtinfo->completion_ts_field = NULL;
355 423
356 rtinfo->block_pid_field = NULL; 424 rtinfo->block_pid_field = NULL;
357 rtinfo->block_when_field = NULL; 425 rtinfo->block_ts_field = NULL;
358 426
359 rtinfo->resume_pid_field = NULL; 427 rtinfo->resume_pid_field = NULL;
360 rtinfo->resume_when_field = NULL; 428 rtinfo->resume_ts_field = NULL;
361} 429}
diff --git a/rt-graph.h b/rt-graph.h
index 8fbe6f3..be9aa44 100644
--- a/rt-graph.h
+++ b/rt-graph.h
@@ -6,6 +6,10 @@
6#include "trace-cmd.h" 6#include "trace-cmd.h"
7#include "rt-plot-task.h" 7#include "rt-plot-task.h"
8 8
9#define RT_TS_FIELD "__rt_ts"
10#define TS_HASH_SIZE 6
11struct ts_list;
12
9struct rt_graph_info { 13struct rt_graph_info {
10 14
11 /* List of all real-time tasks */ 15 /* List of all real-time tasks */
@@ -19,15 +23,15 @@ struct rt_graph_info {
19 struct format_field *param_wcet_field; 23 struct format_field *param_wcet_field;
20 struct format_field *param_period_field; 24 struct format_field *param_period_field;
21 25
22 gint task_switch_to_id; 26 gint switch_to_id;
23 struct format_field *switch_to_pid_field; 27 struct format_field *switch_to_pid_field;
24 struct format_field *switch_to_job_field; 28 struct format_field *switch_to_job_field;
25 struct format_field *switch_to_when_field; 29 struct format_field *switch_to_ts_field;
26 30
27 gint task_switch_away_id; 31 gint switch_away_id;
28 struct format_field *switch_to_pid_field; 32 struct format_field *switch_away_pid_field;
29 struct format_field *switch_to_job_field; 33 struct format_field *switch_away_job_field;
30 struct format_field *switch_to_when_field; 34 struct format_field *switch_away_ts_field;
31 35
32 gint task_release_id; 36 gint task_release_id;
33 struct format_field *release_pid_field; 37 struct format_field *release_pid_field;
@@ -38,28 +42,40 @@ struct rt_graph_info {
38 gint task_completion_id; 42 gint task_completion_id;
39 struct format_field *completion_pid_field; 43 struct format_field *completion_pid_field;
40 struct format_field *completion_job_field; 44 struct format_field *completion_job_field;
41 struct format_field *completion_when_field; 45 struct format_field *completion_ts_field;
42 46
43 gint task_block_id; 47 gint task_block_id;
44 struct format_field *block_pid_field; 48 struct format_field *block_pid_field;
45 struct format_field *block_when_field; 49 struct format_field *block_ts_field;
46 50
47 gint task_resume_id; 51 gint task_resume_id;
48 struct format_field *resume_pid_field; 52 struct format_field *resume_pid_field;
49 struct format_field *resume_when_field; 53 struct format_field *resume_ts_field;
54
55 /* Cache of ts fields for new events */
56 struct ts_list *events[TS_HASH_SIZE];
57};
58
59struct ts_list {
60 struct ts_list *next;
61 gint eid;
62 struct format_field *ts_field;
50}; 63};
51 64
52/* Event parsers */ 65/* Event parsers */
66void rt_graph_check_any(struct rt_graph_info *rtinfo,
67 struct pevent *pevent, struct record *record,
68 gint *epid, unsigned long long *ts);
53int rt_graph_check_task_param(struct rt_graph_info *rtinfo, struct pevent *pevent, 69int rt_graph_check_task_param(struct rt_graph_info *rtinfo, struct pevent *pevent,
54 struct record *record, gint *pid, 70 struct record *record, gint *pid,
55 unsigned long long *wcet, 71 unsigned long long *wcet,
56 unsigned long long *period); 72 unsigned long long *period);
57int rt_graph_check_task_switch_to(struct rt_graph_info *rtinfo, struct pevent *pevent, 73int rt_graph_check_switch_to(struct rt_graph_info *rtinfo, struct pevent *pevent,
58 struct record *record, gint *pid, gint *job, 74 struct record *record, gint *pid, gint *job,
59 unsigned long long *when); 75 unsigned long long *when);
60int rt_graph_check_task_switch_away(struct rt_graph_info *rtinfo, struct pevent *pevent, 76int rt_graph_check_switch_away(struct rt_graph_info *rtinfo, struct pevent *pevent,
61 struct record *record, gint *pid, gint *job, 77 struct record *record, gint *pid, gint *job,
62 unsigned long long *when); 78 unsigned long long *when);
63int rt_graph_check_task_release(struct rt_graph_info *rtinfo, struct pevent *pevent, 79int rt_graph_check_task_release(struct rt_graph_info *rtinfo, struct pevent *pevent,
64 struct record *record, gint *pid, gint *job, 80 struct record *record, gint *pid, gint *job,
65 unsigned long long *release, 81 unsigned long long *release,
diff --git a/rt-plot-task.c b/rt-plot-task.c
index d1af3d6..8be1888 100644
--- a/rt-plot-task.c
+++ b/rt-plot-task.c
@@ -2,26 +2,30 @@
2 2
3#define LLABEL 30 3#define LLABEL 30
4 4
5#define DEBUG_LEVEL 4
6#if DEBUG_LEVEL > 0
7#define dprintf(l, x...) \
8 do { \
9 if (l <= DEBUG_LEVEL) \
10 printf(x); \
11 } while (0)
12#else
13#define dprintf(l, x...) do { if (0) printf(x); } while (0)
14#endif
15
5/* Ok to do it this way as long as it remains single threaded */ 16/* Ok to do it this way as long as it remains single threaded */
6static void update_job(struct rt_task_info *rtt_info, int job) 17static void update_job(struct rt_task_info *rtt_info, int job)
7{ 18{
8 if (job < rtt_info->last_job) { 19 if (job < rtt_info->last_job) {
9 die("Inconsistent job state for %d:%d -> %d\n", 20 die("Inconsistent job state for %d:%d -> %d\n",
10 rtt_info->base.pid, rtt_info->last_job, job); 21 rtt_info->base.pid, rtt_info->last_job, job);
11 } 22 } else if (job > rtt_info->last_job) {
12 if (job > rtt_info->last_job) {
13 rtt_info->last_job = job; 23 rtt_info->last_job = job;
14 snprintf(rtt_info->label, LLABEL, "%d:%d", 24 snprintf(rtt_info->label, LLABEL, "%d:%d",
15 rtt_info->base.pid, rtt_info->last_job); 25 rtt_info->base.pid, rtt_info->last_job);
16 } 26 }
17} 27}
18 28
19static inline void create_job_label(char *label, int pid, int job)
20{
21 label = malloc_or_die(20);
22 snprintf(label, 20, "%d:%d", pid, job);
23}
24
25static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info, 29static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info,
26 struct record *record, struct plot_info *info) 30 struct record *record, struct plot_info *info)
27{ 31{
@@ -35,10 +39,10 @@ static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info,
35 match = rt_graph_check_task_param(&ginfo->rtinfo, ginfo->pevent, 39 match = rt_graph_check_task_param(&ginfo->rtinfo, ginfo->pevent,
36 record, &pid, &wcet, &period); 40 record, &pid, &wcet, &period);
37 if (match && pid == rtt_info->base.pid) { 41 if (match && pid == rtt_info->base.pid) {
42 update_job(rtt_info, 0);
38 rtt_info->wcet = wcet; 43 rtt_info->wcet = wcet;
39 rtt_info->period = period; 44 rtt_info->period = period;
40 rtt_info->params_found = TRUE; 45 rtt_info->params_found = TRUE;
41 update_job(rtt_info, 0);
42 ret = 1; 46 ret = 1;
43 } 47 }
44 out: 48 out:
@@ -56,6 +60,7 @@ static int try_release(struct graph_info *ginfo, struct rt_task_info *rtt_info,
56 record, &pid, &job, 60 record, &pid, &job,
57 &release, &deadline); 61 &release, &deadline);
58 if (match && pid == rtt_info->base.pid) { 62 if (match && pid == rtt_info->base.pid) {
63 update_job(rtt_info, job);
59 info->release = TRUE; 64 info->release = TRUE;
60 info->rtime = release; 65 info->rtime = release;
61 info->rlabel = rtt_info->label; 66 info->rlabel = rtt_info->label;
@@ -64,7 +69,6 @@ static int try_release(struct graph_info *ginfo, struct rt_task_info *rtt_info,
64 info->dtime = deadline; 69 info->dtime = deadline;
65 info->dlabel = rtt_info->label; 70 info->dlabel = rtt_info->label;
66 71
67 update_job(rtt_info, job);
68 ret = 1; 72 ret = 1;
69 } 73 }
70 return ret; 74 return ret;
@@ -75,15 +79,15 @@ static int try_completion(struct graph_info *ginfo,
75 struct record *record, struct plot_info *info) 79 struct record *record, struct plot_info *info)
76{ 80{
77 int pid, job, match, ret = 0; 81 int pid, job, match, ret = 0;
78 unsigned long long when; 82 unsigned long long ts;
79 83
80 match = rt_graph_check_task_completion(&ginfo->rtinfo, ginfo->pevent, 84 match = rt_graph_check_task_completion(&ginfo->rtinfo, ginfo->pevent,
81 record, &pid, &job, &when); 85 record, &pid, &job, &ts);
82 if (match && pid == rtt_info->base.pid) { 86 if (match && pid == rtt_info->base.pid) {
87 update_job(rtt_info, job);
83 info->completion = TRUE; 88 info->completion = TRUE;
84 info->ctime = when; 89 info->ctime = ts;
85 info->clabel = rtt_info->label; 90 info->clabel = rtt_info->label;
86 update_job(rtt_info, job);
87 ret = 1; 91 ret = 1;
88 } 92 }
89 return ret; 93 return ret;
@@ -93,12 +97,12 @@ static int try_block(struct graph_info *ginfo, struct rt_task_info *rtt_info,
93 struct record *record, struct plot_info *info) 97 struct record *record, struct plot_info *info)
94{ 98{
95 int pid, match, ret = 0; 99 int pid, match, ret = 0;
96 unsigned long long when; 100 unsigned long long ts;
97 101
98 match = rt_graph_check_task_block(&ginfo->rtinfo, ginfo->pevent, 102 match = rt_graph_check_task_block(&ginfo->rtinfo, ginfo->pevent,
99 record, &pid, &when); 103 record, &pid, &ts);
100 if (match && pid == rtt_info->base.pid) { 104 if (match && pid == rtt_info->base.pid) {
101 rtt_info->block_time = when; 105 rtt_info->block_time = ts;
102 ret = 1; 106 ret = 1;
103 } 107 }
104 return ret; 108 return ret;
@@ -108,92 +112,106 @@ static int try_resume(struct graph_info *ginfo, struct rt_task_info *rtt_info,
108 struct record *record, struct plot_info *info) 112 struct record *record, struct plot_info *info)
109{ 113{
110 int pid, match, ret = 0; 114 int pid, match, ret = 0;
111 unsigned long long when; 115 unsigned long long ts;
112 116
113 match = rt_graph_check_task_resume(&ginfo->rtinfo, ginfo->pevent, 117 match = rt_graph_check_task_resume(&ginfo->rtinfo, ginfo->pevent,
114 record, &pid, &when); 118 record, &pid, &ts);
115 if (match && pid == rtt_info->base.pid) { 119 if (match && pid == rtt_info->base.pid) {
116 rtt_info->block_time = when;
117 info->box = TRUE; 120 info->box = TRUE;
118 info->bcolor = 0x0; 121 info->bcolor = 0x0;
119 info->bfill = TRUE; 122 info->bfill = TRUE;
120 info->bthin = TRUE; 123 info->bthin = TRUE;
121 info->bstart = rtt_info->block_time; 124 info->bstart = rtt_info->block_time;
122 info->bend = when; 125 info->bend = ts;
123 126
124 rtt_info->block_time = -1; 127 rtt_info->block_time = 0ULL;
125 128
126 ret = 1; 129 ret = 1;
127 } 130 }
128 return ret; 131 return ret;
129} 132}
130 133
131static int try_other(struct graph_info *ginfo, struct rt_task_info *rtt_info, 134static unsigned long long
132 struct record *record, struct plot_info *info) 135try_switch_away(struct graph_info *ginfo, struct rt_task_info *rtt_info,
136 struct record *record, struct plot_info *info)
133{ 137{
134 int pid, is_sched, is_wakeup, rec_pid, sched_pid, match, ret = 0; 138 int job, pid, match, ret = 0;
135 struct task_plot_info *task_info = &rtt_info->base; 139 unsigned long long ts;
140
141 match = rt_graph_check_switch_away(&ginfo->rtinfo, ginfo->pevent,
142 record, &pid, &job, &ts);
143 if (match && pid == rtt_info->base.pid) {
144 update_job(rtt_info, job);
145
146 if (rtt_info->run_time && rtt_info->run_time < ts) {
147 dprintf(3, "Box for %d:%d, %llu to %llu on CPU %d\n",
148 rtt_info->base.pid, rtt_info->last_job,
149 rtt_info->run_time, ts, rtt_info->last_cpu);
150 info->box = TRUE;
151 info->bcolor = hash_cpu(rtt_info->last_cpu);
152 info->bfill = TRUE;
153 info->bstart = rtt_info->run_time;
154 info->bend = ts;
155 info->blabel = rtt_info->label;
156 }
157
158 rtt_info->run_time = 0ULL;
159 rtt_info->last_cpu = -1;
136 160
137 pid = task_info->pid;
138 match = record_matches_pid(ginfo, record, pid, &rec_pid,
139 &sched_pid, &is_sched, &is_wakeup);
140 if (match) {
141 info->line = TRUE;
142 info->lcolor = hash_pid(rec_pid);
143 info->ltime = record->ts;
144 ret = 1; 161 ret = 1;
162 }
163 return ret;
164}
145 165
146 update_last_task_record(ginfo, task_info, record); 166static int try_switch_to(struct graph_info *ginfo, struct rt_task_info *rtt_info,
167 struct record *record, struct plot_info *info)
168{
169 int job, pid, match, ret = 0;
170 unsigned long long ts;
147 171
148 if (is_wakeup) { 172 match = rt_graph_check_switch_to(&ginfo->rtinfo, ginfo->pevent,
149 /* Another task is running on this CPU now */ 173 record, &pid, &job, &ts);
150 info->ltime = hash_pid(rec_pid); 174 if (match && pid == rtt_info->base.pid) {
151 if (task_info->last_cpu == record->cpu) { 175 update_job(rtt_info, job);
152 info->box = TRUE;
153 info->bcolor = hash_cpu(task_info->last_cpu);
154 info->bstart = task_info->last_time;
155 info->bend = record->ts;
156 task_info->last_cpu = -1;
157 }
158 goto out;
159 }
160 176
161 if (task_info->last_cpu != record->cpu) { 177 rtt_info->run_time = ts;
162 /* Switched cpus */ 178 rtt_info->last_cpu = record->cpu;
163 if (task_info->last_cpu >= 0) {
164 info->box = TRUE;
165 info->bcolor = hash_cpu(task_info->last_cpu);
166 info->bstart = task_info->last_time;
167 info->bend = record->ts;
168 }
169 task_info->last_time = record->ts;
170 }
171 179
172 task_info->last_cpu = record->cpu; 180 info->line = TRUE;
173 if (is_sched) { 181 info->lcolor = hash_pid(record->cpu);
174 if (rec_pid != pid) { 182 info->ltime = ts;
175 /* Scheduled in */ 183
176 task_info->last_cpu = record->cpu; 184 dprintf(3, "Switching to %d:%d at %llu on CPU %d\n",
177 task_info->last_time = record->ts; 185 rtt_info->base.pid, rtt_info->last_job,
178 } else if (!info->box) { 186 ts, rtt_info->last_cpu);
179 /* Scheduled out */ 187
180 info->box = TRUE; 188 ret = 1;
181 info->bcolor = hash_cpu(task_info->last_cpu);
182 info->bstart = task_info->last_time;
183 info->bend = record->ts;
184 task_info->last_cpu = -1;
185 }
186 }
187 } 189 }
188 out: 190 return ret;
189 if (info->box) { 191}
190 info->blabel = rtt_info->label; 192
193static int try_other(struct graph_info *ginfo, struct rt_task_info *rtt_info,
194 struct record *record, struct plot_info *info)
195{
196 int pid, epid, ret = 0;
197 unsigned long long ts;
198 struct task_plot_info *task_info = &rtt_info->base;
199
200 pid = task_info->pid;
201 rt_graph_check_any(&ginfo->rtinfo, ginfo->pevent, record, &epid, &ts);
202
203 if (pid == epid || record->cpu == rtt_info->last_cpu) {
204 info->line = TRUE;
205 info->lcolor = hash_pid(record->cpu);
206 info->ltime = ts;
207 ret = 1;
191 } 208 }
209
192 return ret; 210 return ret;
193} 211}
194 212
195int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, 213static int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot,
196 struct record *record, struct plot_info *info) 214 struct record *record, struct plot_info *info)
197{ 215{
198 struct rt_task_info *rtt_info = plot->private; 216 struct rt_task_info *rtt_info = plot->private;
199 struct task_plot_info *task_info = &rtt_info->base; 217 struct task_plot_info *task_info = &rtt_info->base;
@@ -215,11 +233,13 @@ int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot,
215 return 0; 233 return 0;
216 } 234 }
217 235
218 match = try_param(ginfo, rtt_info, record, info) || 236 match = try_param(ginfo, rtt_info, record, info) ||
219 try_release(ginfo, rtt_info, record, info) || 237 try_switch_away(ginfo, rtt_info, record, info) ||
220 try_completion(ginfo, rtt_info, record, info) || 238 try_switch_to(ginfo, rtt_info, record, info) ||
221 try_block(ginfo, rtt_info, record, info) || 239 try_release(ginfo, rtt_info, record, info) ||
222 try_resume(ginfo, rtt_info, record, info) || 240 try_completion(ginfo, rtt_info, record, info) ||
241 try_block(ginfo, rtt_info, record, info) ||
242 try_resume(ginfo, rtt_info, record, info) ||
223 try_other(ginfo, rtt_info, record, info); 243 try_other(ginfo, rtt_info, record, info);
224 244
225 /* This record is neither on our CPU nor related to us, useless */ 245 /* This record is neither on our CPU nor related to us, useless */
@@ -238,24 +258,15 @@ int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot,
238 free_record(task_info->last_records[cpu]); 258 free_record(task_info->last_records[cpu]);
239 task_info->last_records[cpu] = record; 259 task_info->last_records[cpu] = record;
240 } 260 }
241
242 /* We were on a CPU, now scheduled out */
243 if (task_info->last_cpu >= 0) {
244 info->box = TRUE;
245 info->bcolor = hash_cpu(task_info->last_cpu);
246 info->bstart = task_info->last_time;
247 info->bend = record->ts;
248 task_info->last_cpu = -1;
249 }
250 } else { 261 } else {
251 update_last_task_record(ginfo, task_info, record); 262 update_last_task_record(ginfo, task_info, record);
252 } 263 }
253 out: 264
254 return 1; 265 return 1;
255} 266}
256 267
257void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, 268static void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
258 unsigned long long time) 269 unsigned long long time)
259{ 270{
260 struct rt_task_info *rtt_info = plot->private; 271 struct rt_task_info *rtt_info = plot->private;
261 272
@@ -263,13 +274,15 @@ void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
263 274
264 rtt_info->wcet = 0ULL; 275 rtt_info->wcet = 0ULL;
265 rtt_info->period = 0ULL; 276 rtt_info->period = 0ULL;
277 rtt_info->run_time = 0ULL;
266 rtt_info->block_time = 0ULL; 278 rtt_info->block_time = 0ULL;
279 rtt_info->last_cpu = -1;
267 rtt_info->last_job = -1; 280 rtt_info->last_job = -1;
268 rtt_info->params_found = FALSE; 281 rtt_info->params_found = FALSE;
269 update_job(rtt_info, 0); 282 update_job(rtt_info, 0);
270} 283}
271 284
272void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) 285static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot)
273{ 286{
274 struct rt_task_info *rtt_info = plot->private; 287 struct rt_task_info *rtt_info = plot->private;
275 free(rtt_info->label); 288 free(rtt_info->label);
diff --git a/rt-plot-task.h b/rt-plot-task.h
index a11d347..40971fd 100644
--- a/rt-plot-task.h
+++ b/rt-plot-task.h
@@ -5,10 +5,16 @@
5 5
6struct rt_task_info { 6struct rt_task_info {
7 struct task_plot_info base; 7 struct task_plot_info base;
8
8 unsigned long long wcet; 9 unsigned long long wcet;
9 unsigned long long period; 10 unsigned long long period;
11
12 unsigned long long run_time;
10 unsigned long long block_time; 13 unsigned long long block_time;
14
11 int last_job; 15 int last_job;
16 int last_cpu;
17
12 gboolean params_found; 18 gboolean params_found;
13 char *label; 19 char *label;
14}; 20};