Fix some warnings in lttv/modules/gui
[lttv.git] / lttv / modules / gui / resourceview / 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 *
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 #include <inttypes.h>
60
61 //#include <pango/pango.h>
62
63 #include <ltt/event.h>
64 #include <ltt/time.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
74
75 #include "eventhooks.h"
76 #include "cfv.h"
77 #include "processlist.h"
78 #include "drawing.h"
79
80
81 #define MAX_PATH_LEN 256
82 #define STATE_LINE_WIDTH 6
83 #define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
84
85 extern GSList *g_legend_list;
86
87
88 /* Action to do when background computation completed.
89 *
90 * Wait for all the awaited computations to be over.
91 */
92
93 static gint background_ready(void *hook_data, void *call_data)
94 {
95 ControlFlowData *resourceview_data = (ControlFlowData *)hook_data;
96
97 resourceview_data->background_info_waiting--;
98
99 if(resourceview_data->background_info_waiting == 0) {
100 g_message("control flow viewer : background computation data ready.");
101
102 drawing_clear(resourceview_data->drawing);
103 processlist_clear(resourceview_data->process_list);
104 gtk_widget_set_size_request(
105 resourceview_data->drawing->drawing_area,
106 -1, processlist_get_height(resourceview_data->process_list));
107 redraw_notify(resourceview_data, NULL);
108 }
109
110 return 0;
111 }
112
113
114 /* Request background computation. Verify if it is in progress or ready first.
115 * Only for each trace in the tab's traceset.
116 */
117 static void request_background_data(ControlFlowData *resourceview_data)
118 {
119 LttvTracesetContext * tsc =
120 lttvwindow_get_traceset_context(resourceview_data->tab);
121 gint num_traces = lttv_traceset_number(tsc->ts);
122 gint i;
123 LttvTrace *trace;
124 LttvTraceState *tstate;
125
126 LttvHooks *background_ready_hook =
127 lttv_hooks_new();
128 lttv_hooks_add(background_ready_hook, background_ready, resourceview_data,
129 LTTV_PRIO_DEFAULT);
130 resourceview_data->background_info_waiting = 0;
131
132 for(i=0;i<num_traces;i++) {
133 trace = lttv_traceset_get(tsc->ts, i);
134 tstate = LTTV_TRACE_STATE(tsc->traces[i]);
135
136 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
137 && !tstate->has_precomputed_states) {
138
139 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
140 trace) == FALSE) {
141 /* We first remove requests that could have been done for the same
142 * information. Happens when two viewers ask for it before servicing
143 * starts.
144 */
145 if(!lttvwindowtraces_background_request_find(trace, "state"))
146 lttvwindowtraces_background_request_queue(
147 main_window_get_widget(resourceview_data->tab), trace, "state");
148 lttvwindowtraces_background_notify_queue(resourceview_data,
149 trace,
150 ltt_time_infinite,
151 NULL,
152 background_ready_hook);
153 resourceview_data->background_info_waiting++;
154 } else { /* in progress */
155
156 lttvwindowtraces_background_notify_current(resourceview_data,
157 trace,
158 ltt_time_infinite,
159 NULL,
160 background_ready_hook);
161 resourceview_data->background_info_waiting++;
162 }
163 } else {
164 /* Data ready. By its nature, this viewer doesn't need to have
165 * its data ready hook called there, because a background
166 * request is always linked with a redraw.
167 */
168 }
169 }
170
171 lttv_hooks_destroy(background_ready_hook);
172 }
173
174
175 /**
176 * Event Viewer's constructor hook
177 *
178 * This constructor is given as a parameter to the menuitem and toolbar button
179 * registration. It creates the list.
180 * @param tab A pointer to the parent tab.
181 * @return The widget created.
182 */
183 GtkWidget *
184 h_resourceview(LttvPlugin *plugin)
185 {
186 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
187 Tab *tab = ptab->tab;
188 g_info("h_guicontrolflow, %p", tab);
189 ControlFlowData *resourceview_data = resourceview(ptab);
190
191 resourceview_data->tab = tab;
192
193 // Unreg done in the GuiControlFlow_Destructor
194 lttvwindow_register_traceset_notify(tab,
195 traceset_notify,
196 resourceview_data);
197
198 lttvwindow_register_time_window_notify(tab,
199 update_time_window_hook,
200 resourceview_data);
201 lttvwindow_register_current_time_notify(tab,
202 update_current_time_hook,
203 resourceview_data);
204 lttvwindow_register_redraw_notify(tab,
205 redraw_notify,
206 resourceview_data);
207 lttvwindow_register_continue_notify(tab,
208 continue_notify,
209 resourceview_data);
210 request_background_data(resourceview_data);
211
212
213 return guicontrolflow_get_widget(resourceview_data) ;
214
215 }
216
217 void legend_destructor(GtkWindow *legend)
218 {
219 g_legend_list = g_slist_remove(g_legend_list, legend);
220 }
221
222 /* Create a popup legend */
223 GtkWidget *
224 h_legend(LttvPlugin *plugin)
225 {
226 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
227 Tab *tab = ptab->tab;
228 g_info("h_legend, %p", tab);
229
230 GtkWindow *legend = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
231
232 g_legend_list = g_slist_append(
233 g_legend_list,
234 legend);
235
236 g_object_set_data_full(
237 G_OBJECT(legend),
238 "legend",
239 legend,
240 (GDestroyNotify)legend_destructor);
241
242 gtk_window_set_title(legend, "Control Flow View Legend");
243
244 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(legend), "lttv-color-list.png");
245
246 gtk_container_add(GTK_CONTAINER(legend), GTK_WIDGET(pixmap));
247
248 gtk_widget_show(GTK_WIDGET(pixmap));
249 gtk_widget_show(GTK_WIDGET(legend));
250
251
252 return NULL; /* This is a popup window */
253 }
254
255
256 int event_selected_hook(void *hook_data, void *call_data)
257 {
258 guint *event_number = (guint*) call_data;
259
260 g_debug("DEBUG : event selected by main window : %u", *event_number);
261
262 return 0;
263 }
264
265 static void cpu_set_line_color(PropertiesLine *prop_line, LttvCPUState *s)
266 {
267 GQuark present_state;
268
269 if(s->mode_stack->len == 0)
270 present_state = LTTV_CPU_UNKNOWN;
271 else
272 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
273
274 if(present_state == LTTV_CPU_IDLE) {
275 prop_line->color = drawing_colors_cpu[COL_CPU_IDLE];
276 }
277 else if(present_state == LTTV_CPU_BUSY) {
278 prop_line->color = drawing_colors_cpu[COL_CPU_BUSY];
279 }
280 else if(present_state == LTTV_CPU_IRQ) {
281 prop_line->color = drawing_colors_cpu[COL_CPU_IRQ];
282 }
283 else if(present_state == LTTV_CPU_SOFT_IRQ) {
284 prop_line->color = drawing_colors_cpu[COL_CPU_SOFT_IRQ];
285 }
286 else if(present_state == LTTV_CPU_TRAP) {
287 prop_line->color = drawing_colors_cpu[COL_CPU_TRAP];
288 } else {
289 prop_line->color = drawing_colors_cpu[COL_CPU_UNKNOWN];
290 }
291 }
292
293 static void irq_set_line_color(PropertiesLine *prop_line, LttvIRQState *s)
294 {
295 GQuark present_state;
296 if(s->mode_stack->len == 0)
297 present_state = LTTV_IRQ_UNKNOWN;
298 else
299 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
300
301 if(present_state == LTTV_IRQ_IDLE) {
302 prop_line->color = drawing_colors_irq[COL_IRQ_IDLE];
303 }
304 else if(present_state == LTTV_IRQ_BUSY) {
305 prop_line->color = drawing_colors_irq[COL_IRQ_BUSY];
306 }
307 else {
308 prop_line->color = drawing_colors_irq[COL_IRQ_UNKNOWN];
309 }
310 }
311
312 static void soft_irq_set_line_color(PropertiesLine *prop_line, LttvSoftIRQState *s)
313 {
314 if(s->running)
315 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_BUSY];
316 else if(s->pending)
317 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_PENDING];
318 else
319 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_IDLE];
320 }
321
322 static void trap_set_line_color(PropertiesLine *prop_line, LttvTrapState *s)
323 {
324 if(s->running == 0)
325 prop_line->color = drawing_colors_trap[COL_TRAP_IDLE];
326 else
327 prop_line->color = drawing_colors_trap[COL_TRAP_BUSY];
328 }
329
330 static void bdev_set_line_color(PropertiesLine *prop_line, LttvBdevState *s)
331 {
332 GQuark present_state;
333 if(s == 0 || s->mode_stack->len == 0)
334 present_state = LTTV_BDEV_UNKNOWN;
335 else
336 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
337
338 if(present_state == LTTV_BDEV_IDLE) {
339 prop_line->color = drawing_colors_bdev[COL_BDEV_IDLE];
340 }
341 else if(present_state == LTTV_BDEV_BUSY_READING) {
342 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_READING];
343 }
344 else if(present_state == LTTV_BDEV_BUSY_WRITING) {
345 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_WRITING];
346 }
347 else {
348 prop_line->color = drawing_colors_bdev[COL_BDEV_UNKNOWN];
349 }
350 }
351
352 /* before_schedchange_hook
353 *
354 * This function basically draw lines and icons. Two types of lines are drawn :
355 * one small (3 pixels?) representing the state of the process and the second
356 * type is thicker (10 pixels?) representing on which CPU a process is running
357 * (and this only in running state).
358 *
359 * Extremums of the lines :
360 * x_min : time of the last event context for this process kept in memory.
361 * x_max : time of the current event.
362 * y : middle of the process in the process list. The process is found in the
363 * list, therefore is it's position in pixels.
364 *
365 * The choice of lines'color is defined by the context of the last event for this
366 * process.
367 */
368
369
370 int before_schedchange_hook(void *hook_data, void *call_data)
371 {
372 LttvTraceHook *th = (LttvTraceHook*)hook_data;
373 EventsRequest *events_request = (EventsRequest*)th->hook_data;
374 ControlFlowData *resourceview_data = events_request->viewer_data;
375
376 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
377
378 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
379 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
380
381 LttEvent *e;
382 e = ltt_tracefile_get_event(tfc->tf);
383
384 LttTime evtime = ltt_event_time(e);
385
386 /* we are in a schedchange, before the state update. We must draw the
387 * items corresponding to the state before it changes : now is the right
388 * time to do it.
389 */
390
391 guint pid_out;
392 guint pid_in;
393 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
394 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
395 // TODO: can't we reenable this? pmf
396 // if(pid_in != 0 && pid_out != 0) {
397 // /* not a transition to/from idle */
398 // return 0;
399 // }
400
401 tfc->target_pid = pid_out;
402
403 guint cpu = tfs->cpu;
404
405 guint trace_num = ts->parent.index;
406 /* Add process to process list (if not present) */
407 HashedResourceData *hashed_process_data = NULL;
408
409 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
410
411 /* Now, the process is in the state hash and our own process hash.
412 * We definitely can draw the items related to the ending state.
413 */
414
415 if(ltt_time_compare(hashed_process_data->next_good_time,
416 evtime) > 0)
417 {
418 if(hashed_process_data->x.middle_marked == FALSE) {
419
420 TimeWindow time_window =
421 lttvwindow_get_time_window(resourceview_data->tab);
422 #ifdef EXTRA_CHECK
423 if(ltt_time_compare(evtime, time_window.start_time) == -1
424 || ltt_time_compare(evtime, time_window.end_time) == 1)
425 return;
426 #endif //EXTRA_CHECK
427 Drawing_t *drawing = resourceview_data->drawing;
428 guint width = drawing->width;
429 guint x;
430 convert_time_to_pixels(
431 time_window,
432 evtime,
433 width,
434 &x);
435
436 /* Draw collision indicator */
437 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
438 gdk_draw_point(hashed_process_data->pixmap,
439 drawing->gc,
440 x,
441 COLLISION_POSITION(hashed_process_data->height));
442 hashed_process_data->x.middle_marked = TRUE;
443 }
444 } else {
445 TimeWindow time_window =
446 lttvwindow_get_time_window(resourceview_data->tab);
447 #ifdef EXTRA_CHECK
448 if(ltt_time_compare(evtime, time_window.start_time) == -1
449 || ltt_time_compare(evtime, time_window.end_time) == 1)
450 return;
451 #endif //EXTRA_CHECK
452 Drawing_t *drawing = resourceview_data->drawing;
453 guint width = drawing->width;
454 guint x;
455 convert_time_to_pixels(
456 time_window,
457 evtime,
458 width,
459 &x);
460
461 /* Jump over draw if we are at the same x position */
462 if(x == hashed_process_data->x.middle &&
463 hashed_process_data->x.middle_used)
464 {
465 if(hashed_process_data->x.middle_marked == FALSE) {
466 /* Draw collision indicator */
467 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
468 gdk_draw_point(hashed_process_data->pixmap,
469 drawing->gc,
470 x,
471 COLLISION_POSITION(hashed_process_data->height));
472 hashed_process_data->x.middle_marked = TRUE;
473 }
474 /* jump */
475 } else {
476 DrawContext draw_context;
477
478 /* Now create the drawing context that will be used to draw
479 * items related to the last state. */
480 draw_context.drawable = hashed_process_data->pixmap;
481 draw_context.gc = drawing->gc;
482 draw_context.pango_layout = drawing->pango_layout;
483 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
484 draw_context.drawinfo.end.x = x;
485
486 draw_context.drawinfo.y.over = 1;
487 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
488 draw_context.drawinfo.y.under = hashed_process_data->height;
489
490 draw_context.drawinfo.start.offset.over = 0;
491 draw_context.drawinfo.start.offset.middle = 0;
492 draw_context.drawinfo.start.offset.under = 0;
493 draw_context.drawinfo.end.offset.over = 0;
494 draw_context.drawinfo.end.offset.middle = 0;
495 draw_context.drawinfo.end.offset.under = 0;
496
497 {
498 /* Draw the line */
499 //PropertiesLine prop_line = prepare_s_e_line(process);
500 PropertiesLine prop_line;
501 prop_line.line_width = STATE_LINE_WIDTH;
502 prop_line.style = GDK_LINE_SOLID;
503 prop_line.y = MIDDLE;
504 cpu_set_line_color(&prop_line, tfs->cpu_state);
505 draw_line((void*)&prop_line, (void*)&draw_context);
506
507 }
508 /* become the last x position */
509 hashed_process_data->x.middle = x;
510 hashed_process_data->x.middle_used = TRUE;
511 hashed_process_data->x.middle_marked = FALSE;
512
513 /* Calculate the next good time */
514 convert_pixels_to_time(width, x+1, time_window,
515 &hashed_process_data->next_good_time);
516 }
517 }
518
519 return 0;
520 }
521
522 /* after_schedchange_hook
523 *
524 * The draw after hook is called by the reading API to have a
525 * particular event drawn on the screen.
526 * @param hook_data ControlFlowData structure of the viewer.
527 * @param call_data Event context.
528 *
529 * This function adds items to be drawn in a queue for each process.
530 *
531 */
532 int after_schedchange_hook(void *hook_data, void *call_data)
533 {
534 LttvTraceHook *th = (LttvTraceHook*)hook_data;
535 EventsRequest *events_request = (EventsRequest*)th->hook_data;
536 ControlFlowData *resourceview_data = events_request->viewer_data;
537 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
538 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
539 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
540 LttEvent *e;
541
542 e = ltt_tracefile_get_event(tfc->tf);
543
544 LttvFilter *filter = resourceview_data->filter;
545 if(filter != NULL && filter->head != NULL)
546 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
547 tfc->t_context->t,tfc,NULL,NULL))
548 return FALSE;
549
550 LttTime evtime = ltt_event_time(e);
551
552 /* Add process to process list (if not present) */
553 LttvProcessState *process_in;
554 LttTime birth;
555 HashedResourceData *hashed_process_data_in = NULL;
556
557 ProcessList *process_list = resourceview_data->process_list;
558
559 guint pid_in;
560 {
561 guint pid_out;
562 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
563 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
564 }
565
566
567 /* Find process pid_in in the list... */
568 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
569 //process_in = tfs->process;
570 guint cpu = tfs->cpu;
571 guint trace_num = ts->parent.index;
572 process_in = ts->running_process[cpu];
573 /* It should exist, because we are after the state update. */
574 #ifdef EXTRA_CHECK
575 g_assert(process_in != NULL);
576 #endif //EXTRA_CHECK
577 birth = process_in->creation_time;
578
579 //hashed_process_data_in = processlist_get_process_data(process_list, cpuq, trace_num);
580 hashed_process_data_in = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
581
582 /* Set the current process */
583 process_list->current_hash_data[trace_num][process_in->cpu] =
584 hashed_process_data_in;
585
586 if(ltt_time_compare(hashed_process_data_in->next_good_time,
587 evtime) <= 0)
588 {
589 TimeWindow time_window =
590 lttvwindow_get_time_window(resourceview_data->tab);
591
592 #ifdef EXTRA_CHECK
593 if(ltt_time_compare(evtime, time_window.start_time) == -1
594 || ltt_time_compare(evtime, time_window.end_time) == 1)
595 return;
596 #endif //EXTRA_CHECK
597 Drawing_t *drawing = resourceview_data->drawing;
598 guint width = drawing->width;
599 guint new_x;
600
601 convert_time_to_pixels(
602 time_window,
603 evtime,
604 width,
605 &new_x);
606
607 if(hashed_process_data_in->x.middle != new_x) {
608 hashed_process_data_in->x.middle = new_x;
609 hashed_process_data_in->x.middle_used = FALSE;
610 hashed_process_data_in->x.middle_marked = FALSE;
611 }
612 }
613 return 0;
614 }
615
616 int before_execmode_hook_irq(void *hook_data, void *call_data);
617 int before_execmode_hook_soft_irq(void *hook_data, void *call_data);
618 int before_execmode_hook_trap(void *hook_data, void *call_data);
619
620 /* before_execmode_hook
621 *
622 * This function basically draw lines and icons. Two types of lines are drawn :
623 * one small (3 pixels?) representing the state of the process and the second
624 * type is thicker (10 pixels?) representing on which CPU a process is running
625 * (and this only in running state).
626 *
627 * Extremums of the lines :
628 * x_min : time of the last event context for this process kept in memory.
629 * x_max : time of the current event.
630 * y : middle of the process in the process list. The process is found in the
631 * list, therefore is it's position in pixels.
632 *
633 * The choice of lines'color is defined by the context of the last event for this
634 * process.
635 */
636
637 int before_execmode_hook(void *hook_data, void *call_data)
638 {
639 LttvTraceHook *th = (LttvTraceHook*)hook_data;
640 EventsRequest *events_request = (EventsRequest*)th->hook_data;
641 ControlFlowData *resourceview_data = events_request->viewer_data;
642
643 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
644
645 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
646 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
647
648 LttEvent *e;
649 e = ltt_tracefile_get_event(tfc->tf);
650
651 LttTime evtime = ltt_event_time(e);
652
653 before_execmode_hook_irq(hook_data, call_data);
654 before_execmode_hook_soft_irq(hook_data, call_data);
655 before_execmode_hook_trap(hook_data, call_data);
656
657 /* we are in a execmode, before the state update. We must draw the
658 * items corresponding to the state before it changes : now is the right
659 * time to do it.
660 */
661 /* For the pid */
662 guint cpu = tfs->cpu;
663
664 guint trace_num = ts->parent.index;
665 LttvProcessState *process = ts->running_process[cpu];
666 g_assert(process != NULL);
667
668 /* Well, the process_out existed : we must get it in the process hash
669 * or add it, and draw its items.
670 */
671 /* Add process to process list (if not present) */
672 HashedResourceData *hashed_process_data = NULL;
673 ProcessList *process_list = resourceview_data->process_list;
674
675 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
676 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
677 } else {
678 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
679
680 /* Set the current process */
681 process_list->current_hash_data[trace_num][process->cpu] =
682 hashed_process_data;
683 }
684
685 /* Now, the process is in the state hash and our own process hash.
686 * We definitely can draw the items related to the ending state.
687 */
688
689 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
690 evtime) > 0))
691 {
692 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
693 TimeWindow time_window =
694 lttvwindow_get_time_window(resourceview_data->tab);
695
696 #ifdef EXTRA_CHECK
697 if(ltt_time_compare(evtime, time_window.start_time) == -1
698 || ltt_time_compare(evtime, time_window.end_time) == 1)
699 return;
700 #endif //EXTRA_CHECK
701 Drawing_t *drawing = resourceview_data->drawing;
702 guint width = drawing->width;
703 guint x;
704 convert_time_to_pixels(
705 time_window,
706 evtime,
707 width,
708 &x);
709
710 /* Draw collision indicator */
711 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
712 gdk_draw_point(hashed_process_data->pixmap,
713 drawing->gc,
714 x,
715 COLLISION_POSITION(hashed_process_data->height));
716 hashed_process_data->x.middle_marked = TRUE;
717 }
718 }
719 else {
720 TimeWindow time_window =
721 lttvwindow_get_time_window(resourceview_data->tab);
722
723 #ifdef EXTRA_CHECK
724 if(ltt_time_compare(evtime, time_window.start_time) == -1
725 || ltt_time_compare(evtime, time_window.end_time) == 1)
726 return;
727 #endif //EXTRA_CHECK
728 Drawing_t *drawing = resourceview_data->drawing;
729 guint width = drawing->width;
730 guint x;
731
732 convert_time_to_pixels(
733 time_window,
734 evtime,
735 width,
736 &x);
737
738
739 /* Jump over draw if we are at the same x position */
740 if(unlikely(x == hashed_process_data->x.middle &&
741 hashed_process_data->x.middle_used))
742 {
743 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
744 /* Draw collision indicator */
745 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
746 gdk_draw_point(hashed_process_data->pixmap,
747 drawing->gc,
748 x,
749 COLLISION_POSITION(hashed_process_data->height));
750 hashed_process_data->x.middle_marked = TRUE;
751 }
752 /* jump */
753 }
754 else {
755
756 DrawContext draw_context;
757 /* Now create the drawing context that will be used to draw
758 * items related to the last state. */
759 draw_context.drawable = hashed_process_data->pixmap;
760 draw_context.gc = drawing->gc;
761 draw_context.pango_layout = drawing->pango_layout;
762 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
763 draw_context.drawinfo.end.x = x;
764
765 draw_context.drawinfo.y.over = 1;
766 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
767 draw_context.drawinfo.y.under = hashed_process_data->height;
768
769 draw_context.drawinfo.start.offset.over = 0;
770 draw_context.drawinfo.start.offset.middle = 0;
771 draw_context.drawinfo.start.offset.under = 0;
772 draw_context.drawinfo.end.offset.over = 0;
773 draw_context.drawinfo.end.offset.middle = 0;
774 draw_context.drawinfo.end.offset.under = 0;
775
776 {
777 /* Draw the line */
778 PropertiesLine prop_line;
779 prop_line.line_width = STATE_LINE_WIDTH;
780 prop_line.style = GDK_LINE_SOLID;
781 prop_line.y = MIDDLE;
782 cpu_set_line_color(&prop_line, tfs->cpu_state);
783 draw_line((void*)&prop_line, (void*)&draw_context);
784 }
785 /* become the last x position */
786 hashed_process_data->x.middle = x;
787 hashed_process_data->x.middle_used = TRUE;
788 hashed_process_data->x.middle_marked = FALSE;
789
790 /* Calculate the next good time */
791 convert_pixels_to_time(width, x+1, time_window,
792 &hashed_process_data->next_good_time);
793 }
794 }
795
796 return 0;
797 }
798
799 int before_execmode_hook_irq(void *hook_data, void *call_data)
800 {
801 LttvTraceHook *th = (LttvTraceHook*)hook_data;
802 EventsRequest *events_request = (EventsRequest*)th->hook_data;
803 ControlFlowData *resourceview_data = events_request->viewer_data;
804
805 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
806
807 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
808 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
809 struct marker_info *minfo;
810
811 LttEvent *e;
812 e = ltt_tracefile_get_event(tfc->tf);
813
814 LttTime evtime = ltt_event_time(e);
815
816 /* we are in a execmode, before the state update. We must draw the
817 * items corresponding to the state before it changes : now is the right
818 * time to do it.
819 */
820 /* For the pid */
821
822 guint64 irq;
823 guint cpu = tfs->cpu;
824
825 /*
826 * Check for LTT_CHANNEL_KERNEL channel name and event ID
827 * corresponding to LTT_EVENT_IRQ_ENTRY or LTT_EVENT_IRQ_EXIT.
828 */
829 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
830 return 0;
831 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
832 g_assert(minfo != NULL);
833 if (minfo->name == LTT_EVENT_IRQ_ENTRY) {
834 irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
835 } else if (minfo->name == LTT_EVENT_IRQ_EXIT) {
836 gint len = ts->cpu_states[cpu].irq_stack->len;
837 if(len) {
838 irq = g_array_index(ts->cpu_states[cpu].irq_stack, gint, len-1);
839 }
840 else {
841 return 0;
842 }
843 } else
844 return 0;
845
846 guint trace_num = ts->parent.index;
847
848 /* Well, the process_out existed : we must get it in the process hash
849 * or add it, and draw its items.
850 */
851 /* Add process to process list (if not present) */
852 HashedResourceData *hashed_process_data = NULL;
853
854 hashed_process_data = resourcelist_obtain_irq(resourceview_data, trace_num, irq);
855 // TODO: fix this, it's ugly and slow:
856 GQuark name;
857 {
858 gchar *str;
859 str = g_strdup_printf("IRQ %" PRIu64 " [%s]", irq,
860 (char*)g_quark_to_string(ts->name_tables->irq_names[irq]));
861 name = g_quark_from_string(str);
862 g_free(str);
863 }
864 gtk_tree_store_set(resourceview_data->process_list->list_store, &hashed_process_data->y_iter, NAME_COLUMN, g_quark_to_string(name), -1);
865
866 /* Now, the process is in the state hash and our own process hash.
867 * We definitely can draw the items related to the ending state.
868 */
869
870 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
871 evtime) > 0))
872 {
873 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
874 TimeWindow time_window =
875 lttvwindow_get_time_window(resourceview_data->tab);
876
877 #ifdef EXTRA_CHECK
878 if(ltt_time_compare(evtime, time_window.start_time) == -1
879 || ltt_time_compare(evtime, time_window.end_time) == 1)
880 return;
881 #endif //EXTRA_CHECK
882 Drawing_t *drawing = resourceview_data->drawing;
883 guint width = drawing->width;
884 guint x;
885 convert_time_to_pixels(
886 time_window,
887 evtime,
888 width,
889 &x);
890
891 /* Draw collision indicator */
892 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
893 gdk_draw_point(hashed_process_data->pixmap,
894 drawing->gc,
895 x,
896 COLLISION_POSITION(hashed_process_data->height));
897 hashed_process_data->x.middle_marked = TRUE;
898 }
899 }
900 else {
901 TimeWindow time_window =
902 lttvwindow_get_time_window(resourceview_data->tab);
903
904 #ifdef EXTRA_CHECK
905 if(ltt_time_compare(evtime, time_window.start_time) == -1
906 || ltt_time_compare(evtime, time_window.end_time) == 1)
907 return;
908 #endif //EXTRA_CHECK
909 Drawing_t *drawing = resourceview_data->drawing;
910 guint width = drawing->width;
911 guint x;
912
913 convert_time_to_pixels(
914 time_window,
915 evtime,
916 width,
917 &x);
918
919
920 /* Jump over draw if we are at the same x position */
921 if(unlikely(x == hashed_process_data->x.middle &&
922 hashed_process_data->x.middle_used))
923 {
924 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
925 /* Draw collision indicator */
926 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
927 gdk_draw_point(hashed_process_data->pixmap,
928 drawing->gc,
929 x,
930 COLLISION_POSITION(hashed_process_data->height));
931 hashed_process_data->x.middle_marked = TRUE;
932 }
933 /* jump */
934 }
935 else {
936
937 DrawContext draw_context;
938 /* Now create the drawing context that will be used to draw
939 * items related to the last state. */
940 draw_context.drawable = hashed_process_data->pixmap;
941 draw_context.gc = drawing->gc;
942 draw_context.pango_layout = drawing->pango_layout;
943 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
944 draw_context.drawinfo.end.x = x;
945
946 draw_context.drawinfo.y.over = 1;
947 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
948 draw_context.drawinfo.y.under = hashed_process_data->height;
949
950 draw_context.drawinfo.start.offset.over = 0;
951 draw_context.drawinfo.start.offset.middle = 0;
952 draw_context.drawinfo.start.offset.under = 0;
953 draw_context.drawinfo.end.offset.over = 0;
954 draw_context.drawinfo.end.offset.middle = 0;
955 draw_context.drawinfo.end.offset.under = 0;
956
957 {
958 /* Draw the line */
959 PropertiesLine prop_line;
960 prop_line.line_width = STATE_LINE_WIDTH;
961 prop_line.style = GDK_LINE_SOLID;
962 prop_line.y = MIDDLE;
963 irq_set_line_color(&prop_line, &ts->irq_states[irq]);
964 draw_line((void*)&prop_line, (void*)&draw_context);
965 }
966 /* become the last x position */
967 hashed_process_data->x.middle = x;
968 hashed_process_data->x.middle_used = TRUE;
969 hashed_process_data->x.middle_marked = FALSE;
970
971 /* Calculate the next good time */
972 convert_pixels_to_time(width, x+1, time_window,
973 &hashed_process_data->next_good_time);
974 }
975 }
976
977 return 0;
978 }
979
980 int before_execmode_hook_soft_irq(void *hook_data, void *call_data)
981 {
982 LttvTraceHook *th = (LttvTraceHook*)hook_data;
983 EventsRequest *events_request = (EventsRequest*)th->hook_data;
984 ControlFlowData *resourceview_data = events_request->viewer_data;
985
986 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
987
988 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
989 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
990 struct marker_info *minfo;
991
992 LttEvent *e;
993 e = ltt_tracefile_get_event(tfc->tf);
994
995 LttTime evtime = ltt_event_time(e);
996
997 /* we are in a execmode, before the state update. We must draw the
998 * items corresponding to the state before it changes : now is the right
999 * time to do it.
1000 */
1001 /* For the pid */
1002
1003 guint64 softirq;
1004 guint cpu = tfs->cpu;
1005
1006 /*
1007 * Check for LTT_CHANNEL_KERNEL channel name and event ID
1008 * corresponding to LTT_EVENT_SOFT_IRQ_RAISE, LTT_EVENT_SOFT_IRQ_ENTRY
1009 * or LTT_EVENT_SOFT_IRQ_EXIT.
1010 */
1011 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
1012 return 0;
1013 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
1014 g_assert(minfo != NULL);
1015 if (minfo->name == LTT_EVENT_SOFT_IRQ_RAISE
1016 || minfo->name == LTT_EVENT_SOFT_IRQ_ENTRY) {
1017 softirq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1018 } else if (minfo->name == LTT_EVENT_SOFT_IRQ_EXIT) {
1019 gint len = ts->cpu_states[cpu].softirq_stack->len;
1020 if(len) {
1021 softirq = g_array_index(ts->cpu_states[cpu].softirq_stack, gint, len-1);
1022 }
1023 else {
1024 return 0;
1025 }
1026 } else
1027 return 0;
1028
1029 guint trace_num = ts->parent.index;
1030
1031 /* Well, the process_out existed : we must get it in the process hash
1032 * or add it, and draw its items.
1033 */
1034 /* Add process to process list (if not present) */
1035 HashedResourceData *hashed_process_data = NULL;
1036
1037 hashed_process_data = resourcelist_obtain_soft_irq(resourceview_data, trace_num, softirq);
1038
1039 /* Now, the process is in the state hash and our own process hash.
1040 * We definitely can draw the items related to the ending state.
1041 */
1042
1043 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1044 evtime) > 0))
1045 {
1046 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1047 TimeWindow time_window =
1048 lttvwindow_get_time_window(resourceview_data->tab);
1049
1050 #ifdef EXTRA_CHECK
1051 if(ltt_time_compare(evtime, time_window.start_time) == -1
1052 || ltt_time_compare(evtime, time_window.end_time) == 1)
1053 return;
1054 #endif //EXTRA_CHECK
1055 Drawing_t *drawing = resourceview_data->drawing;
1056 guint width = drawing->width;
1057 guint x;
1058 convert_time_to_pixels(
1059 time_window,
1060 evtime,
1061 width,
1062 &x);
1063
1064 /* Draw collision indicator */
1065 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1066 gdk_draw_point(hashed_process_data->pixmap,
1067 drawing->gc,
1068 x,
1069 COLLISION_POSITION(hashed_process_data->height));
1070 hashed_process_data->x.middle_marked = TRUE;
1071 }
1072 }
1073 else {
1074 TimeWindow time_window =
1075 lttvwindow_get_time_window(resourceview_data->tab);
1076
1077 #ifdef EXTRA_CHECK
1078 if(ltt_time_compare(evtime, time_window.start_time) == -1
1079 || ltt_time_compare(evtime, time_window.end_time) == 1)
1080 return;
1081 #endif //EXTRA_CHECK
1082 Drawing_t *drawing = resourceview_data->drawing;
1083 guint width = drawing->width;
1084 guint x;
1085
1086 convert_time_to_pixels(
1087 time_window,
1088 evtime,
1089 width,
1090 &x);
1091
1092
1093 /* Jump over draw if we are at the same x position */
1094 if(unlikely(x == hashed_process_data->x.middle &&
1095 hashed_process_data->x.middle_used))
1096 {
1097 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1098 /* Draw collision indicator */
1099 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1100 gdk_draw_point(hashed_process_data->pixmap,
1101 drawing->gc,
1102 x,
1103 COLLISION_POSITION(hashed_process_data->height));
1104 hashed_process_data->x.middle_marked = TRUE;
1105 }
1106 /* jump */
1107 }
1108 else {
1109
1110 DrawContext draw_context;
1111 /* Now create the drawing context that will be used to draw
1112 * items related to the last state. */
1113 draw_context.drawable = hashed_process_data->pixmap;
1114 draw_context.gc = drawing->gc;
1115 draw_context.pango_layout = drawing->pango_layout;
1116 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1117 draw_context.drawinfo.end.x = x;
1118
1119 draw_context.drawinfo.y.over = 1;
1120 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1121 draw_context.drawinfo.y.under = hashed_process_data->height;
1122
1123 draw_context.drawinfo.start.offset.over = 0;
1124 draw_context.drawinfo.start.offset.middle = 0;
1125 draw_context.drawinfo.start.offset.under = 0;
1126 draw_context.drawinfo.end.offset.over = 0;
1127 draw_context.drawinfo.end.offset.middle = 0;
1128 draw_context.drawinfo.end.offset.under = 0;
1129
1130 {
1131 /* Draw the line */
1132 PropertiesLine prop_line;
1133 prop_line.line_width = STATE_LINE_WIDTH;
1134 prop_line.style = GDK_LINE_SOLID;
1135 prop_line.y = MIDDLE;
1136 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[softirq]);
1137 draw_line((void*)&prop_line, (void*)&draw_context);
1138 }
1139 /* become the last x position */
1140 hashed_process_data->x.middle = x;
1141 hashed_process_data->x.middle_used = TRUE;
1142 hashed_process_data->x.middle_marked = FALSE;
1143
1144 /* Calculate the next good time */
1145 convert_pixels_to_time(width, x+1, time_window,
1146 &hashed_process_data->next_good_time);
1147 }
1148 }
1149
1150 return 0;
1151 }
1152
1153 int before_execmode_hook_trap(void *hook_data, void *call_data)
1154 {
1155 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1156 EventsRequest *events_request = (EventsRequest*)th->hook_data;
1157 ControlFlowData *resourceview_data = events_request->viewer_data;
1158
1159 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1160
1161 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1162 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1163 struct marker_info *minfo;
1164
1165 LttEvent *e;
1166 e = ltt_tracefile_get_event(tfc->tf);
1167
1168 LttTime evtime = ltt_event_time(e);
1169
1170 /* we are in a execmode, before the state update. We must draw the
1171 * items corresponding to the state before it changes : now is the right
1172 * time to do it.
1173 */
1174 /* For the pid */
1175
1176 guint64 trap;
1177 guint cpu = tfs->cpu;
1178
1179 /*
1180 * Check for LTT_CHANNEL_KERNEL channel name and event ID
1181 * corresponding to LTT_EVENT_TRAP/PAGE_FAULT_ENTRY or
1182 * LTT_EVENT_TRAP/PAGE_FAULT_EXIT.
1183 */
1184 if (tfc->tf->name != LTT_CHANNEL_KERNEL)
1185 return 0;
1186 minfo = marker_get_info_from_id(tfc->tf->mdata, e->event_id);
1187 g_assert(minfo != NULL);
1188 if (minfo->name == LTT_EVENT_TRAP_ENTRY
1189 || minfo->name == LTT_EVENT_PAGE_FAULT_ENTRY
1190 || minfo->name == LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY) {
1191 trap = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1192 } else if (minfo->name == LTT_EVENT_TRAP_EXIT
1193 || minfo->name == LTT_EVENT_PAGE_FAULT_EXIT
1194 || minfo->name == LTT_EVENT_PAGE_FAULT_NOSEM_EXIT) {
1195 gint len = ts->cpu_states[cpu].trap_stack->len;
1196 if(len) {
1197 trap = g_array_index(ts->cpu_states[cpu].trap_stack, gint, len-1);
1198 }
1199 else {
1200 return 0;
1201 }
1202 } else
1203 return 0;
1204
1205 guint trace_num = ts->parent.index;
1206
1207 /* Well, the process_out existed : we must get it in the process hash
1208 * or add it, and draw its items.
1209 */
1210 /* Add process to process list (if not present) */
1211 HashedResourceData *hashed_process_data = NULL;
1212
1213 hashed_process_data = resourcelist_obtain_trap(resourceview_data, trace_num, trap);
1214
1215 /* Now, the process is in the state hash and our own process hash.
1216 * We definitely can draw the items related to the ending state.
1217 */
1218
1219 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1220 evtime) > 0))
1221 {
1222 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1223 TimeWindow time_window =
1224 lttvwindow_get_time_window(resourceview_data->tab);
1225
1226 #ifdef EXTRA_CHECK
1227 if(ltt_time_compare(evtime, time_window.start_time) == -1
1228 || ltt_time_compare(evtime, time_window.end_time) == 1)
1229 return;
1230 #endif //EXTRA_CHECK
1231 Drawing_t *drawing = resourceview_data->drawing;
1232 guint width = drawing->width;
1233 guint x;
1234 convert_time_to_pixels(
1235 time_window,
1236 evtime,
1237 width,
1238 &x);
1239
1240 /* Draw collision indicator */
1241 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1242 gdk_draw_point(hashed_process_data->pixmap,
1243 drawing->gc,
1244 x,
1245 COLLISION_POSITION(hashed_process_data->height));
1246 hashed_process_data->x.middle_marked = TRUE;
1247 }
1248 }
1249 else {
1250 TimeWindow time_window =
1251 lttvwindow_get_time_window(resourceview_data->tab);
1252
1253 #ifdef EXTRA_CHECK
1254 if(ltt_time_compare(evtime, time_window.start_time) == -1
1255 || ltt_time_compare(evtime, time_window.end_time) == 1)
1256 return;
1257 #endif //EXTRA_CHECK
1258 Drawing_t *drawing = resourceview_data->drawing;
1259 guint width = drawing->width;
1260 guint x;
1261
1262 convert_time_to_pixels(
1263 time_window,
1264 evtime,
1265 width,
1266 &x);
1267
1268
1269 /* Jump over draw if we are at the same x position */
1270 if(unlikely(x == hashed_process_data->x.middle &&
1271 hashed_process_data->x.middle_used))
1272 {
1273 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1274 /* Draw collision indicator */
1275 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1276 gdk_draw_point(hashed_process_data->pixmap,
1277 drawing->gc,
1278 x,
1279 COLLISION_POSITION(hashed_process_data->height));
1280 hashed_process_data->x.middle_marked = TRUE;
1281 }
1282 /* jump */
1283 }
1284 else {
1285
1286 DrawContext draw_context;
1287 /* Now create the drawing context that will be used to draw
1288 * items related to the last state. */
1289 draw_context.drawable = hashed_process_data->pixmap;
1290 draw_context.gc = drawing->gc;
1291 draw_context.pango_layout = drawing->pango_layout;
1292 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1293 draw_context.drawinfo.end.x = x;
1294
1295 draw_context.drawinfo.y.over = 1;
1296 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1297 draw_context.drawinfo.y.under = hashed_process_data->height;
1298
1299 draw_context.drawinfo.start.offset.over = 0;
1300 draw_context.drawinfo.start.offset.middle = 0;
1301 draw_context.drawinfo.start.offset.under = 0;
1302 draw_context.drawinfo.end.offset.over = 0;
1303 draw_context.drawinfo.end.offset.middle = 0;
1304 draw_context.drawinfo.end.offset.under = 0;
1305
1306 {
1307 /* Draw the line */
1308 PropertiesLine prop_line;
1309 prop_line.line_width = STATE_LINE_WIDTH;
1310 prop_line.style = GDK_LINE_SOLID;
1311 prop_line.y = MIDDLE;
1312 trap_set_line_color(&prop_line, &ts->trap_states[trap]);
1313 draw_line((void*)&prop_line, (void*)&draw_context);
1314 }
1315 /* become the last x position */
1316 hashed_process_data->x.middle = x;
1317 hashed_process_data->x.middle_used = TRUE;
1318 hashed_process_data->x.middle_marked = FALSE;
1319
1320 /* Calculate the next good time */
1321 convert_pixels_to_time(width, x+1, time_window,
1322 &hashed_process_data->next_good_time);
1323 }
1324 }
1325
1326 return 0;
1327 }
1328
1329
1330 int before_bdev_event_hook(void *hook_data, void *call_data)
1331 {
1332 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1333 EventsRequest *events_request = (EventsRequest*)th->hook_data;
1334 ControlFlowData *resourceview_data = events_request->viewer_data;
1335
1336 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1337
1338 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1339
1340 LttEvent *e;
1341 e = ltt_tracefile_get_event(tfc->tf);
1342
1343 LttTime evtime = ltt_event_time(e);
1344
1345 /* we are in a execmode, before the state update. We must draw the
1346 * items corresponding to the state before it changes : now is the right
1347 * time to do it.
1348 */
1349 /* For the pid */
1350
1351 guint8 major = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1352 guint8 minor = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
1353 gint devcode_gint = MKDEV(major,minor);
1354
1355 guint trace_num = ts->parent.index;
1356
1357 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
1358 /* the result of the lookup might be NULL. that's ok, the rest of the function
1359 should understand it was not found and that its state is unknown */
1360
1361 /* Well, the process_out existed : we must get it in the process hash
1362 * or add it, and draw its items.
1363 */
1364 /* Add process to process list (if not present) */
1365 HashedResourceData *hashed_process_data = NULL;
1366 // LttTime birth = process->creation_time;
1367
1368 // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1369 // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1370 // } else {
1371 hashed_process_data = resourcelist_obtain_bdev(resourceview_data, trace_num, devcode_gint);
1372 ////hashed_process_data = processlist_get_process_data(process_list, resourceq, trace_num);
1373 // hashed_process_data = processlist_get_process_data(process_list,
1374 // pid,
1375 // process->cpu,
1376 // &birth,
1377 // trace_num);
1378 //
1379 /* Set the current process */
1380 // process_list->current_hash_data[trace_num][process->cpu] =
1381 // hashed_process_data;
1382 // }
1383
1384 /* Now, the process is in the state hash and our own process hash.
1385 * We definitely can draw the items related to the ending state.
1386 */
1387
1388 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1389 evtime) > 0))
1390 {
1391 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1392 TimeWindow time_window =
1393 lttvwindow_get_time_window(resourceview_data->tab);
1394
1395 #ifdef EXTRA_CHECK
1396 if(ltt_time_compare(evtime, time_window.start_time) == -1
1397 || ltt_time_compare(evtime, time_window.end_time) == 1)
1398 return;
1399 #endif //EXTRA_CHECK
1400 Drawing_t *drawing = resourceview_data->drawing;
1401 guint width = drawing->width;
1402 guint x;
1403 convert_time_to_pixels(
1404 time_window,
1405 evtime,
1406 width,
1407 &x);
1408
1409 /* Draw collision indicator */
1410 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1411 gdk_draw_point(hashed_process_data->pixmap,
1412 drawing->gc,
1413 x,
1414 COLLISION_POSITION(hashed_process_data->height));
1415 hashed_process_data->x.middle_marked = TRUE;
1416 }
1417 }
1418 else {
1419 TimeWindow time_window =
1420 lttvwindow_get_time_window(resourceview_data->tab);
1421
1422 #ifdef EXTRA_CHECK
1423 if(ltt_time_compare(evtime, time_window.start_time) == -1
1424 || ltt_time_compare(evtime, time_window.end_time) == 1)
1425 return;
1426 #endif //EXTRA_CHECK
1427 Drawing_t *drawing = resourceview_data->drawing;
1428 guint width = drawing->width;
1429 guint x;
1430
1431 convert_time_to_pixels(
1432 time_window,
1433 evtime,
1434 width,
1435 &x);
1436
1437
1438 /* Jump over draw if we are at the same x position */
1439 if(unlikely(x == hashed_process_data->x.middle &&
1440 hashed_process_data->x.middle_used))
1441 {
1442 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1443 /* Draw collision indicator */
1444 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1445 gdk_draw_point(hashed_process_data->pixmap,
1446 drawing->gc,
1447 x,
1448 COLLISION_POSITION(hashed_process_data->height));
1449 hashed_process_data->x.middle_marked = TRUE;
1450 }
1451 /* jump */
1452 }
1453 else {
1454
1455 DrawContext draw_context;
1456 /* Now create the drawing context that will be used to draw
1457 * items related to the last state. */
1458 draw_context.drawable = hashed_process_data->pixmap;
1459 draw_context.gc = drawing->gc;
1460 draw_context.pango_layout = drawing->pango_layout;
1461 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1462 draw_context.drawinfo.end.x = x;
1463
1464 draw_context.drawinfo.y.over = 1;
1465 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1466 draw_context.drawinfo.y.under = hashed_process_data->height;
1467
1468 draw_context.drawinfo.start.offset.over = 0;
1469 draw_context.drawinfo.start.offset.middle = 0;
1470 draw_context.drawinfo.start.offset.under = 0;
1471 draw_context.drawinfo.end.offset.over = 0;
1472 draw_context.drawinfo.end.offset.middle = 0;
1473 draw_context.drawinfo.end.offset.under = 0;
1474
1475 {
1476 /* Draw the line */
1477 PropertiesLine prop_line;
1478 prop_line.line_width = STATE_LINE_WIDTH;
1479 prop_line.style = GDK_LINE_SOLID;
1480 prop_line.y = MIDDLE;
1481 bdev_set_line_color(&prop_line, bdev);
1482 draw_line((void*)&prop_line, (void*)&draw_context);
1483 }
1484 /* become the last x position */
1485 hashed_process_data->x.middle = x;
1486 hashed_process_data->x.middle_used = TRUE;
1487 hashed_process_data->x.middle_marked = FALSE;
1488
1489 /* Calculate the next good time */
1490 convert_pixels_to_time(width, x+1, time_window,
1491 &hashed_process_data->next_good_time);
1492 }
1493 }
1494
1495 return 0;
1496 }
1497
1498 gint update_time_window_hook(void *hook_data, void *call_data)
1499 {
1500 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1501 Drawing_t *drawing = resourceview_data->drawing;
1502 ProcessList *process_list = resourceview_data->process_list;
1503
1504 const TimeWindowNotifyData *time_window_nofify_data =
1505 ((const TimeWindowNotifyData *)call_data);
1506
1507 TimeWindow *old_time_window =
1508 time_window_nofify_data->old_time_window;
1509 TimeWindow *new_time_window =
1510 time_window_nofify_data->new_time_window;
1511
1512 /* Update the ruler */
1513 drawing_update_ruler(resourceview_data->drawing,
1514 new_time_window);
1515
1516
1517 /* Two cases : zoom in/out or scrolling */
1518
1519 /* In order to make sure we can reuse the old drawing, the scale must
1520 * be the same and the new time interval being partly located in the
1521 * currently shown time interval. (reuse is only for scrolling)
1522 */
1523
1524 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1525 old_time_window->start_time.tv_sec,
1526 old_time_window->start_time.tv_nsec,
1527 old_time_window->time_width.tv_sec,
1528 old_time_window->time_width.tv_nsec);
1529
1530 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1531 new_time_window->start_time.tv_sec,
1532 new_time_window->start_time.tv_nsec,
1533 new_time_window->time_width.tv_sec,
1534 new_time_window->time_width.tv_nsec);
1535
1536 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1537 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1538 {
1539 /* Same scale (scrolling) */
1540 g_info("scrolling");
1541 LttTime *ns = &new_time_window->start_time;
1542 LttTime *os = &old_time_window->start_time;
1543 LttTime old_end = old_time_window->end_time;
1544 LttTime new_end = new_time_window->end_time;
1545 //if(ns<os+w<ns+w)
1546 //if(ns<os+w && os+w<ns+w)
1547 //if(ns<old_end && os<ns)
1548 if(ltt_time_compare(*ns, old_end) == -1
1549 && ltt_time_compare(*os, *ns) == -1)
1550 {
1551 g_info("scrolling near right");
1552 /* Scroll right, keep right part of the screen */
1553 guint x = 0;
1554 guint width = resourceview_data->drawing->width;
1555 convert_time_to_pixels(
1556 *old_time_window,
1557 *ns,
1558 width,
1559 &x);
1560
1561 /* Copy old data to new location */
1562 copy_pixmap_region(process_list,
1563 NULL,
1564 resourceview_data->drawing->drawing_area->style->black_gc,
1565 NULL,
1566 x, 0,
1567 0, 0,
1568 resourceview_data->drawing->width-x+SAFETY, -1);
1569
1570 if(drawing->damage_begin == drawing->damage_end)
1571 drawing->damage_begin = resourceview_data->drawing->width-x;
1572 else
1573 drawing->damage_begin = 0;
1574
1575 drawing->damage_end = resourceview_data->drawing->width;
1576
1577 /* Clear the data request background, but not SAFETY */
1578 rectangle_pixmap(process_list,
1579 resourceview_data->drawing->drawing_area->style->black_gc,
1580 TRUE,
1581 drawing->damage_begin+SAFETY, 0,
1582 drawing->damage_end - drawing->damage_begin, // do not overlap
1583 -1);
1584 gtk_widget_queue_draw(drawing->drawing_area);
1585
1586 /* Get new data for the rest. */
1587 drawing_data_request(resourceview_data->drawing,
1588 drawing->damage_begin, 0,
1589 drawing->damage_end - drawing->damage_begin,
1590 resourceview_data->drawing->height);
1591 } else {
1592 if(ltt_time_compare(*ns,*os) == -1
1593 && ltt_time_compare(*os,new_end) == -1)
1594 {
1595 g_info("scrolling near left");
1596 /* Scroll left, keep left part of the screen */
1597 guint x = 0;
1598 guint width = resourceview_data->drawing->width;
1599 convert_time_to_pixels(
1600 *new_time_window,
1601 *os,
1602 width,
1603 &x);
1604
1605 /* Copy old data to new location */
1606 copy_pixmap_region (process_list,
1607 NULL,
1608 resourceview_data->drawing->drawing_area->style->black_gc,
1609 NULL,
1610 0, 0,
1611 x, 0,
1612 -1, -1);
1613
1614 if(drawing->damage_begin == drawing->damage_end)
1615 drawing->damage_end = x;
1616 else
1617 drawing->damage_end =
1618 resourceview_data->drawing->width;
1619
1620 drawing->damage_begin = 0;
1621
1622 rectangle_pixmap (process_list,
1623 resourceview_data->drawing->drawing_area->style->black_gc,
1624 TRUE,
1625 drawing->damage_begin, 0,
1626 drawing->damage_end - drawing->damage_begin, // do not overlap
1627 -1);
1628
1629 gtk_widget_queue_draw(drawing->drawing_area);
1630
1631 /* Get new data for the rest. */
1632 drawing_data_request(resourceview_data->drawing,
1633 drawing->damage_begin, 0,
1634 drawing->damage_end - drawing->damage_begin,
1635 resourceview_data->drawing->height);
1636
1637 } else {
1638 if(ltt_time_compare(*ns,*os) == 0)
1639 {
1640 g_info("not scrolling");
1641 } else {
1642 g_info("scrolling far");
1643 /* Cannot reuse any part of the screen : far jump */
1644
1645
1646 rectangle_pixmap (process_list,
1647 resourceview_data->drawing->drawing_area->style->black_gc,
1648 TRUE,
1649 0, 0,
1650 resourceview_data->drawing->width+SAFETY, // do not overlap
1651 -1);
1652
1653 gtk_widget_queue_draw(drawing->drawing_area);
1654
1655 drawing->damage_begin = 0;
1656 drawing->damage_end = resourceview_data->drawing->width;
1657
1658 drawing_data_request(resourceview_data->drawing,
1659 0, 0,
1660 resourceview_data->drawing->width,
1661 resourceview_data->drawing->height);
1662
1663 }
1664 }
1665 }
1666 } else {
1667 /* Different scale (zoom) */
1668 g_info("zoom");
1669
1670 rectangle_pixmap (process_list,
1671 resourceview_data->drawing->drawing_area->style->black_gc,
1672 TRUE,
1673 0, 0,
1674 resourceview_data->drawing->width+SAFETY, // do not overlap
1675 -1);
1676
1677 gtk_widget_queue_draw(drawing->drawing_area);
1678
1679 drawing->damage_begin = 0;
1680 drawing->damage_end = resourceview_data->drawing->width;
1681
1682 drawing_data_request(resourceview_data->drawing,
1683 0, 0,
1684 resourceview_data->drawing->width,
1685 resourceview_data->drawing->height);
1686 }
1687
1688 /* Update directly when scrolling */
1689 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
1690 TRUE);
1691
1692 return 0;
1693 }
1694
1695 gint traceset_notify(void *hook_data, void *call_data)
1696 {
1697 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1698 Drawing_t *drawing = resourceview_data->drawing;
1699
1700 if(unlikely(drawing->gc == NULL)) {
1701 return FALSE;
1702 }
1703 if(drawing->dotted_gc == NULL) {
1704 return FALSE;
1705 }
1706
1707 drawing_clear(resourceview_data->drawing);
1708 processlist_clear(resourceview_data->process_list);
1709 gtk_widget_set_size_request(
1710 resourceview_data->drawing->drawing_area,
1711 -1, processlist_get_height(resourceview_data->process_list));
1712 redraw_notify(resourceview_data, NULL);
1713
1714 request_background_data(resourceview_data);
1715
1716 return FALSE;
1717 }
1718
1719 gint redraw_notify(void *hook_data, void *call_data)
1720 {
1721 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1722 Drawing_t *drawing = resourceview_data->drawing;
1723 GtkWidget *widget = drawing->drawing_area;
1724
1725 drawing->damage_begin = 0;
1726 drawing->damage_end = drawing->width;
1727
1728 /* fun feature, to be separated someday... */
1729 drawing_clear(resourceview_data->drawing);
1730 processlist_clear(resourceview_data->process_list);
1731 gtk_widget_set_size_request(
1732 resourceview_data->drawing->drawing_area,
1733 -1, processlist_get_height(resourceview_data->process_list));
1734 // Clear the images
1735 rectangle_pixmap (resourceview_data->process_list,
1736 widget->style->black_gc,
1737 TRUE,
1738 0, 0,
1739 drawing->alloc_width,
1740 -1);
1741
1742 gtk_widget_queue_draw(drawing->drawing_area);
1743
1744 if(drawing->damage_begin < drawing->damage_end)
1745 {
1746 drawing_data_request(drawing,
1747 drawing->damage_begin,
1748 0,
1749 drawing->damage_end-drawing->damage_begin,
1750 drawing->height);
1751 }
1752
1753 return FALSE;
1754
1755 }
1756
1757
1758 gint continue_notify(void *hook_data, void *call_data)
1759 {
1760 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1761 Drawing_t *drawing = resourceview_data->drawing;
1762
1763 if(drawing->damage_begin < drawing->damage_end)
1764 {
1765 drawing_data_request(drawing,
1766 drawing->damage_begin,
1767 0,
1768 drawing->damage_end-drawing->damage_begin,
1769 drawing->height);
1770 }
1771
1772 return FALSE;
1773 }
1774
1775
1776 gint update_current_time_hook(void *hook_data, void *call_data)
1777 {
1778 ControlFlowData *resourceview_data = (ControlFlowData*)hook_data;
1779
1780 LttTime current_time = *((LttTime*)call_data);
1781
1782 TimeWindow time_window =
1783 lttvwindow_get_time_window(resourceview_data->tab);
1784
1785 LttTime time_begin = time_window.start_time;
1786 LttTime width = time_window.time_width;
1787 LttTime half_width;
1788 {
1789 guint64 time_ll = ltt_time_to_uint64(width);
1790 time_ll = time_ll >> 1; /* divide by two */
1791 half_width = ltt_time_from_uint64(time_ll);
1792 }
1793 LttTime time_end = ltt_time_add(time_begin, width);
1794
1795 LttvTracesetContext * tsc =
1796 lttvwindow_get_traceset_context(resourceview_data->tab);
1797
1798 LttTime trace_start = tsc->time_span.start_time;
1799 LttTime trace_end = tsc->time_span.end_time;
1800
1801 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
1802 current_time.tv_nsec);
1803
1804 /* If current time is inside time interval, just move the highlight
1805 * bar */
1806
1807 /* Else, we have to change the time interval. We have to tell it
1808 * to the main window. */
1809 /* The time interval change will take care of placing the current
1810 * time at the center of the visible area, or nearest possible if we are
1811 * at one end of the trace. */
1812
1813
1814 if(ltt_time_compare(current_time, time_begin) < 0)
1815 {
1816 TimeWindow new_time_window;
1817
1818 if(ltt_time_compare(current_time,
1819 ltt_time_add(trace_start,half_width)) < 0)
1820 time_begin = trace_start;
1821 else
1822 time_begin = ltt_time_sub(current_time,half_width);
1823
1824 new_time_window.start_time = time_begin;
1825 new_time_window.time_width = width;
1826 new_time_window.time_width_double = ltt_time_to_double(width);
1827 new_time_window.end_time = ltt_time_add(time_begin, width);
1828
1829 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
1830 }
1831 else if(ltt_time_compare(current_time, time_end) > 0)
1832 {
1833 TimeWindow new_time_window;
1834
1835 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
1836 time_begin = ltt_time_sub(trace_end,width);
1837 else
1838 time_begin = ltt_time_sub(current_time,half_width);
1839
1840 new_time_window.start_time = time_begin;
1841 new_time_window.time_width = width;
1842 new_time_window.time_width_double = ltt_time_to_double(width);
1843 new_time_window.end_time = ltt_time_add(time_begin, width);
1844
1845 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
1846
1847 }
1848 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
1849
1850 /* Update directly when scrolling */
1851 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
1852 TRUE);
1853
1854 return 0;
1855 }
1856
1857 typedef struct _ClosureData {
1858 EventsRequest *events_request;
1859 LttvTracesetState *tss;
1860 LttTime end_time;
1861 guint x_end;
1862 } ClosureData;
1863
1864 /* Draw line until end of the screen */
1865
1866 void draw_closure(gpointer key, gpointer value, gpointer user_data)
1867 {
1868 ResourceUniqueNumeric *process_info = (ResourceUniqueNumeric*)key;
1869 HashedResourceData *hashed_process_data = (HashedResourceData*)value;
1870 ClosureData *closure_data = (ClosureData*)user_data;
1871
1872 EventsRequest *events_request = closure_data->events_request;
1873 ControlFlowData *resourceview_data = events_request->viewer_data;
1874
1875 LttvTracesetState *tss = closure_data->tss;
1876 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
1877
1878 LttTime evtime = closure_data->end_time;
1879
1880 gboolean dodraw = TRUE;
1881
1882 if(hashed_process_data->type == RV_RESOURCE_MACHINE)
1883 return;
1884
1885 {
1886 /* For the process */
1887 /* First, check if the current process is in the state computation
1888 * process list. If it is there, that means we must add it right now and
1889 * draw items from the beginning of the read for it. If it is not
1890 * present, it's a new process and it was not present : it will
1891 * be added after the state update. */
1892 #ifdef EXTRA_CHECK
1893 g_assert(lttv_traceset_number(tsc->ts) > 0);
1894 #endif //EXTRA_CHECK
1895 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
1896 LttvTraceState *ts = (LttvTraceState*)tc;
1897
1898 /* Only draw for processes that are currently in the trace states */
1899
1900 #ifdef EXTRA_CHECK
1901 /* Should be alike when background info is ready */
1902 if(resourceview_data->background_info_waiting==0)
1903 g_assert(ltt_time_compare(process->creation_time,
1904 process_info->birth) == 0);
1905 #endif //EXTRA_CHECK
1906
1907 /* Now, the process is in the state hash and our own process hash.
1908 * We definitely can draw the items related to the ending state.
1909 */
1910
1911 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1912 evtime) <= 0))
1913 {
1914 TimeWindow time_window =
1915 lttvwindow_get_time_window(resourceview_data->tab);
1916
1917 #ifdef EXTRA_CHECK
1918 if(ltt_time_compare(evtime, time_window.start_time) == -1
1919 || ltt_time_compare(evtime, time_window.end_time) == 1)
1920 return;
1921 #endif //EXTRA_CHECK
1922 Drawing_t *drawing = resourceview_data->drawing;
1923 guint width = drawing->width;
1924
1925 guint x = closure_data->x_end;
1926
1927 DrawContext draw_context;
1928
1929 /* Now create the drawing context that will be used to draw
1930 * items related to the last state. */
1931 draw_context.drawable = hashed_process_data->pixmap;
1932 draw_context.gc = drawing->gc;
1933 draw_context.pango_layout = drawing->pango_layout;
1934 draw_context.drawinfo.end.x = x;
1935
1936 draw_context.drawinfo.y.over = 1;
1937 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1938 draw_context.drawinfo.y.under = hashed_process_data->height;
1939
1940 draw_context.drawinfo.start.offset.over = 0;
1941 draw_context.drawinfo.start.offset.middle = 0;
1942 draw_context.drawinfo.start.offset.under = 0;
1943 draw_context.drawinfo.end.offset.over = 0;
1944 draw_context.drawinfo.end.offset.middle = 0;
1945 draw_context.drawinfo.end.offset.under = 0;
1946 #if 0
1947 /* Jump over draw if we are at the same x position */
1948 if(x == hashed_process_data->x.over)
1949 {
1950 /* jump */
1951 } else {
1952 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1953 /* Draw the line */
1954 PropertiesLine prop_line = prepare_execmode_line(process);
1955 draw_line((void*)&prop_line, (void*)&draw_context);
1956
1957 hashed_process_data->x.over = x;
1958 }
1959 #endif //0
1960
1961 if(unlikely(x == hashed_process_data->x.middle &&
1962 hashed_process_data->x.middle_used)) {
1963 #if 0 /* do not mark closure : not missing information */
1964 if(hashed_process_data->x.middle_marked == FALSE) {
1965 /* Draw collision indicator */
1966 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1967 gdk_draw_point(drawing->pixmap,
1968 drawing->gc,
1969 x,
1970 y+(height/2)-3);
1971 hashed_process_data->x.middle_marked = TRUE;
1972 }
1973 #endif //0
1974 /* Jump */
1975 } else {
1976 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1977 /* Draw the line */
1978 if(dodraw) {
1979 PropertiesLine prop_line;
1980 prop_line.line_width = STATE_LINE_WIDTH;
1981 prop_line.style = GDK_LINE_SOLID;
1982 prop_line.y = MIDDLE;
1983 if(hashed_process_data->type == RV_RESOURCE_CPU)
1984 cpu_set_line_color(&prop_line, &ts->cpu_states[process_info->id]);
1985 else if(hashed_process_data->type == RV_RESOURCE_IRQ)
1986 irq_set_line_color(&prop_line, &ts->irq_states[process_info->id]);
1987 else if(hashed_process_data->type == RV_RESOURCE_SOFT_IRQ)
1988 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[process_info->id]);
1989 else if(hashed_process_data->type == RV_RESOURCE_TRAP)
1990 trap_set_line_color(&prop_line, &ts->trap_states[process_info->id]);
1991 else if(hashed_process_data->type == RV_RESOURCE_BDEV) {
1992 gint devcode_gint = process_info->id;
1993 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
1994 // the lookup may return null; bdev_set_line_color must act appropriately
1995 bdev_set_line_color(&prop_line, bdev);
1996 }
1997
1998 draw_line((void*)&prop_line, (void*)&draw_context);
1999 }
2000
2001 /* become the last x position */
2002 if(likely(x != hashed_process_data->x.middle)) {
2003 hashed_process_data->x.middle = x;
2004 /* but don't use the pixel */
2005 hashed_process_data->x.middle_used = FALSE;
2006
2007 /* Calculate the next good time */
2008 convert_pixels_to_time(width, x+1, time_window,
2009 &hashed_process_data->next_good_time);
2010 }
2011 }
2012 }
2013 }
2014 }
2015
2016 int before_chunk(void *hook_data, void *call_data)
2017 {
2018 EventsRequest *events_request = (EventsRequest*)hook_data;
2019 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2020 #if 0
2021 /* Deactivate sort */
2022 gtk_tree_sortable_set_sort_column_id(
2023 GTK_TREE_SORTABLE(cfd->process_list->list_store),
2024 TRACE_COLUMN,
2025 GTK_SORT_ASCENDING);
2026 #endif //0
2027 drawing_chunk_begin(events_request, tss);
2028
2029 return 0;
2030 }
2031
2032 /* before_request
2033 *
2034 * This gets executed just before an events request is executed
2035 */
2036
2037 int before_request(void *hook_data, void *call_data)
2038 {
2039 EventsRequest *events_request = (EventsRequest*)hook_data;
2040 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2041
2042 drawing_data_request_begin(events_request, tss);
2043
2044 return 0;
2045 }
2046
2047
2048 /*
2049 * after request is necessary in addition of after chunk in order to draw
2050 * lines until the end of the screen. after chunk just draws lines until
2051 * the last event.
2052 *
2053 * for each process
2054 * draw closing line
2055 * expose
2056 */
2057 int after_request(void *hook_data, void *call_data)
2058 {
2059 guint i;
2060 EventsRequest *events_request = (EventsRequest*)hook_data;
2061 ControlFlowData *resourceview_data = events_request->viewer_data;
2062 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2063
2064 LttTime end_time = events_request->end_time;
2065
2066 ClosureData closure_data;
2067 closure_data.events_request = (EventsRequest*)hook_data;
2068 closure_data.tss = tss;
2069 closure_data.end_time = end_time;
2070
2071 TimeWindow time_window =
2072 lttvwindow_get_time_window(resourceview_data->tab);
2073 guint width = resourceview_data->drawing->width;
2074 convert_time_to_pixels(
2075 time_window,
2076 end_time,
2077 width,
2078 &closure_data.x_end);
2079
2080
2081 /* Draw last items */
2082 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2083 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
2084 (void*)&closure_data);
2085 }
2086
2087 /* Request expose */
2088 drawing_request_expose(events_request, tss, end_time);
2089 return 0;
2090 }
2091
2092 /*
2093 * for each process
2094 * draw closing line
2095 * expose
2096 */
2097 int after_chunk(void *hook_data, void *call_data)
2098 {
2099 EventsRequest *events_request = (EventsRequest*)hook_data;
2100 ControlFlowData *resourceview_data = events_request->viewer_data;
2101 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2102 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
2103 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2104 LttTime end_time;
2105
2106 ProcessList *process_list = resourceview_data->process_list;
2107 guint i;
2108 LttvTraceset *traceset = tsc->ts;
2109 guint nb_trace = lttv_traceset_number(traceset);
2110
2111 /* Only execute when called for the first trace's events request */
2112 if(!process_list->current_hash_data)
2113 return 0;
2114
2115 for(i = 0 ; i < nb_trace ; i++) {
2116 g_free(process_list->current_hash_data[i]);
2117 }
2118 g_free(process_list->current_hash_data);
2119 process_list->current_hash_data = NULL;
2120
2121 if(tfc != NULL)
2122 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
2123 else /* end of traceset, or position now out of request : end */
2124 end_time = events_request->end_time;
2125
2126 ClosureData closure_data;
2127 closure_data.events_request = (EventsRequest*)hook_data;
2128 closure_data.tss = tss;
2129 closure_data.end_time = end_time;
2130
2131 TimeWindow time_window =
2132 lttvwindow_get_time_window(resourceview_data->tab);
2133 guint width = resourceview_data->drawing->width;
2134 convert_time_to_pixels(
2135 time_window,
2136 end_time,
2137 width,
2138 &closure_data.x_end);
2139
2140 /* Draw last items */
2141 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2142 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
2143 (void*)&closure_data);
2144 }
2145 #if 0
2146 /* Reactivate sort */
2147 gtk_tree_sortable_set_sort_column_id(
2148 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
2149 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2150 GTK_SORT_ASCENDING);
2151
2152 update_index_to_pixmap(resourceview_data->process_list);
2153 /* Request a full expose : drawing scrambled */
2154 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
2155 #endif //0
2156 /* Request expose (updates damages zone also) */
2157 drawing_request_expose(events_request, tss, end_time);
2158
2159 return 0;
2160 }
2161
2162 /* after_statedump_end
2163 *
2164 * @param hook_data ControlFlowData structure of the viewer.
2165 * @param call_data Event context.
2166 *
2167 * This function adds items to be drawn in a queue for each process.
2168 *
2169 */
2170 int before_statedump_end(void *hook_data, void *call_data)
2171 {
2172 gint i;
2173
2174 LttvTraceHook *th = (LttvTraceHook*)hook_data;
2175 EventsRequest *events_request = (EventsRequest*)th->hook_data;
2176 ControlFlowData *resourceview_data = events_request->viewer_data;
2177
2178 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2179
2180 LttvTracesetState *tss = (LttvTracesetState*)tfc->t_context->ts_context;
2181
2182 LttEvent *e;
2183 e = ltt_tracefile_get_event(tfc->tf);
2184
2185 LttvFilter *filter = resourceview_data->filter;
2186 if(filter != NULL && filter->head != NULL)
2187 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2188 tfc->t_context->t,tfc,NULL,NULL))
2189 return FALSE;
2190
2191 LttTime evtime = ltt_event_time(e);
2192
2193 ClosureData closure_data;
2194 closure_data.events_request = events_request;
2195 closure_data.tss = tss;
2196 closure_data.end_time = evtime;
2197
2198 TimeWindow time_window =
2199 lttvwindow_get_time_window(resourceview_data->tab);
2200 guint width = resourceview_data->drawing->width;
2201 convert_time_to_pixels(
2202 time_window,
2203 evtime,
2204 width,
2205 &closure_data.x_end);
2206
2207 /* Draw last items */
2208
2209 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2210 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
2211 (void*)&closure_data);
2212 }
2213 #if 0
2214 /* Reactivate sort */
2215 gtk_tree_sortable_set_sort_column_id(
2216 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
2217 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2218 GTK_SORT_ASCENDING);
2219
2220 update_index_to_pixmap(resourceview_data->process_list);
2221 /* Request a full expose : drawing scrambled */
2222 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
2223 #endif //0
2224 /* Request expose (updates damages zone also) */
2225 drawing_request_expose(events_request, tss, evtime);
2226
2227 return 0;
2228 }
This page took 0.105247 seconds and 5 git commands to generate.