1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
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;
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.
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,
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
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.
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.
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.
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
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
52 //#define PANGO_ENABLE_BACKEND
60 //#include <pango/pango.h>
62 #include <ltt/event.h>
65 #include <ltt/trace.h>
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>
76 #include <lttv/filter.h>
78 #include "xenoltt_eventhooks.h"
80 #include "xenoltt_threadlist.h"
81 #include "xenoltt_drawing.h"
83 #include "TraceControlStart.xpm"
85 #define MAX_PATH_LEN 256
86 #define STATE_LINE_WIDTH 2
87 #define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
89 extern GSList
*g_legend_list
;
94 /* Action to do when background computation completed.
96 * Wait for all the awaited computations to be over.
99 static gint
background_ready(void *hook_data
, void *call_data
) {
100 XenoLTTData
*xenoltt_data
= (XenoLTTData
*)hook_data
;
101 LttvTrace
*trace
= (LttvTrace
*)call_data
;
103 xenoltt_data
->background_info_waiting
--;
105 if(xenoltt_data
->background_info_waiting
== 0) {
106 g_message("xenoltt viewer : background computation data ready.");
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
));
112 redraw_notify(xenoltt_data
, NULL
);
120 /* Request background computation. Verify if it is in progress or ready first.
121 * Only for each trace in the tab's traceset.
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
);
128 LttvTraceState
*tstate
;
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;
134 for(i
=0;i
<num_traces
;i
++) {
135 trace
= lttv_traceset_get(tsc
->ts
, i
);
136 tstate
= LTTV_TRACE_STATE(tsc
->traces
[i
]);
138 if(lttvwindowtraces_get_ready(g_quark_from_string("state"), trace
)==FALSE
139 && !tstate
->has_precomputed_states
) {
141 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
143 /* We first remove requests that could have been done for the same
144 * information. Happens when two viewers ask for it before servicing
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
,
154 background_ready_hook
);
155 xenoltt_data
->background_info_waiting
++;
156 } else { /* in progress */
157 lttvwindowtraces_background_notify_current(xenoltt_data
,
161 background_ready_hook
);
162 xenoltt_data
->background_info_waiting
++;
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.
172 lttv_hooks_destroy(background_ready_hook
);
176 /***********************************************************************************************************************************/
177 /***********************************************************************************************************************************/
181 * Event Viewer's constructor hook
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.
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
);
194 xenoltt_data
->tab
= tab
;
196 // Unreg done in the guixenoltt_Destructor
197 lttvwindow_register_traceset_notify(tab
,traceset_notify
,xenoltt_data
);
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
);
205 return guixenoltt_get_widget(xenoltt_data
);
209 void xenolttlegend_destructor(GtkWindow
*legend
) {
210 g_legend_list
= g_slist_remove(g_legend_list
, legend
);
212 /***********************************************************************************************************************************/
213 void start_clicked (GtkButton
*button
, gpointer user_data
);
215 typedef struct _ControlData ControlData
;
216 struct _ControlData
{
217 Tab
*tab
; //< current tab of module
219 GtkWidget
*window
; //< window
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
;
228 GtkWidget
*period_settings
;
229 GtkWidget
*task_label
;
230 GtkWidget
*period_label
;
233 void prepare_sim_data(ControlData
*tcd
);
235 /* Create a simulation settings window */
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
);
242 ControlData
* tcd
= g_new(ControlData
,1);
244 tcd
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
245 gtk_window_set_title(GTK_WINDOW(tcd
->window
), "XenoLTT Simulation");
247 g_legend_list
= g_slist_append(g_legend_list
,GTK_WINDOW(tcd
->window
));
249 g_object_set_data_full(G_OBJECT(tcd
->window
),"Simulation",GTK_WINDOW(tcd
->window
),
250 (GDestroyNotify
)xenolttlegend_destructor
);
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);
258 gtk_container_add(GTK_CONTAINER(tcd
->window
), GTK_WIDGET(tcd
->main_box
));
260 prepare_sim_data(tcd
);
266 /***********************************************************************************************************************************/
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();
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);
282 //Insert Task selection
283 tcd
->task_label
= gtk_label_new("Task:");
284 gtk_widget_show (tcd
->task_label
);
286 tcd
->task_selection_combo
= gtk_combo_box_new_text();
287 // iterate on all task to get the name and default period
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
);
297 gtk_combo_box_set_active(GTK_COMBO_BOX(tcd
->task_selection_combo
), 0);
298 gtk_widget_show (tcd
->task_selection_combo
);
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);
311 //Insert Start button
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);
323 // User interface guide
324 GList
*focus_chain
= NULL
;
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
);
331 gtk_container_set_focus_chain(GTK_CONTAINER(tcd
->main_box
), focus_chain
);
333 g_list_free(focus_chain
);
335 g_signal_connect(G_OBJECT(tcd
->start_button
), "clicked",(GCallback
)start_clicked
, tcd
);
337 gtk_widget_show(tcd
->main_box
);
338 gtk_widget_show(tcd
->window
);
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
;
351 GArray
*list
= get_thread_list();
352 ThreadEventData
*temp_thread
;
358 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(tcd
->task_selection_combo
), &iter
);
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
))),
371 gtk_dialog_run(GTK_DIALOG(dialogue
));
372 gtk_widget_destroy(dialogue
);
377 int i
= gtk_combo_box_get_active(GTK_COMBO_BOX(tcd
->task_selection_combo
)) - 1;
379 temp_thread
= g_array_index(list
, ThreadEventData
*, i
);
382 const gchar
*period
= gtk_entry_get_text(GTK_ENTRY(tcd
->period_entry
));
383 int period_value
= atoi(period
);
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
))),
394 gtk_dialog_run(GTK_DIALOG(dialogue
));
395 gtk_widget_destroy(dialogue
);
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
))),
409 gtk_dialog_run(GTK_DIALOG(dialogue
));
410 gtk_widget_destroy(dialogue
);
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
);
420 // Try to open file in read mode to check if it exist
421 a_file
= fopen(file_name
, "r");
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
))),
432 gtk_dialog_run(GTK_DIALOG(dialogue
));
433 gtk_widget_destroy(dialogue
);
439 a_file
= fopen(file_name
, "w");
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
))),
449 gtk_dialog_run(GTK_DIALOG(dialogue
));
450 gtk_widget_destroy(dialogue
);
454 fprintf(a_file
,"<TRACE SIMULATION>\n");
455 compute_simulation(i
,period_value
,a_file
);
456 fprintf(a_file
,"</TRACE SIMULATION>\n");
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
))),
466 gtk_dialog_run(GTK_DIALOG(dialogue
));
467 gtk_widget_destroy(dialogue
);
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
);
478 LttvTraceState
*tstate
;
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
);
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
);
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
,
493 hook_adder
, hook_remover
);
495 LttvHooks
*background_ready_hook
= lttv_hooks_new();
496 lttv_hooks_add(background_ready_hook
, data_ready
, tcd
, LTTV_PRIO_DEFAULT
);
498 for(i
=0;i
<num_traces
;i
++) {
499 trace
= lttvwindowtraces_get_trace(i
);
501 if(lttvwindowtraces_get_ready(g_quark_from_string("xenoltt_sim"),trace
)==FALSE
) {
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
);
513 lttv_hooks_destroy(background_ready_hook
);
516 /***********************************************************************************************************************************/
518 /* Create a popup legend */
519 GtkWidget
*h_xenolttlegend(LttvPlugin
*plugin
)
521 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
522 Tab
*tab
= ptab
->tab
;
523 g_info("h_legend, %p", tab
);
525 GtkWindow
*xenoltt_settings
= GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL
));
527 g_legend_list
= g_slist_append(g_legend_list
,xenoltt_settings
);
529 g_object_set_data_full(G_OBJECT(xenoltt_settings
),"settings",xenoltt_settings
,(GDestroyNotify
)xenolttlegend_destructor
);
531 gtk_window_set_title(xenoltt_settings
, "XenoLTT Settings");
533 GtkWidget
*pixmap
= create_pixmap(GTK_WIDGET(xenoltt_settings
), "xenoltt-color-list.png");
536 gtk_container_add(GTK_CONTAINER(xenoltt_settings
), GTK_WIDGET(pixmap
));
538 gtk_widget_show(GTK_WIDGET(pixmap
));
539 gtk_widget_show(GTK_WIDGET(xenoltt_settings
));
542 return NULL
; /* This is a popup window */
545 /***********************************************************************************************************************************/
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
;
551 g_debug("DEBUG : event selected by main window : %u", *event_number
);
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
) {
559 PropertiesLine prop_line
;
560 prop_line
.style
= GDK_LINE_SOLID
;
561 prop_line
.y
= MIDDLE
;
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
);
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);
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);
587 prop_line
.line_width
= STATE_LINE_WIDTH
;
589 if(thread
->state
->status
== LTTV_XENO_STATE_INIT
) {
590 prop_line
.color
= drawing_colors
[COL_EXIT
]; // Created = MAGENTA
592 } else if(thread
->state
->status
== LTTV_XENO_STATE_START
) {
593 prop_line
.color
= drawing_colors
[COL_RUN_SOFT_IRQ
]; // Started = RED
595 } else if(thread
->state
->status
== LTTV_XENO_STATE_RUN
) {
596 prop_line
.color
= drawing_colors
[COL_RUN_USER_MODE
]; // Running = GREEN
598 } else if(thread
->state
->status
== LTTV_XENO_STATE_READY
) {
599 prop_line
.color
= drawing_colors
[COL_WHITE
]; // READY = WHITE
601 } else if(thread
->state
->status
== LTTV_XENO_STATE_WAIT_PERIOD
) {
602 prop_line
.color
= drawing_colors
[COL_WAIT
]; // WAIT PERIOD = DARK RED
604 } else if(thread
->state
->status
== LTTV_XENO_STATE_SUSPEND
) {
605 prop_line
.color
= drawing_colors
[COL_RUN_SYSCALL
]; // SUSPEND = BLUE
607 } else if(thread
->state
->status
== LTTV_XENO_STATE_DEAD
) {
608 prop_line
.color
= drawing_colors
[COL_BLACK
]; // DEAD = BLACK
610 } else if(thread
->state
->status
== LTTV_XENO_STATE_UNNAMED
) {
611 prop_line
.color
= drawing_colors
[COL_WHITE
];
614 g_critical("unknown status : %s", g_quark_to_string(thread
->state
->status
));
615 g_assert(FALSE
); /* UNKNOWN STATUS */
618 draw_line((void*)&prop_line
, (void*)&draw_context
);
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
;
628 const TimeWindowNotifyData
*time_window_nofify_data
=
629 ((const TimeWindowNotifyData
*)call_data
);
631 TimeWindow
*old_time_window
= time_window_nofify_data
->old_time_window
;
632 TimeWindow
*new_time_window
= time_window_nofify_data
->new_time_window
;
634 /* Update the ruler */
635 drawing_update_ruler(xenoltt_data
->drawing
,new_time_window
);
638 /* Two cases : zoom in/out or scrolling */
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)
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
);
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
);
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) */
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 */
672 guint width
= xenoltt_data
->drawing
->width
;
673 convert_time_to_pixels(
679 /* Copy old data to new location */
680 copy_pixmap_region(thread_list
,
682 xenoltt_data
->drawing
->drawing_area
->style
->black_gc
,
686 xenoltt_data
->drawing
->width
-x
+SAFETY
, -1);
688 if(drawing
->damage_begin
== drawing
->damage_end
)
689 drawing
->damage_begin
= xenoltt_data
->drawing
->width
-x
;
691 drawing
->damage_begin
= 0;
693 drawing
->damage_end
= xenoltt_data
->drawing
->width
;
695 /* Clear the data request background, but not SAFETY */
696 rectangle_pixmap(thread_list
,
697 xenoltt_data
->drawing
->drawing_area
->style
->black_gc
,
699 drawing
->damage_begin
+SAFETY
, 0,
700 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
702 gtk_widget_queue_draw(drawing
->drawing_area
);
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
);
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 */
715 guint width
= xenoltt_data
->drawing
->width
;
716 convert_time_to_pixels(
722 /* Copy old data to new location */
723 copy_pixmap_region (thread_list
,
725 xenoltt_data
->drawing
->drawing_area
->style
->black_gc
,
731 if(drawing
->damage_begin
== drawing
->damage_end
)
732 drawing
->damage_end
= x
;
734 drawing
->damage_end
=
735 xenoltt_data
->drawing
->width
;
737 drawing
->damage_begin
= 0;
739 rectangle_pixmap(thread_list
,
740 xenoltt_data
->drawing
->drawing_area
->style
->black_gc
,
742 drawing
->damage_begin
, 0,
743 drawing
->damage_end
- drawing
->damage_begin
, // do not overlap
746 gtk_widget_queue_draw(drawing
->drawing_area
);
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
);
756 if(ltt_time_compare(*ns
, *os
) == 0) {
757 g_info("not scrolling");
759 g_info("scrolling far");
760 /* Cannot reuse any part of the screen : far jump */
763 rectangle_pixmap(thread_list
,
764 xenoltt_data
->drawing
->drawing_area
->style
->black_gc
,
767 xenoltt_data
->drawing
->width
+SAFETY
, // do not overlap
770 gtk_widget_queue_draw(drawing
->drawing_area
);
772 drawing
->damage_begin
= 0;
773 drawing
->damage_end
= xenoltt_data
->drawing
->width
;
775 drawing_data_request(xenoltt_data
->drawing
,
777 xenoltt_data
->drawing
->width
,
778 xenoltt_data
->drawing
->height
);
784 /* Different scale (zoom) */
787 rectangle_pixmap(thread_list
,
788 xenoltt_data
->drawing
->drawing_area
->style
->black_gc
,
791 xenoltt_data
->drawing
->width
+SAFETY
, // do not overlap
794 gtk_widget_queue_draw(drawing
->drawing_area
);
796 drawing
->damage_begin
= 0;
797 drawing
->damage_end
= xenoltt_data
->drawing
->width
;
799 drawing_data_request(xenoltt_data
->drawing
,
801 xenoltt_data
->drawing
->width
,
802 xenoltt_data
->drawing
->height
);
805 /* Update directly when scrolling */
806 gdk_window_process_updates(xenoltt_data
->drawing
->drawing_area
->window
,
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
;
816 if(unlikely(drawing
->gc
== NULL
)) {
819 if(drawing
->dotted_gc
== NULL
) {
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
);
830 request_background_data(xenoltt_data
);
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
;
840 drawing
->damage_begin
= 0;
841 drawing
->damage_end
= drawing
->width
;
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
));
850 rectangle_pixmap(xenoltt_data
->thread_list
,
851 widget
->style
->black_gc
,
854 drawing
->alloc_width
,
857 gtk_widget_queue_draw(drawing
->drawing_area
);
859 if(drawing
->damage_begin
< drawing
->damage_end
) {
860 drawing_data_request(drawing
,
861 drawing
->damage_begin
,
863 drawing
->damage_end
-drawing
->damage_begin
,
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
;
877 if(drawing
->damage_begin
< drawing
->damage_end
) {
878 drawing_data_request(drawing
,
879 drawing
->damage_begin
,
881 drawing
->damage_end
-drawing
->damage_begin
,
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
;
893 LttTime current_time
= *((LttTime
*)call_data
);
895 TimeWindow time_window
= lttvwindow_get_time_window(xenoltt_data
->tab
);
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
);
904 LttTime time_end
= ltt_time_add(time_begin
, width
);
906 LttvTracesetContext
* tsc
=
907 lttvwindow_get_traceset_context(xenoltt_data
->tab
);
909 LttTime trace_start
= tsc
->time_span
.start_time
;
910 LttTime trace_end
= tsc
->time_span
.end_time
;
912 g_info("New current time HOOK : %lu, %lu", current_time
.tv_sec
,
913 current_time
.tv_nsec
);
917 /* If current time is inside time interval, just move the highlight
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. */
927 if(ltt_time_compare(current_time
, time_begin
) < 0) {
928 TimeWindow new_time_window
;
930 if(ltt_time_compare(current_time
,
931 ltt_time_add(trace_start
, half_width
)) < 0)
932 time_begin
= trace_start
;
934 time_begin
= ltt_time_sub(current_time
, half_width
);
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
);
941 lttvwindow_report_time_window(xenoltt_data
->tab
, new_time_window
);
943 else if(ltt_time_compare(current_time
, time_end
) > 0) {
944 TimeWindow new_time_window
;
946 if(ltt_time_compare(current_time
, ltt_time_sub(trace_end
, half_width
)) > 0)
947 time_begin
= ltt_time_sub(trace_end
, width
);
949 time_begin
= ltt_time_sub(current_time
, half_width
);
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
);
956 lttvwindow_report_time_window(xenoltt_data
->tab
, new_time_window
);
959 gtk_widget_queue_draw(xenoltt_data
->drawing
->drawing_area
);
961 /* Update directly when scrolling */
962 gdk_window_process_updates(xenoltt_data
->drawing
->drawing_area
->window
,
968 typedef struct _ClosureData
{
969 EventsRequest
*events_request
;
970 LttvTracesetState
*tss
;
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
;
981 EventsRequest
*events_request
= closure_data
->events_request
;
982 XenoLTTData
*xenoltt_data
= events_request
->viewer_data
;
984 LttvTracesetState
*tss
= closure_data
->tss
;
985 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
987 LttTime evtime
= closure_data
->end_time
;
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. */
997 g_assert(lttv_traceset_number(tsc
->ts
) > 0);
999 LttvTraceContext
*tc
= tsc
->traces
[thread_Info
->trace_num
];
1000 LttvTraceState
*ts
= (LttvTraceState
*)tc
;
1002 LttvXenoThreadState
*thread
;
1003 thread
= lttv_xeno_state_find_thread(ts
, thread_Info
->cpu
,thread_Info
->address
);
1005 if(unlikely(thread
!= NULL
)) {
1006 ThreadList
*thread_list
= xenoltt_data
->thread_list
;
1008 /* Should be alike when background info is ready */
1009 if(xenoltt_data
->background_info_waiting
==0)
1010 #endif //EXTRA_CHECK
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.
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
);
1020 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1021 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1023 #endif //EXTRA_CHECK
1024 XenoLtt_Drawing_t
*drawing
= xenoltt_data
->drawing
;
1025 guint width
= drawing
->width
;
1027 guint x
= closure_data
->x_end
;
1029 DrawContext draw_context
;
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
;
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
;
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;
1049 if(unlikely(x
== hashed_thread_data
->x
.middle
&&
1050 hashed_thread_data
->x
.middle_used
)) {
1053 draw_context
.drawinfo
.start
.x
= hashed_thread_data
->x
.middle
;
1055 // PropertiesLine prop_line =
1056 prepare_s_e_line(thread
,draw_context
,ts
);
1057 // draw_line((void*)&prop_line, (void*)&draw_context);
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
;
1065 /* Calculate the next good time */
1066 convert_pixels_to_time(width
, x
+1, time_window
,
1067 &hashed_thread_data
->next_good_time
);
1077 int xenoltt_before_chunk(void *hook_data
, void *call_data
) {
1078 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1079 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
1081 drawing_chunk_begin(events_request
, tss
);
1086 int xenoltt_before_request(void *hook_data
, void *call_data
) {
1087 EventsRequest
*events_request
= (EventsRequest
*)hook_data
;
1088 LttvTracesetState
*tss
= (LttvTracesetState
*)call_data
;
1090 drawing_data_request_begin(events_request
, tss
);
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
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
;
1110 ThreadList
*thread_list
= xenoltt_data
->thread_list
;
1111 LttTime end_time
= events_request
->end_time
;
1113 ClosureData closure_data
;
1114 closure_data
.events_request
= (EventsRequest
*)hook_data
;
1115 closure_data
.tss
= tss
;
1116 closure_data
.end_time
= end_time
;
1118 TimeWindow time_window
=
1119 lttvwindow_get_time_window(xenoltt_data
->tab
);
1120 guint width
= xenoltt_data
->drawing
->width
;
1121 convert_time_to_pixels(
1125 &closure_data
.x_end
);
1128 /* Draw last items */
1129 g_hash_table_foreach(thread_list
->thread_hash
, draw_closure
,
1130 (void*)&closure_data
);
1133 /* Request expose */
1134 drawing_request_expose(events_request
, tss
, end_time
);
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
);
1151 ThreadList
*thread_list
= xenoltt_data
->thread_list
;
1153 LttvTraceset
*traceset
= tsc
->ts
;
1154 guint nb_trace
= lttv_traceset_number(traceset
);
1156 /* Only execute when called for the first trace's events request */
1157 if(!thread_list
->current_hash_data
) return;
1159 for(i
= 0 ; i
< nb_trace
; i
++) {
1160 g_free(thread_list
->current_hash_data
[i
]);
1162 g_free(thread_list
->current_hash_data
);
1163 thread_list
->current_hash_data
= 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
;
1170 ClosureData closure_data
;
1171 closure_data
.events_request
= (EventsRequest
*)hook_data
;
1172 closure_data
.tss
= tss
;
1173 closure_data
.end_time
= end_time
;
1175 TimeWindow time_window
=
1176 lttvwindow_get_time_window(xenoltt_data
->tab
);
1177 guint width
= xenoltt_data
->drawing
->width
;
1178 convert_time_to_pixels(
1182 &closure_data
.x_end
);
1184 /* Draw last items */
1185 g_hash_table_foreach(thread_list
->thread_hash
, draw_closure
,
1186 (void*)&closure_data
);
1188 /* Request expose (updates damages zone also) */
1189 drawing_request_expose(events_request
, tss
, end_time
);
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
;
1201 XenoLTTData
*xenoltt_data
= events_request
->viewer_data
;
1203 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1205 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1206 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1208 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
1210 LttTime evtime
= ltt_event_time(e
);
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
);
1216 guint trace_num
= ts
->parent
.index
;
1219 LttvXenoThreadState
*thread
;
1221 guint pl_height
= 0;
1222 /* Find thread in the list... */
1223 thread
= lttv_xeno_state_find_thread(ts
, ANY_CPU
, address
);
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
;
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
;
1234 if(hashed_thread_data
== NULL
){
1235 /* Xenomai Thread not present */
1236 XenoThreadInfo
*thread_Info
;
1237 threadlist_add(thread_list
,
1248 &hashed_thread_data
);
1249 gtk_widget_set_size_request(drawing
->drawing_area
, -1, pl_height
);
1250 gtk_widget_queue_draw(drawing
->drawing_area
);
1255 g_warning("Cannot find thread initialization %s - %u", g_quark_to_string(name), address);
1261 /******************************************************************************
1262 * Xenoami Thread Set Period hook
1263 ******************************************************************************/
1264 int xenoltt_thread_set_period(void *hook_data
, void *call_data
){
1266 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1267 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1269 XenoLTTData
*xenoltt_data
= events_request
->viewer_data
;
1271 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1273 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1274 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1276 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
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
);
1284 guint trace_num
= ts
->parent
.index
;
1286 LttvXenoThreadState
*thread
;
1288 guint pl_height
= 0;
1289 /* Find thread in the list... */
1290 thread
= lttv_xeno_state_find_thread(ts
, ANY_CPU
, address
);
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
;
1298 hashed_thread_data
= threadlist_get_thread_data(thread_list
,thread
->address
,tfs
->cpu
, &birth
, trace_num
);
1299 if(hashed_thread_data
!= NULL
){
1301 threadlist_set_period(thread_list
, period
, hashed_thread_data
);
1303 //Save the timer address
1304 hashed_thread_data
->timer_address
= timer_address
;
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
);
1311 // Xenomai Thread not present
1312 XenoThreadInfo
*thread_Info
;
1313 XenoLtt_Drawing_t
*drawing
= xenoltt_data
->drawing
;
1314 threadlist_add(thread_list
,
1317 thread
->prio
, // Priority
1319 thread
->period
, //Period
1325 &hashed_thread_data
);
1326 gtk_widget_set_size_request(drawing
->drawing_area
, -1, pl_height
);
1327 gtk_widget_queue_draw(drawing
->drawing_area
);
1332 g_warning("Cannot find thread in set_period %s - %u", g_quark_to_string(name), address);
1340 /******************************************************************************/
1342 int xenoltt_before_thread_hook(void *hook_data
, void *call_data
){
1344 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1345 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1347 XenoLTTData
*xenoltt_data
= events_request
->viewer_data
;
1349 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1351 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1352 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1354 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
1356 GQuark event_name
= ltt_eventtype_name(ltt_event_eventtype(e
));
1358 gulong address
= ltt_event_get_long_unsigned(e
, thf
->f1
);
1360 guint trace_num
= ts
->parent
.index
;
1362 LttTime evtime
= ltt_event_time(e
);
1363 LttvXenoThreadState
*thread
;
1365 guint pl_height
= 0;
1366 /* Find thread in the list... */
1368 if (event_name
== LTT_EVENT_XENOLTT_TIMER_TICK
)
1369 thread
= lttv_xeno_state_find_thread_from_timer(ts
, ANY_CPU
, address
);
1371 thread
= lttv_xeno_state_find_thread(ts
, ANY_CPU
, address
);
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
);
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
);
1386 gtk_widget_set_size_request(drawing
->drawing_area
, -1, pl_height
);
1387 gtk_widget_queue_draw(drawing
->drawing_area
);
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.
1395 if(ltt_time_compare(hashed_thread_data
->next_good_time
,evtime
) > 0) {
1396 if(hashed_thread_data
->x
.middle_marked
== FALSE
) {
1398 TimeWindow time_window
= lttvwindow_get_time_window(xenoltt_data
->tab
);
1400 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1402 #endif //EXTRA_CHECK
1403 XenoLtt_Drawing_t
*drawing
= xenoltt_data
->drawing
;
1404 guint width
= drawing
->width
;
1406 convert_time_to_pixels(time_window
,evtime
,width
,&x
);
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
;
1415 TimeWindow time_window
= lttvwindow_get_time_window(xenoltt_data
->tab
);
1417 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1419 #endif //EXTRA_CHECK
1420 XenoLtt_Drawing_t
*drawing
= xenoltt_data
->drawing
;
1421 guint width
= drawing
->width
;
1423 convert_time_to_pixels(time_window
,evtime
,width
,&x
);
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
;
1435 DrawContext draw_context
;
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
;
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
;
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;
1457 prepare_s_e_line(thread
,draw_context
,ts
); // Draw the line
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
;
1464 /* Calculate the next good time */
1465 convert_pixels_to_time(width
, x
+1, time_window
,
1466 &hashed_thread_data
->next_good_time
);
1473 g_warning("Cannot find thread in before hook - %u", g_quark_to_string(address));
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
){
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
);
1491 guint trace_num
= ts
->parent
.index
;
1493 LttTime evtime
= ltt_event_time(e
);
1494 LttvXenoThreadState
*thread
;
1496 guint pl_height
= 0;
1497 /* Find thread in the list... */
1499 thread
= lttv_xeno_state_find_thread(ts
, ANY_CPU
, address
);
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
);
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
);
1517 TimeWindow time_window
= lttvwindow_get_time_window(xenoltt_data
->tab
);
1519 XenoLtt_Drawing_t
*drawing
= xenoltt_data
->drawing
;
1520 guint width
= drawing
->width
;
1522 convert_time_to_pixels(time_window
,evtime
,width
,&x
);
1524 DrawContext draw_context
;
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
;
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
;
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;
1547 prepare_s_e_line(thread
,draw_context
,ts
); // Draw the line
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
;
1554 /* Calculate the next good time */
1555 convert_pixels_to_time(width
, x
+1, time_window
,
1556 &hashed_thread_data
->next_good_time
);
1561 g_warning("Cannot find thread in before hook - %u", g_quark_to_string(address));
1567 /******************************************************************************/
1568 /* xenoltt_after_thread_hook */
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
;
1574 XenoLTTData
*xenoltt_data
= events_request
->viewer_data
;
1576 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1578 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1579 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1581 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
1583 GQuark event_name
= ltt_eventtype_name(ltt_event_eventtype(e
));
1585 gulong address
= ltt_event_get_long_unsigned(e
, thf
->f1
);
1587 guint trace_num
= ts
->parent
.index
;
1588 LttTime evtime
= ltt_event_time(e
);
1589 LttvXenoThreadState
*thread
;
1591 guint pl_height
= 0;
1592 /* Find thread in the list... */
1594 if (event_name
== LTT_EVENT_XENOLTT_TIMER_TICK
){
1595 thread
= lttv_xeno_state_find_thread_from_timer(ts
, ANY_CPU
,address
);
1597 else thread
= lttv_xeno_state_find_thread(ts
, ANY_CPU
, address
);
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;
1606 hashed_thread_data
= threadlist_get_thread_data(thread_list
, thread
->address
,tfs
->cpu
, &birth
, trace_num
);
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
,
1615 thread
->prio
, // Priority
1617 thread
->period
, //Period
1623 &hashed_thread_data
);
1624 gtk_widget_set_size_request(drawing
->drawing_area
, -1, pl_height
);
1625 gtk_widget_queue_draw(drawing
->drawing_area
);
1628 /* Set the current Xenomai thread */
1629 thread_list
->current_hash_data
[trace_num
][tfs
->cpu
] = hashed_thread_data
;
1631 if(ltt_time_compare(hashed_thread_data
->next_good_time
, evtime
) <= 0){
1632 TimeWindow time_window
= lttvwindow_get_time_window(xenoltt_data
->tab
);
1635 if(ltt_time_compare(evtime
, time_window
.start_time
) == -1
1636 || ltt_time_compare(evtime
, time_window
.end_time
) == 1)
1638 #endif //EXTRA_CHECK
1639 XenoLtt_Drawing_t
*drawing
= xenoltt_data
->drawing
;
1640 guint width
= drawing
->width
;
1643 convert_time_to_pixels(time_window
,evtime
,width
,&new_x
);
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
;
1654 g_warning("Cannot find thread in after hook %u", g_quark_to_string(address));
1661 int xenoltt_draw_icons(void *hook_data
, void *call_data
){
1663 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
1664 EventsRequest
*events_request
= (EventsRequest
*)thf
->hook_data
;
1666 XenoLTTData
*xenoltt_data
= events_request
->viewer_data
;
1668 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1670 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1671 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1673 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
1675 // We must update the state of the current Xenomai Thread
1676 GQuark event_name
= ltt_eventtype_name(ltt_event_eventtype(e
));
1678 guint trace_num
= ts
->parent
.index
;
1679 LttTime evtime
= ltt_event_time(e
);
1681 gulong address
= ltt_event_get_long_unsigned(e
, thf
->f2
);
1683 LttvXenoThreadState
*thread
;
1685 guint pl_height
= 0;
1686 /* Find thread in the list... */
1688 HashedThreadData
*hashed_thread_data
= NULL
;
1689 ThreadList
*thread_list
= xenoltt_data
->thread_list
;
1691 XenoLtt_Drawing_t
*drawing
= xenoltt_data
->drawing
;
1693 if (event_name
== LTT_EVENT_XENOLTT_TIMER_TICK
){
1694 thread
= lttv_xeno_state_find_thread_from_timer(ts
, ANY_CPU
,address
);
1696 else thread
= lttv_xeno_state_find_thread(ts
, ANY_CPU
, address
);
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;
1705 hashed_thread_data
= threadlist_get_thread_data(thread_list
, thread
->address
,tfs
->cpu
, &birth
, trace_num
);
1707 if(hashed_thread_data
!= NULL
){
1708 TimeWindow time_window
= lttvwindow_get_time_window(xenoltt_data
->tab
);
1709 guint width
= drawing
->width
;
1713 convert_time_to_pixels(time_window
,evtime
,width
,&new_x
);
1715 DrawContext draw_context
;
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
;
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
;
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;
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;
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
;
1746 draw_context
.drawinfo
.end
.x
= new_x
+ 6;
1747 draw_icon((void*)&prop_icon
, (void*)&draw_context
);
1749 PropertiesText prop_text
;
1750 prop_text
.foreground
= &drawing_colors
[COL_RUN_USER_MODE
];
1751 prop_text
.background
= &drawing_colors
[COL_BLACK
];
1753 prop_text
.text
= ltt_event_get_string(e
, thf
->f1
);
1754 prop_text
.position
.x
= POS_START
;
1755 prop_text
.position
.y
= OVER
;
1757 draw_context
.drawinfo
.end
.x
= new_x
+ 1000;
1758 draw_text((void*)&prop_text
, (void*)&draw_context
);
1761 } else if(event_name
== LTT_EVENT_XENOLTT_THREAD_SET_PERIOD
) {
1762 PropertiesArc prop_arc
;
1763 prop_arc
.color
= &drawing_colors
[COL_RUN_TRAP
];
1765 prop_arc
.filled
= 1;
1766 prop_arc
.position
.x
= POS_START
;
1767 prop_arc
.position
.y
= MIDDLE
;
1769 draw_context
.drawinfo
.end
.x
= new_x
+ 6;
1770 draw_arc((void*)&prop_arc
, (void*)&draw_context
);
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
);
1778 PropertiesText prop_text
;
1779 prop_text
.foreground
= &drawing_colors
[COL_RUN_TRAP
]; //Yellow
1780 prop_text
.background
= &drawing_colors
[COL_BLACK
];
1782 prop_text
.text
= text
;
1783 prop_text
.position
.x
= POS_START
;
1784 prop_text
.position
.y
= MIDDLE
;
1786 draw_context
.drawinfo
.end
.x
= new_x
+ 1000;
1787 draw_text((void*)&prop_text
, (void*)&draw_context
);
1789 } else if(event_name
== LTT_EVENT_XENOLTT_THREAD_RENICE
) {
1790 PropertiesArc prop_arc
;
1791 prop_arc
.color
= &drawing_colors
[COL_WHITE
];
1793 prop_arc
.filled
= 1;
1794 prop_arc
.position
.x
= POS_START
;
1795 prop_arc
.position
.y
= MIDDLE
;
1797 draw_context
.drawinfo
.end
.x
= new_x
+ 6;
1798 draw_arc((void*)&prop_arc
, (void*)&draw_context
);
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
);
1806 PropertiesText prop_text
;
1807 prop_text
.foreground
= &drawing_colors
[COL_WHITE
];
1808 prop_text
.background
= &drawing_colors
[COL_BLACK
];
1810 prop_text
.text
= text
;
1811 prop_text
.position
.x
= POS_START
;
1812 prop_text
.position
.y
= MIDDLE
;
1814 draw_context
.drawinfo
.end
.x
= new_x
+ 500;
1815 draw_text((void*)&prop_text
, (void*)&draw_context
);
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
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
);
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
;
1837 draw_context
.drawinfo
.end
.x
= new_x
+ 10;
1838 draw_icon((void*)&prop_icon
, (void*)&draw_context
);
1840 } else if(event_name
== LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD
) {
1841 PropertiesArc prop_arc
;
1842 prop_arc
.color
= &drawing_colors
[COL_WHITE
];
1844 prop_arc
.filled
= 1;
1845 prop_arc
.position
.x
= POS_START
;
1846 prop_arc
.position
.y
= MIDDLE
;
1848 draw_context
.drawinfo
.end
.x
= new_x
+ 6;
1849 draw_arc((void*)&prop_arc
, (void*)&draw_context
);
1851 guint overruns
= ltt_event_get_unsigned(e
, thf
->f3
);
1852 gchar text
[MAX_PATH_LEN
] = "Overruns :";
1853 sprintf(text
,"%s %u",text
,overruns
);
1855 PropertiesText prop_text
;
1856 prop_text
.foreground
= &drawing_colors
[COL_WHITE
];
1857 prop_text
.background
= &drawing_colors
[COL_BLACK
];
1859 prop_text
.text
= text
;
1860 prop_text
.position
.x
= POS_START
;
1861 prop_text
.position
.y
= MIDDLE
;
1863 draw_context
.drawinfo
.end
.x
= new_x
+ 1000;
1864 draw_text((void*)&prop_text
, (void*)&draw_context
);
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
) {
1870 gulong synch_address
= ltt_event_get_long_unsigned(e
, thf
->f3
);
1872 LttvXenoSynchState
*synch
= lttv_xeno_state_find_synch(ts
,synch_address
);
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
;
1884 LttvXenoThreadState
*temp_thread
;
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";
1898 draw_context
.drawinfo
.end
.x
= new_x
+ 10;
1899 draw_icon((void*)&prop_icon
, (void*)&draw_context
);
1901 } else if(event_name
== LTT_EVENT_XENOLTT_SYNCH_SLEEP_ON
) {
1903 gulong synch_address
= ltt_event_get_long_unsigned(e
, thf
->f3
);
1905 LttvXenoSynchState
*synch
= lttv_xeno_state_find_synch(ts
,synch_address
);
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
;
1916 draw_context
.drawinfo
.end
.x
= new_x
+ 10;
1917 draw_icon((void*)&prop_icon
, (void*)&draw_context
);
1919 } else if(event_name
== LTT_EVENT_XENOLTT_SYNCH_UNLOCK
) {
1921 gulong synch_address
= ltt_event_get_long_unsigned(e
, thf
->f3
);
1923 LttvXenoSynchState
*synch
= lttv_xeno_state_find_synch(ts
,synch_address
);
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
;
1934 draw_context
.drawinfo
.end
.x
= new_x
+ 10;
1935 draw_icon((void*)&prop_icon
, (void*)&draw_context
);