aboutsummaryrefslogtreecommitdiffstats
path: root/rt-graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'rt-graph.c')
-rw-r--r--rt-graph.c705
1 files changed, 553 insertions, 152 deletions
diff --git a/rt-graph.c b/rt-graph.c
index 8b9c360..aba22a9 100644
--- a/rt-graph.c
+++ b/rt-graph.c
@@ -1,7 +1,9 @@
1#include <stdio.h>
2#include <string.h.
1#include "trace-graph.h" 3#include "trace-graph.h"
2#include "trace-hash.h" 4#include "trace-hash.h"
3 5
4#define DEBUG_LEVEL 3 6#define DEBUG_LEVEL 0
5#if DEBUG_LEVEL > 0 7#if DEBUG_LEVEL > 0
6#define dprintf(l, x...) \ 8#define dprintf(l, x...) \
7 do { \ 9 do { \
@@ -17,6 +19,47 @@ static guint get_event_hash_key(gint eid)
17 return trace_hash(eid) % TS_HASH_SIZE; 19 return trace_hash(eid) % TS_HASH_SIZE;
18} 20}
19 21
22static int get_container_key(gint cid)
23{
24 return trace_hash(cid) % CONT_HASH_SIZE;
25}
26
27/*
28 * Returns string value stored in @field.
29 */
30static char* read_string_field(struct format_field *field,
31 struct record *record)
32{
33 char *name, *loc;
34
35 loc = (char*)(record->data + field->offset);
36 name = malloc_or_die(field->size);
37 snprintf(name, field->size, "%s", loc);
38 return name;
39}
40
41#define __FIELD(type, name) type##_##name##_field
42#define FIELD(rtg, type, name) rtg->__FIELD(type, name)
43#define STORE_FIELD(rtg, e, type, name) \
44 do { \
45 FIELD(rtg, type, name) = pevent_find_field(e, #name); \
46 } while (0)
47#define LOAD_LONG(rtg, r, type, name, v) \
48 do { \
49 pevent_read_number_field(FIELD(rtg, type, name), \
50 r->data, v); \
51 } while (0)
52#define LOAD_INT(rtg, r, type, name, v) \
53 do { \
54 unsigned long long val; \
55 LOAD_LONG(rtg, r, type, name, &val); \
56 *v = val; \
57 } while (0)
58#define LOAD_STRING(rtg, r, type, name, v) \
59 do { \
60 *v = read_string_field(FIELD(rtg, type, name), r); \
61 } while (0)
62
20/* 63/*
21 * Returns cached field for @eid at @key. 64 * Returns cached field for @eid at @key.
22 */ 65 */
@@ -36,7 +79,8 @@ struct format_field* find_ts_hash(struct ts_list **events,
36 */ 79 */
37static struct format_field* 80static struct format_field*
38add_ts_hash(struct ts_list **events, gint eid, gint key, 81add_ts_hash(struct ts_list **events, gint eid, gint key,
39 struct pevent *pevent, struct record *record) 82 struct pevent *pevent,
83 struct record *record)
40{ 84{
41 struct ts_list *list; 85 struct ts_list *list;
42 struct format_field *field; 86 struct format_field *field;
@@ -56,17 +100,93 @@ add_ts_hash(struct ts_list **events, gint eid, gint key,
56 return field; 100 return field;
57} 101}
58 102
103/*
104 * Return container for @cid and @key, if present.
105 */
106static struct cont_list*
107find_container(struct cont_list **conts, gint cid, gint key)
108{
109 struct cont_list *list;
110 for (list = conts[key]; list; list = list->next) {
111 if (list->cid == cid)
112 return list;
113 }
114 return NULL;
115}
116
117/*
118 * Add and return container with @cid and @name to @conts.
119 */
120static struct cont_list*
121add_container(struct cont_list **conts, gint cid, char *name)
122{
123 int key;
124 struct cont_list *list;
125
126 key = get_container_key(cid);
127
128 list = find_container(conts, cid, key);
129 if (!list) {
130 list = malloc_or_die(sizeof(*list));
131 list->cid = cid;
132 list->name = name;
133 list->vcpus = NULL;
134
135 list->next = conts[key];
136 conts[key] = list;
137 } else {
138 free(name);
139 }
140 return list;
141}
142
143/*
144 * Add and return server with @sid to container @cid.
145 */
146static struct vcpu_list*
147add_vcpu(struct cont_list **conts,
148 int cid, int sid,
149 unsigned long long wcet, unsigned long long period)
150{
151 int key;
152 struct cont_list *clist;
153 struct vcpu_list *vlist;
154
155 key = get_container_key(cid);
156 clist = find_container(conts, cid, key);
157 if (!clist)
158 die("Cannot add server %d to non-existant container %d!\n",
159 sid, cid);
160
161 for (vlist = clist->vcpus; vlist; vlist = vlist->next) {
162 if (vlist->sid == sid)
163 return vlist;
164 }
165
166 vlist = malloc_or_die(sizeof(*vlist));
167 vlist->sid = sid;
168 vlist->params.wcet = wcet;
169 vlist->params.period = period;
170
171 vlist->next = clist->vcpus;
172 clist->vcpus = vlist;
173
174 return vlist;
175}
176
59/** 177/**
60 * rt_graph_check_any - parse timestamp of any record 178 * rt_graph_check_any - parse timestamp of any record
61 * @epid: set to the event's task PID 179 * @epid: set to the event's task PID
62 * @rt_ts: set to the event's real-time timestamp 180 * @rt_ts: set to the event's real-time timestamp
63 */ 181 */
64int rt_graph_check_any(struct rt_graph_info *rtg_info, 182int rt_graph_check_any(struct graph_info *ginfo,
65 struct pevent *pevent, struct record *record, 183 struct record *record,
66 gint *epid, gint *out_eid, unsigned long long *ts) 184 gint *epid, gint *out_eid, unsigned long long *ts)
67{ 185{
68 guint key, eid; 186 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
187 struct pevent *pevent = ginfo->pevent;
69 struct format_field *field; 188 struct format_field *field;
189 guint key, eid;
70 190
71 eid = pevent_data_type(pevent, record); 191 eid = pevent_data_type(pevent, record);
72 key = get_event_hash_key(eid); 192 key = get_event_hash_key(eid);
@@ -86,17 +206,19 @@ int rt_graph_check_any(struct rt_graph_info *rtg_info,
86 206
87/** 207/**
88 * rt_graph_check_task_param - check for litmus_task_param record 208 * rt_graph_check_task_param - check for litmus_task_param record
89 * Return 1 and @pid, @out_wcet, and @out_period if the record matches 209 * Return 1 and @pid, @owcet, and @operiod if the record matches
90 */ 210 */
91int rt_graph_check_task_param(struct rt_graph_info *rtg_info, 211int rt_graph_check_task_param(struct graph_info *ginfo,
92 struct pevent *pevent, struct record *record, 212 struct record *record,
93 gint *pid, unsigned long long *out_wcet, 213 gint *pid, unsigned long long *owcet,
94 unsigned long long *out_period) 214 unsigned long long *operiod)
95{ 215{
216 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
217 struct pevent *pevent = ginfo->pevent;
96 struct event_format *event; 218 struct event_format *event;
97 struct rt_task_params *params; 219 struct rt_task_params *params;
98 struct task_list *list; 220 struct task_list *list;
99 unsigned long long val, wcet, period; 221 unsigned long long wcet, period;
100 gint id; 222 gint id;
101 int ret = 0; 223 int ret = 0;
102 224
@@ -111,42 +233,35 @@ int rt_graph_check_task_param(struct rt_graph_info *rtg_info,
111 goto out; 233 goto out;
112 rtg_info->task_param_id = event->id; 234 rtg_info->task_param_id = event->id;
113 dprintf(2, "Found task_param id %d\n", event->id); 235 dprintf(2, "Found task_param id %d\n", event->id);
114 rtg_info->param_pid_field = pevent_find_field(event, "pid"); 236 STORE_FIELD(rtg_info, event, param, pid);
115 rtg_info->param_wcet_field = pevent_find_field(event, "wcet"); 237 STORE_FIELD(rtg_info, event, param, wcet);
116 rtg_info->param_period_field = pevent_find_field(event, "period"); 238 STORE_FIELD(rtg_info, event, param, period);
117 } 239 }
118 240
119 id = pevent_data_type(pevent, record); 241 id = pevent_data_type(pevent, record);
120 if (id == rtg_info->task_param_id) { 242 if (id == rtg_info->task_param_id) {
121 pevent_read_number_field(rtg_info->param_pid_field, 243 LOAD_INT(rtg_info, record, param, pid, pid);
122 record->data, &val); 244 LOAD_LONG(rtg_info, record, param, wcet, &wcet);
123 *pid = val; 245 LOAD_LONG(rtg_info, record, param, wcet, &period);
124 pevent_read_number_field(rtg_info->param_wcet_field, 246
125 record->data, &wcet);
126 pevent_read_number_field(rtg_info->param_period_field,
127 record->data, &period);
128 ret = 1; 247 ret = 1;
129 dprintf(3, "Read task_param (%d) record for task %d " 248 dprintf(3, "Read task_param record for task %d (%llu, %llu)\n",
130 "(%llu, %llu)\n", id, *pid, wcet, period); 249 *pid, wcet, period);
131 250
132 list = add_task_hash(rtg_info->tasks, *pid); 251 list = add_task_hash(rtg_info->tasks, *pid);
133 if (!list->data) { 252 if (!list->data) {
134 /* If this pid is plotted, sections of time might later
135 * be viewed which are after this _param event. In this
136 * case, that plot would never read a _param event and
137 * would not know about the task's wcet and deadline.
138 * Store them with the task to avoid this issue.
139 */
140 params = malloc_or_die(sizeof(*params)); 253 params = malloc_or_die(sizeof(*params));
141 params->wcet = wcet; 254 params->wcet = wcet;
142 params->period = period; 255 params->period = period;
143 list->data = params; 256 list->data = params;
144 } 257 }
145 258
259 /* Store max period to calculate max search distance */
146 if (period > rtg_info->max_period) 260 if (period > rtg_info->max_period)
147 rtg_info->max_period = period; 261 rtg_info->max_period = period;
148 *out_wcet = wcet; 262
149 *out_period = period; 263 *owcet = wcet;
264 *operiod = period;
150 } 265 }
151 out: 266 out:
152 return ret; 267 return ret;
@@ -156,13 +271,14 @@ int rt_graph_check_task_param(struct rt_graph_info *rtg_info,
156 * rt_graph_check_switch_to - check for litmus_switch_to record 271 * rt_graph_check_switch_to - check for litmus_switch_to record
157 * Return 1 and @pid, @job, and @ts if the record matches 272 * Return 1 and @pid, @job, and @ts if the record matches
158 */ 273 */
159int rt_graph_check_switch_to(struct rt_graph_info *rtg_info, 274int rt_graph_check_switch_to(struct graph_info *ginfo,
160 struct pevent *pevent, struct record *record, 275 struct record *record,
161 gint *pid, gint *job, 276 gint *pid, gint *job,
162 unsigned long long *ts) 277 unsigned long long *ts)
163{ 278{
279 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
280 struct pevent *pevent = ginfo->pevent;
164 struct event_format *event; 281 struct event_format *event;
165 unsigned long long val;
166 gint id; 282 gint id;
167 int ret = 0; 283 int ret = 0;
168 284
@@ -172,22 +288,16 @@ int rt_graph_check_switch_to(struct rt_graph_info *rtg_info,
172 if (!event) 288 if (!event)
173 goto out; 289 goto out;
174 rtg_info->switch_to_id = event->id; 290 rtg_info->switch_to_id = event->id;
175 dprintf(2, "Found switch_to id %d\n", event->id); 291 STORE_FIELD(rtg_info, event, switch_to, pid);
176 rtg_info->switch_to_pid_field = pevent_find_field(event, "pid"); 292 STORE_FIELD(rtg_info, event, switch_to, job);
177 rtg_info->switch_to_job_field = pevent_find_field(event, "job");
178 rtg_info->switch_to_ts_field = pevent_find_field(event, RT_TS_FIELD);
179 } 293 }
180 294
181 id = pevent_data_type(pevent, record); 295 id = pevent_data_type(pevent, record);
182 if (id == rtg_info->switch_to_id) { 296 if (id == rtg_info->switch_to_id) {
183 pevent_read_number_field(rtg_info->switch_to_pid_field, 297 LOAD_INT(rtg_info, record, switch_to, pid, pid);
184 record->data, &val); 298 LOAD_INT(rtg_info, record, switch_to, job, job);
185 *pid = val; 299 *ts = get_rts(ginfo, record);
186 pevent_read_number_field(rtg_info->switch_to_job_field, 300
187 record->data, &val);
188 *job = val;
189 pevent_read_number_field(rtg_info->switch_to_ts_field,
190 record->data, ts);
191 ret = 1; 301 ret = 1;
192 dprintf(3, "Read switch_to (%d) record for job %d:%d, " 302 dprintf(3, "Read switch_to (%d) record for job %d:%d, "
193 "ts: %llu\n", id, *pid, *job, *ts); 303 "ts: %llu\n", id, *pid, *job, *ts);
@@ -200,13 +310,14 @@ int rt_graph_check_switch_to(struct rt_graph_info *rtg_info,
200 * rt_graph_check_switch_away - check for litmus_switch_away record 310 * rt_graph_check_switch_away - check for litmus_switch_away record
201 * Return 1 and @pid, @job, and @ts if the record matches 311 * Return 1 and @pid, @job, and @ts if the record matches
202 */ 312 */
203int rt_graph_check_switch_away(struct rt_graph_info *rtg_info, 313int rt_graph_check_switch_away(struct graph_info *ginfo,
204 struct pevent *pevent, struct record *record, 314 struct record *record,
205 gint *pid, gint *job, 315 gint *pid, gint *job,
206 unsigned long long *ts) 316 unsigned long long *ts)
207{ 317{
318 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
319 struct pevent *pevent = ginfo->pevent;
208 struct event_format *event; 320 struct event_format *event;
209 unsigned long long val;
210 gint id; 321 gint id;
211 int ret = 0; 322 int ret = 0;
212 323
@@ -217,21 +328,16 @@ int rt_graph_check_switch_away(struct rt_graph_info *rtg_info,
217 goto out; 328 goto out;
218 rtg_info->switch_away_id = event->id; 329 rtg_info->switch_away_id = event->id;
219 dprintf(2, "Found switch_away id %d\n", event->id); 330 dprintf(2, "Found switch_away id %d\n", event->id);
220 rtg_info->switch_away_pid_field = pevent_find_field(event, "pid"); 331 STORE_FIELD(rtg_info, event, switch_away, pid);
221 rtg_info->switch_away_job_field = pevent_find_field(event, "job"); 332 STORE_FIELD(rtg_info, event, switch_away, job);
222 rtg_info->switch_away_ts_field = pevent_find_field(event, RT_TS_FIELD);
223 } 333 }
224 334
225 id = pevent_data_type(pevent, record); 335 id = pevent_data_type(pevent, record);
226 if (id == rtg_info->switch_away_id) { 336 if (id == rtg_info->switch_away_id) {
227 pevent_read_number_field(rtg_info->switch_away_pid_field, 337 LOAD_INT(rtg_info, record, switch_away, pid, pid);
228 record->data, &val); 338 LOAD_INT(rtg_info, record, switch_away, job, job);
229 *pid = val; 339 *ts = get_rts(ginfo, record);
230 pevent_read_number_field(rtg_info->switch_away_job_field, 340
231 record->data, &val);
232 *job = val;
233 pevent_read_number_field(rtg_info->switch_away_ts_field,
234 record->data, ts);
235 ret = 1; 341 ret = 1;
236 dprintf(3, "Read switch_away (%d) record for job %d:%d, " 342 dprintf(3, "Read switch_away (%d) record for job %d:%d, "
237 "ts: %llu\n", id, *pid, *job, *ts); 343 "ts: %llu\n", id, *pid, *job, *ts);
@@ -244,14 +350,15 @@ int rt_graph_check_switch_away(struct rt_graph_info *rtg_info,
244 * rt_graph_check_task_release - check for litmus_task_release record 350 * rt_graph_check_task_release - check for litmus_task_release record
245 * Return 1 and @pid, @job, @release, and @deadline if the record matches 351 * Return 1 and @pid, @job, @release, and @deadline if the record matches
246 */ 352 */
247int rt_graph_check_task_release(struct rt_graph_info *rtg_info, 353int rt_graph_check_task_release(struct graph_info *ginfo,
248 struct pevent *pevent, struct record *record, 354 struct record *record,
249 gint *pid, gint *job, 355 gint *pid, gint *job,
250 unsigned long long *release, 356 unsigned long long *release,
251 unsigned long long *deadline) 357 unsigned long long *deadline)
252{ 358{
359 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
360 struct pevent *pevent = ginfo->pevent;
253 struct event_format *event; 361 struct event_format *event;
254 unsigned long long val;
255 gint id; 362 gint id;
256 int ret = 0; 363 int ret = 0;
257 364
@@ -262,24 +369,19 @@ int rt_graph_check_task_release(struct rt_graph_info *rtg_info,
262 goto out; 369 goto out;
263 rtg_info->task_release_id = event->id; 370 rtg_info->task_release_id = event->id;
264 dprintf(2, "Found task_release id %d\n", event->id); 371 dprintf(2, "Found task_release id %d\n", event->id);
265 rtg_info->release_pid_field = pevent_find_field(event, "pid"); 372 STORE_FIELD(rtg_info, event, release, pid);
266 rtg_info->release_job_field = pevent_find_field(event, "job"); 373 STORE_FIELD(rtg_info, event, release, job);
267 rtg_info->release_release_field = pevent_find_field(event, "release"); 374 STORE_FIELD(rtg_info, event, release, release);
268 rtg_info->release_deadline_field = pevent_find_field(event, "deadline"); 375 STORE_FIELD(rtg_info, event, release, deadline);
269 } 376 }
270 377
271 id = pevent_data_type(pevent, record); 378 id = pevent_data_type(pevent, record);
272 if (id == rtg_info->task_release_id) { 379 if (id == rtg_info->task_release_id) {
273 pevent_read_number_field(rtg_info->release_pid_field, 380 LOAD_INT(rtg_info, record, release, pid, pid);
274 record->data, &val); 381 LOAD_INT(rtg_info, record, release, job, job);
275 *pid = val; 382 LOAD_LONG(rtg_info, record, release, release, release);
276 pevent_read_number_field(rtg_info->release_job_field, 383 LOAD_LONG(rtg_info, record, release, deadline, deadline);
277 record->data, &val); 384
278 *job = val;
279 pevent_read_number_field(rtg_info->release_release_field,
280 record->data, release);
281 pevent_read_number_field(rtg_info->release_deadline_field,
282 record->data, deadline);
283 ret = 1; 385 ret = 1;
284 dprintf(3, "Read task_release (%d) record for job %d:%d, " 386 dprintf(3, "Read task_release (%d) record for job %d:%d, "
285 "release: %llu, dead: %llu\n", id, *pid, *job, *release, 387 "release: %llu, dead: %llu\n", id, *pid, *job, *release,
@@ -293,12 +395,13 @@ int rt_graph_check_task_release(struct rt_graph_info *rtg_info,
293 * rt_graph_check_task_completion - check for litmus_task_completion record 395 * rt_graph_check_task_completion - check for litmus_task_completion record
294 * Return 1 and @pid, @job, and @ts if the record matches 396 * Return 1 and @pid, @job, and @ts if the record matches
295 */ 397 */
296int rt_graph_check_task_completion(struct rt_graph_info *rtg_info, 398int rt_graph_check_task_completion(struct graph_info *ginfo,
297 struct pevent *pevent, struct record *record, 399 struct record *record,
298 gint *pid, gint *job, unsigned long long *ts) 400 gint *pid, gint *job, unsigned long long *ts)
299{ 401{
402 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
403 struct pevent *pevent = ginfo->pevent;
300 struct event_format *event; 404 struct event_format *event;
301 unsigned long long val;
302 gint id; 405 gint id;
303 int ret = 0; 406 int ret = 0;
304 407
@@ -309,21 +412,15 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtg_info,
309 goto out; 412 goto out;
310 rtg_info->task_completion_id = event->id; 413 rtg_info->task_completion_id = event->id;
311 dprintf(2, "Found task_completion id %d\n", event->id); 414 dprintf(2, "Found task_completion id %d\n", event->id);
312 rtg_info->completion_pid_field = pevent_find_field(event, "pid"); 415 STORE_FIELD(rtg_info, event, completion, pid);
313 rtg_info->completion_job_field = pevent_find_field(event, "job"); 416 STORE_FIELD(rtg_info, event, completion, job);
314 rtg_info->completion_ts_field = pevent_find_field(event, RT_TS_FIELD);
315 } 417 }
316 418
317 id = pevent_data_type(pevent, record); 419 id = pevent_data_type(pevent, record);
318 if (id == rtg_info->task_completion_id) { 420 if (id == rtg_info->task_completion_id) {
319 pevent_read_number_field(rtg_info->completion_pid_field, 421 LOAD_INT(rtg_info, record, completion, pid, pid);
320 record->data, &val); 422 LOAD_INT(rtg_info, record, completion, job, job);
321 *pid = val; 423
322 pevent_read_number_field(rtg_info->completion_job_field,
323 record->data, &val);
324 *job = val;
325 pevent_read_number_field(rtg_info->completion_ts_field,
326 record->data, ts);
327 ret = 1; 424 ret = 1;
328 dprintf(3, "Read task_completion (%d) record for job %d:%d " 425 dprintf(3, "Read task_completion (%d) record for job %d:%d "
329 "ts: %llu\n", id, *pid, *job, *ts); 426 "ts: %llu\n", id, *pid, *job, *ts);
@@ -336,12 +433,13 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtg_info,
336 * rt_graph_check_task_block - check for litmus_task_block record 433 * rt_graph_check_task_block - check for litmus_task_block record
337 * Return 1, @pid, and @ts if the record matches 434 * Return 1, @pid, and @ts if the record matches
338 */ 435 */
339int rt_graph_check_task_block(struct rt_graph_info *rtg_info, 436int rt_graph_check_task_block(struct graph_info *ginfo,
340 struct pevent *pevent, struct record *record, 437 struct record *record,
341 gint *pid, unsigned long long *ts) 438 gint *pid, unsigned long long *ts)
342{ 439{
440 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
441 struct pevent *pevent = ginfo->pevent;
343 struct event_format *event; 442 struct event_format *event;
344 unsigned long long val;
345 gint id; 443 gint id;
346 int ret = 0; 444 int ret = 0;
347 445
@@ -351,18 +449,14 @@ int rt_graph_check_task_block(struct rt_graph_info *rtg_info,
351 if (!event) 449 if (!event)
352 goto out; 450 goto out;
353 dprintf(2, "Found task_block id %d\n", event->id); 451 dprintf(2, "Found task_block id %d\n", event->id);
354 rtg_info->task_block_id = event->id; 452 STORE_FIELD(rtg_info, event, block, pid);
355 rtg_info->block_pid_field = pevent_find_field(event, "pid");
356 rtg_info->block_ts_field = pevent_find_field(event, RT_TS_FIELD);
357 } 453 }
358 454
359 id = pevent_data_type(pevent, record); 455 id = pevent_data_type(pevent, record);
360 if (id == rtg_info->task_block_id) { 456 if (id == rtg_info->task_block_id) {
361 pevent_read_number_field(rtg_info->block_pid_field, 457 LOAD_INT(rtg_info, record, block, pid, pid);
362 record->data, &val); 458 *ts = get_rts(ginfo, record);
363 *pid = val; 459
364 pevent_read_number_field(rtg_info->block_ts_field,
365 record->data, ts);
366 ret = 1; 460 ret = 1;
367 dprintf(3, "Read task_block (%d) record for task %d\n", 461 dprintf(3, "Read task_block (%d) record for task %d\n",
368 id, *pid); 462 id, *pid);
@@ -373,14 +467,15 @@ int rt_graph_check_task_block(struct rt_graph_info *rtg_info,
373 467
374/** 468/**
375 * rt_graph_check_task_resume - check for litmus_task_resume record 469 * rt_graph_check_task_resume - check for litmus_task_resume record
376 * Return 1 and @pid if the record matches 470 * Return 1, @pid, and @ts if the record matches
377 */ 471 */
378int rt_graph_check_task_resume(struct rt_graph_info *rtg_info, 472int rt_graph_check_task_resume(struct graph_info *ginfo,
379 struct pevent *pevent, struct record *record, 473 struct record *record,
380 gint *pid, unsigned long long *ts) 474 gint *pid, unsigned long long *ts)
381{ 475{
476 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
477 struct pevent *pevent = ginfo->pevent;
382 struct event_format *event; 478 struct event_format *event;
383 unsigned long long val;
384 gint id; 479 gint id;
385 int ret = 0; 480 int ret = 0;
386 481
@@ -390,18 +485,14 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtg_info,
390 if (!event) 485 if (!event)
391 goto out; 486 goto out;
392 dprintf(2, "Found task_resume id %d\n", event->id); 487 dprintf(2, "Found task_resume id %d\n", event->id);
393 rtg_info->task_resume_id = event->id; 488 STORE_FIELD(rtg_info, event, resume, pid);
394 rtg_info->resume_pid_field = pevent_find_field(event, "pid");
395 rtg_info->resume_ts_field = pevent_find_field(event, RT_TS_FIELD);
396 } 489 }
397 490
398 id = pevent_data_type(pevent, record); 491 id = pevent_data_type(pevent, record);
399 if (id == rtg_info->task_resume_id) { 492 if (id == rtg_info->task_resume_id) {
400 pevent_read_number_field(rtg_info->resume_pid_field, 493 LOAD_INT(rtg_info, record, resume, pid, pid);
401 record->data, &val); 494 *ts = get_rts(ginfo, record);
402 *pid = val; 495
403 pevent_read_number_field(rtg_info->resume_ts_field,
404 record->data, ts);
405 ret = 1; 496 ret = 1;
406 dprintf(3, "Read task_resume (%d) record for task %d\n", 497 dprintf(3, "Read task_resume (%d) record for task %d\n",
407 id, *pid); 498 id, *pid);
@@ -411,11 +502,342 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtg_info,
411} 502}
412 503
413/** 504/**
505 * rt_graph_check_container_param - check for litmus_container_param record
506 * Return 1, @cid, and @name if the record matches
507 */
508int rt_graph_check_container_param(struct graph_info *ginfo,
509 struct record *record,
510 gint *cid, char **name)
511{
512 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
513 struct pevent *pevent = ginfo->pevent;
514 struct event_format *event;
515 gint id;
516 int ret = 0;
517
518 if (rtg_info->container_param_id < 0) {
519 event = pevent_find_event_by_name(pevent, "litmus",
520 "litmus_container_param");
521 if (!event)
522 goto out;
523 rtg_info->task_param_id = event->id;
524 dprintf(2, "Found container_param id %d\n", event->id);
525 STORE_FIELD(rtg_info, event, cparam, cid);
526 STORE_FIELD(rtg_info, event, cparam, name);
527 }
528
529 id = pevent_data_type(pevent, record);
530 if (id == rtg_info->container_param_id) {
531 LOAD_INT(rtg_info, record, cparam, cid, cid);
532 LOAD_STRING(rtg_info, record, cparam, name, name);
533
534 add_container(rtg_info->containers, *cid, *name);
535
536 dprintf(3, "Read container_param for %s - %d\n",
537 *name, *cid);
538 ret = 1;
539 }
540 out:
541 return ret;
542}
543
544/**
545 * rt_graph_check_server_param - check for litmus_server_param record
546 * Return 1, @sid, @ocid, @owcet, and @operiod if the record matches
547 */
548int rt_graph_check_server_param(struct graph_info *ginfo, struct record *record,
549 gint *sid, gint *ocid,
550 unsigned long long *owcet,
551 unsigned long long *operiod)
552{
553 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
554 struct pevent *pevent = ginfo->pevent;
555 struct event_format *event;
556 unsigned long long wcet, period;
557 gint cid, id;
558 int ret = 0;
559
560 if (rtg_info->server_param_id < 0) {
561 event = pevent_find_event_by_name(pevent, "litmus",
562 "litmus_server_param");
563 if (!event)
564 goto out;
565 rtg_info->task_param_id = event->id;
566 dprintf(2, "Found server_param id %d\n", event->id);
567 STORE_FIELD(rtg_info, event, sparam, cid);
568 STORE_FIELD(rtg_info, event, sparam, sid);
569 STORE_FIELD(rtg_info, event, sparam, wcet);
570 STORE_FIELD(rtg_info, event, sparam, period);
571 }
572
573 id = pevent_data_type(pevent, record);
574 if (id == rtg_info->server_param_id) {
575 LOAD_INT(rtg_info, record, sparam, sid, sid);
576 LOAD_INT(rtg_info, record, sparam, cid, &cid);
577 LOAD_LONG(rtg_info, record, sparam, wcet, &wcet);
578 LOAD_LONG(rtg_info, record, sparam, period, &period);
579
580 add_vcpu(rtg_info->containers, cid, *sid, wcet, period);
581
582 ret = 1;
583 dprintf(3, "Read server_param record for server %d "
584 "(%llu, %llu) in container %d\n",
585 *sid, wcet, period, cid);
586 *ocid = cid;
587 *owcet = wcet;
588 *operiod = period;
589 }
590 out:
591 return ret;
592}
593
594/**
595 * rt_graph_check_server_switch_to - check for litmus_server_switch_to record
596 * Return 1, @sid, @job, @tid, and @ts if the record matches
597 */
598int rt_graph_check_server_switch_to(struct graph_info *ginfo,
599 struct record *record,
600 gint *sid, gint *job, gint *tid,
601 unsigned long long *ts)
602{
603 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
604 struct pevent *pevent = ginfo->pevent;
605 struct event_format *event;
606 gint id;
607 int ret = 0;
608
609 if (rtg_info->server_switch_to_id < 0) {
610 event = pevent_find_event_by_name(pevent, "litmus",
611 "litmus_server_switch_to");
612 if (!event)
613 goto out;
614 rtg_info->server_switch_to_id = event->id;
615 dprintf(2, "Found server_switch_to id %d\n", event->id);
616 STORE_FIELD(rtg_info, event, sswitch_to, sid);
617 STORE_FIELD(rtg_info, event, sswitch_to, job);
618 STORE_FIELD(rtg_info, event, sswitch_to, tid);
619 }
620
621 id = pevent_data_type(pevent, record);
622 if (id == rtg_info->server_switch_to_id) {
623 LOAD_INT(rtg_info, record, sswitch_to, sid, sid);
624 LOAD_INT(rtg_info, record, sswitch_to, job, job);
625 LOAD_INT(rtg_info, record, sswitch_to, tid, tid);
626 *ts = get_rts(ginfo, record);
627
628 dprintf(3, "Read server_switch_to(job(%d, %d)): %d",
629 *sid, *job, *tid);
630 ret = 1;
631 }
632 out:
633 return ret;
634}
635
636/**
637 * rt_graph_check_server_switch_away - check for litmus_server_switch_away
638 * Return 1, @sid, @job, @tid, and @ts if the record matches
639 */
640int rt_graph_check_server_switch_away(struct graph_info *ginfo,
641 struct record *record,
642 gint *sid, gint *job, gint *tid,
643 unsigned long long *ts)
644{
645 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
646 struct pevent *pevent = ginfo->pevent;
647 struct event_format *event;
648 gint id;
649 int ret = 0;
650
651 if (rtg_info->server_switch_away_id < 0) {
652 event = pevent_find_event_by_name(pevent, "litmus",
653 "litmus_server_switch_away");
654 if (!event)
655 goto out;
656 rtg_info->server_switch_away_id = event->id;
657 dprintf(2, "Found server_switch_away id %d\n", event->id);
658 STORE_FIELD(rtg_info, event, sswitch_away, sid);
659 STORE_FIELD(rtg_info, event, sswitch_away, job);
660 STORE_FIELD(rtg_info, event, sswitch_away, tid);
661 }
662
663 id = pevent_data_type(pevent, record);
664 if (id == rtg_info->server_switch_away_id) {
665 LOAD_INT(rtg_info, record, sswitch_away, sid, sid);
666 LOAD_INT(rtg_info, record, sswitch_away, job, job);
667 LOAD_INT(rtg_info, record, sswitch_away, tid, tid);
668 *ts = get_rts(ginfo, record);
669
670
671 dprintf(3, "Read server_switch_away(job(%d, %d)): %d",
672 *sid, *job, *tid);
673 ret = 1;
674 }
675 out:
676 return ret;
677}
678
679/**
680 * rt_graph_check_server_release - check for litmus_server_release
681 * Return 1, @sid, @job, @release, and @deadline if the record matches
682 */
683int rt_graph_check_server_release(struct graph_info *ginfo,
684 struct record *record,
685 gint *sid, gint *job,
686 unsigned long long *release,
687 unsigned long long *deadline)
688{
689 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
690 struct pevent *pevent = ginfo->pevent;
691 struct event_format *event;
692 gint id;
693 int ret = 0;
694
695 if (rtg_info->server_release_id < 0) {
696 event = pevent_find_event_by_name(pevent, "litmus",
697 "litmus_server_release");
698 if (!event)
699 goto out;
700 rtg_info->server_release_id = event->id;
701 dprintf(2, "Found server_switch_away id %d\n", event->id);
702 STORE_FIELD(rtg_info, event, srelease, sid);
703 STORE_FIELD(rtg_info, event, srelease, job);
704 STORE_FIELD(rtg_info, event, srelease, release);
705 STORE_FIELD(rtg_info, event, srelease, deadline);
706 }
707
708 id = pevent_data_type(pevent, record);
709 if (id == rtg_info->server_release_id) {
710 LOAD_INT(rtg_info, record, srelease, sid, sid);
711 LOAD_INT(rtg_info, record, srelease, job, job);
712 LOAD_LONG(rtg_info, record, srelease, release, release);
713 LOAD_LONG(rtg_info, record, srelease, deadline, deadline);
714
715 dprintf(3, "Read server_switch_release(job(%d, %d)), rel: %llu,"
716 " dead: %llu\n", *sid, *job, *release, *deadline);
717 ret = 1;
718 }
719 out:
720 return ret;
721}
722
723/**
724 * rt_graph_check_server_completion - check for litmus_server_completion record
725 * Return 1, @sid, and @job if the record matches
726 */
727int rt_graph_check_server_completion(struct graph_info *ginfo,
728 struct record *record,
729 gint *sid, gint *job)
730{
731 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
732 struct pevent *pevent = ginfo->pevent;
733 struct event_format *event;
734 gint id;
735 int ret = 0;
736
737 if (rtg_info->server_completion_id < 0) {
738 event = pevent_find_event_by_name(pevent, "litmus",
739 "litmus_server_completion");
740 if (!event)
741 goto out;
742 rtg_info->server_completion_id = event->id;
743 dprintf(2, "Found server_switch_away id %d\n", event->id);
744 STORE_FIELD(rtg_info, event, scompletion, sid);
745 STORE_FIELD(rtg_info, event, scompletion, job);
746 }
747
748 id = pevent_data_type(pevent, record);
749 if (id == rtg_info->server_completion_id) {
750 LOAD_INT(rtg_info, record, scompletion, sid, sid);
751 LOAD_INT(rtg_info, record, scompletion, job, job);
752
753 dprintf(3, "Read server_completion(job(%d, %d))\n", *sid, *job);
754 ret = 1;
755 }
756 out:
757 return ret;
758}
759
760
761/**
762 * rt_graph_check_server_block - check for litmus_server_block record
763 * Return 1, @sid, and @ts if the record matches
764 */
765int rt_graph_check_server_block(struct graph_info *ginfo,
766 struct record *record,
767 gint *sid, unsigned long long *ts)
768{
769 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
770 struct pevent *pevent = ginfo->pevent;
771 struct event_format *event;
772 gint id;
773 int ret = 0;
774
775 if (rtg_info->server_block_id < 0) {
776 event = pevent_find_event_by_name(pevent, "litmus",
777 "litmus_server_block");
778 if (!event)
779 goto out;
780 dprintf(2, "Found server_block id %d\n", event->id);
781 STORE_FIELD(rtg_info, event, sblock, sid);
782 }
783
784 id = pevent_data_type(pevent, record);
785 if (id == rtg_info->server_block_id) {
786 LOAD_INT(rtg_info, record, sblock, sid, sid);
787 *ts = get_rts(ginfo, record);
788
789 ret = 1;
790 dprintf(3, "Read server_block record for server %d\n", *sid);
791 }
792 out:
793 return ret;
794}
795
796/**
797 * rt_graph_check_server_resume - check for litmus_server_resume record
798 * Return 1, @sid, and @ts if the record matches
799 */
800int rt_graph_check_server_resume(struct graph_info *ginfo,
801 struct record *record,
802 gint *sid, unsigned long long *ts)
803{
804 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
805 struct pevent *pevent = ginfo->pevent;
806 struct event_format *event;
807 gint id;
808 int ret = 0;
809
810 if (rtg_info->server_resume_id < 0) {
811 event = pevent_find_event_by_name(pevent, "litmus",
812 "litmus_server_resume");
813 if (!event)
814 goto out;
815 dprintf(2, "Found server_resume id %d\n", event->id);
816 STORE_FIELD(rtg_info, event, sresume, sid);
817 }
818
819 id = pevent_data_type(pevent, record);
820 if (id == rtg_info->server_resume_id) {
821 LOAD_INT(rtg_info, record, sresume, sid, sid);
822 *ts = get_rts(ginfo, record);
823
824 ret = 1;
825 dprintf(3, "Read server_resume record for server %d\n", *sid);
826 }
827 out:
828 return ret;
829}
830
831
832/**
414 * init_rt_event_cache - reset cached field values 833 * init_rt_event_cache - reset cached field values
415 */ 834 */
416void init_rt_event_cache(struct rt_graph_info *rtg_info) 835void init_rt_event_cache(struct rt_graph_info *rtg_info)
417{ 836{
418 dprintf(1, "Initializing RT event cache\n"); 837 dprintf(1, "Initializing RT event cache\n");
838
839 memset(rtg_info, 0, sizeof(*rtg_info));
840
419 rtg_info->task_param_id = -1; 841 rtg_info->task_param_id = -1;
420 rtg_info->switch_to_id = -1; 842 rtg_info->switch_to_id = -1;
421 rtg_info->switch_away_id = -1; 843 rtg_info->switch_away_id = -1;
@@ -424,34 +846,14 @@ void init_rt_event_cache(struct rt_graph_info *rtg_info)
424 rtg_info->task_block_id = -1; 846 rtg_info->task_block_id = -1;
425 rtg_info->task_resume_id = -1; 847 rtg_info->task_resume_id = -1;
426 848
427 rtg_info->max_period = 0; 849 rtg_info->container_param_id = -1;
428 850 rtg_info->server_param_id = -1;
429 rtg_info->param_pid_field = NULL; 851 rtg_info->server_switch_to_id = -1;
430 rtg_info->param_wcet_field = NULL; 852 rtg_info->server_switch_away_id = -1;
431 rtg_info->param_period_field = NULL; 853 rtg_info->server_release_id = -1;
432 854 rtg_info->server_completion_id = -1;
433 rtg_info->switch_to_pid_field = NULL; 855 rtg_info->server_block_id = -1;
434 rtg_info->switch_to_job_field = NULL; 856 rtg_info->server_resume_id = -1;
435 rtg_info->switch_to_ts_field = NULL;
436
437 rtg_info->switch_away_pid_field = NULL;
438 rtg_info->switch_away_job_field = NULL;
439 rtg_info->switch_away_ts_field = NULL;
440
441 rtg_info->release_pid_field = NULL;
442 rtg_info->release_job_field = NULL;
443 rtg_info->release_release_field = NULL;
444 rtg_info->release_deadline_field = NULL;
445
446 rtg_info->completion_pid_field = NULL;
447 rtg_info->completion_job_field = NULL;
448 rtg_info->completion_ts_field = NULL;
449
450 rtg_info->block_pid_field = NULL;
451 rtg_info->block_ts_field = NULL;
452
453 rtg_info->resume_pid_field = NULL;
454 rtg_info->resume_ts_field = NULL;
455} 857}
456 858
457/** 859/**
@@ -466,8 +868,7 @@ get_rts(struct graph_info *ginfo, struct record *record)
466 gint epid, eid; 868 gint epid, eid;
467 unsigned long long ts; 869 unsigned long long ts;
468 if (!record->cached_rts) { 870 if (!record->cached_rts) {
469 rt_graph_check_any(&ginfo->rtg_info, ginfo->pevent, record, 871 rt_graph_check_any(ginfo, record, &epid, &eid, &ts);
470 &epid, &eid, &ts);
471 record->cached_rts = ts; 872 record->cached_rts = ts;
472 } else 873 } else
473 ts = record->cached_rts; 874 ts = record->cached_rts;
@@ -524,9 +925,9 @@ set_cpu_to_rts(struct graph_info *ginfo, unsigned long long rt_target, int cpu)
524 925
525 /* Zero in in 1.5x the difference increments */ 926 /* Zero in in 1.5x the difference increments */
526 if (rts && diff > 0) { 927 if (rts && diff > 0) {
527 /* rts rt_target 928 /* rts rt_target | real-time time
528 * seek ? 929 * seek ? | trace-cmd time
529 * ---|---->>----|--- 930 * ---|---->>----|--------
530 */ 931 */
531 do { 932 do {
532 last_seek = seek_time; 933 last_seek = seek_time;
@@ -537,9 +938,9 @@ set_cpu_to_rts(struct graph_info *ginfo, unsigned long long rt_target, int cpu)
537 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek); 938 tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek);
538 seek_time = last_seek; 939 seek_time = last_seek;
539 } else if (rts && diff < 0) { 940 } else if (rts && diff < 0) {
540 /* rt_target rts 941 /* rt_target rts | real-time time
541 * ? seek 942 * ? seek | trace-cmd time
542 * ---|----<<----|--- 943 * ---|----<<----|--------
543 */ 944 */
544 do { 945 do {
545 seek_time = seek_time - 1.5 * (rts - rt_target); 946 seek_time = seek_time - 1.5 * (rts - rt_target);