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