aboutsummaryrefslogtreecommitdiffstats
path: root/rt-plot-vcpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'rt-plot-vcpu.c')
-rw-r--r--rt-plot-vcpu.c372
1 files changed, 372 insertions, 0 deletions
diff --git a/rt-plot-vcpu.c b/rt-plot-vcpu.c
new file mode 100644
index 0000000..fb1cf8d
--- /dev/null
+++ b/rt-plot-vcpu.c
@@ -0,0 +1,372 @@
1#include <stdio.h>
2#include <string.h>
3#include "trace-graph.h"
4
5#define DEBUG_LEVEL 0
6#if DEBUG_LEVEL > 0
7#define dprintf(l, x...) \
8 do { \
9 if (l <= DEBUG_LEVEL) \
10 printf(x); \
11 } while (0)
12#else
13#define dprintf(l, x...) do { if (0) printf(x); } while (0)
14#endif
15
16static void update_tid(struct vcpu_info *info, int tid)
17{
18 info->fresh = FALSE;
19 if (tid != info->run_tid) {
20 info->run_tid = tid;
21 snprintf(info->label, LLABEL, "%d", tid);
22 }
23}
24
25
26static int try_release(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
27 struct record *record, struct plot_info *info)
28{
29 int sid, job, match, ret = 0;
30 unsigned long long release, deadline;
31
32 match = rt_graph_check_server_release(ginfo, record, &sid, &job,
33 &release, &deadline);
34 if (match && sid == vcpu_info->sid) {
35 info->release = TRUE;
36 info->rtime = release;
37
38 info->deadline = TRUE;
39 info->dtime = deadline;
40
41 dprintf(3, "VCPU release for %d:%d on %d, rel: %llu, dead: %llu\n",
42 sid, job, record->cpu, release, deadline);
43
44 ret = 1;
45 }
46 return ret;
47}
48
49static int try_completion(struct graph_info *ginfo,
50 struct vcpu_info *vcpu_info,
51 struct record *record, struct plot_info *info)
52{
53 int sid, job, match, ret = 0;
54 unsigned long long ts;
55
56 match = rt_graph_check_server_completion(ginfo, record, &sid, &job, &ts);
57 if (match && sid == vcpu_info->sid) {
58
59 info->completion = TRUE;
60 info->ctime = ts;
61
62 dprintf(3, "VCPU completion for %d:%d on %d at %llu\n",
63 sid, job, record->cpu, ts);
64 ret = 1;
65 }
66 return ret;
67}
68
69static int try_block(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
70 struct record *record, struct plot_info *info)
71{
72 int sid, match, ret = 0;
73 unsigned long long ts;
74
75 match = rt_graph_check_server_block(ginfo, record, &sid, &ts);
76 if (match && sid == vcpu_info->sid) {
77 vcpu_info->fresh = FALSE;
78 vcpu_info->block_time = ts;
79 vcpu_info->block_cpu = NO_CPU;
80 dprintf(3, "VCPU resume for %d on %d at %llu\n",
81 sid, record->cpu, ts);
82 ret = 1;
83 }
84 return ret;
85}
86
87static int try_resume(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
88 struct record *record, struct plot_info *info)
89{
90 int sid, match, ret = 0;
91 unsigned long long ts;
92
93 match = rt_graph_check_server_resume(ginfo, record, &sid, &ts);
94
95 if (match && sid == vcpu_info->sid) {
96 info->box = TRUE;
97 info->bcolor = 0x0;
98 info->bfill = TRUE;
99 info->bthin = TRUE;
100 info->bstart = vcpu_info->block_time;
101 info->bend = ts;
102 vcpu_info->fresh = FALSE;
103
104 vcpu_info->block_time = 0ULL;
105 vcpu_info->block_cpu = NO_CPU;
106 dprintf(3, "VCPU resume for %d on %d at %llu\n",
107 sid, record->cpu, ts);
108
109 ret = 1;
110 }
111 return ret;
112}
113
114static int
115try_server_switch_away(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
116 struct record *record, struct plot_info *info)
117{
118 int job, sid, tid, match, ret = 0;
119 unsigned long long ts;
120
121 match = rt_graph_check_server_switch_away(ginfo, record,
122 &sid, &job,
123 &tid, &ts);
124 if (match && sid == vcpu_info->sid) {
125 update_tid(vcpu_info, tid);
126
127 if (vcpu_info->run_time && vcpu_info->run_time < ts &&
128 job != 1) {
129 info->box = TRUE;
130 info->bcolor = hash_pid(tid);
131 info->bfill = vcpu_info->running;
132 info->bstart = vcpu_info->run_time;
133 info->bend = ts;
134 info->blabel = vcpu_info->label;
135 }
136
137 dprintf(3, "VCPU switch away from %d on %d:%d at %llu\n",
138 tid, sid, job, ts);
139 vcpu_info->run_time = 0ULL;
140 vcpu_info->run_cpu = NO_CPU;
141 vcpu_info->run_tid = 0;
142 vcpu_info->running = FALSE;
143
144 ret = 1;
145 }
146
147 return ret;
148}
149
150static int try_server_switch_to(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
151 struct record *record, struct plot_info *info)
152{
153 int job, sid, tid, match, ret = 0;
154 unsigned long long ts;
155
156 match = rt_graph_check_server_switch_to(ginfo, record,
157 &sid, &job, &tid, &ts);
158 if (match && sid == vcpu_info->sid) {
159 update_tid(vcpu_info, tid);
160 vcpu_info->run_time = ts;
161 vcpu_info->run_cpu = record->cpu;
162 vcpu_info->run_tid = tid;
163 dprintf(3, "Switch to %d for %d:%d at %llu\n",
164 tid, sid, job, ts);
165 ret = 1;
166 }
167 return ret;
168}
169
170static int try_switch_to(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
171 struct record *record, struct plot_info *info)
172{
173 int job, pid, match, ret = 0;
174 unsigned long long ts;
175
176 match = rt_graph_check_switch_to(ginfo, record, &pid, &job, &ts);
177 if (match && pid && pid == vcpu_info->run_tid && vcpu_info->run_time) {
178 vcpu_info->running = TRUE;
179
180 /* Draw empty box for time spent not running a task */
181 info->box = TRUE;
182 info->bcolor = hash_pid(pid);
183 info->bfill = FALSE;
184 info->bstart = vcpu_info->run_time;
185 info->bend = ts;
186 info->blabel = vcpu_info->label;
187
188 vcpu_info->run_time = ts;
189 ret = 1;
190 }
191 return ret;
192}
193
194static int try_switch_away(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
195 struct record *record, struct plot_info *info)
196{
197 int job, pid, match, ret = 0;
198 unsigned long long ts;
199
200 match = rt_graph_check_switch_away(ginfo, record, &pid, &job, &ts);
201 if (match && pid && pid == vcpu_info->run_tid && vcpu_info->running) {
202 vcpu_info->running = FALSE;
203
204 info->box = TRUE;
205 info->bcolor = hash_pid(pid);
206 info->bfill = TRUE;
207 info->bstart = vcpu_info->run_time;
208 info->bend = ts;
209 info->blabel = vcpu_info->label;
210
211 vcpu_info->run_time = ts;
212 ret = 1;
213 }
214 return ret;
215}
216
217
218static void do_plot_end(struct graph_info *ginfo, struct vcpu_info *vcpu_info,
219 struct plot_info *info)
220{
221 /* TODO: me */
222}
223
224
225static int rt_vcpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot,
226 struct record *record, struct plot_info *info)
227{
228 int match;
229 struct vcpu_info *vcpu_info = plot->private;
230
231 if (!record) {
232 do_plot_end(ginfo, vcpu_info, info);
233 return 0;
234 }
235
236 match = try_server_switch_away(ginfo, vcpu_info, record, info) ||
237 try_server_switch_to(ginfo, vcpu_info, record, info) ||
238 try_block(ginfo, vcpu_info, record, info) ||
239 try_resume(ginfo, vcpu_info, record, info) ||
240 try_release(ginfo, vcpu_info, record, info) ||
241 try_completion(ginfo, vcpu_info, record, info) ||
242 try_switch_to(ginfo, vcpu_info, record, info) ||
243 try_switch_away(ginfo, vcpu_info, record, info);
244 return match;
245}
246
247static void rt_vcpu_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
248 unsigned long long time)
249{
250 struct vcpu_info *vcpu_info = plot->private;
251
252 dprintf(4,"%s\n", __FUNCTION__);
253
254 vcpu_info->run_time = time;
255 vcpu_info->block_time = time;
256 vcpu_info->run_cpu = NO_CPU;
257 vcpu_info->run_tid = 0;
258 vcpu_info->block_cpu = NO_CPU;
259 vcpu_info->fresh = FALSE;
260
261 vcpu_info->fresh = TRUE;
262 vcpu_info->running = FALSE;
263
264 vcpu_info->run_tid = -1;
265 update_tid(vcpu_info, 0);
266}
267
268static void rt_vcpu_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot)
269{
270 struct vcpu_info *vcpu_info = plot->private;
271 trace_graph_plot_remove_all_recs(ginfo, plot);
272 free(vcpu_info->label);
273 free(vcpu_info);
274}
275
276/*
277 * Return 1 if @record is relevant to @match_sid.
278 */
279static int rt_vcpu_plot_record_matches(struct rt_plot_common *rt,
280 struct graph_info *ginfo,
281 struct record *record)
282{
283 struct vcpu_info *vcpu_info = (struct vcpu_info*)rt;
284 int dint, sid, match;
285 unsigned long long dull;
286
287#define ARG ginfo, record, &sid
288 match = rt_graph_check_server_switch_to(ARG, &dint, &dint, &dull) ||
289 rt_graph_check_server_switch_away(ARG, &dint, &dint, &dull) ||
290 rt_graph_check_server_completion(ARG, &dint, &dull) ||
291 rt_graph_check_server_release(ARG, &dint, &dull, &dull) ||
292 rt_graph_check_server_block(ARG, &dull) ||
293 rt_graph_check_server_resume(ARG, &dull);
294#undef ARG
295 return (sid == vcpu_info->sid);
296}
297
298/*
299 * Return true if the given record type is drawn on screen. This does not
300 * include event line markes.
301 */
302static int
303rt_vcpu_plot_is_drawn(struct graph_info *ginfo, int eid)
304{
305 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
306 return (eid == rtg_info->server_switch_to_id ||
307 eid == rtg_info->server_switch_away_id ||
308 eid == rtg_info->server_release_id ||
309 eid == rtg_info->server_completion_id ||
310 eid == rtg_info->server_block_id ||
311 eid == rtg_info->server_resume_id);
312}
313
314static struct record*
315rt_vcpu_plot_write_header(struct rt_plot_common *rt,
316 struct graph_info *ginfo,
317 struct trace_seq *s,
318 unsigned long long time)
319{
320 int is_running, job, tid;
321 unsigned long long release, deadline;
322 struct vcpu_info *vcpu_info = (struct vcpu_info*)rt;
323 struct record *record;
324
325 is_running = get_server_info(ginfo, rt, vcpu_info->sid, time,
326 &release, &deadline,
327 &job, &tid, &record);
328
329 trace_seq_printf(s, "%s-%d:%d", vcpu_info->cont->name,
330 vcpu_info->sid, job);
331 if (is_running) {
332 trace_seq_printf(s, " - %d", tid);
333 }
334 trace_seq_putc(s, '\n');
335 return record;
336}
337
338
339const struct plot_callbacks rt_vcpu_cb = {
340 .start = rt_vcpu_plot_start,
341 .destroy = rt_vcpu_plot_destroy,
342 .plot_event = rt_vcpu_plot_event,
343 .display_last_event = rt_plot_display_last_event,
344 .display_info = rt_plot_display_info,
345 .match_time = rt_plot_match_time,
346 .find_record = rt_plot_find_record,
347};
348
349void insert_vcpu(struct graph_info *ginfo, struct cont_list *cont,
350 struct vcpu_list *vcpu_info)
351{
352 struct graph_plot *plot;
353 struct vcpu_info *vcpu;
354 char *label;
355
356 vcpu = malloc_or_die(sizeof(*vcpu));
357 vcpu->sid = vcpu_info->sid;
358 vcpu->cont = cont;
359 vcpu->label = malloc_or_die(LLABEL);
360
361 vcpu->common.record_matches = rt_vcpu_plot_record_matches;
362 vcpu->common.is_drawn = rt_vcpu_plot_is_drawn;
363 vcpu->common.write_header = rt_vcpu_plot_write_header;
364
365 g_assert(cont);
366
367 label = malloc_or_die(1);
368 snprintf(label, 2, " ");
369 plot = trace_graph_plot_append(ginfo, label, PLOT_TYPE_SERVER_CPU,
370 TIME_TYPE_RT, &rt_vcpu_cb, vcpu);
371 trace_graph_plot_add_all_recs(ginfo, plot);
372}