diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-03-16 16:40:37 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-03-16 16:40:37 -0400 |
| commit | cc295d3e4924efd31c268a57f01b1412c6513301 (patch) | |
| tree | 60a4f1e70a5dc0607330b18d24336f8b2fea5462 | |
| parent | 1ceec23c6817d0d3cba77ea0e17b95a9fc506d42 (diff) | |
containers: added record parsing
| -rwxr-xr-x | make_cscope_database.sh | 5 | ||||
| -rw-r--r-- | rt-graph.c | 705 | ||||
| -rw-r--r-- | rt-graph.h | 140 | ||||
| -rw-r--r-- | rt-plot-cpu.c | 37 | ||||
| -rw-r--r-- | rt-plot-cpu.h | 1 | ||||
| -rw-r--r-- | rt-plot-task.c | 47 | ||||
| -rw-r--r-- | trace-graph.c | 4 | ||||
| -rw-r--r-- | trace-plot-cpu.c | 5 |
8 files changed, 721 insertions, 223 deletions
diff --git a/make_cscope_database.sh b/make_cscope_database.sh new file mode 100755 index 0000000..c1edd2e --- /dev/null +++ b/make_cscope_database.sh | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | |||
| 3 | CSCOPE_FILES="cscope.files" | ||
| 4 | find . -name "*.[ch]" -print > "${CSCOPE_FILES}" | ||
| 5 | cscope -b -q -k \ No newline at end of file | ||
| @@ -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 | ||
| 22 | static 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 | */ | ||
| 30 | static 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 | */ |
| 37 | static struct format_field* | 80 | static struct format_field* |
| 38 | add_ts_hash(struct ts_list **events, gint eid, gint key, | 81 | add_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 | */ | ||
| 106 | static struct cont_list* | ||
| 107 | find_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 | */ | ||
| 120 | static struct cont_list* | ||
| 121 | add_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 | */ | ||
| 146 | static struct vcpu_list* | ||
| 147 | add_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 | */ |
| 64 | int rt_graph_check_any(struct rt_graph_info *rtg_info, | 182 | int 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 | */ |
| 91 | int rt_graph_check_task_param(struct rt_graph_info *rtg_info, | 211 | int 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 | */ |
| 159 | int rt_graph_check_switch_to(struct rt_graph_info *rtg_info, | 274 | int 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 | */ |
| 203 | int rt_graph_check_switch_away(struct rt_graph_info *rtg_info, | 313 | int 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 | */ |
| 247 | int rt_graph_check_task_release(struct rt_graph_info *rtg_info, | 353 | int 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 | */ |
| 296 | int rt_graph_check_task_completion(struct rt_graph_info *rtg_info, | 398 | int 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 | */ |
| 339 | int rt_graph_check_task_block(struct rt_graph_info *rtg_info, | 436 | int 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 | */ |
| 378 | int rt_graph_check_task_resume(struct rt_graph_info *rtg_info, | 472 | int 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 | */ | ||
| 508 | int 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 | */ | ||
| 548 | int 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 | */ | ||
| 598 | int 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 | */ | ||
| 640 | int 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 | */ | ||
| 683 | int 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 | */ | ||
| 727 | int 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 | */ | ||
| 765 | int 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 | */ | ||
| 800 | int 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 | */ |
| 416 | void init_rt_event_cache(struct rt_graph_info *rtg_info) | 835 | void 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); |
| @@ -9,23 +9,23 @@ | |||
| 9 | 9 | ||
| 10 | #define LLABEL 30 | 10 | #define LLABEL 30 |
| 11 | #define SEARCH_PERIODS 3 | 11 | #define SEARCH_PERIODS 3 |
| 12 | |||
| 13 | #define NO_CPU -1 | 12 | #define NO_CPU -1 |
| 14 | |||
| 15 | #define RT_TS_FIELD "__rt_ts" | 13 | #define RT_TS_FIELD "__rt_ts" |
| 14 | |||
| 16 | #define TS_HASH_SIZE 12 | 15 | #define TS_HASH_SIZE 12 |
| 17 | struct ts_list; | 16 | #define CONT_HASH_SIZE 12 |
| 18 | 17 | ||
| 19 | struct rt_task_params { | 18 | struct ts_list; |
| 20 | unsigned long long wcet; | 19 | struct vcpu_list; |
| 21 | unsigned long long period; | ||
| 22 | }; | ||
| 23 | 20 | ||
| 24 | struct rt_graph_info { | 21 | struct rt_graph_info { |
| 25 | 22 | ||
| 26 | /* List of all real-time tasks */ | 23 | /* List of all real-time tasks */ |
| 27 | struct task_list *tasks[TASK_HASH_SIZE]; | 24 | struct task_list *tasks[TASK_HASH_SIZE]; |
| 28 | 25 | ||
| 26 | /* List of all real-time containers */ | ||
| 27 | struct cont_list *containers[CONT_HASH_SIZE]; | ||
| 28 | |||
| 29 | /* Cache of event fields so that they don't need to be located | 29 | /* Cache of event fields so that they don't need to be located |
| 30 | * during each access. | 30 | * during each access. |
| 31 | */ | 31 | */ |
| @@ -37,12 +37,10 @@ struct rt_graph_info { | |||
| 37 | gint switch_to_id; | 37 | gint switch_to_id; |
| 38 | struct format_field *switch_to_pid_field; | 38 | struct format_field *switch_to_pid_field; |
| 39 | struct format_field *switch_to_job_field; | 39 | struct format_field *switch_to_job_field; |
| 40 | struct format_field *switch_to_ts_field; | ||
| 41 | 40 | ||
| 42 | gint switch_away_id; | 41 | gint switch_away_id; |
| 43 | struct format_field *switch_away_pid_field; | 42 | struct format_field *switch_away_pid_field; |
| 44 | struct format_field *switch_away_job_field; | 43 | struct format_field *switch_away_job_field; |
| 45 | struct format_field *switch_away_ts_field; | ||
| 46 | 44 | ||
| 47 | gint task_release_id; | 45 | gint task_release_id; |
| 48 | struct format_field *release_pid_field; | 46 | struct format_field *release_pid_field; |
| @@ -53,55 +51,146 @@ struct rt_graph_info { | |||
| 53 | gint task_completion_id; | 51 | gint task_completion_id; |
| 54 | struct format_field *completion_pid_field; | 52 | struct format_field *completion_pid_field; |
| 55 | struct format_field *completion_job_field; | 53 | struct format_field *completion_job_field; |
| 56 | struct format_field *completion_ts_field; | ||
| 57 | 54 | ||
| 58 | gint task_block_id; | 55 | gint task_block_id; |
| 59 | struct format_field *block_pid_field; | 56 | struct format_field *block_pid_field; |
| 60 | struct format_field *block_ts_field; | ||
| 61 | 57 | ||
| 62 | gint task_resume_id; | 58 | gint task_resume_id; |
| 63 | struct format_field *resume_pid_field; | 59 | struct format_field *resume_pid_field; |
| 64 | struct format_field *resume_ts_field; | 60 | |
| 61 | gint container_param_id; | ||
| 62 | struct format_field *cparam_cid_field; | ||
| 63 | struct format_field *cparam_name_field; | ||
| 64 | |||
| 65 | gint server_param_id; | ||
| 66 | struct format_field *sparam_sid_field; | ||
| 67 | struct format_field *sparam_cid_field; | ||
| 68 | struct format_field *sparam_wcet_field; | ||
| 69 | struct format_field *sparam_period_field; | ||
| 70 | |||
| 71 | gint server_switch_to_id; | ||
| 72 | struct format_field *sswitch_to_sid_field; | ||
| 73 | struct format_field *sswitch_to_job_field; | ||
| 74 | struct format_field *sswitch_to_tid_field; | ||
| 75 | |||
| 76 | gint server_switch_away_id; | ||
| 77 | struct format_field *sswitch_away_sid_field; | ||
| 78 | struct format_field *sswitch_away_job_field; | ||
| 79 | struct format_field *sswitch_away_tid_field; | ||
| 80 | |||
| 81 | gint server_release_id; | ||
| 82 | struct format_field *srelease_sid_field; | ||
| 83 | struct format_field *srelease_job_field; | ||
| 84 | struct format_field *srelease_release_field; | ||
| 85 | struct format_field *srelease_deadline_field; | ||
| 86 | |||
| 87 | gint server_completion_id; | ||
| 88 | struct format_field *scompletion_sid_field; | ||
| 89 | struct format_field *scompletion_job_field; | ||
| 90 | |||
| 91 | gint server_block_id; | ||
| 92 | struct format_field *sblock_sid_field; | ||
| 93 | |||
| 94 | gint server_resume_id; | ||
| 95 | struct format_field *sresume_sid_field; | ||
| 96 | |||
| 65 | 97 | ||
| 66 | /* Cache of ts fields for non-litmus events */ | 98 | /* Cache of ts fields for non-litmus events */ |
| 67 | struct ts_list *events[TS_HASH_SIZE]; | 99 | struct ts_list *events[TS_HASH_SIZE]; |
| 68 | 100 | ||
| 101 | /* Used to calculate maximum search times */ | ||
| 69 | unsigned long long max_period; | 102 | unsigned long long max_period; |
| 70 | }; | 103 | }; |
| 71 | 104 | ||
| 105 | /* | ||
| 106 | * A list of cached time-stamp fields | ||
| 107 | */ | ||
| 72 | struct ts_list { | 108 | struct ts_list { |
| 73 | struct ts_list *next; | 109 | struct ts_list *next; |
| 74 | gint eid; | 110 | gint eid; |
| 75 | struct format_field *ts_field; | 111 | struct format_field *ts_field; |
| 76 | }; | 112 | }; |
| 77 | 113 | ||
| 114 | /* | ||
| 115 | * Per-task real-time data | ||
| 116 | */ | ||
| 117 | struct rt_task_params { | ||
| 118 | unsigned long long wcet; | ||
| 119 | unsigned long long period; | ||
| 120 | }; | ||
| 121 | |||
| 122 | /* | ||
| 123 | * A list of servers | ||
| 124 | */ | ||
| 125 | struct vcpu_list { | ||
| 126 | struct vcpu_list *next; | ||
| 127 | gint sid; | ||
| 128 | struct rt_task_params params; | ||
| 129 | }; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * A list of containers | ||
| 133 | */ | ||
| 134 | struct cont_list { | ||
| 135 | struct cont_list *next; | ||
| 136 | gint cid; | ||
| 137 | const char* name; | ||
| 138 | struct vcpu_list *vcpus; | ||
| 139 | }; | ||
| 140 | |||
| 78 | /* Event parsers */ | 141 | /* Event parsers */ |
| 79 | int rt_graph_check_any(struct rt_graph_info *rtinfo, | 142 | int rt_graph_check_any(struct graph_info *ginfo, struct record *record, |
| 80 | struct pevent *pevent, struct record *record, | ||
| 81 | gint *pid, gint *eid, unsigned long long *ts); | 143 | gint *pid, gint *eid, unsigned long long *ts); |
| 82 | int rt_graph_check_task_param(struct rt_graph_info *rtinfo, struct pevent *pevent, | 144 | int rt_graph_check_task_param(struct graph_info *ginfo, |
| 83 | struct record *record, gint *pid, | 145 | struct record *record, gint *pid, |
| 84 | unsigned long long *wcet, | 146 | unsigned long long *wcet, |
| 85 | unsigned long long *period); | 147 | unsigned long long *period); |
| 86 | int rt_graph_check_switch_to(struct rt_graph_info *rtinfo, struct pevent *pevent, | 148 | int rt_graph_check_switch_to(struct graph_info *ginfo, |
| 87 | struct record *record, gint *pid, gint *job, | 149 | struct record *record, gint *pid, gint *job, |
| 88 | unsigned long long *when); | 150 | unsigned long long *when); |
| 89 | int rt_graph_check_switch_away(struct rt_graph_info *rtinfo, struct pevent *pevent, | 151 | int rt_graph_check_switch_away(struct graph_info *ginfo, |
| 90 | struct record *record, gint *pid, gint *job, | 152 | struct record *record, gint *pid, gint *job, |
| 91 | unsigned long long *when); | 153 | unsigned long long *when); |
| 92 | int rt_graph_check_task_release(struct rt_graph_info *rtinfo, struct pevent *pevent, | 154 | int rt_graph_check_task_release(struct graph_info *ginfo, |
| 93 | struct record *record, gint *pid, gint *job, | 155 | struct record *record, gint *pid, gint *job, |
| 94 | unsigned long long *release, | 156 | unsigned long long *release, |
| 95 | unsigned long long *deadline); | 157 | unsigned long long *deadline); |
| 96 | int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, struct pevent *pevent, | 158 | int rt_graph_check_task_completion(struct graph_info *ginfo, |
| 97 | struct record *record, gint *pid, gint *job, | 159 | struct record *record, gint *pid, gint *job, |
| 98 | unsigned long long *when); | 160 | unsigned long long *when); |
| 99 | int rt_graph_check_task_block(struct rt_graph_info *rtinfo, struct pevent *pevent, | 161 | int rt_graph_check_task_block(struct graph_info *ginfo, |
| 100 | struct record *record, gint *pid, | 162 | struct record *record, gint *pid, |
| 101 | unsigned long long *when); | 163 | unsigned long long *when); |
| 102 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, struct pevent *pevent, | 164 | int rt_graph_check_task_resume(struct graph_info *ginfo, struct record *record, |
| 103 | struct record *record, gint *pid, | 165 | gint *pid, unsigned long long *when); |
| 104 | unsigned long long *when); | 166 | int rt_graph_check_container_param(struct graph_info *ginfo, |
| 167 | struct record *record, | ||
| 168 | gint *cid, char **name); | ||
| 169 | int rt_graph_check_server_param(struct graph_info *ginfo, struct record *record, | ||
| 170 | gint *sid, gint *cid, | ||
| 171 | unsigned long long *wcet, | ||
| 172 | unsigned long long *period); | ||
| 173 | int rt_graph_check_server_switch_to(struct graph_info *ginfo, | ||
| 174 | struct record *record, | ||
| 175 | gint *sid, gint *job, gint *tid, | ||
| 176 | unsigned long long *when); | ||
| 177 | int rt_graph_check_server_switch_away(struct graph_info *ginfo, | ||
| 178 | struct record *record, | ||
| 179 | gint *sid, gint *job, gint *tid, | ||
| 180 | unsigned long long *when); | ||
| 181 | int rt_graph_check_server_release(struct graph_info *ginfo, | ||
| 182 | struct record *record, | ||
| 183 | gint *sid, gint *job, | ||
| 184 | unsigned long long *release, | ||
| 185 | unsigned long long *deadline); | ||
| 186 | int rt_graph_check_server_completion(struct graph_info *ginfo, | ||
| 187 | struct record *record, | ||
| 188 | gint *sid, gint *job); | ||
| 189 | int rt_graph_check_server_block(struct graph_info *ginfo, | ||
| 190 | struct record *record, gint *pid, | ||
| 191 | unsigned long long *when); | ||
| 192 | int rt_graph_check_server_resume(struct graph_info *ginfo, struct record *record, | ||
| 193 | gint *pid, unsigned long long *when); | ||
| 105 | void init_rt_event_cache(struct rt_graph_info *rtinfo); | 194 | void init_rt_event_cache(struct rt_graph_info *rtinfo); |
| 106 | 195 | ||
| 107 | /* Methods for dealing with RT timestamps */ | 196 | /* Methods for dealing with RT timestamps */ |
| @@ -122,4 +211,9 @@ static inline void nano_to_milli(unsigned long long time, | |||
| 122 | *nsec = time % 1000000ULL; | 211 | *nsec = time % 1000000ULL; |
| 123 | } | 212 | } |
| 124 | 213 | ||
| 214 | static inline float nano_as_milli(unsigned long long time) | ||
| 215 | { | ||
| 216 | return (float)time / 1000000ULL; | ||
| 217 | } | ||
| 218 | |||
| 125 | #endif | 219 | #endif |
diff --git a/rt-plot-cpu.c b/rt-plot-cpu.c index 4c98a95..e32f085 100644 --- a/rt-plot-cpu.c +++ b/rt-plot-cpu.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #include <string.h> | ||
| 1 | #include "trace-graph.h" | 2 | #include "trace-graph.h" |
| 2 | #include "cpu.h" | 3 | #include "cpu.h" |
| 3 | 4 | ||
| @@ -35,7 +36,7 @@ next_sa_record(struct graph_info *ginfo, struct rt_cpu_info *rtc_info, | |||
| 35 | free_record(record); | 36 | free_record(record); |
| 36 | break; | 37 | break; |
| 37 | } | 38 | } |
| 38 | match = rt_graph_check_switch_away(rtg_info, pevent, record, | 39 | match = rt_graph_check_switch_away(ginfo, record, |
| 39 | &pid, &dint, &dull); | 40 | &pid, &dint, &dull); |
| 40 | if (match) { | 41 | if (match) { |
| 41 | ret = record; | 42 | ret = record; |
| @@ -149,7 +150,7 @@ static int get_time_info(struct graph_info *ginfo, | |||
| 149 | if (get_rts(ginfo, record) > max_ts) | 150 | if (get_rts(ginfo, record) > max_ts) |
| 150 | break; | 151 | break; |
| 151 | 152 | ||
| 152 | #define ARG rtg_info, ginfo->pevent, record, &pid, &job, &dull | 153 | #define ARG ginfo, record, &pid, &job, &dull |
| 153 | if (rt_graph_check_switch_to(ARG) && pid) { | 154 | if (rt_graph_check_switch_to(ARG) && pid) { |
| 154 | goto out; | 155 | goto out; |
| 155 | } else if (rt_graph_check_switch_away(ARG) && pid) { | 156 | } else if (rt_graph_check_switch_away(ARG) && pid) { |
| @@ -184,8 +185,7 @@ try_switch_away(struct graph_info *ginfo, struct rt_cpu_info *rtc_info, | |||
| 184 | int job, pid, match; | 185 | int job, pid, match; |
| 185 | unsigned long long ts; | 186 | unsigned long long ts; |
| 186 | 187 | ||
| 187 | match = rt_graph_check_switch_away(&ginfo->rtg_info, ginfo->pevent, | 188 | match = rt_graph_check_switch_away(ginfo, record, &pid, &job, &ts); |
| 188 | record, &pid, &job, &ts); | ||
| 189 | match = match && pid; | 189 | match = match && pid; |
| 190 | if (match) { | 190 | if (match) { |
| 191 | update_pid(rtc_info, pid); | 191 | update_pid(rtc_info, pid); |
| @@ -212,10 +212,8 @@ try_switch_to(struct graph_info *ginfo, struct rt_cpu_info *rtc_info, | |||
| 212 | int job, pid, match; | 212 | int job, pid, match; |
| 213 | unsigned long long ts; | 213 | unsigned long long ts; |
| 214 | 214 | ||
| 215 | match = rt_graph_check_switch_to(&ginfo->rtg_info, ginfo->pevent, | 215 | match = rt_graph_check_switch_to(ginfo, record, &pid, &job, &ts); |
| 216 | record, &pid, &job, &ts); | ||
| 217 | match = match && pid; | 216 | match = match && pid; |
| 218 | |||
| 219 | if (match) { | 217 | if (match) { |
| 220 | update_pid(rtc_info, pid); | 218 | update_pid(rtc_info, pid); |
| 221 | rtc_info->rt_run_time = ts; | 219 | rtc_info->rt_run_time = ts; |
| @@ -231,8 +229,7 @@ try_completion(struct graph_info *ginfo, struct rt_cpu_info *rtc_info, | |||
| 231 | int pid, job, match; | 229 | int pid, job, match; |
| 232 | unsigned long long ts; | 230 | unsigned long long ts; |
| 233 | 231 | ||
| 234 | match = rt_graph_check_task_completion(&ginfo->rtg_info, ginfo->pevent, | 232 | match = rt_graph_check_task_completion(ginfo, record, &pid, &job, &ts); |
| 235 | record, &pid, &job, &ts); | ||
| 236 | if (match) { | 233 | if (match) { |
| 237 | info->completion = TRUE; | 234 | info->completion = TRUE; |
| 238 | info->ctime = ts; | 235 | info->ctime = ts; |
| @@ -336,7 +333,6 @@ static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 336 | int pid, eid, match, dint; | 333 | int pid, eid, match, dint; |
| 337 | unsigned long long ts, dull; | 334 | unsigned long long ts, dull; |
| 338 | struct rt_cpu_info *rtc_info = plot->private; | 335 | struct rt_cpu_info *rtc_info = plot->private; |
| 339 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
| 340 | 336 | ||
| 341 | if (!record) { | 337 | if (!record) { |
| 342 | do_plot_end(ginfo, rtc_info, info); | 338 | do_plot_end(ginfo, rtc_info, info); |
| @@ -355,7 +351,7 @@ static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 355 | /* Have to call checks to ensure ids are loaded. Otherwise, | 351 | /* Have to call checks to ensure ids are loaded. Otherwise, |
| 356 | * is_displayed will not work here or in any other methods. | 352 | * is_displayed will not work here or in any other methods. |
| 357 | */ | 353 | */ |
| 358 | #define ARG rtg_info, ginfo->pevent, record, &pid | 354 | #define ARG ginfo,record, &pid |
| 359 | rt_graph_check_task_param(ARG, &dull, &dull); | 355 | rt_graph_check_task_param(ARG, &dull, &dull); |
| 360 | rt_graph_check_task_release(ARG, &dint, &dull, &dull); | 356 | rt_graph_check_task_release(ARG, &dint, &dull, &dull); |
| 361 | rt_graph_check_task_block(ARG, &dull); | 357 | rt_graph_check_task_block(ARG, &dull); |
| @@ -559,26 +555,33 @@ void rt_plot_cpus_plotted(struct graph_info *ginfo, | |||
| 559 | } | 555 | } |
| 560 | 556 | ||
| 561 | /** | 557 | /** |
| 562 | * rt_plot_cpu - create a plot for @cpu. | 558 | * rt_plot_cpu_label - create a plot for @cpu with @label. |
| 563 | */ | 559 | */ |
| 564 | void rt_plot_cpu(struct graph_info *ginfo, int cpu) | 560 | void rt_plot_cpu_label(struct graph_info *ginfo, int cpu, char* label) |
| 565 | { | 561 | { |
| 566 | struct rt_cpu_info *rtc_info; | 562 | struct rt_cpu_info *rtc_info; |
| 567 | struct graph_plot *plot; | 563 | struct graph_plot *plot; |
| 568 | char label[100]; | ||
| 569 | 564 | ||
| 570 | rtc_info = malloc_or_die(sizeof(*rtc_info)); | 565 | rtc_info = malloc_or_die(sizeof(*rtc_info)); |
| 571 | memset(rtc_info, 0, sizeof(*rtc_info)); | 566 | memset(rtc_info, 0, sizeof(*rtc_info)); |
| 572 | rtc_info->cpu = cpu; | 567 | rtc_info->cpu = cpu; |
| 573 | rtc_info->label = malloc_or_die(LLABEL); | 568 | rtc_info->label = label; |
| 574 | |||
| 575 | snprintf(label, 100, "RT-CPU %d", cpu); | ||
| 576 | 569 | ||
| 577 | plot = trace_graph_plot_append(ginfo, label, PLOT_TYPE_RT_CPU, | 570 | plot = trace_graph_plot_append(ginfo, label, PLOT_TYPE_RT_CPU, |
| 578 | TIME_TYPE_RT, &rt_cpu_cb, rtc_info); | 571 | TIME_TYPE_RT, &rt_cpu_cb, rtc_info); |
| 579 | trace_graph_plot_add_all_recs(ginfo, plot); | 572 | trace_graph_plot_add_all_recs(ginfo, plot); |
| 580 | } | 573 | } |
| 581 | 574 | ||
| 575 | /** | ||
| 576 | * rt_plot_cpu - create a plot for @cpu. | ||
| 577 | */ | ||
| 578 | void rt_plot_cpu(struct graph_info *ginfo, int cpu) | ||
| 579 | { | ||
| 580 | char *label = malloc_or_die(LLABEL); | ||
| 581 | snprintf(label, 100, "RT-CPU %d", cpu); | ||
| 582 | rt_plot_cpu_label(ginfo, cpu, label); | ||
| 583 | } | ||
| 584 | |||
| 582 | void rt_plot_init_cpus(struct graph_info *ginfo, int cpus) | 585 | void rt_plot_init_cpus(struct graph_info *ginfo, int cpus) |
| 583 | { | 586 | { |
| 584 | long cpu; | 587 | long cpu; |
diff --git a/rt-plot-cpu.h b/rt-plot-cpu.h index 4af978d..2742c76 100644 --- a/rt-plot-cpu.h +++ b/rt-plot-cpu.h | |||
| @@ -10,6 +10,7 @@ struct rt_cpu_info { | |||
| 10 | char *label; | 10 | char *label; |
| 11 | }; | 11 | }; |
| 12 | 12 | ||
| 13 | void rt_plot_labeled_cpu(struct graph_info *ginfo, int cpu, char *label); | ||
| 13 | void rt_plot_cpu(struct graph_info *ginfo, int cpu); | 14 | void rt_plot_cpu(struct graph_info *ginfo, int cpu); |
| 14 | void rt_plot_cpus_plotted(struct graph_info *ginfo, | 15 | void rt_plot_cpus_plotted(struct graph_info *ginfo, |
| 15 | gboolean *all_cpus, guint64 **cpu_mask); | 16 | gboolean *all_cpus, guint64 **cpu_mask); |
diff --git a/rt-plot-task.c b/rt-plot-task.c index a5b475f..524b1f9 100644 --- a/rt-plot-task.c +++ b/rt-plot-task.c | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <string.h> | ||
| 1 | #include "trace-graph.h" | 3 | #include "trace-graph.h" |
| 2 | #include "trace-filter.h" | 4 | #include "trace-filter.h" |
| 3 | 5 | ||
| @@ -21,12 +23,11 @@ static gboolean record_matches_pid(struct graph_info *ginfo, | |||
| 21 | { | 23 | { |
| 22 | gint dint, pid = 0, match; | 24 | gint dint, pid = 0, match; |
| 23 | unsigned long long dull; | 25 | unsigned long long dull; |
| 24 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
| 25 | 26 | ||
| 26 | /* Must use check_* in case record has not been found yet, | 27 | /* Must use check_* in case record has not been found yet, |
| 27 | * this macro was the best of many terrible options. | 28 | * this macro was the best of many terrible options. |
| 28 | */ | 29 | */ |
| 29 | #define ARG rtg_info, ginfo->pevent, record, &pid | 30 | #define ARG ginfo, record, &pid |
| 30 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || | 31 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || |
| 31 | rt_graph_check_switch_away(ARG, &dint, &dull) || | 32 | rt_graph_check_switch_away(ARG, &dint, &dull) || |
| 32 | rt_graph_check_task_release(ARG, &dint, &dull, &dull) || | 33 | rt_graph_check_task_release(ARG, &dint, &dull, &dull) || |
| @@ -63,10 +64,10 @@ next_box_record(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 63 | } | 64 | } |
| 64 | 65 | ||
| 65 | /* Sorry mother */ | 66 | /* Sorry mother */ |
| 66 | #define ARG rtg_info, pevent, record, &pid | 67 | #define ARG ginfo, record, &pid |
| 67 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || | 68 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || |
| 68 | rt_graph_check_switch_away(ARG, &dint, &dull) || | 69 | rt_graph_check_switch_away(ARG, &dint, &dull) || |
| 69 | rt_graph_check_task_block(ARG, &dull) || | 70 | rt_graph_check_task_block(ARG, &dull) || |
| 70 | rt_graph_check_task_resume(ARG, &dull); | 71 | rt_graph_check_task_resume(ARG, &dull); |
| 71 | #undef ARG | 72 | #undef ARG |
| 72 | eid = (match) ? pevent_data_type(pevent, record) : 0; | 73 | eid = (match) ? pevent_data_type(pevent, record) : 0; |
| @@ -164,7 +165,6 @@ get_previous_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 164 | int pid, job, match; | 165 | int pid, job, match; |
| 165 | unsigned long long release, deadline; | 166 | unsigned long long release, deadline; |
| 166 | struct record *last_record, *record, *ret = NULL; | 167 | struct record *last_record, *record, *ret = NULL; |
| 167 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
| 168 | 168 | ||
| 169 | last_record = tracecmd_peek_data(ginfo->handle, cpu); | 169 | last_record = tracecmd_peek_data(ginfo->handle, cpu); |
| 170 | *out_job = *out_release = *out_deadline = 0; | 170 | *out_job = *out_release = *out_deadline = 0; |
| @@ -177,8 +177,7 @@ get_previous_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 177 | free_record(record); | 177 | free_record(record); |
| 178 | goto out; | 178 | goto out; |
| 179 | } | 179 | } |
| 180 | match = rt_graph_check_task_release(rtg_info, ginfo->pevent, | 180 | match = rt_graph_check_task_release(ginfo, record, &pid, &job, |
| 181 | record, &pid, &job, | ||
| 182 | &release, &deadline); | 181 | &release, &deadline); |
| 183 | free_record(last_record); | 182 | free_record(last_record); |
| 184 | last_record = record; | 183 | last_record = record; |
| @@ -267,8 +266,7 @@ static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 267 | if (rtt_info->params_found) | 266 | if (rtt_info->params_found) |
| 268 | goto out; | 267 | goto out; |
| 269 | 268 | ||
| 270 | match = rt_graph_check_task_param(&ginfo->rtg_info, ginfo->pevent, | 269 | match = rt_graph_check_task_param(ginfo, record, &pid, &wcet, &period); |
| 271 | record, &pid, &wcet, &period); | ||
| 272 | if (match && pid == rtt_info->pid) { | 270 | if (match && pid == rtt_info->pid) { |
| 273 | update_job(rtt_info, 0); | 271 | update_job(rtt_info, 0); |
| 274 | rtt_info->wcet = wcet; | 272 | rtt_info->wcet = wcet; |
| @@ -290,8 +288,7 @@ static int try_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 290 | int pid, job, match, ret = 0; | 288 | int pid, job, match, ret = 0; |
| 291 | unsigned long long release, deadline; | 289 | unsigned long long release, deadline; |
| 292 | 290 | ||
| 293 | match = rt_graph_check_task_release(&ginfo->rtg_info, ginfo->pevent, | 291 | match = rt_graph_check_task_release(ginfo, record, &pid, &job, |
| 294 | record, &pid, &job, | ||
| 295 | &release, &deadline); | 292 | &release, &deadline); |
| 296 | if (match && pid == rtt_info->pid) { | 293 | if (match && pid == rtt_info->pid) { |
| 297 | update_job(rtt_info, job); | 294 | update_job(rtt_info, job); |
| @@ -320,8 +317,7 @@ static int try_completion(struct graph_info *ginfo, | |||
| 320 | int pid, job, match, ret = 0; | 317 | int pid, job, match, ret = 0; |
| 321 | unsigned long long ts; | 318 | unsigned long long ts; |
| 322 | 319 | ||
| 323 | match = rt_graph_check_task_completion(&ginfo->rtg_info, ginfo->pevent, | 320 | match = rt_graph_check_task_completion(ginfo, record, &pid, &job, &ts); |
| 324 | record, &pid, &job, &ts); | ||
| 325 | if (match && pid == rtt_info->pid) { | 321 | if (match && pid == rtt_info->pid) { |
| 326 | 322 | ||
| 327 | info->completion = TRUE; | 323 | info->completion = TRUE; |
| @@ -341,8 +337,7 @@ static int try_block(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 341 | int pid, match, ret = 0; | 337 | int pid, match, ret = 0; |
| 342 | unsigned long long ts; | 338 | unsigned long long ts; |
| 343 | 339 | ||
| 344 | match = rt_graph_check_task_block(&ginfo->rtg_info, ginfo->pevent, | 340 | match = rt_graph_check_task_block(ginfo, record, &pid, &ts); |
| 345 | record, &pid, &ts); | ||
| 346 | if (match && pid == rtt_info->pid) { | 341 | if (match && pid == rtt_info->pid) { |
| 347 | rtt_info->fresh = FALSE; | 342 | rtt_info->fresh = FALSE; |
| 348 | rtt_info->block_time = ts; | 343 | rtt_info->block_time = ts; |
| @@ -360,8 +355,7 @@ static int try_resume(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 360 | int pid, match, ret = 0; | 355 | int pid, match, ret = 0; |
| 361 | unsigned long long ts; | 356 | unsigned long long ts; |
| 362 | 357 | ||
| 363 | match = rt_graph_check_task_resume(&ginfo->rtg_info, ginfo->pevent, | 358 | match = rt_graph_check_task_resume(ginfo, record, &pid, &ts); |
| 364 | record, &pid, &ts); | ||
| 365 | if (match && pid == rtt_info->pid) { | 359 | if (match && pid == rtt_info->pid) { |
| 366 | info->box = TRUE; | 360 | info->box = TRUE; |
| 367 | info->bcolor = 0x0; | 361 | info->bcolor = 0x0; |
| @@ -388,8 +382,7 @@ try_switch_away(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 388 | int job, pid, match, ret = 0; | 382 | int job, pid, match, ret = 0; |
| 389 | unsigned long long ts; | 383 | unsigned long long ts; |
| 390 | 384 | ||
| 391 | match = rt_graph_check_switch_away(&ginfo->rtg_info, ginfo->pevent, | 385 | match = rt_graph_check_switch_away(ginfo, record, &pid, &job, &ts); |
| 392 | record, &pid, &job, &ts); | ||
| 393 | if (match && pid == rtt_info->pid) { | 386 | if (match && pid == rtt_info->pid) { |
| 394 | update_job(rtt_info, job); | 387 | update_job(rtt_info, job); |
| 395 | 388 | ||
| @@ -422,8 +415,7 @@ static int try_switch_to(struct graph_info *ginfo, struct rt_task_info *rtt_info | |||
| 422 | int job, pid, match, ret = 0; | 415 | int job, pid, match, ret = 0; |
| 423 | unsigned long long ts; | 416 | unsigned long long ts; |
| 424 | 417 | ||
| 425 | match = rt_graph_check_switch_to(&ginfo->rtg_info, ginfo->pevent, | 418 | match = rt_graph_check_switch_to(ginfo, record, &pid, &job, &ts); |
| 426 | record, &pid, &job, &ts); | ||
| 427 | if (match && pid == rtt_info->pid) { | 419 | if (match && pid == rtt_info->pid) { |
| 428 | update_job(rtt_info, job); | 420 | update_job(rtt_info, job); |
| 429 | rtt_info->run_time = ts; | 421 | rtt_info->run_time = ts; |
| @@ -442,8 +434,7 @@ static int try_other(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 442 | unsigned long long ts; | 434 | unsigned long long ts; |
| 443 | 435 | ||
| 444 | pid = rtt_info->pid; | 436 | pid = rtt_info->pid; |
| 445 | rt_graph_check_any(&ginfo->rtg_info, ginfo->pevent, record, | 437 | rt_graph_check_any(ginfo, record, &epid, &eid, &ts); |
| 446 | &epid, &eid, &ts); | ||
| 447 | 438 | ||
| 448 | my_pid = (pid == epid); | 439 | my_pid = (pid == epid); |
| 449 | my_cpu = (rtt_info->run_time && record->cpu == rtt_info->run_cpu); | 440 | my_cpu = (rtt_info->run_time && record->cpu == rtt_info->run_cpu); |
| @@ -801,7 +792,7 @@ void rt_plot_task(struct graph_info *ginfo, int pid, int pos) | |||
| 801 | struct graph_plot *plot; | 792 | struct graph_plot *plot; |
| 802 | struct task_list *list; | 793 | struct task_list *list; |
| 803 | const char *comm; | 794 | const char *comm; |
| 804 | unsigned long long wm, wn, pm, pn; | 795 | float ms_wcet, ms_period; |
| 805 | char *plot_label; | 796 | char *plot_label; |
| 806 | int len; | 797 | int len; |
| 807 | 798 | ||
| @@ -816,16 +807,16 @@ void rt_plot_task(struct graph_info *ginfo, int pid, int pos) | |||
| 816 | rtt_info->pid = pid; | 807 | rtt_info->pid = pid; |
| 817 | rtt_info->label = malloc_or_die(LLABEL); | 808 | rtt_info->label = malloc_or_die(LLABEL); |
| 818 | 809 | ||
| 819 | nano_to_milli(params->wcet, &wm, &wn); | 810 | ms_wcet = nano_as_milli(params->wcet); |
| 820 | nano_to_milli(params->period, &pm, &pn); | 811 | ms_period = nano_as_milli(params->period); |
| 821 | 812 | ||
| 822 | /* Create plot */ | 813 | /* Create plot */ |
| 823 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); | 814 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); |
| 824 | len = strlen(comm) + 100; | 815 | len = strlen(comm) + 100; |
| 825 | plot_label = malloc_or_die(len); | 816 | plot_label = malloc_or_die(len); |
| 826 | snprintf(plot_label, len, | 817 | snprintf(plot_label, len, |
| 827 | "%s-%d\n(%llu.%1llu, %llu.%1llu)", | 818 | "%s-%d\n(%1.1f, %1.1f)", |
| 828 | comm, pid, wm, wn, pm, pn); | 819 | comm, pid, ms_wcet, ms_period); |
| 829 | plot = trace_graph_plot_insert(ginfo, pos, plot_label, PLOT_TYPE_RT_TASK, | 820 | plot = trace_graph_plot_insert(ginfo, pos, plot_label, PLOT_TYPE_RT_TASK, |
| 830 | TIME_TYPE_RT, | 821 | TIME_TYPE_RT, |
| 831 | &rt_task_cb, rtt_info); | 822 | &rt_task_cb, rtt_info); |
diff --git a/trace-graph.c b/trace-graph.c index 226c893..d309bc8 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
| @@ -55,7 +55,7 @@ | |||
| 55 | #define PLOT_GIVE 2 | 55 | #define PLOT_GIVE 2 |
| 56 | #define PLOT_BEGIN 80 | 56 | #define PLOT_BEGIN 80 |
| 57 | #define PLOT_SEP 50 | 57 | #define PLOT_SEP 50 |
| 58 | #define MAX_TRI_TIME 20000000 | 58 | #define MAX_TRI_TIME 10000000 |
| 59 | #define PLOT_LINE(plot) (PLOT_SEP * (plot) + PLOT_BEGIN + PLOT_SIZE) | 59 | #define PLOT_LINE(plot) (PLOT_SEP * (plot) + PLOT_BEGIN + PLOT_SIZE) |
| 60 | #define PLOT_TOP(plot) (PLOT_LINE(plot) - PLOT_SIZE * 2) | 60 | #define PLOT_TOP(plot) (PLOT_LINE(plot) - PLOT_SIZE * 2) |
| 61 | #define PLOT_BOX_TOP(plot) (PLOT_LINE(plot) - PLOT_SIZE) | 61 | #define PLOT_BOX_TOP(plot) (PLOT_LINE(plot) - PLOT_SIZE) |
| @@ -1646,7 +1646,7 @@ static gint draw_plot_line(struct graph_info *ginfo, int i, | |||
| 1646 | x = convert_time_to_x(ginfo, time); | 1646 | x = convert_time_to_x(ginfo, time); |
| 1647 | y = PLOT_TOP(i); | 1647 | y = PLOT_TOP(i); |
| 1648 | 1648 | ||
| 1649 | if (!small || is_high_res(ginfo)) { | 1649 | if (is_high_res(ginfo)) { |
| 1650 | gdk_draw_line(ginfo->curr_pixmap, gc, | 1650 | gdk_draw_line(ginfo->curr_pixmap, gc, |
| 1651 | x, y, x, PLOT_BOTTOM(i)); | 1651 | x, y, x, PLOT_BOTTOM(i)); |
| 1652 | } | 1652 | } |
diff --git a/trace-plot-cpu.c b/trace-plot-cpu.c index 9b927e1..469b4fd 100644 --- a/trace-plot-cpu.c +++ b/trace-plot-cpu.c | |||
| @@ -77,6 +77,7 @@ static int filter_record(struct graph_info *ginfo, | |||
| 77 | gboolean is_sched_switch = FALSE; | 77 | gboolean is_sched_switch = FALSE; |
| 78 | gboolean is_wakeup = FALSE; | 78 | gboolean is_wakeup = FALSE; |
| 79 | const char *comm; | 79 | const char *comm; |
| 80 | char *name; | ||
| 80 | int wake_pid; | 81 | int wake_pid; |
| 81 | int filter; | 82 | int filter; |
| 82 | gint rpid; | 83 | gint rpid; |
| @@ -89,8 +90,10 @@ static int filter_record(struct graph_info *ginfo, | |||
| 89 | 90 | ||
| 90 | 91 | ||
| 91 | /* Load real-time records */ | 92 | /* Load real-time records */ |
| 92 | rt_graph_check_task_param(&ginfo->rtg_info, ginfo->pevent, record, | 93 | rt_graph_check_task_param(ginfo, record, |
| 93 | &rpid, &wcet, &period); | 94 | &rpid, &wcet, &period); |
| 95 | rt_graph_check_container_param(ginfo, record, &rpid, &name); | ||
| 96 | rt_graph_check_server_param(ginfo, record, &rpid, &rpid, &period, &wcet); | ||
| 94 | 97 | ||
| 95 | if (trace_graph_check_sched_switch(ginfo, record, sched_pid, &comm)) { | 98 | if (trace_graph_check_sched_switch(ginfo, record, sched_pid, &comm)) { |
| 96 | is_sched_switch = TRUE; | 99 | is_sched_switch = TRUE; |
