aboutsummaryrefslogtreecommitdiffstats
path: root/rt-plot-container.c
diff options
context:
space:
mode:
Diffstat (limited to 'rt-plot-container.c')
-rw-r--r--rt-plot-container.c374
1 files changed, 374 insertions, 0 deletions
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}