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