move everything out of trunk
[lttv.git] / lttng-xenomai / LinuxTraceToolkitViewer-0.8.61-xenoltt / lttv / modules / gui / xenoltt / xenoltt_eventhooks.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
24
25 /* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
27 *
28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
31 *
32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
34 *
35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next before_schedchange
41 * hook.
42 *JO
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
45 * line/background.
46 */
47
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51
52 //#define PANGO_ENABLE_BACKEND
53 #include <gtk/gtk.h>
54 #include <gdk/gdk.h>
55 #include <glib.h>
56 #include <assert.h>
57 #include <string.h>
58 #include <stdio.h>
59
60 //#include <pango/pango.h>
61
62 #include <ltt/event.h>
63 #include <ltt/time.h>
64 #include <ltt/type.h>
65 #include <ltt/trace.h>
66
67 #include <lttv/lttv.h>
68 #include <lttv/hook.h>
69 #include <lttv/state.h>
70 #include <lttvwindow/lttvwindow.h>
71 #include <lttvwindow/lttvwindowtraces.h>
72 #include <lttvwindow/support.h>
73 #include <lttv/stats.h>
74 #include <lttv/xenoltt_sim.h>
75
76 #include <lttv/filter.h>
77
78 #include "xenoltt_eventhooks.h"
79 #include "xfv.h"
80 #include "xenoltt_threadlist.h"
81 #include "xenoltt_drawing.h"
82
83 #include "TraceControlStart.xpm"
84
85 #define MAX_PATH_LEN 256
86 #define STATE_LINE_WIDTH 2
87 #define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
88
89 extern GSList *g_legend_list;
90
91
92
93
94 /* Action to do when background computation completed.
95 *
96 * Wait for all the awaited computations to be over.
97 */
98
99 static gint background_ready(void *hook_data, void *call_data) {
100 XenoLTTData *xenoltt_data = (XenoLTTData *)hook_data;
101 LttvTrace *trace = (LttvTrace*)call_data;
102
103 xenoltt_data->background_info_waiting--;
104
105 if(xenoltt_data->background_info_waiting == 0) {
106 g_message("xenoltt viewer : background computation data ready.");
107
108 drawing_clear(xenoltt_data->drawing);
109 threadlist_clear(xenoltt_data->thread_list);
110 gtk_widget_set_size_request(xenoltt_data->drawing->drawing_area,-1, threadlist_get_height(xenoltt_data->thread_list));
111
112 redraw_notify(xenoltt_data, NULL);
113
114 }
115
116 return 0;
117 }
118
119
120 /* Request background computation. Verify if it is in progress or ready first.
121 * Only for each trace in the tab's traceset.
122 */
123 static void request_background_data(XenoLTTData *xenoltt_data) {
124 LttvTracesetContext * tsc = lttvwindow_get_traceset_context(xenoltt_data->tab);
125 gint num_traces = lttv_traceset_number(tsc->ts);
126 gint i;
127 LttvTrace *trace;
128 LttvTraceState *tstate;
129
130 LttvHooks *background_ready_hook = lttv_hooks_new();
131 lttv_hooks_add(background_ready_hook, background_ready, xenoltt_data,LTTV_PRIO_DEFAULT);
132 xenoltt_data->background_info_waiting = 0;
133
134 for(i=0;i<num_traces;i++) {
135 trace = lttv_traceset_get(tsc->ts, i);
136 tstate = LTTV_TRACE_STATE(tsc->traces[i]);
137
138 if(lttvwindowtraces_get_ready(g_quark_from_string("state"), trace)==FALSE
139 && !tstate->has_precomputed_states) {
140
141 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
142 trace) == FALSE) {
143 /* We first remove requests that could have been done for the same
144 * information. Happens when two viewers ask for it before servicing
145 * starts.
146 */
147 if(!lttvwindowtraces_background_request_find(trace, "state"))
148 lttvwindowtraces_background_request_queue(
149 main_window_get_widget(xenoltt_data->tab), trace, "state");
150 lttvwindowtraces_background_notify_queue(xenoltt_data,
151 trace,
152 ltt_time_infinite,
153 NULL,
154 background_ready_hook);
155 xenoltt_data->background_info_waiting++;
156 } else { /* in progress */
157 lttvwindowtraces_background_notify_current(xenoltt_data,
158 trace,
159 ltt_time_infinite,
160 NULL,
161 background_ready_hook);
162 xenoltt_data->background_info_waiting++;
163 }
164 } else {
165 /* Data ready. By its nature, this viewer doesn't need to have
166 * its data ready hook called there, because a background
167 * request is always linked with a redraw.
168 */
169 }
170
171 }
172 lttv_hooks_destroy(background_ready_hook);
173 }
174
175
176 /***********************************************************************************************************************************/
177 /***********************************************************************************************************************************/
178
179
180 /**
181 * Event Viewer's constructor hook
182 *
183 * This constructor is given as a parameter to the menuitem and toolbar button
184 * registration. It creates the list.
185 * @param tab A pointer to the parent tab.
186 * @return The widget created.
187 */
188 GtkWidget *h_guixenoltt(LttvPlugin *plugin) {
189 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
190 Tab *tab = ptab->tab;
191 g_info("h_guixenoltt, %p", tab);
192 XenoLTTData *xenoltt_data = guixenoltt(ptab);
193
194 xenoltt_data->tab = tab;
195
196 // Unreg done in the guixenoltt_Destructor
197 lttvwindow_register_traceset_notify(tab,traceset_notify,xenoltt_data);
198
199 lttvwindow_register_time_window_notify(tab,update_time_window_hook,xenoltt_data);
200 lttvwindow_register_current_time_notify(tab,update_current_time_hook,xenoltt_data);
201 lttvwindow_register_redraw_notify(tab,redraw_notify,xenoltt_data);
202 lttvwindow_register_continue_notify(tab,continue_notify,xenoltt_data);
203 request_background_data(xenoltt_data);
204
205 return guixenoltt_get_widget(xenoltt_data);
206
207 }
208
209 void xenolttlegend_destructor(GtkWindow *legend) {
210 g_legend_list = g_slist_remove(g_legend_list, legend);
211 }
212 /***********************************************************************************************************************************/
213 void start_clicked (GtkButton *button, gpointer user_data);
214
215 typedef struct _ControlData ControlData;
216 struct _ControlData {
217 Tab *tab; //< current tab of module
218
219 GtkWidget *window; //< window
220
221 GtkWidget *main_box; //< main container
222 GtkWidget *start_button;
223 GtkWidget *task_selection_combo;
224 GtkWidget *period_entry;
225 GtkWidget *sim_file_label;
226 GtkWidget *file_entry;
227 GtkWidget *title;
228 GtkWidget *period_settings;
229 GtkWidget *task_label;
230 GtkWidget *period_label;
231 };
232
233 void prepare_sim_data(ControlData *tcd);
234
235 /* Create a simulation settings window */
236
237 GtkWidget *h_xenolttsimulation(LttvPlugin *plugin) {
238 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
239 Tab *tab = ptab->tab;
240 g_info("h_Simulation, %p", tab);
241
242 ControlData* tcd = g_new(ControlData,1);
243
244 tcd->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
245 gtk_window_set_title(GTK_WINDOW(tcd->window), "XenoLTT Simulation");
246
247 g_legend_list = g_slist_append(g_legend_list,GTK_WINDOW(tcd->window));
248
249 g_object_set_data_full(G_OBJECT(tcd->window),"Simulation",GTK_WINDOW(tcd->window),
250 (GDestroyNotify)xenolttlegend_destructor);
251
252
253 tcd->tab = tab;
254 tcd->main_box = gtk_table_new(3,7,FALSE);
255 gtk_table_set_row_spacings(GTK_TABLE(tcd->main_box),5);
256 gtk_table_set_col_spacings(GTK_TABLE(tcd->main_box),5);
257
258 gtk_container_add(GTK_CONTAINER(tcd->window), GTK_WIDGET(tcd->main_box));
259
260 prepare_sim_data(tcd);
261
262 return NULL;
263
264 }
265
266 /***********************************************************************************************************************************/
267
268 static gint data_ready(void *hook_data, void *call_data){
269 ControlData *tcd = (ControlData*)hook_data;
270 ThreadEventData *temp_thread;
271 GArray *list = get_thread_list();
272
273 tcd->sim_file_label = gtk_label_new("Simulation directory:");
274 gtk_widget_show (tcd->sim_file_label);
275 tcd->file_entry = gtk_entry_new();
276 gtk_entry_set_text(GTK_ENTRY(tcd->file_entry),"/tmp/trace1.xml");
277 gtk_widget_show (tcd->file_entry);
278 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->sim_file_label,0,2,0,1,GTK_FILL,GTK_FILL,2,2);
279 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->file_entry,2,6,0,1,GTK_FILL,GTK_FILL,0,0);
280
281
282 //Insert Task selection
283 tcd->task_label = gtk_label_new("Task:");
284 gtk_widget_show (tcd->task_label);
285
286 tcd->task_selection_combo = gtk_combo_box_new_text();
287 // iterate on all task to get the name and default period
288 int i;
289
290 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd->task_selection_combo), " - Choose a task - ");
291 for(i=0;i<list->len;i++){
292 temp_thread = g_array_index(list, ThreadEventData*, i);
293 gchar text[MAX_PATH_LEN] = "";
294 sprintf(text,"%s (%u)",g_quark_to_string(temp_thread->name),temp_thread->period);
295 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd->task_selection_combo), text);
296 }
297 gtk_combo_box_set_active(GTK_COMBO_BOX(tcd->task_selection_combo), 0);
298 gtk_widget_show (tcd->task_selection_combo);
299
300 // Period Entry
301 tcd->period_label = gtk_label_new("New period:");
302 gtk_widget_show (tcd->period_label);
303 tcd->period_entry = gtk_entry_new();
304 gtk_entry_set_text(GTK_ENTRY(tcd->period_entry),"");
305 gtk_widget_show (tcd->period_entry);
306 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->task_label,0,2,1,2,GTK_FILL,GTK_FILL,0,0);
307 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->task_selection_combo,2,6,1,2,GTK_FILL,GTK_FILL,2,2);
308 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->period_label,0,2,2,3,GTK_FILL,GTK_FILL,0,0);
309 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->period_entry,2,6,2,3,GTK_FILL,GTK_FILL,0,0);
310
311 //Insert Start button
312 GdkPixbuf *pixbuf;
313 GtkWidget *image;
314 pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStart_xpm);
315 image = gtk_image_new_from_pixbuf(pixbuf);
316 tcd->start_button = gtk_button_new_with_label("Start");
317 g_object_set(G_OBJECT(tcd->start_button), "image", image, NULL);
318 gtk_button_set_alignment(GTK_BUTTON(tcd->start_button), 0.0, 0.0);
319 gtk_widget_show (tcd->start_button);
320 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->start_button,6,7,2,3,GTK_FILL,GTK_FILL,5,2);
321
322
323 // User interface guide
324 GList *focus_chain = NULL;
325
326 focus_chain = g_list_append (focus_chain, tcd->file_entry);
327 focus_chain = g_list_append (focus_chain, tcd->task_selection_combo);
328 focus_chain = g_list_append (focus_chain, tcd->period_entry);
329 focus_chain = g_list_append (focus_chain, tcd->start_button);
330
331 gtk_container_set_focus_chain(GTK_CONTAINER(tcd->main_box), focus_chain);
332
333 g_list_free(focus_chain);
334
335 g_signal_connect(G_OBJECT(tcd->start_button), "clicked",(GCallback)start_clicked, tcd);
336
337 gtk_widget_show(tcd->main_box);
338 gtk_widget_show(tcd->window);
339
340
341 return 0;
342 }
343
344 // When Start button is clicked, we need to perform some checks
345 // First, check if simulation is needed (period not the same)
346 // Then try to create the file
347 // Then compute simulation
348 void start_clicked (GtkButton *button, gpointer user_data){
349 ControlData *tcd = (ControlData*)user_data;
350 FILE *a_file;
351 GArray *list = get_thread_list();
352 ThreadEventData *temp_thread;
353 gchar msg[256];
354
355 const gchar *name;
356 GtkTreeIter iter;
357
358 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(tcd->task_selection_combo), &iter);
359 gtk_tree_model_get(
360 gtk_combo_box_get_model(GTK_COMBO_BOX(tcd->task_selection_combo)),
361 &iter, 0, &name, -1);
362 if(strcmp(name, " - Choose a task - ") == 0){
363 strcpy(msg, "Please choose a task in the list");
364 GtkWidget *dialogue =
365 gtk_message_dialog_new(
366 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
367 GTK_DIALOG_MODAL,
368 GTK_MESSAGE_ERROR,
369 GTK_BUTTONS_OK,
370 msg);
371 gtk_dialog_run(GTK_DIALOG(dialogue));
372 gtk_widget_destroy(dialogue);
373 return;
374 }
375
376 // test period value
377 int i = gtk_combo_box_get_active(GTK_COMBO_BOX(tcd->task_selection_combo)) - 1;
378
379 temp_thread = g_array_index(list, ThreadEventData*, i);
380
381
382 const gchar *period = gtk_entry_get_text(GTK_ENTRY(tcd->period_entry));
383 int period_value = atoi(period);
384
385 if(period_value <= 0){
386 strcpy(msg, "Please enter a valid period value");
387 GtkWidget *dialogue =
388 gtk_message_dialog_new(
389 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
390 GTK_DIALOG_MODAL,
391 GTK_MESSAGE_ERROR,
392 GTK_BUTTONS_OK,
393 msg);
394 gtk_dialog_run(GTK_DIALOG(dialogue));
395 gtk_widget_destroy(dialogue);
396 return;
397 }
398
399 // Checkif same period
400 else if (period_value == temp_thread->period){
401 strcpy(msg, "Please enter a different period value");
402 GtkWidget *dialogue =
403 gtk_message_dialog_new(
404 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
405 GTK_DIALOG_MODAL,
406 GTK_MESSAGE_ERROR,
407 GTK_BUTTONS_OK,
408 msg);
409 gtk_dialog_run(GTK_DIALOG(dialogue));
410 gtk_widget_destroy(dialogue);
411 return;
412 }
413
414 // Everything is ok
415
416 // test existence of files in the directory
417 const gchar *file_name = gtk_entry_get_text(GTK_ENTRY(tcd->file_entry));
418 printf("%s\n",file_name);
419
420 // Try to open file in read mode to check if it exist
421 a_file = fopen(file_name, "r");
422 if(a_file != NULL){
423
424 strcpy(msg, "Wrong file name, file already exist");
425 GtkWidget *dialogue =
426 gtk_message_dialog_new(
427 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
428 GTK_DIALOG_MODAL,
429 GTK_MESSAGE_ERROR,
430 GTK_BUTTONS_OK,
431 msg);
432 gtk_dialog_run(GTK_DIALOG(dialogue));
433 gtk_widget_destroy(dialogue);
434 fclose(a_file);
435 return;
436 }
437 else{
438 // Create the file
439 a_file = fopen(file_name, "w");
440 if(a_file == NULL){
441 sprintf(msg,"Unable to create file: %s",file_name);
442 GtkWidget *dialogue =
443 gtk_message_dialog_new(
444 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
445 GTK_DIALOG_MODAL,
446 GTK_MESSAGE_ERROR,
447 GTK_BUTTONS_OK,
448 msg);
449 gtk_dialog_run(GTK_DIALOG(dialogue));
450 gtk_widget_destroy(dialogue);
451 return;
452 }
453
454 fprintf(a_file,"<TRACE SIMULATION>\n");
455 compute_simulation(i,period_value,a_file);
456 fprintf(a_file,"</TRACE SIMULATION>\n");
457 fclose(a_file);
458 sprintf(msg,"Simulation finished\n\nSimulation file: %s",file_name);
459 GtkWidget *dialogue =
460 gtk_message_dialog_new(
461 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
462 GTK_DIALOG_MODAL,
463 GTK_MESSAGE_INFO,
464 GTK_BUTTONS_OK,
465 msg);
466 gtk_dialog_run(GTK_DIALOG(dialogue));
467 gtk_widget_destroy(dialogue);
468
469 }
470 }
471
472 void prepare_sim_data(ControlData *tcd){
473 // ControlData *tcd = (ControlData*)user_data;
474 LttvTracesetContext * tsc = lttvwindow_get_traceset_context(tcd->tab);
475 gint num_traces = lttv_traceset_number(tsc->ts);
476 gint i;
477 LttvTrace *trace;
478 LttvTraceState *tstate;
479
480 /* Register simulation calculator */
481 LttvHooks *hook_adder = lttv_hooks_new();
482 lttv_hooks_add(hook_adder, lttv_xenoltt_sim_hook_add_event_hooks, NULL,LTTV_PRIO_DEFAULT);
483 lttv_hooks_add(hook_adder, lttv_state_hook_add_event_hooks, NULL,LTTV_PRIO_DEFAULT);
484
485 LttvHooks *hook_remover = lttv_hooks_new();
486 lttv_hooks_add(hook_remover, lttv_xenoltt_sim_hook_remove_event_hooks,NULL, LTTV_PRIO_DEFAULT);
487 lttv_hooks_add(hook_remover, lttv_state_hook_remove_event_hooks,NULL, LTTV_PRIO_DEFAULT);
488
489 /* Add simulation hook adder to attributes */
490 lttvwindowtraces_register_computation_hooks(g_quark_from_string("xenoltt_sim"),
491 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
492 NULL, NULL, NULL,
493 hook_adder, hook_remover);
494
495 LttvHooks *background_ready_hook = lttv_hooks_new();
496 lttv_hooks_add(background_ready_hook, data_ready, tcd, LTTV_PRIO_DEFAULT);
497
498 for(i=0;i<num_traces;i++) {
499 trace = lttvwindowtraces_get_trace(i);
500
501 if(lttvwindowtraces_get_ready(g_quark_from_string("xenoltt_sim"),trace)==FALSE) {
502
503 if(lttvwindowtraces_get_in_progress(g_quark_from_string("xenoltt_sim"),trace) == FALSE) {
504 if(!lttvwindowtraces_background_request_find(trace, "xenoltt_sim"))
505 lttvwindowtraces_background_request_queue(main_window_get_widget(tcd->tab), trace, "xenoltt_sim");
506 lttvwindowtraces_background_notify_queue(tcd,trace,ltt_time_infinite,NULL,background_ready_hook);
507 } else { /* in progress */
508 lttvwindowtraces_background_notify_current(tcd,trace,ltt_time_infinite,NULL,background_ready_hook);
509
510 }
511 } else {}
512 }
513 lttv_hooks_destroy(background_ready_hook);
514 }
515
516 /***********************************************************************************************************************************/
517
518 /* Create a popup legend */
519 GtkWidget *h_xenolttlegend(LttvPlugin *plugin)
520 {
521 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
522 Tab *tab = ptab->tab;
523 g_info("h_legend, %p", tab);
524
525 GtkWindow *xenoltt_settings = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
526
527 g_legend_list = g_slist_append(g_legend_list,xenoltt_settings);
528
529 g_object_set_data_full(G_OBJECT(xenoltt_settings),"settings",xenoltt_settings,(GDestroyNotify)xenolttlegend_destructor);
530
531 gtk_window_set_title(xenoltt_settings, "XenoLTT Settings");
532
533 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(xenoltt_settings), "xenoltt-color-list.png");
534
535
536 gtk_container_add(GTK_CONTAINER(xenoltt_settings), GTK_WIDGET(pixmap));
537
538 gtk_widget_show(GTK_WIDGET(pixmap));
539 gtk_widget_show(GTK_WIDGET(xenoltt_settings));
540
541
542 return NULL; /* This is a popup window */
543 }
544
545 /***********************************************************************************************************************************/
546
547 int event_selected_hook(void *hook_data, void *call_data) {
548 XenoLTTData *xenoltt_data = (XenoLTTData*) hook_data;
549 guint *event_number = (guint*) call_data;
550
551 g_debug("DEBUG : event selected by main window : %u", *event_number);
552
553 return 0;
554 }
555
556 /* Function that selects the color of status&exemode line */
557 static inline void prepare_s_e_line(LttvXenoThreadState *thread, DrawContext draw_context,LttvTraceState *ts) {
558
559 PropertiesLine prop_line;
560 prop_line.style = GDK_LINE_SOLID;
561 prop_line.y = MIDDLE;
562
563 //If thread is in ovverun state, we want to display a diffent background color
564 if(thread->state->mode == LTTV_XENO_MODE_OVERRUN){
565 prop_line.line_width = 6;
566 prop_line.color = drawing_colors[COL_RUN_IRQ];
567 draw_line((void*)&prop_line, (void*)&draw_context);
568 }
569
570 // We want to draw a line if thread is the owner of at least one synch
571 if (lttv_xeno_thread_synch_owner(ts,thread)){
572 prop_line.line_width = 1;
573 prop_line.color = drawing_colors[COL_RUN_USER_MODE];
574 draw_context.drawinfo.y.middle = (draw_context.drawinfo.y.middle/4);
575 draw_line((void*)&prop_line, (void*)&draw_context);
576 draw_context.drawinfo.y.middle = (draw_context.drawinfo.y.under/2);
577 }
578
579 if (lttv_xeno_thread_synch_waiting(ts,thread)){
580 prop_line.line_width = 1;
581 prop_line.color = drawing_colors[COL_RUN_SOFT_IRQ];
582 draw_context.drawinfo.y.middle = (draw_context.drawinfo.y.middle/2);
583 draw_line((void*)&prop_line, (void*)&draw_context);
584 draw_context.drawinfo.y.middle = (draw_context.drawinfo.y.under/2);
585 }
586
587 prop_line.line_width = STATE_LINE_WIDTH;
588
589 if(thread->state->status == LTTV_XENO_STATE_INIT) {
590 prop_line.color = drawing_colors[COL_EXIT]; // Created = MAGENTA
591
592 } else if(thread->state->status == LTTV_XENO_STATE_START) {
593 prop_line.color = drawing_colors[COL_RUN_SOFT_IRQ]; // Started = RED
594
595 } else if(thread->state->status == LTTV_XENO_STATE_RUN) {
596 prop_line.color = drawing_colors[COL_RUN_USER_MODE]; // Running = GREEN
597
598 } else if(thread->state->status == LTTV_XENO_STATE_READY) {
599 prop_line.color = drawing_colors[COL_WHITE]; // READY = WHITE
600
601 } else if(thread->state->status == LTTV_XENO_STATE_WAIT_PERIOD) {
602 prop_line.color = drawing_colors[COL_WAIT]; // WAIT PERIOD = DARK RED
603
604 } else if(thread->state->status == LTTV_XENO_STATE_SUSPEND) {
605 prop_line.color = drawing_colors[COL_RUN_SYSCALL]; // SUSPEND = BLUE
606
607 } else if(thread->state->status == LTTV_XENO_STATE_DEAD) {
608 prop_line.color = drawing_colors[COL_BLACK]; // DEAD = BLACK
609
610 } else if(thread->state->status == LTTV_XENO_STATE_UNNAMED) {
611 prop_line.color = drawing_colors[COL_WHITE];
612
613 } else {
614 g_critical("unknown status : %s", g_quark_to_string(thread->state->status));
615 g_assert(FALSE); /* UNKNOWN STATUS */
616 }
617
618 draw_line((void*)&prop_line, (void*)&draw_context);
619 }
620
621
622
623 gint update_time_window_hook(void *hook_data, void *call_data) {
624 XenoLTTData *xenoltt_data = (XenoLTTData*) hook_data;
625 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
626 ThreadList *thread_list = xenoltt_data->thread_list;
627
628 const TimeWindowNotifyData *time_window_nofify_data =
629 ((const TimeWindowNotifyData *)call_data);
630
631 TimeWindow *old_time_window = time_window_nofify_data->old_time_window;
632 TimeWindow *new_time_window = time_window_nofify_data->new_time_window;
633
634 /* Update the ruler */
635 drawing_update_ruler(xenoltt_data->drawing,new_time_window);
636
637
638 /* Two cases : zoom in/out or scrolling */
639
640 /* In order to make sure we can reuse the old drawing, the scale must
641 * be the same and the new time interval being partly located in the
642 * currently shown time interval. (reuse is only for scrolling)
643 */
644
645 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
646 old_time_window->start_time.tv_sec,
647 old_time_window->start_time.tv_nsec,
648 old_time_window->time_width.tv_sec,
649 old_time_window->time_width.tv_nsec);
650
651 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
652 new_time_window->start_time.tv_sec,
653 new_time_window->start_time.tv_nsec,
654 new_time_window->time_width.tv_sec,
655 new_time_window->time_width.tv_nsec);
656
657 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
658 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec) {
659 /* Same scale (scrolling) */
660 g_info("scrolling");
661 LttTime *ns = &new_time_window->start_time;
662 LttTime *nw = &new_time_window->time_width;
663 LttTime *os = &old_time_window->start_time;
664 LttTime *ow = &old_time_window->time_width;
665 LttTime old_end = old_time_window->end_time;
666 LttTime new_end = new_time_window->end_time;
667 if(ltt_time_compare(*ns, old_end) == -1
668 && ltt_time_compare(*os, *ns) == -1) {
669 g_info("scrolling near right");
670 /* Scroll right, keep right part of the screen */
671 guint x = 0;
672 guint width = xenoltt_data->drawing->width;
673 convert_time_to_pixels(
674 *old_time_window,
675 *ns,
676 width,
677 &x);
678
679 /* Copy old data to new location */
680 copy_pixmap_region(thread_list,
681 NULL,
682 xenoltt_data->drawing->drawing_area->style->black_gc,
683 NULL,
684 x, 0,
685 0, 0,
686 xenoltt_data->drawing->width-x+SAFETY, -1);
687
688 if(drawing->damage_begin == drawing->damage_end)
689 drawing->damage_begin = xenoltt_data->drawing->width-x;
690 else
691 drawing->damage_begin = 0;
692
693 drawing->damage_end = xenoltt_data->drawing->width;
694
695 /* Clear the data request background, but not SAFETY */
696 rectangle_pixmap(thread_list,
697 xenoltt_data->drawing->drawing_area->style->black_gc,
698 TRUE,
699 drawing->damage_begin+SAFETY, 0,
700 drawing->damage_end - drawing->damage_begin, // do not overlap
701 -1);
702 gtk_widget_queue_draw(drawing->drawing_area);
703
704 /* Get new data for the rest. */
705 drawing_data_request(xenoltt_data->drawing,
706 drawing->damage_begin, 0,
707 drawing->damage_end - drawing->damage_begin,
708 xenoltt_data->drawing->height);
709 } else {
710 if(ltt_time_compare(*ns, *os) == -1
711 && ltt_time_compare(*os, new_end) == -1) {
712 g_info("scrolling near left");
713 /* Scroll left, keep left part of the screen */
714 guint x = 0;
715 guint width = xenoltt_data->drawing->width;
716 convert_time_to_pixels(
717 *new_time_window,
718 *os,
719 width,
720 &x);
721
722 /* Copy old data to new location */
723 copy_pixmap_region (thread_list,
724 NULL,
725 xenoltt_data->drawing->drawing_area->style->black_gc,
726 NULL,
727 0, 0,
728 x, 0,
729 -1, -1);
730
731 if(drawing->damage_begin == drawing->damage_end)
732 drawing->damage_end = x;
733 else
734 drawing->damage_end =
735 xenoltt_data->drawing->width;
736
737 drawing->damage_begin = 0;
738
739 rectangle_pixmap(thread_list,
740 xenoltt_data->drawing->drawing_area->style->black_gc,
741 TRUE,
742 drawing->damage_begin, 0,
743 drawing->damage_end - drawing->damage_begin, // do not overlap
744 -1);
745
746 gtk_widget_queue_draw(drawing->drawing_area);
747
748
749 /* Get new data for the rest. */
750 drawing_data_request(xenoltt_data->drawing,
751 drawing->damage_begin, 0,
752 drawing->damage_end - drawing->damage_begin,
753 xenoltt_data->drawing->height);
754
755 } else {
756 if(ltt_time_compare(*ns, *os) == 0) {
757 g_info("not scrolling");
758 } else {
759 g_info("scrolling far");
760 /* Cannot reuse any part of the screen : far jump */
761
762
763 rectangle_pixmap(thread_list,
764 xenoltt_data->drawing->drawing_area->style->black_gc,
765 TRUE,
766 0, 0,
767 xenoltt_data->drawing->width+SAFETY, // do not overlap
768 -1);
769
770 gtk_widget_queue_draw(drawing->drawing_area);
771
772 drawing->damage_begin = 0;
773 drawing->damage_end = xenoltt_data->drawing->width;
774
775 drawing_data_request(xenoltt_data->drawing,
776 0, 0,
777 xenoltt_data->drawing->width,
778 xenoltt_data->drawing->height);
779
780 }
781 }
782 }
783 } else {
784 /* Different scale (zoom) */
785 g_info("zoom");
786
787 rectangle_pixmap(thread_list,
788 xenoltt_data->drawing->drawing_area->style->black_gc,
789 TRUE,
790 0, 0,
791 xenoltt_data->drawing->width+SAFETY, // do not overlap
792 -1);
793
794 gtk_widget_queue_draw(drawing->drawing_area);
795
796 drawing->damage_begin = 0;
797 drawing->damage_end = xenoltt_data->drawing->width;
798
799 drawing_data_request(xenoltt_data->drawing,
800 0, 0,
801 xenoltt_data->drawing->width,
802 xenoltt_data->drawing->height);
803 }
804
805 /* Update directly when scrolling */
806 gdk_window_process_updates(xenoltt_data->drawing->drawing_area->window,
807 TRUE);
808
809 return 0;
810 }
811
812 gint traceset_notify(void *hook_data, void *call_data) {
813 XenoLTTData *xenoltt_data = (XenoLTTData*) hook_data;
814 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
815
816 if(unlikely(drawing->gc == NULL)) {
817 return FALSE;
818 }
819 if(drawing->dotted_gc == NULL) {
820 return FALSE;
821 }
822
823 drawing_clear(xenoltt_data->drawing);
824 threadlist_clear(xenoltt_data->thread_list);
825 gtk_widget_set_size_request(
826 xenoltt_data->drawing->drawing_area,
827 -1, threadlist_get_height(xenoltt_data->thread_list));
828 redraw_notify(xenoltt_data, NULL);
829
830 request_background_data(xenoltt_data);
831
832 return FALSE;
833 }
834
835 gint redraw_notify(void *hook_data, void *call_data) {
836 XenoLTTData *xenoltt_data = (XenoLTTData*) hook_data;
837 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
838 GtkWidget *widget = drawing->drawing_area;
839
840 drawing->damage_begin = 0;
841 drawing->damage_end = drawing->width;
842
843 /* fun feature, to be separated someday... */
844 drawing_clear(xenoltt_data->drawing);
845 threadlist_clear(xenoltt_data->thread_list);
846 gtk_widget_set_size_request(
847 xenoltt_data->drawing->drawing_area,
848 -1, threadlist_get_height(xenoltt_data->thread_list));
849 // Clear the images
850 rectangle_pixmap(xenoltt_data->thread_list,
851 widget->style->black_gc,
852 TRUE,
853 0, 0,
854 drawing->alloc_width,
855 -1);
856
857 gtk_widget_queue_draw(drawing->drawing_area);
858
859 if(drawing->damage_begin < drawing->damage_end) {
860 drawing_data_request(drawing,
861 drawing->damage_begin,
862 0,
863 drawing->damage_end-drawing->damage_begin,
864 drawing->height);
865 }
866
867 return FALSE;
868
869 }
870
871
872 gint continue_notify(void *hook_data, void *call_data) {
873 XenoLTTData *xenoltt_data = (XenoLTTData*) hook_data;
874 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
875
876
877 if(drawing->damage_begin < drawing->damage_end) {
878 drawing_data_request(drawing,
879 drawing->damage_begin,
880 0,
881 drawing->damage_end-drawing->damage_begin,
882 drawing->height);
883 }
884
885 return FALSE;
886 }
887
888
889 gint update_current_time_hook(void *hook_data, void *call_data) {
890 XenoLTTData *xenoltt_data = (XenoLTTData*)hook_data;
891 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
892
893 LttTime current_time = *((LttTime*)call_data);
894
895 TimeWindow time_window = lttvwindow_get_time_window(xenoltt_data->tab);
896
897 LttTime time_begin = time_window.start_time;
898 LttTime width = time_window.time_width;
899 LttTime half_width; {
900 guint64 time_ll = ltt_time_to_uint64(width);
901 time_ll = time_ll >> 1; /* divide by two */
902 half_width = ltt_time_from_uint64(time_ll);
903 }
904 LttTime time_end = ltt_time_add(time_begin, width);
905
906 LttvTracesetContext * tsc =
907 lttvwindow_get_traceset_context(xenoltt_data->tab);
908
909 LttTime trace_start = tsc->time_span.start_time;
910 LttTime trace_end = tsc->time_span.end_time;
911
912 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
913 current_time.tv_nsec);
914
915
916
917 /* If current time is inside time interval, just move the highlight
918 * bar */
919
920 /* Else, we have to change the time interval. We have to tell it
921 * to the main window. */
922 /* The time interval change will take care of placing the current
923 * time at the center of the visible area, or nearest possible if we are
924 * at one end of the trace. */
925
926
927 if(ltt_time_compare(current_time, time_begin) < 0) {
928 TimeWindow new_time_window;
929
930 if(ltt_time_compare(current_time,
931 ltt_time_add(trace_start, half_width)) < 0)
932 time_begin = trace_start;
933 else
934 time_begin = ltt_time_sub(current_time, half_width);
935
936 new_time_window.start_time = time_begin;
937 new_time_window.time_width = width;
938 new_time_window.time_width_double = ltt_time_to_double(width);
939 new_time_window.end_time = ltt_time_add(time_begin, width);
940
941 lttvwindow_report_time_window(xenoltt_data->tab, new_time_window);
942 }
943 else if(ltt_time_compare(current_time, time_end) > 0) {
944 TimeWindow new_time_window;
945
946 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
947 time_begin = ltt_time_sub(trace_end, width);
948 else
949 time_begin = ltt_time_sub(current_time, half_width);
950
951 new_time_window.start_time = time_begin;
952 new_time_window.time_width = width;
953 new_time_window.time_width_double = ltt_time_to_double(width);
954 new_time_window.end_time = ltt_time_add(time_begin, width);
955
956 lttvwindow_report_time_window(xenoltt_data->tab, new_time_window);
957
958 }
959 gtk_widget_queue_draw(xenoltt_data->drawing->drawing_area);
960
961 /* Update directly when scrolling */
962 gdk_window_process_updates(xenoltt_data->drawing->drawing_area->window,
963 TRUE);
964
965 return 0;
966 }
967
968 typedef struct _ClosureData {
969 EventsRequest *events_request;
970 LttvTracesetState *tss;
971 LttTime end_time;
972 guint x_end;
973 } ClosureData;
974
975
976 void draw_closure(gpointer key, gpointer value, gpointer user_data) {
977 XenoThreadInfo *thread_Info = (XenoThreadInfo*)key;
978 HashedThreadData *hashed_thread_data = (HashedThreadData*)value;
979 ClosureData *closure_data = (ClosureData*)user_data;
980
981 EventsRequest *events_request = closure_data->events_request;
982 XenoLTTData *xenoltt_data = events_request->viewer_data;
983
984 LttvTracesetState *tss = closure_data->tss;
985 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
986
987 LttTime evtime = closure_data->end_time;
988
989 {
990 /* For the thread */
991 /* First, check if the current thread is in the state computation
992 * thread list. If it is there, that means we must add it right now and
993 * draw items from the beginning of the read for it. If it is not
994 * present, it's a new process and it was not present : it will
995 * be added after the state update. */
996 #ifdef EXTRA_CHECK
997 g_assert(lttv_traceset_number(tsc->ts) > 0);
998 #endif //EXTRA_CHECK
999 LttvTraceContext *tc = tsc->traces[thread_Info->trace_num];
1000 LttvTraceState *ts = (LttvTraceState*)tc;
1001
1002 LttvXenoThreadState *thread;
1003 thread = lttv_xeno_state_find_thread(ts, thread_Info->cpu,thread_Info->address);
1004
1005 if(unlikely(thread != NULL)) {
1006 ThreadList *thread_list = xenoltt_data->thread_list;
1007 #ifdef EXTRA_CHECK
1008 /* Should be alike when background info is ready */
1009 if(xenoltt_data->background_info_waiting==0)
1010 #endif //EXTRA_CHECK
1011
1012 /* Now, the process is in the state hash and our own process hash.
1013 * We definitely can draw the items related to the ending state.
1014 */
1015
1016 if(unlikely(ltt_time_compare(hashed_thread_data->next_good_time,evtime) <= 0)) {
1017 TimeWindow time_window = lttvwindow_get_time_window(xenoltt_data->tab);
1018
1019 #ifdef EXTRA_CHECK
1020 if(ltt_time_compare(evtime, time_window.start_time) == -1
1021 || ltt_time_compare(evtime, time_window.end_time) == 1)
1022 return;
1023 #endif //EXTRA_CHECK
1024 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1025 guint width = drawing->width;
1026
1027 guint x = closure_data->x_end;
1028
1029 DrawContext draw_context;
1030
1031 /* Now create the drawing context that will be used to draw
1032 * items related to the last state. */
1033 draw_context.drawable = hashed_thread_data->pixmap;
1034 draw_context.gc = drawing->gc;
1035 draw_context.pango_layout = drawing->pango_layout;
1036 draw_context.drawinfo.end.x = x;
1037
1038 draw_context.drawinfo.y.over = 1;
1039 draw_context.drawinfo.y.middle = (hashed_thread_data->height/2);
1040 draw_context.drawinfo.y.under = hashed_thread_data->height;
1041
1042 draw_context.drawinfo.start.offset.over = 0;
1043 draw_context.drawinfo.start.offset.middle = 0;
1044 draw_context.drawinfo.start.offset.under = 0;
1045 draw_context.drawinfo.end.offset.over = 0;
1046 draw_context.drawinfo.end.offset.middle = 0;
1047 draw_context.drawinfo.end.offset.under = 0;
1048
1049 if(unlikely(x == hashed_thread_data->x.middle &&
1050 hashed_thread_data->x.middle_used)) {
1051 /* Jump */
1052 } else {
1053 draw_context.drawinfo.start.x = hashed_thread_data->x.middle;
1054 /* Draw the line */
1055 // PropertiesLine prop_line =
1056 prepare_s_e_line(thread,draw_context,ts);
1057 // draw_line((void*)&prop_line, (void*)&draw_context);
1058
1059 /* become the last x position */
1060 if(likely(x != hashed_thread_data->x.middle)) {
1061 hashed_thread_data->x.middle = x;
1062 /* but don't use the pixel */
1063 hashed_thread_data->x.middle_used = FALSE;
1064
1065 /* Calculate the next good time */
1066 convert_pixels_to_time(width, x+1, time_window,
1067 &hashed_thread_data->next_good_time);
1068 }
1069 }
1070 }
1071 }
1072 }
1073 return;
1074 }
1075
1076
1077 int xenoltt_before_chunk(void *hook_data, void *call_data) {
1078 EventsRequest *events_request = (EventsRequest*)hook_data;
1079 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1080
1081 drawing_chunk_begin(events_request, tss);
1082
1083 return 0;
1084 }
1085
1086 int xenoltt_before_request(void *hook_data, void *call_data) {
1087 EventsRequest *events_request = (EventsRequest*)hook_data;
1088 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1089
1090 drawing_data_request_begin(events_request, tss);
1091
1092 return 0;
1093 }
1094
1095
1096 /*
1097 * after request is necessary in addition of after chunk in order to draw
1098 * lines until the end of the screen. after chunk just draws lines until
1099 * the last event.
1100 *
1101 * for each process
1102 * draw closing line
1103 * expose
1104 */
1105 int xenoltt_after_request(void *hook_data, void *call_data) {
1106 EventsRequest *events_request = (EventsRequest*)hook_data;
1107 XenoLTTData *xenoltt_data = events_request->viewer_data;
1108 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1109
1110 ThreadList *thread_list = xenoltt_data->thread_list;
1111 LttTime end_time = events_request->end_time;
1112
1113 ClosureData closure_data;
1114 closure_data.events_request = (EventsRequest*)hook_data;
1115 closure_data.tss = tss;
1116 closure_data.end_time = end_time;
1117
1118 TimeWindow time_window =
1119 lttvwindow_get_time_window(xenoltt_data->tab);
1120 guint width = xenoltt_data->drawing->width;
1121 convert_time_to_pixels(
1122 time_window,
1123 end_time,
1124 width,
1125 &closure_data.x_end);
1126
1127
1128 /* Draw last items */
1129 g_hash_table_foreach(thread_list->thread_hash, draw_closure,
1130 (void*)&closure_data);
1131
1132
1133 /* Request expose */
1134 drawing_request_expose(events_request, tss, end_time);
1135 return 0;
1136 }
1137
1138 /*
1139 * for each process
1140 * draw closing line
1141 * expose
1142 */
1143 int xenoltt_after_chunk(void *hook_data, void *call_data) {
1144 EventsRequest *events_request = (EventsRequest*)hook_data;
1145 XenoLTTData *xenoltt_data = events_request->viewer_data;
1146 LttvTracesetState *tss = (LttvTracesetState*)call_data;
1147 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
1148 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
1149 LttTime end_time;
1150
1151 ThreadList *thread_list = xenoltt_data->thread_list;
1152 guint i;
1153 LttvTraceset *traceset = tsc->ts;
1154 guint nb_trace = lttv_traceset_number(traceset);
1155
1156 /* Only execute when called for the first trace's events request */
1157 if(!thread_list->current_hash_data) return;
1158
1159 for(i = 0 ; i < nb_trace ; i++) {
1160 g_free(thread_list->current_hash_data[i]);
1161 }
1162 g_free(thread_list->current_hash_data);
1163 thread_list->current_hash_data = NULL;
1164
1165 if(tfc != NULL)
1166 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
1167 else /* end of traceset, or position now out of request : end */
1168 end_time = events_request->end_time;
1169
1170 ClosureData closure_data;
1171 closure_data.events_request = (EventsRequest*)hook_data;
1172 closure_data.tss = tss;
1173 closure_data.end_time = end_time;
1174
1175 TimeWindow time_window =
1176 lttvwindow_get_time_window(xenoltt_data->tab);
1177 guint width = xenoltt_data->drawing->width;
1178 convert_time_to_pixels(
1179 time_window,
1180 end_time,
1181 width,
1182 &closure_data.x_end);
1183
1184 /* Draw last items */
1185 g_hash_table_foreach(thread_list->thread_hash, draw_closure,
1186 (void*)&closure_data);
1187
1188 /* Request expose (updates damages zone also) */
1189 drawing_request_expose(events_request, tss, end_time);
1190
1191 return 0;
1192 }
1193
1194 /******************************************************************************
1195 * Xenoami Thread Initialization hook
1196 ******************************************************************************/
1197 int xenoltt_thread_init(void *hook_data, void *call_data){
1198 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1199 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1200
1201 XenoLTTData *xenoltt_data = events_request->viewer_data;
1202
1203 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1204
1205 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1206 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1207
1208 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1209
1210 LttTime evtime = ltt_event_time(e);
1211
1212 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f1));
1213 gulong address = ltt_event_get_long_unsigned(e, thf->f2);
1214 guint prio = ltt_event_get_unsigned(e, thf->f3);
1215
1216 guint trace_num = ts->parent.index;
1217
1218
1219 LttvXenoThreadState *thread;
1220 LttTime birth;
1221 guint pl_height = 0;
1222 /* Find thread in the list... */
1223 thread = lttv_xeno_state_find_thread(ts, ANY_CPU, address);
1224
1225 if (thread != NULL){
1226 birth = thread->creation_time;
1227 /* Add thread to thread list (if not present) */
1228 HashedThreadData *hashed_thread_data = NULL;
1229 ThreadList *thread_list = xenoltt_data->thread_list;
1230
1231 hashed_thread_data = threadlist_get_thread_data(thread_list,thread->address,tfs->cpu, &birth, trace_num);
1232 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1233
1234 if(hashed_thread_data == NULL){
1235 /* Xenomai Thread not present */
1236 XenoThreadInfo *thread_Info;
1237 threadlist_add(thread_list,
1238 drawing,
1239 address,
1240 thread->prio,
1241 tfs->cpu,
1242 thread->period,
1243 &birth,
1244 trace_num,
1245 thread->name,
1246 &pl_height,
1247 &thread_Info,
1248 &hashed_thread_data);
1249 gtk_widget_set_size_request(drawing->drawing_area, -1, pl_height);
1250 gtk_widget_queue_draw(drawing->drawing_area);
1251 }
1252 }
1253 /*
1254 else{
1255 g_warning("Cannot find thread initialization %s - %u", g_quark_to_string(name), address);
1256 }
1257 */
1258 return 0;
1259 }
1260
1261 /******************************************************************************
1262 * Xenoami Thread Set Period hook
1263 ******************************************************************************/
1264 int xenoltt_thread_set_period(void *hook_data, void *call_data){
1265
1266 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1267 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1268
1269 XenoLTTData *xenoltt_data = events_request->viewer_data;
1270
1271 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1272
1273 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1274 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1275
1276 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1277
1278 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f1));
1279 gulong address = ltt_event_get_long_unsigned(e, thf->f2);
1280 guint period = ltt_event_get_unsigned(e, thf->f3);
1281 gulong timer_address = ltt_event_get_long_unsigned(e,ltt_eventtype_field_by_name(ltt_event_eventtype(e),g_quark_from_string("timer_address")));
1282 LttTime evtime = ltt_event_time(e);
1283
1284 guint trace_num = ts->parent.index;
1285
1286 LttvXenoThreadState *thread;
1287 LttTime birth;
1288 guint pl_height = 0;
1289 /* Find thread in the list... */
1290 thread = lttv_xeno_state_find_thread(ts, ANY_CPU, address);
1291
1292 if (thread != NULL){ // Thread present in table
1293 birth = thread->creation_time;
1294 // Add thread to thread list (if not present)
1295 HashedThreadData *hashed_thread_data = NULL;
1296 ThreadList *thread_list = xenoltt_data->thread_list;
1297
1298 hashed_thread_data = threadlist_get_thread_data(thread_list,thread->address,tfs->cpu, &birth, trace_num);
1299 if(hashed_thread_data != NULL){
1300
1301 threadlist_set_period(thread_list, period, hashed_thread_data);
1302
1303 //Save the timer address
1304 hashed_thread_data->timer_address = timer_address;
1305
1306 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1307 gtk_widget_set_size_request(drawing->drawing_area, -1, pl_height);
1308 gtk_widget_queue_draw(drawing->drawing_area);
1309 }
1310 else{
1311 // Xenomai Thread not present
1312 XenoThreadInfo *thread_Info;
1313 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1314 threadlist_add(thread_list,
1315 drawing,
1316 address,
1317 thread->prio, // Priority
1318 tfs->cpu,
1319 thread->period, //Period
1320 &birth,
1321 trace_num,
1322 thread->name,
1323 &pl_height,
1324 &thread_Info,
1325 &hashed_thread_data);
1326 gtk_widget_set_size_request(drawing->drawing_area, -1, pl_height);
1327 gtk_widget_queue_draw(drawing->drawing_area);
1328 }
1329 }
1330 /*
1331 else{
1332 g_warning("Cannot find thread in set_period %s - %u", g_quark_to_string(name), address);
1333 }
1334 */
1335 return 0;
1336 }
1337
1338
1339
1340 /******************************************************************************/
1341
1342 int xenoltt_before_thread_hook(void *hook_data, void *call_data){
1343
1344 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1345 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1346
1347 XenoLTTData *xenoltt_data = events_request->viewer_data;
1348
1349 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1350
1351 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1352 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1353
1354 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1355
1356 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
1357
1358 gulong address = ltt_event_get_long_unsigned(e, thf->f1);
1359
1360 guint trace_num = ts->parent.index;
1361
1362 LttTime evtime = ltt_event_time(e);
1363 LttvXenoThreadState *thread;
1364 LttTime birth;
1365 guint pl_height = 0;
1366 /* Find thread in the list... */
1367
1368 if (event_name == LTT_EVENT_XENOLTT_TIMER_TICK)
1369 thread = lttv_xeno_state_find_thread_from_timer(ts, ANY_CPU, address);
1370 else
1371 thread = lttv_xeno_state_find_thread(ts, ANY_CPU, address);
1372
1373 if (thread != NULL){ // Thread present in table
1374 birth = thread->creation_time;
1375 HashedThreadData *hashed_thread_data = NULL;
1376 ThreadList *thread_list = xenoltt_data->thread_list;
1377 hashed_thread_data = threadlist_get_thread_data(thread_list,thread->address,tfs->cpu, &birth, trace_num);
1378
1379 if(hashed_thread_data == NULL){ // Xenomai Thread not present
1380 XenoThreadInfo *thread_Info;
1381 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1382 threadlist_add(thread_list,drawing,thread->address,thread->prio,tfs->cpu,
1383 thread->period, &birth, trace_num, thread->name, &pl_height,
1384 &thread_Info, &hashed_thread_data);
1385
1386 gtk_widget_set_size_request(drawing->drawing_area, -1, pl_height);
1387 gtk_widget_queue_draw(drawing->drawing_area);
1388 }
1389 else{
1390
1391 /* Now, the process is in the state hash and our own process hash.
1392 * We definitely can draw the items related to the ending state.
1393 */
1394
1395 if(ltt_time_compare(hashed_thread_data->next_good_time,evtime) > 0) {
1396 if(hashed_thread_data->x.middle_marked == FALSE) {
1397
1398 TimeWindow time_window = lttvwindow_get_time_window(xenoltt_data->tab);
1399 #ifdef EXTRA_CHECK
1400 if(ltt_time_compare(evtime, time_window.start_time) == -1 || ltt_time_compare(evtime, time_window.end_time) == 1)
1401 return;
1402 #endif //EXTRA_CHECK
1403 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1404 guint width = drawing->width;
1405 guint x;
1406 convert_time_to_pixels(time_window,evtime,width,&x);
1407
1408 // Draw collision indicator
1409 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1410 gdk_draw_point(hashed_thread_data->pixmap,drawing->gc,x,
1411 COLLISION_POSITION(hashed_thread_data->height));
1412 hashed_thread_data->x.middle_marked = TRUE;
1413 }
1414 } else {
1415 TimeWindow time_window = lttvwindow_get_time_window(xenoltt_data->tab);
1416 #ifdef EXTRA_CHECK
1417 if(ltt_time_compare(evtime, time_window.start_time) == -1 || ltt_time_compare(evtime, time_window.end_time) == 1)
1418 return;
1419 #endif //EXTRA_CHECK
1420 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1421 guint width = drawing->width;
1422 guint x;
1423 convert_time_to_pixels(time_window,evtime,width,&x);
1424
1425 /* Jump over draw if we are at the same x position */
1426 if(x == hashed_thread_data->x.middle && hashed_thread_data->x.middle_used) {
1427 if(hashed_thread_data->x.middle_marked == FALSE) {
1428 // Draw collision indicator
1429 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1430 gdk_draw_point(hashed_thread_data->pixmap,drawing->gc,x,
1431 COLLISION_POSITION(hashed_thread_data->height));
1432 hashed_thread_data->x.middle_marked = TRUE;
1433 }
1434 } else {
1435 DrawContext draw_context;
1436
1437
1438 /* Now create the drawing context that will be used to draw
1439 * items related to the last state. */
1440 draw_context.drawable = hashed_thread_data->pixmap;
1441 draw_context.gc = drawing->gc;
1442 draw_context.pango_layout = drawing->pango_layout;
1443 draw_context.drawinfo.start.x = hashed_thread_data->x.middle;
1444 draw_context.drawinfo.end.x = x;
1445
1446 draw_context.drawinfo.y.over = 1;
1447 draw_context.drawinfo.y.middle = (hashed_thread_data->height/2);
1448 draw_context.drawinfo.y.under = hashed_thread_data->height;
1449
1450 draw_context.drawinfo.start.offset.over = 0;
1451 draw_context.drawinfo.start.offset.middle = 0;
1452 draw_context.drawinfo.start.offset.under = 0;
1453 draw_context.drawinfo.end.offset.over = 0;
1454 draw_context.drawinfo.end.offset.middle = 0;
1455 draw_context.drawinfo.end.offset.under = 0;
1456
1457 prepare_s_e_line(thread,draw_context,ts); // Draw the line
1458
1459 /* become the last x position */
1460 hashed_thread_data->x.middle = x;
1461 hashed_thread_data->x.middle_used = TRUE;
1462 hashed_thread_data->x.middle_marked = FALSE;
1463
1464 /* Calculate the next good time */
1465 convert_pixels_to_time(width, x+1, time_window,
1466 &hashed_thread_data->next_good_time);
1467 }
1468 }
1469 }
1470 }
1471 /*
1472 else{
1473 g_warning("Cannot find thread in before hook - %u", g_quark_to_string(address));
1474 }
1475 */
1476 return 0;
1477 }
1478
1479 // When the thread switch is read, we need to change the state of the thread_out also
1480 int xenoltt_before_thread_switch_hook(void *hook_data, void *call_data){
1481
1482 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1483 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1484 XenoLTTData *xenoltt_data = events_request->viewer_data;
1485 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1486 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1487 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1488 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1489 gulong address = ltt_event_get_long_unsigned(e, thf->f2);
1490
1491 guint trace_num = ts->parent.index;
1492
1493 LttTime evtime = ltt_event_time(e);
1494 LttvXenoThreadState *thread;
1495 LttTime birth;
1496 guint pl_height = 0;
1497 /* Find thread in the list... */
1498
1499 thread = lttv_xeno_state_find_thread(ts, ANY_CPU, address);
1500
1501 if (thread != NULL){ // Thread present in table
1502 birth = thread->creation_time;
1503 HashedThreadData *hashed_thread_data = NULL;
1504 ThreadList *thread_list = xenoltt_data->thread_list;
1505 hashed_thread_data = threadlist_get_thread_data(thread_list,thread->address,tfs->cpu, &birth, trace_num);
1506
1507 if(hashed_thread_data == NULL){ // Xenomai Thread not present
1508 XenoThreadInfo *thread_Info;
1509 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1510 threadlist_add(thread_list,drawing,thread->address,thread->prio, tfs->cpu,
1511 thread->period, &birth,trace_num, thread->name, &pl_height,
1512 &thread_Info,&hashed_thread_data);
1513 gtk_widget_set_size_request(drawing->drawing_area, -1, pl_height);
1514 gtk_widget_queue_draw(drawing->drawing_area);
1515 }
1516 else{
1517 TimeWindow time_window = lttvwindow_get_time_window(xenoltt_data->tab);
1518
1519 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1520 guint width = drawing->width;
1521 guint x;
1522 convert_time_to_pixels(time_window,evtime,width,&x);
1523
1524 DrawContext draw_context;
1525
1526
1527 /* Now create the drawing context that will be used to draw
1528 * items related to the last state. */
1529 draw_context.drawable = hashed_thread_data->pixmap;
1530 draw_context.gc = drawing->gc;
1531 draw_context.pango_layout = drawing->pango_layout;
1532 draw_context.drawinfo.start.x = hashed_thread_data->x.middle;
1533 draw_context.drawinfo.end.x = x;
1534
1535 draw_context.drawinfo.y.over = 1;
1536 draw_context.drawinfo.y.middle = (hashed_thread_data->height/2);
1537 draw_context.drawinfo.y.under = hashed_thread_data->height;
1538
1539 draw_context.drawinfo.start.offset.over = 0;
1540 draw_context.drawinfo.start.offset.middle = 0;
1541 draw_context.drawinfo.start.offset.under = 0;
1542 draw_context.drawinfo.end.offset.over = 0;
1543 draw_context.drawinfo.end.offset.middle = 0;
1544 draw_context.drawinfo.end.offset.under = 0;
1545
1546
1547 prepare_s_e_line(thread,draw_context,ts); // Draw the line
1548
1549 /* become the last x position */
1550 hashed_thread_data->x.middle = x;
1551 hashed_thread_data->x.middle_used = TRUE;
1552 hashed_thread_data->x.middle_marked = FALSE;
1553
1554 /* Calculate the next good time */
1555 convert_pixels_to_time(width, x+1, time_window,
1556 &hashed_thread_data->next_good_time);
1557 }
1558 }
1559 /*
1560 else{
1561 g_warning("Cannot find thread in before hook - %u", g_quark_to_string(address));
1562 }
1563 */
1564 return 0;
1565 }
1566
1567 /******************************************************************************/
1568 /* xenoltt_after_thread_hook */
1569
1570 int xenoltt_after_thread_hook(void *hook_data, void *call_data){
1571 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1572 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1573
1574 XenoLTTData *xenoltt_data = events_request->viewer_data;
1575
1576 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1577
1578 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1579 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1580
1581 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1582
1583 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
1584
1585 gulong address = ltt_event_get_long_unsigned(e, thf->f1);
1586
1587 guint trace_num = ts->parent.index;
1588 LttTime evtime = ltt_event_time(e);
1589 LttvXenoThreadState *thread;
1590 LttTime birth;
1591 guint pl_height = 0;
1592 /* Find thread in the list... */
1593
1594 if (event_name == LTT_EVENT_XENOLTT_TIMER_TICK){
1595 thread = lttv_xeno_state_find_thread_from_timer(ts, ANY_CPU,address);
1596 }
1597 else thread = lttv_xeno_state_find_thread(ts, ANY_CPU, address);
1598
1599 if (thread != NULL){ // Thread present in table
1600 birth = thread->creation_time;
1601 // Add thread to thread list (if not present)
1602 HashedThreadData *hashed_thread_data = NULL;
1603 ThreadList *thread_list = xenoltt_data->thread_list;
1604 guint pl_height = 0;
1605
1606 hashed_thread_data = threadlist_get_thread_data(thread_list, thread->address,tfs->cpu, &birth, trace_num);
1607
1608 if(hashed_thread_data == NULL){
1609 // Xenomai Thread not present
1610 XenoThreadInfo *thread_Info;
1611 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1612 threadlist_add(thread_list,
1613 drawing,
1614 thread->address,
1615 thread->prio, // Priority
1616 tfs->cpu,
1617 thread->period, //Period
1618 &birth,
1619 trace_num,
1620 thread->name,
1621 &pl_height,
1622 &thread_Info,
1623 &hashed_thread_data);
1624 gtk_widget_set_size_request(drawing->drawing_area, -1, pl_height);
1625 gtk_widget_queue_draw(drawing->drawing_area);
1626 }
1627
1628 /* Set the current Xenomai thread */
1629 thread_list->current_hash_data[trace_num][tfs->cpu] = hashed_thread_data;
1630
1631 if(ltt_time_compare(hashed_thread_data->next_good_time, evtime) <= 0){
1632 TimeWindow time_window = lttvwindow_get_time_window(xenoltt_data->tab);
1633
1634 #ifdef EXTRA_CHECK
1635 if(ltt_time_compare(evtime, time_window.start_time) == -1
1636 || ltt_time_compare(evtime, time_window.end_time) == 1)
1637 return;
1638 #endif //EXTRA_CHECK
1639 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1640 guint width = drawing->width;
1641 guint new_x;
1642
1643 convert_time_to_pixels(time_window,evtime,width,&new_x);
1644
1645 if(hashed_thread_data->x.middle != new_x) {
1646 hashed_thread_data->x.middle = new_x;
1647 hashed_thread_data->x.middle_used = FALSE;
1648 hashed_thread_data->x.middle_marked = FALSE;
1649 }
1650 }
1651 }
1652 /*
1653 else{
1654 g_warning("Cannot find thread in after hook %u", g_quark_to_string(address));
1655 }
1656 */
1657 return 0;
1658 }
1659
1660
1661 int xenoltt_draw_icons(void *hook_data, void *call_data){
1662
1663 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1664 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1665
1666 XenoLTTData *xenoltt_data = events_request->viewer_data;
1667
1668 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1669
1670 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1671 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1672
1673 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1674
1675 // We must update the state of the current Xenomai Thread
1676 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
1677
1678 guint trace_num = ts->parent.index;
1679 LttTime evtime = ltt_event_time(e);
1680
1681 gulong address = ltt_event_get_long_unsigned(e, thf->f2);
1682
1683 LttvXenoThreadState *thread;
1684 LttTime birth;
1685 guint pl_height = 0;
1686 /* Find thread in the list... */
1687
1688 HashedThreadData *hashed_thread_data = NULL;
1689 ThreadList *thread_list = xenoltt_data->thread_list;
1690
1691 XenoLtt_Drawing_t *drawing = xenoltt_data->drawing;
1692
1693 if (event_name == LTT_EVENT_XENOLTT_TIMER_TICK){
1694 thread = lttv_xeno_state_find_thread_from_timer(ts, ANY_CPU,address);
1695 }
1696 else thread = lttv_xeno_state_find_thread(ts, ANY_CPU, address);
1697
1698 if (thread != NULL){ // Thread present in table
1699 birth = thread->creation_time;
1700 // Add thread to thread list (if not present)
1701 HashedThreadData *hashed_thread_data = NULL;
1702 ThreadList *thread_list = xenoltt_data->thread_list;
1703 guint pl_height = 0;
1704
1705 hashed_thread_data = threadlist_get_thread_data(thread_list, thread->address,tfs->cpu, &birth, trace_num);
1706
1707 if(hashed_thread_data != NULL){
1708 TimeWindow time_window = lttvwindow_get_time_window(xenoltt_data->tab);
1709 guint width = drawing->width;
1710 guint new_x;
1711
1712
1713 convert_time_to_pixels(time_window,evtime,width,&new_x);
1714
1715 DrawContext draw_context;
1716
1717 /* Now create the drawing context that will be used to draw
1718 * items related to the event. */
1719 draw_context.drawable = hashed_thread_data->pixmap;
1720 draw_context.gc = drawing->gc;
1721 draw_context.pango_layout = drawing->pango_layout;
1722
1723 draw_context.drawinfo.y.over = -1;
1724 draw_context.drawinfo.y.middle = (hashed_thread_data->height/2);
1725 draw_context.drawinfo.y.under = hashed_thread_data->height;
1726
1727 draw_context.drawinfo.start.x = new_x;
1728 draw_context.drawinfo.start.offset.over = 0;
1729 draw_context.drawinfo.start.offset.middle = 0;
1730 draw_context.drawinfo.start.offset.under = 0;
1731
1732 draw_context.drawinfo.end.x = new_x + 2;
1733 draw_context.drawinfo.end.offset.over = 0;
1734 draw_context.drawinfo.end.offset.middle = 0;
1735 draw_context.drawinfo.end.offset.under = 0;
1736
1737 if(event_name == LTT_EVENT_XENOLTT_THREAD_INIT) {
1738 // When a thread is initialized, we place a small green flag
1739 PropertiesIcon prop_icon;
1740 prop_icon.icon_name = "/usr/local/share/LinuxTraceToolkitViewer/pixmaps/FlagThreadInit.xpm";
1741 prop_icon.width = 6;
1742 prop_icon.height = 13;
1743 prop_icon.position.x = POS_START;
1744 prop_icon.position.y = OVER;
1745
1746 draw_context.drawinfo.end.x = new_x + 6;
1747 draw_icon((void*)&prop_icon, (void*)&draw_context);
1748
1749 PropertiesText prop_text;
1750 prop_text.foreground = &drawing_colors[COL_RUN_USER_MODE];
1751 prop_text.background = &drawing_colors[COL_BLACK];
1752 prop_text.size = 8;
1753 prop_text.text = ltt_event_get_string(e, thf->f1);
1754 prop_text.position.x = POS_START;
1755 prop_text.position.y = OVER;
1756
1757 draw_context.drawinfo.end.x = new_x + 1000;
1758 draw_text((void*)&prop_text, (void*)&draw_context);
1759
1760
1761 } else if(event_name == LTT_EVENT_XENOLTT_THREAD_SET_PERIOD) {
1762 PropertiesArc prop_arc;
1763 prop_arc.color = &drawing_colors[COL_RUN_TRAP];
1764 prop_arc.size = 6;
1765 prop_arc.filled = 1;
1766 prop_arc.position.x = POS_START;
1767 prop_arc.position.y = MIDDLE;
1768
1769 draw_context.drawinfo.end.x = new_x + 6;
1770 draw_arc((void*)&prop_arc, (void*)&draw_context);
1771
1772 guint period = ltt_event_get_unsigned(e, thf->f3);
1773 gchar text[MAX_PATH_LEN] = "Period :";
1774 sprintf(text,"%s %u",text,period);
1775 //We must update the thread priority in the list
1776 threadlist_set_period(thread_list, period, hashed_thread_data);
1777
1778 PropertiesText prop_text;
1779 prop_text.foreground = &drawing_colors[COL_RUN_TRAP]; //Yellow
1780 prop_text.background = &drawing_colors[COL_BLACK];
1781 prop_text.size = 8;
1782 prop_text.text = text;
1783 prop_text.position.x = POS_START;
1784 prop_text.position.y = MIDDLE;
1785
1786 draw_context.drawinfo.end.x = new_x + 1000;
1787 draw_text((void*)&prop_text, (void*)&draw_context);
1788
1789 } else if(event_name == LTT_EVENT_XENOLTT_THREAD_RENICE) {
1790 PropertiesArc prop_arc;
1791 prop_arc.color = &drawing_colors[COL_WHITE];
1792 prop_arc.size = 6;
1793 prop_arc.filled = 1;
1794 prop_arc.position.x = POS_START;
1795 prop_arc.position.y = MIDDLE;
1796
1797 draw_context.drawinfo.end.x = new_x + 6;
1798 draw_arc((void*)&prop_arc, (void*)&draw_context);
1799
1800 guint prio = ltt_event_get_unsigned(e, thf->f3);
1801 gchar text[MAX_PATH_LEN] = "Priority :";
1802 sprintf(text,"%s %u",text,prio);
1803 //We must update the thread priority in the list
1804 threadlist_set_prio(thread_list,prio,hashed_thread_data);
1805
1806 PropertiesText prop_text;
1807 prop_text.foreground = &drawing_colors[COL_WHITE];
1808 prop_text.background = &drawing_colors[COL_BLACK];
1809 prop_text.size = 8;
1810 prop_text.text = text;
1811 prop_text.position.x = POS_START;
1812 prop_text.position.y = MIDDLE;
1813
1814 draw_context.drawinfo.end.x = new_x + 500;
1815 draw_text((void*)&prop_text, (void*)&draw_context);
1816
1817 } else if(event_name == LTT_EVENT_XENOLTT_TIMER_TICK) {
1818 PropertiesLine prop_line;
1819 prop_line.line_width = 20;
1820 prop_line.style = GDK_LINE_SOLID;
1821 prop_line.y = MIDDLE;
1822 prop_line.color = drawing_colors[COL_WHITE]; // WHITE
1823
1824 draw_context.drawinfo.start.x = new_x;
1825 draw_context.drawinfo.end.x = new_x + 2;
1826 draw_line((void*)&prop_line, (void*)&draw_context);
1827
1828 } else if(event_name == LTT_EVENT_XENOLTT_THREAD_DELETE) {
1829 // When a thread is deleted, we place a small red flag
1830 PropertiesIcon prop_icon;
1831 prop_icon.icon_name = "/usr/local/share/LinuxTraceToolkitViewer/pixmaps/FlagThreadDelete.xpm";
1832 prop_icon.width = 6;
1833 prop_icon.height = 13;
1834 prop_icon.position.x = POS_START;
1835 prop_icon.position.y = OVER;
1836
1837 draw_context.drawinfo.end.x = new_x + 10;
1838 draw_icon((void*)&prop_icon, (void*)&draw_context);
1839
1840 } else if(event_name == LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD) {
1841 PropertiesArc prop_arc;
1842 prop_arc.color = &drawing_colors[COL_WHITE];
1843 prop_arc.size = 6;
1844 prop_arc.filled = 1;
1845 prop_arc.position.x = POS_START;
1846 prop_arc.position.y = MIDDLE;
1847
1848 draw_context.drawinfo.end.x = new_x + 6;
1849 draw_arc((void*)&prop_arc, (void*)&draw_context);
1850
1851 guint overruns = ltt_event_get_unsigned(e, thf->f3);
1852 gchar text[MAX_PATH_LEN] = "Overruns :";
1853 sprintf(text,"%s %u",text,overruns);
1854
1855 PropertiesText prop_text;
1856 prop_text.foreground = &drawing_colors[COL_WHITE];
1857 prop_text.background = &drawing_colors[COL_BLACK];
1858 prop_text.size = 8;
1859 prop_text.text = text;
1860 prop_text.position.x = POS_START;
1861 prop_text.position.y = MIDDLE;
1862
1863 draw_context.drawinfo.end.x = new_x + 1000;
1864 draw_text((void*)&prop_text, (void*)&draw_context);
1865
1866 } else if(event_name == LTT_EVENT_XENOLTT_SYNCH_SET_OWNER ||
1867 event_name == LTT_EVENT_XENOLTT_SYNCH_WAKEUP1 ||
1868 event_name == LTT_EVENT_XENOLTT_SYNCH_WAKEUPX) {
1869
1870 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f3);
1871
1872 LttvXenoSynchState *synch = lttv_xeno_state_find_synch(ts,synch_address);
1873
1874 if (synch != NULL){
1875 // When a thread has a synch, we place a small blue flag
1876 PropertiesIcon prop_icon;
1877 prop_icon.icon_name = "/usr/local/share/LinuxTraceToolkitViewer/pixmaps/FlagSynchOwner.xpm";
1878 prop_icon.width = 6;
1879 prop_icon.height = 13;
1880 prop_icon.position.x = POS_START;
1881 prop_icon.position.y = OVER;
1882
1883 int i;
1884 LttvXenoThreadState *temp_thread;
1885
1886 // If the thread has a lower priority than another we need to inform
1887 // about priority inversion
1888 for(i=0;i<synch->state->waiting_threads->len;i++){
1889 temp_thread = g_array_index(synch->state->waiting_threads, LttvXenoThreadState*, i);
1890 if (temp_thread->address != thread->address){
1891 if (thread->prio < temp_thread->prio){
1892 prop_icon.width = 13;
1893 prop_icon.icon_name = "/usr/local/share/LinuxTraceToolkitViewer/pixmaps/FlagPriority.xpm";
1894 }
1895 }
1896 }
1897
1898 draw_context.drawinfo.end.x = new_x + 10;
1899 draw_icon((void*)&prop_icon, (void*)&draw_context);
1900 }
1901 } else if(event_name == LTT_EVENT_XENOLTT_SYNCH_SLEEP_ON) {
1902
1903 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f3);
1904
1905 LttvXenoSynchState *synch = lttv_xeno_state_find_synch(ts,synch_address);
1906
1907 if (synch != NULL){
1908 // When a thread has a synch, we place a small blue flag
1909 PropertiesIcon prop_icon;
1910 prop_icon.icon_name = "/usr/local/share/LinuxTraceToolkitViewer/pixmaps/FlagSynchSleep.xpm";
1911 prop_icon.width = 6;
1912 prop_icon.height = 13;
1913 prop_icon.position.x = POS_START;
1914 prop_icon.position.y = OVER;
1915
1916 draw_context.drawinfo.end.x = new_x + 10;
1917 draw_icon((void*)&prop_icon, (void*)&draw_context);
1918 }
1919 } else if(event_name == LTT_EVENT_XENOLTT_SYNCH_UNLOCK) {
1920
1921 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f3);
1922
1923 LttvXenoSynchState *synch = lttv_xeno_state_find_synch(ts,synch_address);
1924
1925 if (synch != NULL){
1926 // When a thread has a synch, we place a small blue flag
1927 PropertiesIcon prop_icon;
1928 prop_icon.icon_name = "/usr/local/share/LinuxTraceToolkitViewer/pixmaps/FlagSynchUnlock.xpm";
1929 prop_icon.width = 6;
1930 prop_icon.height = 13;
1931 prop_icon.position.x = POS_START;
1932 prop_icon.position.y = OVER;
1933
1934 draw_context.drawinfo.end.x = new_x + 10;
1935 draw_icon((void*)&prop_icon, (void*)&draw_context);
1936 }
1937 }
1938 }
1939 }
1940 return 0;
1941 }
This page took 0.121681 seconds and 4 git commands to generate.