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