diff options
author | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2012-03-08 01:37:03 -0500 |
---|---|---|
committer | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2012-03-08 01:37:03 -0500 |
commit | e15cf27a6fb6f8498def2a4e036483fd7089a530 (patch) | |
tree | fab7f0e20c1681bca1e3b584c6d420fbc8406ae4 | |
parent | e9f207ed3c68bca111d0e21a2bf601b4564ed748 (diff) |
rt-graph: input to real-time plots is processed using real-time timestamps
Each plot processes only the records which fit within the time window displayed.
When passing records into a real-time plot, kernelshark will now decide if a
record is within the current time window using real-time timestamps, instead of
the old ftrace timestamps.
This change also enables infinite zooming into the real-time plots.
-rw-r--r-- | kernel-shark.c | 6 | ||||
-rw-r--r-- | rt-graph.c | 223 | ||||
-rw-r--r-- | rt-graph.h | 4 | ||||
-rw-r--r-- | rt-plot-task.c | 438 | ||||
-rw-r--r-- | rt-plot-task.h | 5 | ||||
-rw-r--r-- | trace-graph.c | 107 | ||||
-rw-r--r-- | trace-graph.h | 2 | ||||
-rw-r--r-- | trace-plot-cpu.c | 2 |
8 files changed, 476 insertions, 311 deletions
diff --git a/kernel-shark.c b/kernel-shark.c index b24e3b6..1aaf149 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
@@ -1272,15 +1272,15 @@ plot_rt_tasks_clicked (gpointer data) | |||
1272 | { | 1272 | { |
1273 | struct shark_info *info = data; | 1273 | struct shark_info *info = data; |
1274 | struct graph_info *ginfo = info->ginfo; | 1274 | struct graph_info *ginfo = info->ginfo; |
1275 | struct rt_graph_info *rtinfo; | 1275 | struct rt_graph_info *rtg_info; |
1276 | gint *selected; | 1276 | gint *selected; |
1277 | gint *tasks; | 1277 | gint *tasks; |
1278 | 1278 | ||
1279 | if (!ginfo->handle) | 1279 | if (!ginfo->handle) |
1280 | return; | 1280 | return; |
1281 | 1281 | ||
1282 | rtinfo = &ginfo->rtinfo; | 1282 | rtg_info = &ginfo->rtg_info; |
1283 | tasks = task_list_pids(rtinfo->tasks); | 1283 | tasks = task_list_pids(rtg_info->tasks); |
1284 | rt_plot_task_plotted(ginfo, &selected); | 1284 | rt_plot_task_plotted(ginfo, &selected); |
1285 | 1285 | ||
1286 | trace_task_dialog(ginfo->handle, tasks, selected, | 1286 | trace_task_dialog(ginfo->handle, tasks, selected, |
@@ -1,7 +1,7 @@ | |||
1 | #include "trace-graph.h" | 1 | #include "trace-graph.h" |
2 | #include "trace-hash.h" | 2 | #include "trace-hash.h" |
3 | 3 | ||
4 | #define DEBUG_LEVEL 4 | 4 | #define DEBUG_LEVEL 0 |
5 | #if DEBUG_LEVEL > 0 | 5 | #if DEBUG_LEVEL > 0 |
6 | #define dprintf(l, x...) \ | 6 | #define dprintf(l, x...) \ |
7 | do { \ | 7 | do { \ |
@@ -61,7 +61,7 @@ add_ts_hash(struct ts_list **events, gint eid, gint key, | |||
61 | * @epid: set to the event's task PID | 61 | * @epid: set to the event's task PID |
62 | * @rt_ts: set to the event's real-time timestamp | 62 | * @rt_ts: set to the event's real-time timestamp |
63 | */ | 63 | */ |
64 | int rt_graph_check_any(struct rt_graph_info *rtinfo, | 64 | int rt_graph_check_any(struct rt_graph_info *rtg_info, |
65 | struct pevent *pevent, struct record *record, | 65 | struct pevent *pevent, struct record *record, |
66 | gint *epid, gint *out_eid, unsigned long long *ts) | 66 | gint *epid, gint *out_eid, unsigned long long *ts) |
67 | { | 67 | { |
@@ -70,10 +70,10 @@ int rt_graph_check_any(struct rt_graph_info *rtinfo, | |||
70 | 70 | ||
71 | eid = pevent_data_type(pevent, record); | 71 | eid = pevent_data_type(pevent, record); |
72 | key = get_event_hash_key(eid); | 72 | key = get_event_hash_key(eid); |
73 | field = find_ts_hash(rtinfo->events, key, eid); | 73 | field = find_ts_hash(rtg_info->events, key, eid); |
74 | 74 | ||
75 | if (!field) | 75 | if (!field) |
76 | field = add_ts_hash(rtinfo->events, eid, key, pevent, record); | 76 | field = add_ts_hash(rtg_info->events, eid, key, pevent, record); |
77 | 77 | ||
78 | *epid = pevent_data_pid(pevent, record); | 78 | *epid = pevent_data_pid(pevent, record); |
79 | pevent_read_number_field(field, record->data, ts); | 79 | pevent_read_number_field(field, record->data, ts); |
@@ -88,7 +88,7 @@ int rt_graph_check_any(struct rt_graph_info *rtinfo, | |||
88 | * rt_graph_check_task_param - check for litmus_task_param record | 88 | * rt_graph_check_task_param - check for litmus_task_param record |
89 | * Return 1 and @pid, @wcet, and @period if the record matches | 89 | * Return 1 and @pid, @wcet, and @period if the record matches |
90 | */ | 90 | */ |
91 | int rt_graph_check_task_param(struct rt_graph_info *rtinfo, | 91 | int rt_graph_check_task_param(struct rt_graph_info *rtg_info, |
92 | struct pevent *pevent, struct record *record, | 92 | struct pevent *pevent, struct record *record, |
93 | gint *pid, unsigned long long *wcet, | 93 | gint *pid, unsigned long long *wcet, |
94 | unsigned long long *period) | 94 | unsigned long long *period) |
@@ -102,32 +102,35 @@ int rt_graph_check_task_param(struct rt_graph_info *rtinfo, | |||
102 | * after the pevent has "seen" its first litmus_task_param | 102 | * after the pevent has "seen" its first litmus_task_param |
103 | * event. | 103 | * event. |
104 | */ | 104 | */ |
105 | if (rtinfo->task_param_id < 0) { | 105 | if (rtg_info->task_param_id < 0) { |
106 | event = pevent_find_event_by_name(pevent, "litmus", | 106 | event = pevent_find_event_by_name(pevent, "litmus", |
107 | "litmus_task_param"); | 107 | "litmus_task_param"); |
108 | if (!event) | 108 | if (!event) |
109 | goto out; | 109 | goto out; |
110 | rtinfo->task_param_id = event->id; | 110 | rtg_info->task_param_id = event->id; |
111 | dprintf(2, "Found task_param id %d\n", event->id); | 111 | dprintf(2, "Found task_param id %d\n", event->id); |
112 | rtinfo->param_pid_field = pevent_find_field(event, "pid"); | 112 | rtg_info->param_pid_field = pevent_find_field(event, "pid"); |
113 | rtinfo->param_wcet_field = pevent_find_field(event, "wcet"); | 113 | rtg_info->param_wcet_field = pevent_find_field(event, "wcet"); |
114 | rtinfo->param_period_field = pevent_find_field(event, "period"); | 114 | rtg_info->param_period_field = pevent_find_field(event, "period"); |
115 | } | 115 | } |
116 | 116 | ||
117 | id = pevent_data_type(pevent, record); | 117 | id = pevent_data_type(pevent, record); |
118 | if (id == rtinfo->task_param_id) { | 118 | if (id == rtg_info->task_param_id) { |
119 | pevent_read_number_field(rtinfo->param_pid_field, | 119 | pevent_read_number_field(rtg_info->param_pid_field, |
120 | record->data, &val); | 120 | record->data, &val); |
121 | *pid = val; | 121 | *pid = val; |
122 | pevent_read_number_field(rtinfo->param_wcet_field, | 122 | pevent_read_number_field(rtg_info->param_wcet_field, |
123 | record->data, wcet); | 123 | record->data, wcet); |
124 | pevent_read_number_field(rtinfo->param_period_field, | 124 | pevent_read_number_field(rtg_info->param_period_field, |
125 | record->data, period); | 125 | record->data, period); |
126 | ret = 1; | 126 | ret = 1; |
127 | dprintf(3, "Read task_param (%d) record for task %d " | 127 | dprintf(3, "Read task_param (%d) record for task %d " |
128 | "(%llu, %llu)\n", id, *pid, *wcet, *period); | 128 | "(%llu, %llu)\n", id, *pid, *wcet, *period); |
129 | 129 | ||
130 | add_task_hash(rtinfo->tasks, *pid); | 130 | add_task_hash(rtg_info->tasks, *pid); |
131 | |||
132 | if (*period > rtg_info->max_period) | ||
133 | rtg_info->max_period = *period; | ||
131 | } | 134 | } |
132 | out: | 135 | out: |
133 | return ret; | 136 | return ret; |
@@ -137,7 +140,7 @@ int rt_graph_check_task_param(struct rt_graph_info *rtinfo, | |||
137 | * rt_graph_check_switch_to - check for litmus_switch_to record | 140 | * rt_graph_check_switch_to - check for litmus_switch_to record |
138 | * Return 1 and @pid, @job, and @ts if the record matches | 141 | * Return 1 and @pid, @job, and @ts if the record matches |
139 | */ | 142 | */ |
140 | int rt_graph_check_switch_to(struct rt_graph_info *rtinfo, | 143 | int rt_graph_check_switch_to(struct rt_graph_info *rtg_info, |
141 | struct pevent *pevent, struct record *record, | 144 | struct pevent *pevent, struct record *record, |
142 | gint *pid, gint *job, | 145 | gint *pid, gint *job, |
143 | unsigned long long *ts) | 146 | unsigned long long *ts) |
@@ -147,27 +150,27 @@ int rt_graph_check_switch_to(struct rt_graph_info *rtinfo, | |||
147 | gint id; | 150 | gint id; |
148 | int ret = 0; | 151 | int ret = 0; |
149 | 152 | ||
150 | if (rtinfo->switch_to_id < 0) { | 153 | if (rtg_info->switch_to_id < 0) { |
151 | event = pevent_find_event_by_name(pevent, "litmus", | 154 | event = pevent_find_event_by_name(pevent, "litmus", |
152 | "litmus_switch_to"); | 155 | "litmus_switch_to"); |
153 | if (!event) | 156 | if (!event) |
154 | goto out; | 157 | goto out; |
155 | rtinfo->switch_to_id = event->id; | 158 | rtg_info->switch_to_id = event->id; |
156 | dprintf(2, "Found switch_to id %d\n", event->id); | 159 | dprintf(2, "Found switch_to id %d\n", event->id); |
157 | rtinfo->switch_to_pid_field = pevent_find_field(event, "pid"); | 160 | rtg_info->switch_to_pid_field = pevent_find_field(event, "pid"); |
158 | rtinfo->switch_to_job_field = pevent_find_field(event, "job"); | 161 | rtg_info->switch_to_job_field = pevent_find_field(event, "job"); |
159 | rtinfo->switch_to_ts_field = pevent_find_field(event, RT_TS_FIELD); | 162 | rtg_info->switch_to_ts_field = pevent_find_field(event, RT_TS_FIELD); |
160 | } | 163 | } |
161 | 164 | ||
162 | id = pevent_data_type(pevent, record); | 165 | id = pevent_data_type(pevent, record); |
163 | if (id == rtinfo->switch_to_id) { | 166 | if (id == rtg_info->switch_to_id) { |
164 | pevent_read_number_field(rtinfo->switch_to_pid_field, | 167 | pevent_read_number_field(rtg_info->switch_to_pid_field, |
165 | record->data, &val); | 168 | record->data, &val); |
166 | *pid = val; | 169 | *pid = val; |
167 | pevent_read_number_field(rtinfo->switch_to_job_field, | 170 | pevent_read_number_field(rtg_info->switch_to_job_field, |
168 | record->data, &val); | 171 | record->data, &val); |
169 | *job = val; | 172 | *job = val; |
170 | pevent_read_number_field(rtinfo->switch_to_ts_field, | 173 | pevent_read_number_field(rtg_info->switch_to_ts_field, |
171 | record->data, ts); | 174 | record->data, ts); |
172 | ret = 1; | 175 | ret = 1; |
173 | dprintf(3, "Read switch_to (%d) record for job %d:%d, " | 176 | dprintf(3, "Read switch_to (%d) record for job %d:%d, " |
@@ -181,7 +184,7 @@ int rt_graph_check_switch_to(struct rt_graph_info *rtinfo, | |||
181 | * rt_graph_check_switch_away - check for litmus_switch_away record | 184 | * rt_graph_check_switch_away - check for litmus_switch_away record |
182 | * Return 1 and @pid, @job, and @ts if the record matches | 185 | * Return 1 and @pid, @job, and @ts if the record matches |
183 | */ | 186 | */ |
184 | int rt_graph_check_switch_away(struct rt_graph_info *rtinfo, | 187 | int rt_graph_check_switch_away(struct rt_graph_info *rtg_info, |
185 | struct pevent *pevent, struct record *record, | 188 | struct pevent *pevent, struct record *record, |
186 | gint *pid, gint *job, | 189 | gint *pid, gint *job, |
187 | unsigned long long *ts) | 190 | unsigned long long *ts) |
@@ -191,27 +194,27 @@ int rt_graph_check_switch_away(struct rt_graph_info *rtinfo, | |||
191 | gint id; | 194 | gint id; |
192 | int ret = 0; | 195 | int ret = 0; |
193 | 196 | ||
194 | if (rtinfo->switch_away_id < 0) { | 197 | if (rtg_info->switch_away_id < 0) { |
195 | event = pevent_find_event_by_name(pevent, "litmus", | 198 | event = pevent_find_event_by_name(pevent, "litmus", |
196 | "litmus_switch_away"); | 199 | "litmus_switch_away"); |
197 | if (!event) | 200 | if (!event) |
198 | goto out; | 201 | goto out; |
199 | rtinfo->switch_away_id = event->id; | 202 | rtg_info->switch_away_id = event->id; |
200 | dprintf(2, "Found switch_away id %d\n", event->id); | 203 | dprintf(2, "Found switch_away id %d\n", event->id); |
201 | rtinfo->switch_away_pid_field = pevent_find_field(event, "pid"); | 204 | rtg_info->switch_away_pid_field = pevent_find_field(event, "pid"); |
202 | rtinfo->switch_away_job_field = pevent_find_field(event, "job"); | 205 | rtg_info->switch_away_job_field = pevent_find_field(event, "job"); |
203 | rtinfo->switch_away_ts_field = pevent_find_field(event, RT_TS_FIELD); | 206 | rtg_info->switch_away_ts_field = pevent_find_field(event, RT_TS_FIELD); |
204 | } | 207 | } |
205 | 208 | ||
206 | id = pevent_data_type(pevent, record); | 209 | id = pevent_data_type(pevent, record); |
207 | if (id == rtinfo->switch_away_id) { | 210 | if (id == rtg_info->switch_away_id) { |
208 | pevent_read_number_field(rtinfo->switch_away_pid_field, | 211 | pevent_read_number_field(rtg_info->switch_away_pid_field, |
209 | record->data, &val); | 212 | record->data, &val); |
210 | *pid = val; | 213 | *pid = val; |
211 | pevent_read_number_field(rtinfo->switch_away_job_field, | 214 | pevent_read_number_field(rtg_info->switch_away_job_field, |
212 | record->data, &val); | 215 | record->data, &val); |
213 | *job = val; | 216 | *job = val; |
214 | pevent_read_number_field(rtinfo->switch_away_ts_field, | 217 | pevent_read_number_field(rtg_info->switch_away_ts_field, |
215 | record->data, ts); | 218 | record->data, ts); |
216 | ret = 1; | 219 | ret = 1; |
217 | dprintf(3, "Read switch_away (%d) record for job %d:%d, " | 220 | dprintf(3, "Read switch_away (%d) record for job %d:%d, " |
@@ -225,7 +228,7 @@ int rt_graph_check_switch_away(struct rt_graph_info *rtinfo, | |||
225 | * rt_graph_check_task_release - check for litmus_task_release record | 228 | * rt_graph_check_task_release - check for litmus_task_release record |
226 | * Return 1 and @pid, @job, @release, and @deadline if the record matches | 229 | * Return 1 and @pid, @job, @release, and @deadline if the record matches |
227 | */ | 230 | */ |
228 | int rt_graph_check_task_release(struct rt_graph_info *rtinfo, | 231 | int rt_graph_check_task_release(struct rt_graph_info *rtg_info, |
229 | struct pevent *pevent, struct record *record, | 232 | struct pevent *pevent, struct record *record, |
230 | gint *pid, gint *job, | 233 | gint *pid, gint *job, |
231 | unsigned long long *release, | 234 | unsigned long long *release, |
@@ -236,30 +239,30 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo, | |||
236 | gint id; | 239 | gint id; |
237 | int ret = 0; | 240 | int ret = 0; |
238 | 241 | ||
239 | if (rtinfo->task_release_id < 0) { | 242 | if (rtg_info->task_release_id < 0) { |
240 | event = pevent_find_event_by_name(pevent, "litmus", | 243 | event = pevent_find_event_by_name(pevent, "litmus", |
241 | "litmus_task_release"); | 244 | "litmus_task_release"); |
242 | if (!event) | 245 | if (!event) |
243 | goto out; | 246 | goto out; |
244 | rtinfo->task_release_id = event->id; | 247 | rtg_info->task_release_id = event->id; |
245 | dprintf(2, "Found task_release id %d\n", event->id); | 248 | dprintf(2, "Found task_release id %d\n", event->id); |
246 | rtinfo->release_pid_field = pevent_find_field(event, "pid"); | 249 | rtg_info->release_pid_field = pevent_find_field(event, "pid"); |
247 | rtinfo->release_job_field = pevent_find_field(event, "job"); | 250 | rtg_info->release_job_field = pevent_find_field(event, "job"); |
248 | rtinfo->release_release_field = pevent_find_field(event, "release"); | 251 | rtg_info->release_release_field = pevent_find_field(event, "release"); |
249 | rtinfo->release_deadline_field = pevent_find_field(event, "deadline"); | 252 | rtg_info->release_deadline_field = pevent_find_field(event, "deadline"); |
250 | } | 253 | } |
251 | 254 | ||
252 | id = pevent_data_type(pevent, record); | 255 | id = pevent_data_type(pevent, record); |
253 | if (id == rtinfo->task_release_id) { | 256 | if (id == rtg_info->task_release_id) { |
254 | pevent_read_number_field(rtinfo->release_pid_field, | 257 | pevent_read_number_field(rtg_info->release_pid_field, |
255 | record->data, &val); | 258 | record->data, &val); |
256 | *pid = val; | 259 | *pid = val; |
257 | pevent_read_number_field(rtinfo->release_job_field, | 260 | pevent_read_number_field(rtg_info->release_job_field, |
258 | record->data, &val); | 261 | record->data, &val); |
259 | *job = val; | 262 | *job = val; |
260 | pevent_read_number_field(rtinfo->release_release_field, | 263 | pevent_read_number_field(rtg_info->release_release_field, |
261 | record->data, release); | 264 | record->data, release); |
262 | pevent_read_number_field(rtinfo->release_deadline_field, | 265 | pevent_read_number_field(rtg_info->release_deadline_field, |
263 | record->data, deadline); | 266 | record->data, deadline); |
264 | ret = 1; | 267 | ret = 1; |
265 | dprintf(3, "Read task_release (%d) record for job %d:%d, " | 268 | dprintf(3, "Read task_release (%d) record for job %d:%d, " |
@@ -274,7 +277,7 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo, | |||
274 | * rt_graph_check_task_completion - check for litmus_task_completion record | 277 | * rt_graph_check_task_completion - check for litmus_task_completion record |
275 | * Return 1 and @pid, @job, and @ts if the record matches | 278 | * Return 1 and @pid, @job, and @ts if the record matches |
276 | */ | 279 | */ |
277 | int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, | 280 | int rt_graph_check_task_completion(struct rt_graph_info *rtg_info, |
278 | struct pevent *pevent, struct record *record, | 281 | struct pevent *pevent, struct record *record, |
279 | gint *pid, gint *job, unsigned long long *ts) | 282 | gint *pid, gint *job, unsigned long long *ts) |
280 | { | 283 | { |
@@ -283,27 +286,27 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, | |||
283 | gint id; | 286 | gint id; |
284 | int ret = 0; | 287 | int ret = 0; |
285 | 288 | ||
286 | if (rtinfo->task_completion_id < 0) { | 289 | if (rtg_info->task_completion_id < 0) { |
287 | event = pevent_find_event_by_name(pevent, "litmus", | 290 | event = pevent_find_event_by_name(pevent, "litmus", |
288 | "litmus_task_completion"); | 291 | "litmus_task_completion"); |
289 | if (!event) | 292 | if (!event) |
290 | goto out; | 293 | goto out; |
291 | rtinfo->task_completion_id = event->id; | 294 | rtg_info->task_completion_id = event->id; |
292 | dprintf(2, "Found task_completion id %d\n", event->id); | 295 | dprintf(2, "Found task_completion id %d\n", event->id); |
293 | rtinfo->completion_pid_field = pevent_find_field(event, "pid"); | 296 | rtg_info->completion_pid_field = pevent_find_field(event, "pid"); |
294 | rtinfo->completion_job_field = pevent_find_field(event, "job"); | 297 | rtg_info->completion_job_field = pevent_find_field(event, "job"); |
295 | rtinfo->completion_ts_field = pevent_find_field(event, RT_TS_FIELD); | 298 | rtg_info->completion_ts_field = pevent_find_field(event, RT_TS_FIELD); |
296 | } | 299 | } |
297 | 300 | ||
298 | id = pevent_data_type(pevent, record); | 301 | id = pevent_data_type(pevent, record); |
299 | if (id == rtinfo->task_completion_id) { | 302 | if (id == rtg_info->task_completion_id) { |
300 | pevent_read_number_field(rtinfo->completion_pid_field, | 303 | pevent_read_number_field(rtg_info->completion_pid_field, |
301 | record->data, &val); | 304 | record->data, &val); |
302 | *pid = val; | 305 | *pid = val; |
303 | pevent_read_number_field(rtinfo->completion_job_field, | 306 | pevent_read_number_field(rtg_info->completion_job_field, |
304 | record->data, &val); | 307 | record->data, &val); |
305 | *job = val; | 308 | *job = val; |
306 | pevent_read_number_field(rtinfo->completion_ts_field, | 309 | pevent_read_number_field(rtg_info->completion_ts_field, |
307 | record->data, ts); | 310 | record->data, ts); |
308 | ret = 1; | 311 | ret = 1; |
309 | dprintf(3, "Read task_completion (%d) record for job %d:%d " | 312 | dprintf(3, "Read task_completion (%d) record for job %d:%d " |
@@ -317,7 +320,7 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, | |||
317 | * rt_graph_check_task_block - check for litmus_task_block record | 320 | * rt_graph_check_task_block - check for litmus_task_block record |
318 | * Return 1, @pid, and @ts if the record matches | 321 | * Return 1, @pid, and @ts if the record matches |
319 | */ | 322 | */ |
320 | int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | 323 | int rt_graph_check_task_block(struct rt_graph_info *rtg_info, |
321 | struct pevent *pevent, struct record *record, | 324 | struct pevent *pevent, struct record *record, |
322 | gint *pid, unsigned long long *ts) | 325 | gint *pid, unsigned long long *ts) |
323 | { | 326 | { |
@@ -326,23 +329,23 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | |||
326 | gint id; | 329 | gint id; |
327 | int ret = 0; | 330 | int ret = 0; |
328 | 331 | ||
329 | if (rtinfo->task_block_id < 0) { | 332 | if (rtg_info->task_block_id < 0) { |
330 | event = pevent_find_event_by_name(pevent, "litmus", | 333 | event = pevent_find_event_by_name(pevent, "litmus", |
331 | "litmus_task_block"); | 334 | "litmus_task_block"); |
332 | if (!event) | 335 | if (!event) |
333 | goto out; | 336 | goto out; |
334 | dprintf(2, "Found task_block id %d\n", event->id); | 337 | dprintf(2, "Found task_block id %d\n", event->id); |
335 | rtinfo->task_block_id = event->id; | 338 | rtg_info->task_block_id = event->id; |
336 | rtinfo->block_pid_field = pevent_find_field(event, "pid"); | 339 | rtg_info->block_pid_field = pevent_find_field(event, "pid"); |
337 | rtinfo->block_ts_field = pevent_find_field(event, RT_TS_FIELD); | 340 | rtg_info->block_ts_field = pevent_find_field(event, RT_TS_FIELD); |
338 | } | 341 | } |
339 | 342 | ||
340 | id = pevent_data_type(pevent, record); | 343 | id = pevent_data_type(pevent, record); |
341 | if (id == rtinfo->task_block_id) { | 344 | if (id == rtg_info->task_block_id) { |
342 | pevent_read_number_field(rtinfo->block_pid_field, | 345 | pevent_read_number_field(rtg_info->block_pid_field, |
343 | record->data, &val); | 346 | record->data, &val); |
344 | *pid = val; | 347 | *pid = val; |
345 | pevent_read_number_field(rtinfo->block_ts_field, | 348 | pevent_read_number_field(rtg_info->block_ts_field, |
346 | record->data, ts); | 349 | record->data, ts); |
347 | ret = 1; | 350 | ret = 1; |
348 | dprintf(3, "Read task_block (%d) record for task %d\n", | 351 | dprintf(3, "Read task_block (%d) record for task %d\n", |
@@ -356,7 +359,7 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | |||
356 | * rt_graph_check_task_resume - check for litmus_task_resume record | 359 | * rt_graph_check_task_resume - check for litmus_task_resume record |
357 | * Return 1 and @pid if the record matches | 360 | * Return 1 and @pid if the record matches |
358 | */ | 361 | */ |
359 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | 362 | int rt_graph_check_task_resume(struct rt_graph_info *rtg_info, |
360 | struct pevent *pevent, struct record *record, | 363 | struct pevent *pevent, struct record *record, |
361 | gint *pid, unsigned long long *ts) | 364 | gint *pid, unsigned long long *ts) |
362 | { | 365 | { |
@@ -365,23 +368,23 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | |||
365 | gint id; | 368 | gint id; |
366 | int ret = 0; | 369 | int ret = 0; |
367 | 370 | ||
368 | if (rtinfo->task_resume_id < 0) { | 371 | if (rtg_info->task_resume_id < 0) { |
369 | event = pevent_find_event_by_name(pevent, "litmus", | 372 | event = pevent_find_event_by_name(pevent, "litmus", |
370 | "litmus_task_resume"); | 373 | "litmus_task_resume"); |
371 | if (!event) | 374 | if (!event) |
372 | goto out; | 375 | goto out; |
373 | dprintf(2, "Found task_resume id %d\n", event->id); | 376 | dprintf(2, "Found task_resume id %d\n", event->id); |
374 | rtinfo->task_resume_id = event->id; | 377 | rtg_info->task_resume_id = event->id; |
375 | rtinfo->resume_pid_field = pevent_find_field(event, "pid"); | 378 | rtg_info->resume_pid_field = pevent_find_field(event, "pid"); |
376 | rtinfo->resume_ts_field = pevent_find_field(event, RT_TS_FIELD); | 379 | rtg_info->resume_ts_field = pevent_find_field(event, RT_TS_FIELD); |
377 | } | 380 | } |
378 | 381 | ||
379 | id = pevent_data_type(pevent, record); | 382 | id = pevent_data_type(pevent, record); |
380 | if (id == rtinfo->task_resume_id) { | 383 | if (id == rtg_info->task_resume_id) { |
381 | pevent_read_number_field(rtinfo->resume_pid_field, | 384 | pevent_read_number_field(rtg_info->resume_pid_field, |
382 | record->data, &val); | 385 | record->data, &val); |
383 | *pid = val; | 386 | *pid = val; |
384 | pevent_read_number_field(rtinfo->resume_ts_field, | 387 | pevent_read_number_field(rtg_info->resume_ts_field, |
385 | record->data, ts); | 388 | record->data, ts); |
386 | ret = 1; | 389 | ret = 1; |
387 | dprintf(3, "Read task_resume (%d) record for task %d\n", | 390 | dprintf(3, "Read task_resume (%d) record for task %d\n", |
@@ -394,43 +397,45 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | |||
394 | /** | 397 | /** |
395 | * init_rt_event_cache - reset cached field values | 398 | * init_rt_event_cache - reset cached field values |
396 | */ | 399 | */ |
397 | void init_rt_event_cache(struct rt_graph_info *rtinfo) | 400 | void init_rt_event_cache(struct rt_graph_info *rtg_info) |
398 | { | 401 | { |
399 | dprintf(1, "Initializing RT event cache\n"); | 402 | dprintf(1, "Initializing RT event cache\n"); |
400 | rtinfo->task_param_id = -1; | 403 | rtg_info->task_param_id = -1; |
401 | rtinfo->switch_to_id = -1; | 404 | rtg_info->switch_to_id = -1; |
402 | rtinfo->switch_away_id = -1; | 405 | rtg_info->switch_away_id = -1; |
403 | rtinfo->task_release_id = -1; | 406 | rtg_info->task_release_id = -1; |
404 | rtinfo->task_completion_id = -1; | 407 | rtg_info->task_completion_id = -1; |
405 | rtinfo->task_block_id = -1; | 408 | rtg_info->task_block_id = -1; |
406 | rtinfo->task_resume_id = -1; | 409 | rtg_info->task_resume_id = -1; |
407 | 410 | ||
408 | rtinfo->param_pid_field = NULL; | 411 | rtg_info->max_period = 0; |
409 | rtinfo->param_wcet_field = NULL; | 412 | |
410 | rtinfo->param_period_field = NULL; | 413 | rtg_info->param_pid_field = NULL; |
411 | 414 | rtg_info->param_wcet_field = NULL; | |
412 | rtinfo->switch_to_pid_field = NULL; | 415 | rtg_info->param_period_field = NULL; |
413 | rtinfo->switch_to_job_field = NULL; | 416 | |
414 | rtinfo->switch_to_ts_field = NULL; | 417 | rtg_info->switch_to_pid_field = NULL; |
415 | 418 | rtg_info->switch_to_job_field = NULL; | |
416 | rtinfo->switch_away_pid_field = NULL; | 419 | rtg_info->switch_to_ts_field = NULL; |
417 | rtinfo->switch_away_job_field = NULL; | 420 | |
418 | rtinfo->switch_away_ts_field = NULL; | 421 | rtg_info->switch_away_pid_field = NULL; |
419 | 422 | rtg_info->switch_away_job_field = NULL; | |
420 | rtinfo->release_pid_field = NULL; | 423 | rtg_info->switch_away_ts_field = NULL; |
421 | rtinfo->release_job_field = NULL; | 424 | |
422 | rtinfo->release_release_field = NULL; | 425 | rtg_info->release_pid_field = NULL; |
423 | rtinfo->release_deadline_field = NULL; | 426 | rtg_info->release_job_field = NULL; |
424 | 427 | rtg_info->release_release_field = NULL; | |
425 | rtinfo->completion_pid_field = NULL; | 428 | rtg_info->release_deadline_field = NULL; |
426 | rtinfo->completion_job_field = NULL; | 429 | |
427 | rtinfo->completion_ts_field = NULL; | 430 | rtg_info->completion_pid_field = NULL; |
428 | 431 | rtg_info->completion_job_field = NULL; | |
429 | rtinfo->block_pid_field = NULL; | 432 | rtg_info->completion_ts_field = NULL; |
430 | rtinfo->block_ts_field = NULL; | 433 | |
431 | 434 | rtg_info->block_pid_field = NULL; | |
432 | rtinfo->resume_pid_field = NULL; | 435 | rtg_info->block_ts_field = NULL; |
433 | rtinfo->resume_ts_field = NULL; | 436 | |
437 | rtg_info->resume_pid_field = NULL; | ||
438 | rtg_info->resume_ts_field = NULL; | ||
434 | } | 439 | } |
435 | 440 | ||
436 | /** | 441 | /** |
@@ -445,7 +450,7 @@ get_rts(struct graph_info *ginfo, struct record *record) | |||
445 | gint epid, eid; | 450 | gint epid, eid; |
446 | unsigned long long ts; | 451 | unsigned long long ts; |
447 | if (!record->cached_rts) { | 452 | if (!record->cached_rts) { |
448 | rt_graph_check_any(&ginfo->rtinfo, ginfo->pevent, record, | 453 | rt_graph_check_any(&ginfo->rtg_info, ginfo->pevent, record, |
449 | &epid, &eid, &ts); | 454 | &epid, &eid, &ts); |
450 | record->cached_rts = ts; | 455 | record->cached_rts = ts; |
451 | } else | 456 | } else |
@@ -6,6 +6,8 @@ | |||
6 | #include "trace-cmd.h" | 6 | #include "trace-cmd.h" |
7 | #include "rt-plot-task.h" | 7 | #include "rt-plot-task.h" |
8 | 8 | ||
9 | #define NO_CPU -1 | ||
10 | |||
9 | #define RT_TS_FIELD "__rt_ts" | 11 | #define RT_TS_FIELD "__rt_ts" |
10 | #define TS_HASH_SIZE 12 | 12 | #define TS_HASH_SIZE 12 |
11 | struct ts_list; | 13 | struct ts_list; |
@@ -54,6 +56,8 @@ struct rt_graph_info { | |||
54 | 56 | ||
55 | /* Cache of ts fields for non-litmus events */ | 57 | /* Cache of ts fields for non-litmus events */ |
56 | struct ts_list *events[TS_HASH_SIZE]; | 58 | struct ts_list *events[TS_HASH_SIZE]; |
59 | |||
60 | unsigned long long max_period; | ||
57 | }; | 61 | }; |
58 | 62 | ||
59 | struct ts_list { | 63 | struct ts_list { |
diff --git a/rt-plot-task.c b/rt-plot-task.c index f28b7b1..9e8ffe7 100644 --- a/rt-plot-task.c +++ b/rt-plot-task.c | |||
@@ -2,8 +2,9 @@ | |||
2 | #include "trace-filter.h" | 2 | #include "trace-filter.h" |
3 | 3 | ||
4 | #define LLABEL 30 | 4 | #define LLABEL 30 |
5 | #define SEARCH_PERIODS 3 | ||
5 | 6 | ||
6 | #define DEBUG_LEVEL 4 | 7 | #define DEBUG_LEVEL 3 |
7 | #if DEBUG_LEVEL > 0 | 8 | #if DEBUG_LEVEL > 0 |
8 | #define dprintf(l, x...) \ | 9 | #define dprintf(l, x...) \ |
9 | do { \ | 10 | do { \ |
@@ -14,35 +15,87 @@ | |||
14 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) | 15 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) |
15 | #endif | 16 | #endif |
16 | 17 | ||
18 | /* | ||
19 | * Return 1 if @record is relevant to @match_pid. | ||
20 | */ | ||
17 | static gboolean record_matches_pid(struct graph_info *ginfo, | 21 | static gboolean record_matches_pid(struct graph_info *ginfo, |
18 | struct record *record, | 22 | struct record *record, |
19 | int match_pid) | 23 | int match_pid) |
20 | { | 24 | { |
21 | gint dint, pid = 0, match; | 25 | gint dint, pid = 0, match; |
22 | unsigned long long dull; | 26 | unsigned long long dull; |
23 | struct rt_graph_info *rtg_info = &ginfo->rtinfo; | 27 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; |
24 | 28 | ||
25 | /* Must use check_* in case record has not been found yet, | 29 | /* Must use check_* in case record has not been found yet, |
26 | * this macro was the best of many terrible options | 30 | * this macro was the best of many terrible options. |
27 | */ | 31 | */ |
28 | #define MARGS rtg_info, ginfo->pevent, record, &pid | 32 | #define ARG rtg_info, ginfo->pevent, record, &pid |
29 | match = rt_graph_check_switch_to(MARGS, &dint, &dull) || | 33 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || |
30 | rt_graph_check_switch_away(MARGS, &dint, &dull) || | 34 | rt_graph_check_switch_away(ARG, &dint, &dull) || |
31 | rt_graph_check_task_release(MARGS, &dint, &dull, &dull) || | 35 | rt_graph_check_task_release(ARG, &dint, &dull, &dull) || |
32 | rt_graph_check_task_completion(MARGS, &dint, &dull) || | 36 | rt_graph_check_task_completion(ARG, &dint, &dull) || |
33 | rt_graph_check_task_block(MARGS, &dull) || | 37 | rt_graph_check_task_block(ARG, &dull) || |
34 | rt_graph_check_task_resume(MARGS, &dull) || | 38 | rt_graph_check_task_resume(ARG, &dull) || |
35 | rt_graph_check_any(MARGS, &dint, &dull); | 39 | rt_graph_check_any(ARG, &dint, &dull); |
36 | #undef MARGS | 40 | #undef ARG |
37 | return pid == match_pid; | 41 | return pid == match_pid; |
38 | } | 42 | } |
39 | 43 | ||
44 | /* | ||
45 | * Return the first record after @time (within a range) which draws a box. | ||
46 | */ | ||
47 | static struct record* | ||
48 | next_box_record(struct graph_info *ginfo, struct rt_task_info *rtt_info, | ||
49 | unsigned long long time, int *out_eid) | ||
50 | { | ||
51 | struct record *record = NULL, *ret = NULL; | ||
52 | struct pevent *pevent; | ||
53 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
54 | unsigned long long dull, max_ts; | ||
55 | int match, pid, eid, dint, cpu; | ||
56 | |||
57 | *out_eid = 0; | ||
58 | pevent = ginfo->pevent; | ||
59 | max_ts = ginfo->view_end_time + | ||
60 | SEARCH_PERIODS * rtg_info->max_period; | ||
61 | set_cpus_to_rts(ginfo, time); | ||
62 | do { | ||
63 | free_record(record); | ||
64 | record = tracecmd_read_next_data(ginfo->handle, &cpu); | ||
65 | if (!record || get_rts(ginfo, record) > max_ts) { | ||
66 | free_record(record); | ||
67 | goto out; | ||
68 | } | ||
69 | |||
70 | /* Sorry mother */ | ||
71 | #define ARG rtg_info, pevent, record, &pid | ||
72 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || | ||
73 | rt_graph_check_switch_away(ARG, &dint, &dull) || | ||
74 | rt_graph_check_task_block(ARG, &dull) || | ||
75 | rt_graph_check_task_resume(ARG, &dull); | ||
76 | #undef ARG | ||
77 | eid = (match) ? pevent_data_type(pevent, record) : 0; | ||
78 | |||
79 | if (eid && pid == rtt_info->pid) { | ||
80 | ret = record; | ||
81 | *out_eid = eid; | ||
82 | goto out; | ||
83 | } | ||
84 | } while (get_rts(ginfo, record) < max_ts); | ||
85 | out: | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Return first relevant record after @time. | ||
91 | * @display: If set, only considers records which are plotted in some way | ||
92 | */ | ||
40 | static struct record* | 93 | static struct record* |
41 | __find_record(struct graph_info *ginfo, gint pid, guint64 time, int display) | 94 | __find_record(struct graph_info *ginfo, gint pid, guint64 time, int display) |
42 | { | 95 | { |
43 | int next_cpu, match, eid, is_sa = 0; | 96 | int next_cpu, match, eid, is_sa = 0; |
44 | struct record *record = NULL; | 97 | struct record *record = NULL; |
45 | struct rt_graph_info *rtg_info = &ginfo->rtinfo; | 98 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; |
46 | 99 | ||
47 | set_cpus_to_rts(ginfo, time); | 100 | set_cpus_to_rts(ginfo, time); |
48 | do { | 101 | do { |
@@ -73,10 +126,11 @@ find_display_record(struct graph_info *ginfo, gint pid, guint64 time) | |||
73 | } | 126 | } |
74 | 127 | ||
75 | /* | 128 | /* |
76 | * Update current job in @rtt_info, ensuring monotonic increase | 129 | * Update current job in @rtt_info, ensuring monotonic increase. |
77 | */ | 130 | */ |
78 | static int update_job(struct rt_task_info *rtt_info, int job) | 131 | static int update_job(struct rt_task_info *rtt_info, int job) |
79 | { | 132 | { |
133 | rtt_info->fresh = FALSE; | ||
80 | if (job < rtt_info->last_job) { | 134 | if (job < rtt_info->last_job) { |
81 | printf("Inconsistent job state for %d:%d -> %d\n", | 135 | printf("Inconsistent job state for %d:%d -> %d\n", |
82 | rtt_info->pid, rtt_info->last_job, job); | 136 | rtt_info->pid, rtt_info->last_job, job); |
@@ -89,6 +143,115 @@ static int update_job(struct rt_task_info *rtt_info, int job) | |||
89 | return 1; | 143 | return 1; |
90 | } | 144 | } |
91 | 145 | ||
146 | |||
147 | |||
148 | /* | ||
149 | * Find the information for the last release of @rtt_info on @cpu before @time. | ||
150 | * @min_ts: the minimum time stamp to parse | ||
151 | * | ||
152 | * Returns release record and @out_job, @out_release, and @out_deadline if a | ||
153 | * release was found after @mints matching @time. | ||
154 | */ | ||
155 | static struct record* | ||
156 | get_previous_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | ||
157 | int cpu, | ||
158 | unsigned long long min_ts, unsigned long long time, | ||
159 | int *out_job, | ||
160 | unsigned long long *out_release, | ||
161 | unsigned long long *out_deadline) | ||
162 | { | ||
163 | int pid, job, match; | ||
164 | unsigned long long release, deadline; | ||
165 | struct record *last_record, *record, *ret = NULL; | ||
166 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
167 | |||
168 | last_record = tracecmd_peek_data(ginfo->handle, cpu); | ||
169 | *out_job = *out_release = *out_deadline = 0; | ||
170 | if (!last_record) | ||
171 | return NULL; | ||
172 | last_record->ref_count++; | ||
173 | |||
174 | while ((record = tracecmd_read_prev(ginfo->handle, last_record))) { | ||
175 | if (record->ts < min_ts) { | ||
176 | free_record(record); | ||
177 | goto out; | ||
178 | } | ||
179 | match = rt_graph_check_task_release(rtg_info, ginfo->pevent, | ||
180 | record, &pid, &job, | ||
181 | &release, &deadline); | ||
182 | free_record(last_record); | ||
183 | last_record = record; | ||
184 | if (match && (pid == rtt_info->pid) && release <= time) { | ||
185 | ret = record; | ||
186 | last_record = NULL; | ||
187 | *out_job = job; | ||
188 | *out_release = release; | ||
189 | *out_deadline = deadline; | ||
190 | break; | ||
191 | } | ||
192 | }; | ||
193 | out: | ||
194 | free_record(last_record); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * Return information for @time, returns @job, @release, @deadline, and @record. | ||
200 | * @job: Job number at this time | ||
201 | * @release: Job's release time | ||
202 | * @deadline: Job's deadline | ||
203 | * @record: Matching record | ||
204 | */ | ||
205 | static int get_time_info(struct graph_info *ginfo, | ||
206 | struct rt_task_info *rtt_info, | ||
207 | unsigned long long time, | ||
208 | int *out_job, | ||
209 | unsigned long long *out_release, | ||
210 | unsigned long long *out_deadline, | ||
211 | struct record **out_record) | ||
212 | |||
213 | { | ||
214 | int cpu, job; | ||
215 | unsigned long long release, deadline, min_ts; | ||
216 | struct record *record; | ||
217 | struct offset_cache *offsets; | ||
218 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
219 | |||
220 | /* Seek CPUs to first record after this time */ | ||
221 | *out_job = *out_release = *out_deadline = 0; | ||
222 | *out_record = find_record(ginfo, rtt_info->pid, time); | ||
223 | if (!*out_record) | ||
224 | return 0; | ||
225 | |||
226 | /* This is not necessarily correct for sporadic, but will do for now */ | ||
227 | if (time < rtt_info->first_rels[2]) { | ||
228 | job = (time >= rtt_info->first_rels[1]) ? 2 : 1; | ||
229 | *out_job = job; | ||
230 | *out_release = rtt_info->first_rels[job - 1]; | ||
231 | *out_deadline = rtt_info->first_rels[job]; | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | min_ts = time - SEARCH_PERIODS * rtg_info->max_period; | ||
236 | *out_job = *out_release = *out_deadline = 0; | ||
237 | |||
238 | offsets = save_offsets(ginfo); | ||
239 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | ||
240 | record = get_previous_release(ginfo, rtt_info, cpu, min_ts, | ||
241 | time, &job, &release, &deadline); | ||
242 | if (record && record->ts > min_ts) { | ||
243 | *out_job = job; | ||
244 | *out_release = release; | ||
245 | *out_deadline = deadline; | ||
246 | min_ts = record->ts; | ||
247 | } | ||
248 | free_record(record); | ||
249 | } | ||
250 | restore_offsets(ginfo, offsets); | ||
251 | out: | ||
252 | return 1; | ||
253 | } | ||
254 | |||
92 | static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info, | 255 | static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info, |
93 | struct record *record, struct plot_info *info) | 256 | struct record *record, struct plot_info *info) |
94 | { | 257 | { |
@@ -99,7 +262,7 @@ static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
99 | if (rtt_info->params_found) | 262 | if (rtt_info->params_found) |
100 | goto out; | 263 | goto out; |
101 | 264 | ||
102 | match = rt_graph_check_task_param(&ginfo->rtinfo, ginfo->pevent, | 265 | match = rt_graph_check_task_param(&ginfo->rtg_info, ginfo->pevent, |
103 | record, &pid, &wcet, &period); | 266 | record, &pid, &wcet, &period); |
104 | if (match && pid == rtt_info->pid) { | 267 | if (match && pid == rtt_info->pid) { |
105 | update_job(rtt_info, 0); | 268 | update_job(rtt_info, 0); |
@@ -108,6 +271,8 @@ static int try_param(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
108 | rtt_info->params_found = TRUE; | 271 | rtt_info->params_found = TRUE; |
109 | ret = 1; | 272 | ret = 1; |
110 | rtt_info->first_rels[0] = get_rts(ginfo, record); | 273 | rtt_info->first_rels[0] = get_rts(ginfo, record); |
274 | dprintf(3, "Params for %d (%llu, %llu)\n on %d", | ||
275 | pid, wcet, period, record->cpu); | ||
111 | } | 276 | } |
112 | out: | 277 | out: |
113 | return ret; | 278 | return ret; |
@@ -120,7 +285,7 @@ static int try_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
120 | int pid, job, match, ret = 0; | 285 | int pid, job, match, ret = 0; |
121 | unsigned long long release, deadline; | 286 | unsigned long long release, deadline; |
122 | 287 | ||
123 | match = rt_graph_check_task_release(&ginfo->rtinfo, ginfo->pevent, | 288 | match = rt_graph_check_task_release(&ginfo->rtg_info, ginfo->pevent, |
124 | record, &pid, &job, | 289 | record, &pid, &job, |
125 | &release, &deadline); | 290 | &release, &deadline); |
126 | if (match && pid == rtt_info->pid) { | 291 | if (match && pid == rtt_info->pid) { |
@@ -136,6 +301,9 @@ static int try_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
136 | if (job <= 3) | 301 | if (job <= 3) |
137 | rtt_info->first_rels[job - 1] = release; | 302 | rtt_info->first_rels[job - 1] = release; |
138 | 303 | ||
304 | dprintf(3, "Release for %d:%d on %d, rel: %llu, dead: %llu\n", | ||
305 | pid, job, record->cpu, release, deadline); | ||
306 | |||
139 | ret = 1; | 307 | ret = 1; |
140 | } | 308 | } |
141 | return ret; | 309 | return ret; |
@@ -148,13 +316,15 @@ static int try_completion(struct graph_info *ginfo, | |||
148 | int pid, job, match, ret = 0; | 316 | int pid, job, match, ret = 0; |
149 | unsigned long long ts; | 317 | unsigned long long ts; |
150 | 318 | ||
151 | match = rt_graph_check_task_completion(&ginfo->rtinfo, ginfo->pevent, | 319 | match = rt_graph_check_task_completion(&ginfo->rtg_info, ginfo->pevent, |
152 | record, &pid, &job, &ts); | 320 | record, &pid, &job, &ts); |
153 | if (match && pid == rtt_info->pid) { | 321 | if (match && pid == rtt_info->pid) { |
154 | update_job(rtt_info, job); | 322 | update_job(rtt_info, job); |
155 | info->completion = TRUE; | 323 | info->completion = TRUE; |
156 | info->ctime = ts; | 324 | info->ctime = ts; |
157 | info->clabel = rtt_info->label; | 325 | info->clabel = rtt_info->label; |
326 | dprintf(3, "Completion for %d:%d on %d at %llu\n", | ||
327 | pid, job, record->cpu, ts); | ||
158 | ret = 1; | 328 | ret = 1; |
159 | } | 329 | } |
160 | return ret; | 330 | return ret; |
@@ -166,10 +336,14 @@ static int try_block(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
166 | int pid, match, ret = 0; | 336 | int pid, match, ret = 0; |
167 | unsigned long long ts; | 337 | unsigned long long ts; |
168 | 338 | ||
169 | match = rt_graph_check_task_block(&ginfo->rtinfo, ginfo->pevent, | 339 | match = rt_graph_check_task_block(&ginfo->rtg_info, ginfo->pevent, |
170 | record, &pid, &ts); | 340 | record, &pid, &ts); |
171 | if (match && pid == rtt_info->pid) { | 341 | if (match && pid == rtt_info->pid) { |
342 | rtt_info->fresh = FALSE; | ||
172 | rtt_info->block_time = ts; | 343 | rtt_info->block_time = ts; |
344 | rtt_info->block_cpu = NO_CPU; | ||
345 | dprintf(3, "Resume for %d on %d at %llu\n", | ||
346 | pid, record->cpu, ts); | ||
173 | ret = 1; | 347 | ret = 1; |
174 | } | 348 | } |
175 | return ret; | 349 | return ret; |
@@ -181,7 +355,7 @@ static int try_resume(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
181 | int pid, match, ret = 0; | 355 | int pid, match, ret = 0; |
182 | unsigned long long ts; | 356 | unsigned long long ts; |
183 | 357 | ||
184 | match = rt_graph_check_task_resume(&ginfo->rtinfo, ginfo->pevent, | 358 | match = rt_graph_check_task_resume(&ginfo->rtg_info, ginfo->pevent, |
185 | record, &pid, &ts); | 359 | record, &pid, &ts); |
186 | if (match && pid == rtt_info->pid) { | 360 | if (match && pid == rtt_info->pid) { |
187 | /* info->box = TRUE; */ | 361 | /* info->box = TRUE; */ |
@@ -190,22 +364,26 @@ static int try_resume(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
190 | /* info->bthin = TRUE; */ | 364 | /* info->bthin = TRUE; */ |
191 | /* info->bstart = rtt_info->block_time; */ | 365 | /* info->bstart = rtt_info->block_time; */ |
192 | /* info->bend = ts; */ | 366 | /* info->bend = ts; */ |
367 | rtt_info->fresh = FALSE; | ||
193 | 368 | ||
194 | rtt_info->block_time = 0ULL; | 369 | rtt_info->block_time = 0ULL; |
370 | rtt_info->block_cpu = NO_CPU; | ||
371 | dprintf(3, "Resume for %d on %d at %llu\n", | ||
372 | pid, record->cpu, ts); | ||
195 | 373 | ||
196 | ret = 1; | 374 | ret = 1; |
197 | } | 375 | } |
198 | return ret; | 376 | return ret; |
199 | } | 377 | } |
200 | 378 | ||
201 | static unsigned long long | 379 | static int |
202 | try_switch_away(struct graph_info *ginfo, struct rt_task_info *rtt_info, | 380 | try_switch_away(struct graph_info *ginfo, struct rt_task_info *rtt_info, |
203 | struct record *record, struct plot_info *info) | 381 | struct record *record, struct plot_info *info) |
204 | { | 382 | { |
205 | int job, pid, match, ret = 0; | 383 | int job, pid, match, ret = 0; |
206 | unsigned long long ts; | 384 | unsigned long long ts; |
207 | 385 | ||
208 | match = rt_graph_check_switch_away(&ginfo->rtinfo, ginfo->pevent, | 386 | match = rt_graph_check_switch_away(&ginfo->rtg_info, ginfo->pevent, |
209 | record, &pid, &job, &ts); | 387 | record, &pid, &job, &ts); |
210 | if (match && pid == rtt_info->pid) { | 388 | if (match && pid == rtt_info->pid) { |
211 | update_job(rtt_info, job); | 389 | update_job(rtt_info, job); |
@@ -213,18 +391,19 @@ try_switch_away(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
213 | if (rtt_info->run_time && rtt_info->run_time < ts) { | 391 | if (rtt_info->run_time && rtt_info->run_time < ts) { |
214 | dprintf(3, "Box for %d:%d, %llu to %llu on CPU %d\n", | 392 | dprintf(3, "Box for %d:%d, %llu to %llu on CPU %d\n", |
215 | rtt_info->pid, rtt_info->last_job, | 393 | rtt_info->pid, rtt_info->last_job, |
216 | rtt_info->run_time, ts, rtt_info->last_cpu); | 394 | rtt_info->run_time, ts, record->cpu); |
217 | info->box = TRUE; | 395 | info->box = TRUE; |
218 | info->bcolor = hash_cpu(rtt_info->last_cpu); | 396 | info->bcolor = hash_cpu(record->cpu); |
219 | info->bfill = TRUE; | 397 | info->bfill = TRUE; |
220 | info->bstart = rtt_info->run_time; | 398 | info->bstart = rtt_info->run_time; |
221 | info->bend = ts; | 399 | info->bend = ts; |
222 | info->blabel = rtt_info->label; | 400 | info->blabel = rtt_info->label; |
223 | } | 401 | } |
224 | 402 | ||
225 | dprintf(3, "Switch away at %llu\n", ts); | 403 | dprintf(3, "Switch away for %d:%d on %d at %llu\n", |
404 | pid, job, record->cpu, ts); | ||
226 | rtt_info->run_time = 0ULL; | 405 | rtt_info->run_time = 0ULL; |
227 | rtt_info->last_cpu = -1; | 406 | rtt_info->run_cpu = NO_CPU; |
228 | 407 | ||
229 | ret = 1; | 408 | ret = 1; |
230 | } | 409 | } |
@@ -237,18 +416,14 @@ static int try_switch_to(struct graph_info *ginfo, struct rt_task_info *rtt_info | |||
237 | int job, pid, match, ret = 0; | 416 | int job, pid, match, ret = 0; |
238 | unsigned long long ts; | 417 | unsigned long long ts; |
239 | 418 | ||
240 | match = rt_graph_check_switch_to(&ginfo->rtinfo, ginfo->pevent, | 419 | match = rt_graph_check_switch_to(&ginfo->rtg_info, ginfo->pevent, |
241 | record, &pid, &job, &ts); | 420 | record, &pid, &job, &ts); |
242 | if (match && pid == rtt_info->pid) { | 421 | if (match && pid == rtt_info->pid) { |
243 | update_job(rtt_info, job); | 422 | update_job(rtt_info, job); |
244 | |||
245 | rtt_info->run_time = ts; | 423 | rtt_info->run_time = ts; |
246 | rtt_info->last_cpu = record->cpu; | 424 | rtt_info->run_cpu = record->cpu; |
247 | 425 | dprintf(3, "Switch to for %d:%d on %d at %llu\n", | |
248 | dprintf(3, "Switching to %d:%d at %llu on CPU %d\n", | 426 | pid, job, record->cpu, ts); |
249 | rtt_info->pid, rtt_info->last_job, | ||
250 | ts, rtt_info->last_cpu); | ||
251 | |||
252 | ret = 1; | 427 | ret = 1; |
253 | } | 428 | } |
254 | return ret; | 429 | return ret; |
@@ -261,12 +436,12 @@ static int try_other(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
261 | unsigned long long ts; | 436 | unsigned long long ts; |
262 | 437 | ||
263 | pid = rtt_info->pid; | 438 | pid = rtt_info->pid; |
264 | rt_graph_check_any(&ginfo->rtinfo, ginfo->pevent, record, | 439 | rt_graph_check_any(&ginfo->rtg_info, ginfo->pevent, record, |
265 | &epid, &eid, &ts); | 440 | &epid, &eid, &ts); |
266 | 441 | ||
267 | my_pid = (pid == epid); | 442 | my_pid = (pid == epid); |
268 | my_cpu = (rtt_info->run_time && record->cpu == rtt_info->last_cpu); | 443 | my_cpu = (rtt_info->run_time && record->cpu == rtt_info->run_cpu); |
269 | not_sa = (eid != ginfo->rtinfo.switch_away_id); | 444 | not_sa = (eid != ginfo->rtg_info.switch_away_id); |
270 | if (not_sa && (my_pid || my_cpu)) { | 445 | if (not_sa && (my_pid || my_cpu)) { |
271 | info->line = TRUE; | 446 | info->line = TRUE; |
272 | info->lcolor = hash_pid(record->cpu); | 447 | info->lcolor = hash_pid(record->cpu); |
@@ -277,117 +452,42 @@ static int try_other(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
277 | return ret; | 452 | return ret; |
278 | } | 453 | } |
279 | 454 | ||
280 | /* | 455 | static void do_plot_end(struct graph_info *ginfo, struct rt_task_info *rtt_info, |
281 | * Find the information for the last release of @rtt_info on @cpu before @time. | 456 | struct plot_info *info) |
282 | * @min_ts: the minimum time stamp to parse | ||
283 | * | ||
284 | * Returns release record and @out_job, @out_release, and @out_deadline if a | ||
285 | * release was found after @mints matching @time. | ||
286 | */ | ||
287 | static struct record* | ||
288 | get_previous_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | ||
289 | int cpu, | ||
290 | unsigned long long min_ts, unsigned long long time, | ||
291 | int *out_job, | ||
292 | unsigned long long *out_release, | ||
293 | unsigned long long *out_deadline) | ||
294 | { | ||
295 | int pid, job, match; | ||
296 | unsigned long long release, deadline; | ||
297 | struct record *last_record, *record, *ret = NULL; | ||
298 | struct rt_graph_info *rtg_info = &ginfo->rtinfo; | ||
299 | |||
300 | last_record = tracecmd_peek_data(ginfo->handle, cpu); | ||
301 | *out_job = *out_release = *out_deadline = 0; | ||
302 | if (!last_record) | ||
303 | return NULL; | ||
304 | last_record->ref_count++; | ||
305 | |||
306 | while ((record = tracecmd_read_prev(ginfo->handle, last_record))) { | ||
307 | if (record->ts < min_ts) { | ||
308 | free_record(record); | ||
309 | goto out; | ||
310 | } | ||
311 | match = rt_graph_check_task_release(rtg_info, ginfo->pevent, | ||
312 | record, &pid, &job, | ||
313 | &release, &deadline); | ||
314 | free_record(last_record); | ||
315 | last_record = record; | ||
316 | if (match && (pid == rtt_info->pid) && release <= time) { | ||
317 | ret = record; | ||
318 | last_record = NULL; | ||
319 | *out_job = job; | ||
320 | *out_release = release; | ||
321 | *out_deadline = deadline; | ||
322 | break; | ||
323 | } | ||
324 | }; | ||
325 | out: | ||
326 | free_record(last_record); | ||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Return information for @time, returns @job, @release, @deadline, and @record. | ||
332 | * @job: Job number at this time | ||
333 | * @release: Job's release time | ||
334 | * @deadline: Job's deadline | ||
335 | * @record: Matching record | ||
336 | */ | ||
337 | static int get_time_info(struct graph_info *ginfo, | ||
338 | struct rt_task_info *rtt_info, | ||
339 | unsigned long long time, | ||
340 | int *out_job, | ||
341 | unsigned long long *out_release, | ||
342 | unsigned long long *out_deadline, | ||
343 | struct record **out_record) | ||
344 | |||
345 | { | 457 | { |
346 | int cpu, job; | ||
347 | unsigned long long release, deadline, min_ts; | ||
348 | struct record *record; | 458 | struct record *record; |
349 | struct offset_cache *offsets; | 459 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; |
350 | 460 | int eid; | |
351 | /* Seek CPUs to first record after this time */ | ||
352 | *out_job = *out_release = *out_deadline = 0; | ||
353 | *out_record = find_record(ginfo, rtt_info->pid, time); | ||
354 | if (!*out_record) | ||
355 | return 0; | ||
356 | |||
357 | /* This is not necessarily correct for sporadic, but will do for now */ | ||
358 | if (time < rtt_info->first_rels[2]) { | ||
359 | job = (time >= rtt_info->first_rels[1]) ? 2 : 1; | ||
360 | *out_job = job; | ||
361 | *out_release = rtt_info->first_rels[job - 1]; | ||
362 | *out_deadline = rtt_info->first_rels[job]; | ||
363 | goto out; | ||
364 | } | ||
365 | |||
366 | min_ts = time - 2*rtt_info->wcet; | ||
367 | *out_job = *out_release = *out_deadline = 0; | ||
368 | 461 | ||
369 | offsets = save_offsets(ginfo); | 462 | if (rtt_info->run_time && rtt_info->run_cpu != NO_CPU) { |
370 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | 463 | /* A box was started, finish it */ |
371 | record = get_previous_release(ginfo, rtt_info, cpu, min_ts, | 464 | info->box = TRUE; |
372 | time, &job, &release, &deadline); | 465 | info->bcolor = hash_cpu(rtt_info->run_cpu); |
373 | if (record && record->ts > min_ts) { | 466 | info->bfill = TRUE; |
374 | *out_job = job; | 467 | info->bstart = rtt_info->run_time; |
375 | *out_release = release; | 468 | info->bend = ginfo->view_end_time; |
376 | *out_deadline = deadline; | 469 | info->blabel = rtt_info->label; |
377 | min_ts = record->ts; | 470 | } else if (rtt_info->block_time && rtt_info->block_cpu != NO_CPU) { |
471 | /* Blocking happened */ | ||
472 | } else if (rtt_info->fresh) { | ||
473 | /* Nothing happened!*/ | ||
474 | record = next_box_record(ginfo, rtt_info, | ||
475 | ginfo->view_end_time, &eid); | ||
476 | |||
477 | if (record) { | ||
478 | if (eid == rtg_info->switch_away_id) { | ||
479 | /* In a run */ | ||
480 | info->box = TRUE; | ||
481 | info->bcolor = hash_cpu(record->cpu); | ||
482 | info->bfill = TRUE; | ||
483 | info->bstart = ginfo->view_start_time; | ||
484 | info->bend = ginfo->view_end_time; | ||
485 | } else if (eid == rtg_info->task_resume_id) { | ||
486 | /* In a block */ | ||
487 | } | ||
488 | free_record(record); | ||
378 | } | 489 | } |
379 | free_record(record); | ||
380 | } | 490 | } |
381 | restore_offsets(ginfo, offsets); | ||
382 | out: | ||
383 | return 1; | ||
384 | } | ||
385 | |||
386 | static inline int in_res(struct graph_info *ginfo, unsigned long long time, | ||
387 | unsigned long target) | ||
388 | { | ||
389 | return time > target - 2/ginfo->resolution && | ||
390 | time < target + 2/ginfo->resolution; | ||
391 | } | 491 | } |
392 | 492 | ||
393 | static int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | 493 | static int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, |
@@ -396,15 +496,11 @@ static int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | |||
396 | struct rt_task_info *rtt_info = plot->private; | 496 | struct rt_task_info *rtt_info = plot->private; |
397 | int match; | 497 | int match; |
398 | 498 | ||
499 | dprintf(4,"%s\n", __FUNCTION__); | ||
500 | |||
399 | /* No more records, finish what we started */ | 501 | /* No more records, finish what we started */ |
400 | if (!record) { | 502 | if (!record) { |
401 | if (rtt_info->last_cpu >= 0 && | 503 | do_plot_end(ginfo, rtt_info, info); |
402 | rtt_info->run_time) { | ||
403 | info->box = TRUE; | ||
404 | info->bstart = rtt_info->last_time; | ||
405 | info->bend = ginfo->view_end_time; | ||
406 | info->bcolor = hash_cpu(rtt_info->last_cpu); | ||
407 | } | ||
408 | return 0; | 504 | return 0; |
409 | } | 505 | } |
410 | 506 | ||
@@ -417,11 +513,6 @@ static int rt_task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | |||
417 | try_resume(ginfo, rtt_info, record, info) || | 513 | try_resume(ginfo, rtt_info, record, info) || |
418 | try_other(ginfo, rtt_info, record, info); | 514 | try_other(ginfo, rtt_info, record, info); |
419 | 515 | ||
420 | if (match) { | ||
421 | rtt_info->last_time = get_rts(ginfo, record); | ||
422 | rtt_info->last_cpu = record->cpu; | ||
423 | } | ||
424 | |||
425 | return match; | 516 | return match; |
426 | } | 517 | } |
427 | 518 | ||
@@ -431,22 +522,26 @@ static void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot | |||
431 | int i; | 522 | int i; |
432 | struct rt_task_info *rtt_info = plot->private; | 523 | struct rt_task_info *rtt_info = plot->private; |
433 | 524 | ||
525 | dprintf(4,"%s\n", __FUNCTION__); | ||
526 | |||
434 | rtt_info->wcet = 0ULL; | 527 | rtt_info->wcet = 0ULL; |
435 | rtt_info->period = 0ULL; | 528 | rtt_info->period = 0ULL; |
436 | rtt_info->run_time = 0ULL; | 529 | |
437 | rtt_info->block_time = 0ULL; | 530 | rtt_info->run_time = time; |
438 | rtt_info->last_cpu = -1; | 531 | rtt_info->block_time = time; |
439 | rtt_info->last_job = -1; | 532 | rtt_info->run_cpu = NO_CPU; |
533 | rtt_info->block_cpu = NO_CPU; | ||
440 | rtt_info->params_found = FALSE; | 534 | rtt_info->params_found = FALSE; |
535 | rtt_info->fresh = TRUE; | ||
441 | for (i = 0; i < 3; i++) | 536 | for (i = 0; i < 3; i++) |
442 | rtt_info->first_rels[i] = 0ULL; | 537 | rtt_info->first_rels[i] = 0ULL; |
443 | update_job(rtt_info, 0); | 538 | rtt_info->last_job = 0; |
444 | } | 539 | } |
445 | 540 | ||
446 | static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) | 541 | static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) |
447 | { | 542 | { |
448 | struct rt_task_info *rtt_info = plot->private; | 543 | struct rt_task_info *rtt_info = plot->private; |
449 | printf("Destroying plot %d\n", rtt_info->pid); | 544 | dprintf(4,"%s\n", __FUNCTION__); |
450 | free(rtt_info->label); | 545 | free(rtt_info->label); |
451 | task_plot_destroy(ginfo, plot); | 546 | task_plot_destroy(ginfo, plot); |
452 | } | 547 | } |
@@ -462,6 +557,8 @@ static int rt_task_plot_display_last_event(struct graph_info *ginfo, | |||
462 | struct offset_cache *offsets; | 557 | struct offset_cache *offsets; |
463 | struct rt_task_info *rtt_info = plot->private; | 558 | struct rt_task_info *rtt_info = plot->private; |
464 | 559 | ||
560 | dprintf(4,"%s\n", __FUNCTION__); | ||
561 | |||
465 | offsets = save_offsets(ginfo); | 562 | offsets = save_offsets(ginfo); |
466 | record = find_display_record(ginfo, rtt_info->pid, time); | 563 | record = find_display_record(ginfo, rtt_info->pid, time); |
467 | restore_offsets(ginfo, offsets); | 564 | restore_offsets(ginfo, offsets); |
@@ -481,10 +578,17 @@ static int rt_task_plot_display_last_event(struct graph_info *ginfo, | |||
481 | return 1; | 578 | return 1; |
482 | } | 579 | } |
483 | 580 | ||
581 | static inline int in_res(struct graph_info *ginfo, unsigned long long time, | ||
582 | unsigned long target) | ||
583 | { | ||
584 | return time > target - 2/ginfo->resolution && | ||
585 | time < target + 2/ginfo->resolution; | ||
586 | } | ||
587 | |||
484 | static int rt_task_plot_display_info(struct graph_info *ginfo, | 588 | static int rt_task_plot_display_info(struct graph_info *ginfo, |
485 | struct graph_plot *plot, | 589 | struct graph_plot *plot, |
486 | struct trace_seq *s, | 590 | struct trace_seq *s, |
487 | unsigned long long time) | 591 | unsigned long long time) |
488 | { | 592 | { |
489 | const char *comm; | 593 | const char *comm; |
490 | int pid, job, eid; | 594 | int pid, job, eid; |
@@ -495,6 +599,8 @@ static int rt_task_plot_display_info(struct graph_info *ginfo, | |||
495 | struct rt_task_info *rtt_info = plot->private; | 599 | struct rt_task_info *rtt_info = plot->private; |
496 | struct offset_cache *offsets; | 600 | struct offset_cache *offsets; |
497 | 601 | ||
602 | dprintf(4,"%s\n", __FUNCTION__); | ||
603 | |||
498 | offsets = save_offsets(ginfo); | 604 | offsets = save_offsets(ginfo); |
499 | get_time_info(ginfo, rtt_info, time, | 605 | get_time_info(ginfo, rtt_info, time, |
500 | &job, &release, &deadline, &record); | 606 | &job, &release, &deadline, &record); |
@@ -535,6 +641,8 @@ static int rt_task_plot_match_time(struct graph_info *ginfo, | |||
535 | struct rt_task_info *rtt_info = plot->private; | 641 | struct rt_task_info *rtt_info = plot->private; |
536 | int next_cpu, match, ret; | 642 | int next_cpu, match, ret; |
537 | 643 | ||
644 | dprintf(4,"%s\n", __FUNCTION__); | ||
645 | |||
538 | set_cpus_to_rts(ginfo, time); | 646 | set_cpus_to_rts(ginfo, time); |
539 | 647 | ||
540 | do { | 648 | do { |
@@ -600,14 +708,14 @@ void rt_plot_task_plotted(struct graph_info *ginfo, gint **plotted) | |||
600 | 708 | ||
601 | void rt_plot_task(struct graph_info *ginfo, int pid, int pos) | 709 | void rt_plot_task(struct graph_info *ginfo, int pid, int pos) |
602 | { | 710 | { |
603 | struct rt_graph_info *rtinfo = &ginfo->rtinfo; | 711 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; |
604 | struct rt_task_info *rtt_info; | 712 | struct rt_task_info *rtt_info; |
605 | struct graph_plot *plot; | 713 | struct graph_plot *plot; |
606 | const char *comm; | 714 | const char *comm; |
607 | char *plot_label; | 715 | char *plot_label; |
608 | int len; | 716 | int len; |
609 | 717 | ||
610 | if (!find_task_list(rtinfo->tasks, pid)) | 718 | if (!find_task_list(rtg_info->tasks, pid)) |
611 | die("Cannot create RT plot of non-RT task %d!\n", pid); | 719 | die("Cannot create RT plot of non-RT task %d!\n", pid); |
612 | 720 | ||
613 | rtt_info = malloc_or_die(sizeof(*rtt_info)); | 721 | rtt_info = malloc_or_die(sizeof(*rtt_info)); |
diff --git a/rt-plot-task.h b/rt-plot-task.h index d3464e9..9f031e9 100644 --- a/rt-plot-task.h +++ b/rt-plot-task.h | |||
@@ -10,17 +10,18 @@ struct rt_task_info { | |||
10 | 10 | ||
11 | /* For drawing squares */ | 11 | /* For drawing squares */ |
12 | unsigned long long run_time; | 12 | unsigned long long run_time; |
13 | int run_cpu; | ||
13 | unsigned long long block_time; | 14 | unsigned long long block_time; |
15 | int block_cpu; | ||
14 | 16 | ||
15 | /* For managing state */ | 17 | /* For managing state */ |
16 | int last_job; | 18 | int last_job; |
17 | int last_cpu; | ||
18 | unsigned long long last_time; | ||
19 | 19 | ||
20 | /* Used to get around bugs(ish) */ | 20 | /* Used to get around bugs(ish) */ |
21 | unsigned long long first_rels[3]; | 21 | unsigned long long first_rels[3]; |
22 | 22 | ||
23 | gboolean params_found; | 23 | gboolean params_found; |
24 | gboolean fresh; | ||
24 | char *label; | 25 | char *label; |
25 | }; | 26 | }; |
26 | 27 | ||
diff --git a/trace-graph.c b/trace-graph.c index 2cf7a95..f3a5916 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
@@ -119,7 +119,7 @@ static void init_event_cache(struct graph_info *ginfo) | |||
119 | */ | 119 | */ |
120 | ginfo->read_comms = TRUE; | 120 | ginfo->read_comms = TRUE; |
121 | 121 | ||
122 | init_rt_event_cache(&ginfo->rtinfo); | 122 | init_rt_event_cache(&ginfo->rtg_info); |
123 | } | 123 | } |
124 | 124 | ||
125 | struct filter_task_item * | 125 | struct filter_task_item * |
@@ -1719,16 +1719,86 @@ static void draw_plot(struct graph_info *ginfo, struct graph_plot *plot, | |||
1719 | plot->p1, plot->p2, ginfo->draw_width, width_16, font); | 1719 | plot->p1, plot->p2, ginfo->draw_width, width_16, font); |
1720 | } | 1720 | } |
1721 | 1721 | ||
1722 | static void draw_nonrt_plots(struct graph_info *ginfo) | ||
1723 | { | ||
1724 | gint cpu, pid; | ||
1725 | struct record *record; | ||
1726 | struct plot_hash *hash; | ||
1727 | struct plot_list *list; | ||
1728 | |||
1729 | tracecmd_set_all_cpus_to_timestamp(ginfo->handle, | ||
1730 | ginfo->view_start_time); | ||
1731 | while ((record = tracecmd_read_next_data(ginfo->handle, &cpu))) { | ||
1732 | if (record->ts < ginfo->view_start_time) { | ||
1733 | free_record(record); | ||
1734 | continue; | ||
1735 | } | ||
1736 | if (record->ts > ginfo->view_end_time) { | ||
1737 | free_record(record); | ||
1738 | break; | ||
1739 | } | ||
1740 | hash = trace_graph_plot_find_cpu(ginfo, cpu); | ||
1741 | if (hash) { | ||
1742 | for (list = hash->plots; list; list = list->next) { | ||
1743 | if (list->plot->type == PLOT_TYPE_RT_TASK) | ||
1744 | continue; | ||
1745 | draw_plot(ginfo, list->plot, record); | ||
1746 | } | ||
1747 | } | ||
1748 | pid = pevent_data_pid(ginfo->pevent, record); | ||
1749 | hash = trace_graph_plot_find_task(ginfo, pid); | ||
1750 | if (hash) { | ||
1751 | for (list = hash->plots; list; list = list->next) { | ||
1752 | if (list->plot->type == PLOT_TYPE_RT_TASK) | ||
1753 | continue; | ||
1754 | draw_plot(ginfo, list->plot, record); | ||
1755 | } | ||
1756 | } | ||
1757 | for (list = ginfo->all_recs; list; list = list->next) { | ||
1758 | if (list->plot->type == PLOT_TYPE_RT_TASK) | ||
1759 | continue; | ||
1760 | draw_plot(ginfo, list->plot, record); | ||
1761 | } | ||
1762 | free_record(record); | ||
1763 | } | ||
1764 | } | ||
1765 | |||
1766 | static void draw_rt_plots(struct graph_info *ginfo) | ||
1767 | { | ||
1768 | gint cpu; | ||
1769 | struct record *record; | ||
1770 | struct plot_list *list; | ||
1771 | |||
1772 | set_cpus_to_rts(ginfo, ginfo->view_start_time); | ||
1773 | while ((record = tracecmd_read_next_data(ginfo->handle, &cpu))) { | ||
1774 | if (get_rts(ginfo, record) < ginfo->view_start_time) { | ||
1775 | free_record(record); | ||
1776 | continue; | ||
1777 | } | ||
1778 | if (get_rts(ginfo, record) > ginfo->view_end_time) { | ||
1779 | free_record(record); | ||
1780 | break; | ||
1781 | } | ||
1782 | for (list = ginfo->all_recs; list; list = list->next) { | ||
1783 | if (list->plot->type != PLOT_TYPE_RT_TASK) | ||
1784 | continue; | ||
1785 | draw_plot(ginfo, list->plot, record); | ||
1786 | } | ||
1787 | free_record(record); | ||
1788 | } | ||
1789 | } | ||
1790 | |||
1722 | static void draw_plots(struct graph_info *ginfo, gint new_width) | 1791 | static void draw_plots(struct graph_info *ginfo, gint new_width) |
1723 | { | 1792 | { |
1724 | struct plot_list *list; | 1793 | struct plot_list *list; |
1725 | struct graph_plot *plot; | 1794 | struct graph_plot *plot; |
1726 | struct record *record; | 1795 | struct record *record; |
1727 | struct plot_hash *hash; | 1796 | struct plot_hash *hash; |
1728 | gint pid; | ||
1729 | gint cpu; | 1797 | gint cpu; |
1730 | gint i; | 1798 | gint i; |
1731 | 1799 | ||
1800 | printf("----Drawing plots----\n"); | ||
1801 | |||
1732 | /* Initialize plots */ | 1802 | /* Initialize plots */ |
1733 | for (i = 0; i < ginfo->plots; i++) { | 1803 | for (i = 0; i < ginfo->plots; i++) { |
1734 | plot = ginfo->plot_array[i]; | 1804 | plot = ginfo->plot_array[i]; |
@@ -1748,13 +1818,11 @@ static void draw_plots(struct graph_info *ginfo, gint new_width) | |||
1748 | set_color(ginfo->draw, plot->gc, plot->last_color); | 1818 | set_color(ginfo->draw, plot->gc, plot->last_color); |
1749 | } | 1819 | } |
1750 | 1820 | ||
1751 | tracecmd_set_all_cpus_to_timestamp(ginfo->handle, | ||
1752 | ginfo->view_start_time); | ||
1753 | |||
1754 | trace_set_cursor(GDK_WATCH); | 1821 | trace_set_cursor(GDK_WATCH); |
1755 | |||
1756 | /* Shortcut if we don't have any task plots */ | 1822 | /* Shortcut if we don't have any task plots */ |
1757 | if (!ginfo->nr_task_hash && !ginfo->all_recs) { | 1823 | if (!ginfo->nr_task_hash && !ginfo->all_recs) { |
1824 | tracecmd_set_all_cpus_to_timestamp(ginfo->handle, | ||
1825 | ginfo->view_start_time); | ||
1758 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | 1826 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { |
1759 | hash = trace_graph_plot_find_cpu(ginfo, cpu); | 1827 | hash = trace_graph_plot_find_cpu(ginfo, cpu); |
1760 | if (!hash) | 1828 | if (!hash) |
@@ -1777,30 +1845,8 @@ static void draw_plots(struct graph_info *ginfo, gint new_width) | |||
1777 | goto out; | 1845 | goto out; |
1778 | } | 1846 | } |
1779 | 1847 | ||
1780 | while ((record = tracecmd_read_next_data(ginfo->handle, &cpu))) { | 1848 | draw_nonrt_plots(ginfo); |
1781 | if (record->ts < ginfo->view_start_time) { | 1849 | draw_rt_plots(ginfo); |
1782 | free_record(record); | ||
1783 | continue; | ||
1784 | } | ||
1785 | if (record->ts > ginfo->view_end_time) { | ||
1786 | free_record(record); | ||
1787 | break; | ||
1788 | } | ||
1789 | hash = trace_graph_plot_find_cpu(ginfo, cpu); | ||
1790 | if (hash) { | ||
1791 | for (list = hash->plots; list; list = list->next) | ||
1792 | draw_plot(ginfo, list->plot, record); | ||
1793 | } | ||
1794 | pid = pevent_data_pid(ginfo->pevent, record); | ||
1795 | hash = trace_graph_plot_find_task(ginfo, pid); | ||
1796 | if (hash) { | ||
1797 | for (list = hash->plots; list; list = list->next) | ||
1798 | draw_plot(ginfo, list->plot, record); | ||
1799 | } | ||
1800 | for (list = ginfo->all_recs; list; list = list->next) | ||
1801 | draw_plot(ginfo, list->plot, record); | ||
1802 | free_record(record); | ||
1803 | } | ||
1804 | 1850 | ||
1805 | out: | 1851 | out: |
1806 | for (i = 0; i < ginfo->plots; i++) { | 1852 | for (i = 0; i < ginfo->plots; i++) { |
@@ -2376,6 +2422,7 @@ void trace_graph_refresh(struct graph_info *ginfo) | |||
2376 | ginfo->draw_height = PLOT_SPACE(ginfo->plots); | 2422 | ginfo->draw_height = PLOT_SPACE(ginfo->plots); |
2377 | gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height); | 2423 | gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height); |
2378 | update_label_window(ginfo); | 2424 | update_label_window(ginfo); |
2425 | printf("----Redrawing graph----\n"); | ||
2379 | redraw_graph(ginfo); | 2426 | redraw_graph(ginfo); |
2380 | } | 2427 | } |
2381 | 2428 | ||
diff --git a/trace-graph.h b/trace-graph.h index 1cb77b9..788c77d 100644 --- a/trace-graph.h +++ b/trace-graph.h | |||
@@ -246,7 +246,7 @@ struct graph_info { | |||
246 | struct format_field *wakeup_new_pid_field; | 246 | struct format_field *wakeup_new_pid_field; |
247 | struct format_field *wakeup_new_success_field; | 247 | struct format_field *wakeup_new_success_field; |
248 | 248 | ||
249 | struct rt_graph_info rtinfo; | 249 | struct rt_graph_info rtg_info; |
250 | 250 | ||
251 | gboolean read_comms; /* Read all comms on first load */ | 251 | gboolean read_comms; /* Read all comms on first load */ |
252 | 252 | ||
diff --git a/trace-plot-cpu.c b/trace-plot-cpu.c index 00f07af..28baaa5 100644 --- a/trace-plot-cpu.c +++ b/trace-plot-cpu.c | |||
@@ -89,7 +89,7 @@ static int filter_record(struct graph_info *ginfo, | |||
89 | 89 | ||
90 | 90 | ||
91 | /* Load real-time records */ | 91 | /* Load real-time records */ |
92 | rt_graph_check_task_param(&ginfo->rtinfo, ginfo->pevent, record, | 92 | rt_graph_check_task_param(&ginfo->rtg_info, ginfo->pevent, record, |
93 | &rpid, &wcet, &period); | 93 | &rpid, &wcet, &period); |
94 | 94 | ||
95 | if (trace_graph_check_sched_switch(ginfo, record, sched_pid, &comm)) { | 95 | if (trace_graph_check_sched_switch(ginfo, record, sched_pid, &comm)) { |