aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-03-28 16:34:20 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-03-28 16:34:20 -0400
commit57672aa4f46311a82d4a9437d512adb099a7f8bf (patch)
treedcd072ee724f62327599df2b3c3edaaabacbe45b
parentb53dd6d749e0a164010f2cf1fedab2b10b8bb305 (diff)
containers: virtual cpus display in the normal case
-rw-r--r--rt-graph.h2
-rw-r--r--rt-plot-container.c374
-rw-r--r--rt-plot-container.h21
-rw-r--r--rt-plot-task.c2
-rw-r--r--rt-plot-vcpu-task.h9
-rw-r--r--rt-plot-vcpu.c372
-rw-r--r--rt-plot-vcpu.h22
-rw-r--r--rt-plot.h65
-rw-r--r--trace-graph.c2
9 files changed, 866 insertions, 3 deletions
diff --git a/rt-graph.h b/rt-graph.h
index 8252d61..12ce72d 100644
--- a/rt-graph.h
+++ b/rt-graph.h
@@ -10,7 +10,7 @@
10#include "rt-plot-container.h" 10#include "rt-plot-container.h"
11 11
12#define LLABEL 30 12#define LLABEL 30
13#define SEARCH_PERIODS 3 13#define SEARCH_PERIODS 1
14#define NO_CPU -1 14#define NO_CPU -1
15#define RT_TS_FIELD "__rt_ts" 15#define RT_TS_FIELD "__rt_ts"
16 16
diff --git a/rt-plot-container.c b/rt-plot-container.c
new file mode 100644
index 0000000..f36e2f8
--- /dev/null
+++ b/rt-plot-container.c
@@ -0,0 +1,374 @@
1#include <stdio.h>
2#include <string.h>
3#include "trace-graph.h"
4#include "trace-hash.h"
5#include "trace-filter.h"
6
7struct vtask_info {
8 struct rt_task_info task_info;
9 struct cont_list *cont;
10};
11
12static void insert_vtask(struct graph_info *ginfo, struct cont_list *cont,
13 struct vcpu_list *vcpu_info)
14{
15 struct graph_plot *plot;
16 struct vtask_info *vtask;
17 char *label;
18 int len;
19
20 vtask = malloc_or_die(sizeof(*vtask));
21 vtask->task_info.pid = vcpu_info->sid;
22 vtask->task_info.wcet = vcpu_info->params.wcet;
23 vtask->task_info.period = vcpu_info->params.period;
24 vtask->task_info.label = malloc_or_die(LLABEL);
25 vtask->cont = cont;
26
27 g_assert(cont);
28
29 len = strlen(cont->name) + 100;
30 label = malloc_or_die(len);
31 snprintf(label, len, "%s-%d\n(%1.1f, %1.1f)",
32 cont->name, -vtask->task_info.pid,
33 nano_as_milli(vtask->task_info.wcet),
34 nano_as_milli(vtask->task_info.period));
35
36 plot = trace_graph_plot_append(ginfo, label, PLOT_TYPE_SERVER_TASK,
37 TIME_TYPE_RT, &rt_task_cb, vtask);
38 trace_graph_plot_add_all_recs(ginfo, plot);
39}
40
41int rt_plot_get_containers(struct graph_info *ginfo, gint **conts,
42 gboolean plotted_only)
43{
44 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
45 struct cont_list *cont;
46 int i, count = 0;
47
48 *conts = NULL;
49 for (i = 0; i < CONT_HASH_SIZE; i++) {
50 for (cont = rtg_info->containers[i]; cont; cont = cont->next) {
51 if (!plotted_only || cont->plotted) {
52 trace_array_add(conts, &count, cont->cid);
53 }
54 }
55 }
56 return count;
57}
58
59int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt,
60 int match_sid, unsigned long long time,
61 unsigned long long *out_release,
62 unsigned long long *out_deadline,
63 int *out_job, int *out_tid,
64 struct record **out_record)
65{
66 struct record *record;
67 int sid, job, tid, match, next_cpu, is_running = 0;
68 unsigned long long when, max_ts;
69
70 *out_record = find_rt_record(ginfo, rt, time);
71 if (!(*out_record))
72 return 0;
73
74 *out_release = *out_deadline = *out_job = *out_tid = 0;
75
76 /* Get current job info for server task */
77 get_previous_release(ginfo, sid, time,
78 out_job, out_release, out_deadline);
79
80 /* Need to reset back to current location */
81 record = find_rt_record(ginfo, rt, time);
82 if (!record)
83 goto out;
84
85 /* TODO: read backwards too */
86 max_ts = time + max_rt_search(ginfo);
87 do {
88 if (get_rts(ginfo, record) > max_ts)
89 break;
90
91 match = rt_graph_check_server_switch_away(ginfo, record,
92 &sid, &job, &tid,
93 &when);
94 if (match && sid == match_sid) {
95 *out_tid = tid;
96 is_running = 1;
97 break;
98 }
99 free_record(record);
100 } while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu)));
101
102 if (record && record != *out_record)
103 free_record(record);
104 out:
105 return is_running;
106}
107
108void rt_plot_container(struct graph_info *ginfo, int cid)
109{
110 struct cont_list *cont;
111 struct vcpu_list *vlist;
112 struct rt_graph_info *rtg_info = &ginfo->rtg_info;
113 int key;
114
115 key = get_container_key(cid);
116 cont = find_container(rtg_info->containers, cid, key);
117 if (!cont)
118 die("Cannot create plot of non-existent container %d!\n", cid);
119 if (!cont->vcpus)
120 die("Cannot plot container %d with no vcpus!\n", cid);
121
122 cont->plotted = TRUE;
123
124 for (vlist = cont->vcpus; vlist; vlist = vlist->next) {
125 /* insert_vtask(ginfo, cont, vlist); */
126 insert_vcpu(ginfo, cont, vlist);
127 }
128}
129
130void rt_plot_add_all_containers(struct graph_info *ginfo)
131{
132 struct cont_list *cont, **conts;
133 int i;
134
135 conts = ginfo->rtg_info.containers;
136 for (i = 0; i < CONT_HASH_SIZE; i++) {
137 for (cont = *conts; cont; cont = cont->next) {
138 rt_plot_container(ginfo, cont->cid);
139 }
140 }
141}
142
143struct cont_filter_helper {
144 gboolean all_conts;
145 GtkWidget **buttons;
146 int *conts;
147 gboolean *selected;
148 int num_conts;
149};
150
151#define ALL_CONTS_STR "All Containers"
152#define DIALOG_WIDTH 400
153#define DIALOG_HEIGHT 600
154
155static void cont_toggle(gpointer data, GtkWidget *widget)
156{
157 struct cont_filter_helper *helper = data;
158 const gchar *label;
159 gboolean active;
160 int cont;
161
162 label = gtk_button_get_label(GTK_BUTTON(widget));
163 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
164
165 if (strcmp(label, ALL_CONTS_STR) == 0) {
166 helper->all_conts = active;
167 if (active) {
168 for (cont = 0; cont < helper->num_conts; cont++) {
169 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(helper->buttons[cont]),
170 TRUE);
171 }
172 }
173 }
174
175 for (cont = 0; cont < helper->num_conts; cont++) {
176 if (helper->buttons[cont] == widget) {
177 helper->selected[cont] = active;
178 }
179 }
180}
181
182
183
184static void do_container_filter(struct graph_info *ginfo,
185 struct cont_filter_helper *helper, gpointer data)
186{
187 struct graph_plot *plot;
188 struct vtask_info *vtask;
189 struct vcpu_info *vcpu;
190 struct cont_list *cont;
191 int i, c, *append;
192
193 append = malloc_or_die(helper->num_conts * sizeof(gint));
194 for (i = 0; i < helper->num_conts; i++)
195 append[i] = helper->selected[i];
196
197 for (i = ginfo->plots - 1; i >= 0; i--) {
198 plot = ginfo->plot_array[i];
199
200 if (plot->type != PLOT_TYPE_SERVER_TASK &&
201 plot->type != PLOT_TYPE_SERVER_CPU)
202 continue;
203
204 if (plot->type == PLOT_TYPE_SERVER_TASK) {
205 vtask = plot->private;
206 cont = vtask->cont;
207 } else {
208 vcpu = plot->private;
209 cont = vcpu->cont;
210 }
211
212 for (c = 0; c < helper->num_conts; c++) {
213 if (helper->conts[c] == cont->cid)
214 break;
215 }
216 if (c > helper->num_conts)
217 continue;
218
219 if (helper->selected[c]) {
220 append[c] = FALSE;
221 } else {
222 cont->plotted = FALSE;
223 trace_graph_plot_remove(ginfo, plot);
224 }
225 }
226
227 /* Add new plots */
228 for (c = 0; c < helper->num_conts; c++) {
229 if (append[c])
230 rt_plot_container(ginfo, helper->conts[c]);
231 }
232 trace_graph_refresh(ginfo);
233}
234
235void trace_container_dialog(struct graph_info *ginfo,
236 gpointer data)
237{
238 GtkWidget *dialog, *scrollwin, *viewport, *hbox, *vbox, *check, *twidget;
239 GtkRequisition req;
240 struct tracecmd_input *handle;
241 struct pevent *pevent;
242 struct cont_filter_helper *cont_helper;
243 struct cont_list *cont;
244 gchar label[100];
245 gint *selected, *conts;
246 gboolean tbool;
247 int i, result, cont_num, height, width, cont_count, select_count;
248 int start, min_cont, tint;
249
250 handle = ginfo->handle;
251 if (!handle)
252 return;
253 pevent = tracecmd_get_pevent(handle);
254 if (!pevent)
255 return;
256
257 select_count = rt_plot_get_containers(ginfo, &selected, TRUE);
258 free(selected);
259 cont_count = rt_plot_get_containers(ginfo, &conts, FALSE);
260
261 /* Create helper */
262 cont_helper = g_new0(typeof(*cont_helper), 1);
263 cont_helper->num_conts = cont_count;
264 cont_helper->buttons = g_new0(GtkWidget*, cont_count + 1);
265 cont_helper->conts = conts;
266 cont_helper->selected = g_new0(gint, cont_count);
267
268 /* Create dialog window */
269 dialog = gtk_dialog_new_with_buttons("Select Containers", NULL,
270 GTK_DIALOG_MODAL, "Apply",
271 GTK_RESPONSE_ACCEPT,
272 GTK_STOCK_CANCEL,
273 GTK_RESPONSE_REJECT, NULL);
274 scrollwin = gtk_scrolled_window_new(NULL, NULL);
275 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
276 GTK_POLICY_AUTOMATIC,
277 GTK_POLICY_AUTOMATIC);
278 viewport = gtk_viewport_new(NULL, NULL);
279 gtk_widget_show(viewport);
280
281 /* Create scroll area */
282 gtk_container_add(GTK_CONTAINER(scrollwin), viewport);
283 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0);
284 hbox = gtk_hbox_new(FALSE, 0);
285 gtk_container_add(GTK_CONTAINER(viewport), hbox);
286 gtk_widget_show(hbox);
287
288 vbox = gtk_vbox_new(TRUE, 0);
289 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, FALSE, 0);
290 gtk_widget_show(vbox);
291
292 /* Create all container button */
293 check = gtk_check_button_new_with_label(ALL_CONTS_STR);
294 gtk_box_pack_start(GTK_BOX(vbox), check, TRUE, TRUE, 0);
295 cont_helper->buttons[cont_count] = check;
296 if (select_count == cont_count)
297 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
298 gtk_widget_show(check);
299 g_signal_connect_swapped (check, "toggled",
300 G_CALLBACK (cont_toggle),
301 (gpointer) cont_helper);
302
303 /* Create per-container buttons */
304 cont_num = 0;
305 for (i = 0; i < CONT_HASH_SIZE; i++) {
306 for (cont = ginfo->rtg_info.containers[i]; cont; cont = cont->next) {
307 g_snprintf(label, 200, "%s-%d", cont->name, cont->cid);
308 check = gtk_check_button_new_with_label(label);
309 cont_helper->buttons[cont_num] = check;
310 cont_helper->conts[cont_num] = cont->cid;
311 cont_helper->selected[cont_num] = cont->plotted;
312
313 cont_num++;
314 }
315 }
316
317 for (start = 0; start < cont_count - 1; start++) {
318 min_cont = start;
319 for (i = start + 1; i < cont_count; i++) {
320 if (cont_helper->conts[i] < cont_helper->conts[min_cont])
321 min_cont = i;
322 }
323 if (min_cont != start) {
324 twidget = cont_helper->buttons[min_cont];
325 tint = cont_helper->conts[min_cont];
326 tbool = cont_helper->selected[min_cont];
327
328 cont_helper->buttons[min_cont] = cont_helper->buttons[start];
329 cont_helper->conts[min_cont] = cont_helper->conts[start];
330 cont_helper->selected[min_cont] = cont_helper->selected[start];
331 cont_helper->buttons[start] = twidget;
332 cont_helper->conts[start] = tint;
333 cont_helper->selected[start] = tbool;
334 }
335 }
336 for (i = 0; i < cont_count; i++) {
337 check = cont_helper->buttons[i];
338 gtk_box_pack_start(GTK_BOX(vbox), check, TRUE, FALSE, 0);
339 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), cont_helper->selected[i]);
340 gtk_widget_show(check);
341 g_signal_connect_swapped (check, "toggled",
342 G_CALLBACK (cont_toggle),
343 (gpointer) cont_helper);
344
345 }
346
347
348 /* Size */
349 gtk_widget_size_request(hbox, &req);
350 height = req.height;
351 gtk_widget_size_request(scrollwin, &req);
352 height += req.height;
353 gtk_widget_size_request(dialog, &req);
354 width = req.width;
355 height += req.height;
356 if (width > DIALOG_WIDTH)
357 width = DIALOG_WIDTH;
358 if (height > DIALOG_HEIGHT)
359 height = DIALOG_HEIGHT;
360 gtk_widget_set_size_request(GTK_WIDGET(dialog),
361 width, height);
362 gtk_widget_show_all(dialog);
363
364 /* Run dialog */
365 result = gtk_dialog_run(GTK_DIALOG(dialog));
366 if (result == GTK_RESPONSE_ACCEPT)
367 do_container_filter(ginfo, cont_helper, data);
368
369 gtk_widget_destroy(dialog);
370 g_free(cont_helper->conts);
371 g_free(cont_helper->buttons);
372 g_free(cont_helper->selected);
373 g_free(cont_helper);
374}
diff --git a/rt-plot-container.h b/rt-plot-container.h
new file mode 100644
index 0000000..e6c57b0
--- /dev/null
+++ b/rt-plot-container.h
@@ -0,0 +1,21 @@
1#ifndef __RT_PLOT_CONTAINER_H
2#define __RT_PLOT_CONTAINER_H
3
4#include "rt-plot-vcpu.h"
5
6typedef void (*cont_dialog_cb_func)(gboolean, gint*, gint*, gpointer);
7
8void trace_container_dialog(struct graph_info *ginfo,
9 gpointer data);
10void rt_plot_container(struct graph_info *ginfo, int cid);
11int rt_plot_get_containers(struct graph_info *ginfo, gint **plotted,
12 gboolean plotted_only);
13void rt_plot_add_all_containers(struct graph_info *ginfo);
14
15int get_server_info(struct graph_info *ginfo,
16 struct rt_plot_common *rt,
17 int match_sid, unsigned long long time,
18 unsigned long long *release, unsigned long long *deadline,
19 int *job, int *tid, struct record **record);
20
21#endif
diff --git a/rt-plot-task.c b/rt-plot-task.c
index 3175f23..c72013f 100644
--- a/rt-plot-task.c
+++ b/rt-plot-task.c
@@ -3,7 +3,7 @@
3#include "trace-graph.h" 3#include "trace-graph.h"
4#include "trace-filter.h" 4#include "trace-filter.h"
5 5
6#define DEBUG_LEVEL 4 6#define DEBUG_LEVEL 0
7#if DEBUG_LEVEL > 0 7#if DEBUG_LEVEL > 0
8#define dprintf(l, x...) \ 8#define dprintf(l, x...) \
9 do { \ 9 do { \
diff --git a/rt-plot-vcpu-task.h b/rt-plot-vcpu-task.h
new file mode 100644
index 0000000..7edd4aa
--- /dev/null
+++ b/rt-plot-vcpu-task.h
@@ -0,0 +1,9 @@
1struct vcpu_info {
2 int sid;
3 int run_tid;
4 unsigned long long run_time;
5 gboolean fresh;
6 char *label;
7
8 struct cont_list *cont;
9};
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}
diff --git a/rt-plot-vcpu.h b/rt-plot-vcpu.h
new file mode 100644
index 0000000..14add34
--- /dev/null
+++ b/rt-plot-vcpu.h
@@ -0,0 +1,22 @@
1#include "trace-graph.h"
2
3struct vcpu_list;
4
5struct vcpu_info {
6 struct rt_plot_common common;
7
8 int sid;
9 int run_tid;
10 int run_cpu;
11 unsigned long long run_time;
12 int block_cpu;
13 unsigned long long block_time;
14 gboolean fresh;
15 gboolean running;
16 char *label;
17
18 struct cont_list *cont;
19};
20
21void insert_vcpu(struct graph_info *ginfo, struct cont_list *cont,
22 struct vcpu_list *vcpu_info);
diff --git a/rt-plot.h b/rt-plot.h
new file mode 100644
index 0000000..0abc5c4
--- /dev/null
+++ b/rt-plot.h
@@ -0,0 +1,65 @@
1#ifndef __RT_PLOT_H
2#define __RT_PLOT_H
3
4#include <gtk/gtk.h>
5#include "trace-cmd.h"
6
7struct graph_plot;
8struct graph_info;
9struct rt_plot_common;
10
11typedef int (*record_matches_cb)(struct rt_plot_common *rt,
12 struct graph_info *ginfo,
13 struct record *record);
14typedef int (*is_drawn_cb)(struct graph_info *ginfo, int eid);
15typedef struct record* (*write_header_cb)(struct rt_plot_common *rt,
16 struct graph_info *ginfo,
17 struct trace_seq *s,
18 unsigned long long time);
19struct rt_plot_common {
20 record_matches_cb record_matches;
21 is_drawn_cb is_drawn;
22 write_header_cb write_header;
23};
24
25int
26rt_plot_display_last_event(struct graph_info *ginfo, struct graph_plot *plot,
27 struct trace_seq *s, unsigned long long time);
28int
29rt_plot_display_info(struct graph_info *ginfo, struct graph_plot *plot,
30 struct trace_seq *s, unsigned long long time);
31struct record*
32rt_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot,
33 unsigned long long time);
34int
35rt_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot,
36 unsigned long long time);
37struct record*
38__find_rt_record(struct graph_info *ginfo, struct rt_plot_common *rt,
39 guint64 time, int display);
40
41static inline struct record*
42find_rt_record(struct graph_info *ginfo, struct rt_plot_common *rt, guint64 time)
43{
44 return __find_rt_record(ginfo, rt, time, 0);
45}
46
47static inline struct record*
48find_rt_display_record(struct graph_info *ginfo,
49 struct rt_plot_common *rt, guint64 time)
50{
51 return __find_rt_record(ginfo, rt, time, 1);
52}
53
54unsigned long long next_rts(struct graph_info *ginfo, int cpu,
55 unsigned long long ft_target);
56void set_cpu_to_rts(struct graph_info *ginfo,
57 unsigned long long rt_target, int cpu);
58void set_cpus_to_rts(struct graph_info *ginfo,
59 unsigned long long rt_target);
60struct record* get_previous_release(struct graph_info *ginfo, int tid,
61 unsigned long long time, int *job,
62 unsigned long long *release,
63 unsigned long long *deadline);
64
65#endif
diff --git a/trace-graph.c b/trace-graph.c
index d309bc8..d8367ae 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -1695,7 +1695,7 @@ static void draw_plot_box(struct graph_info *ginfo, int i,
1695 fill, 1695 fill,
1696 x1, y, 1696 x1, y,
1697 x2 - x1, size); 1697 x2 - x1, size);
1698 if (!thin && is_high_res(ginfo)) { 1698 if (!thin && fill && is_high_res(ginfo)) {
1699 gdk_draw_rectangle(ginfo->curr_pixmap, 1699 gdk_draw_rectangle(ginfo->curr_pixmap,
1700 ginfo->draw->style->black_gc, 1700 ginfo->draw->style->black_gc,
1701 FALSE, 1701 FALSE,