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