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