mega fix for states : per cpu and _not_ per tracefile state. We have many tracefiles...
[lttv.git] / ltt / branches / poly / lttv / modules / gui / controlflow / eventhooks.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
24
25 /* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
27 *
28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
31 *
32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
34 *
35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next before_schedchange
41 * hook.
42 *
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
45 * line/background.
46 */
47
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51
52 //#define PANGO_ENABLE_BACKEND
53 #include <gtk/gtk.h>
54 #include <gdk/gdk.h>
55 #include <glib.h>
56 #include <assert.h>
57 #include <string.h>
58 #include <stdio.h>
59
60 //#include <pango/pango.h>
61
62 #include <ltt/event.h>
63 #include <ltt/time.h>
64 #include <ltt/type.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
73
74 #include "eventhooks.h"
75 #include "cfv.h"
76 #include "processlist.h"
77 #include "drawing.h"
78
79
80 #define MAX_PATH_LEN 256
81
82 #if 0
83 typedef struct _ProcessAddClosure {
84 ControlFlowData *cfd;
85 guint trace_num;
86 } ProcessAddClosure;
87
88 static void process_add(gpointer key,
89 gpointer value,
90 gpointer user_data)
91 {
92 LttvProcessState *process = (LttvProcessState*)value;
93 ProcessAddClosure *closure = (ProcessAddClosure*)user_data;
94 ControlFlowData *control_flow_data = closure->cfd;
95 guint trace_num = closure->trace_num;
96
97 /* Add process to process list (if not present) */
98 guint pid;
99 LttTime birth;
100 guint y = 0, height = 0, pl_height = 0;
101
102 ProcessList *process_list = control_flow_data->process_list;
103
104 pid = process->pid;
105 birth = process->creation_time;
106 const gchar *name = g_quark_to_string(process->name);
107 HashedProcessData *hashed_process_data = NULL;
108
109 if(processlist_get_process_pixels(process_list,
110 pid,
111 &birth,
112 trace_num,
113 &y,
114 &height,
115 &hashed_process_data) == 1)
116 {
117 /* Process not present */
118 processlist_add(process_list,
119 pid,
120 &birth,
121 trace_num,
122 name,
123 &pl_height,
124 &hashed_process_data);
125 processlist_get_process_pixels(process_list,
126 pid,
127 &birth,
128 trace_num,
129 &y,
130 &height,
131 &hashed_process_data);
132 drawing_insert_square( control_flow_data->drawing, y, height);
133 }
134 }
135 #endif //0
136
137
138 /* Action to do when background computation completed.
139 *
140 * Wait for all the awaited computations to be over.
141 */
142
143 gint background_ready(void *hook_data, void *call_data)
144 {
145 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
146 LttvTrace *trace = (LttvTrace*)call_data;
147
148 control_flow_data->background_info_waiting--;
149
150 if(control_flow_data->background_info_waiting == 0) {
151 g_debug("control flow viewer : background computation data ready.");
152
153 drawing_clear(control_flow_data->drawing);
154 processlist_clear(control_flow_data->process_list);
155 gtk_widget_set_size_request(
156 control_flow_data->drawing->drawing_area,
157 -1, processlist_get_height(control_flow_data->process_list));
158 redraw_notify(control_flow_data, NULL);
159 }
160
161 return 0;
162 }
163
164
165 /* Request background computation. Verify if it is in progress or ready first.
166 * Only for each trace in the tab's traceset.
167 */
168 void request_background_data(ControlFlowData *control_flow_data)
169 {
170 LttvTracesetContext * tsc =
171 lttvwindow_get_traceset_context(control_flow_data->tab);
172 gint num_traces = lttv_traceset_number(tsc->ts);
173 gint i;
174 LttvTrace *trace;
175
176 LttvHooks *background_ready_hook =
177 lttv_hooks_new();
178 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
179 LTTV_PRIO_DEFAULT);
180 control_flow_data->background_info_waiting = 0;
181
182 for(i=0;i<num_traces;i++) {
183 trace = lttv_traceset_get(tsc->ts, i);
184
185 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) {
186
187 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
188 trace) == FALSE) {
189 /* We first remove requests that could have been done for the same
190 * information. Happens when two viewers ask for it before servicing
191 * starts.
192 */
193 lttvwindowtraces_background_request_remove(trace, "state");
194 lttvwindowtraces_background_request_queue(trace,
195 "state");
196 lttvwindowtraces_background_notify_queue(control_flow_data,
197 trace,
198 ltt_time_infinite,
199 NULL,
200 background_ready_hook);
201 control_flow_data->background_info_waiting++;
202 } else { /* in progress */
203
204 lttvwindowtraces_background_notify_current(control_flow_data,
205 trace,
206 ltt_time_infinite,
207 NULL,
208 background_ready_hook);
209 control_flow_data->background_info_waiting++;
210 }
211 } else {
212 /* Data ready. Be its nature, this viewer doesn't need to have
213 * its data ready hook called htere, because a background
214 * request is always linked with a redraw.
215 */
216 }
217
218 }
219
220 lttv_hooks_destroy(background_ready_hook);
221 }
222
223
224
225
226 /**
227 * Event Viewer's constructor hook
228 *
229 * This constructor is given as a parameter to the menuitem and toolbar button
230 * registration. It creates the list.
231 * @param tab A pointer to the parent tab.
232 * @return The widget created.
233 */
234 GtkWidget *
235 h_guicontrolflow(Tab *tab)
236 {
237 g_info("h_guicontrolflow, %p", tab);
238 ControlFlowData *control_flow_data = guicontrolflow() ;
239
240 control_flow_data->tab = tab;
241
242 // Unreg done in the GuiControlFlow_Destructor
243 lttvwindow_register_traceset_notify(tab,
244 traceset_notify,
245 control_flow_data);
246
247 lttvwindow_register_time_window_notify(tab,
248 update_time_window_hook,
249 control_flow_data);
250 lttvwindow_register_current_time_notify(tab,
251 update_current_time_hook,
252 control_flow_data);
253 lttvwindow_register_redraw_notify(tab,
254 redraw_notify,
255 control_flow_data);
256 lttvwindow_register_continue_notify(tab,
257 continue_notify,
258 control_flow_data);
259 request_background_data(control_flow_data);
260
261
262 return guicontrolflow_get_widget(control_flow_data) ;
263
264 }
265
266 int event_selected_hook(void *hook_data, void *call_data)
267 {
268 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
269 guint *event_number = (guint*) call_data;
270
271 g_debug("DEBUG : event selected by main window : %u", *event_number);
272
273 return 0;
274 }
275
276 /* Function that selects the color of status&exemode line */
277 static inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
278 {
279 PropertiesLine prop_line;
280 prop_line.line_width = 2;
281 prop_line.style = GDK_LINE_SOLID;
282 prop_line.y = MIDDLE;
283 //GdkColormap *colormap = gdk_colormap_get_system();
284
285 if(process->state->s == LTTV_STATE_RUN) {
286 if(process->state->t == LTTV_STATE_USER_MODE)
287 prop_line.color = drawing_colors[COL_RUN_USER_MODE];
288 else if(process->state->t == LTTV_STATE_SYSCALL)
289 prop_line.color = drawing_colors[COL_RUN_SYSCALL];
290 else if(process->state->t == LTTV_STATE_TRAP)
291 prop_line.color = drawing_colors[COL_RUN_TRAP];
292 else if(process->state->t == LTTV_STATE_IRQ)
293 prop_line.color = drawing_colors[COL_RUN_IRQ];
294 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
295 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
296 else
297 g_assert(FALSE); /* RUNNING MODE UNKNOWN */
298 } else if(process->state->s == LTTV_STATE_WAIT) {
299 /* We don't show if we wait while in user mode, trap, irq or syscall */
300 prop_line.color = drawing_colors[COL_WAIT];
301 } else if(process->state->s == LTTV_STATE_WAIT_CPU) {
302 /* We don't show if we wait for CPU while in user mode, trap, irq
303 * or syscall */
304 prop_line.color = drawing_colors[COL_WAIT_CPU];
305 } else if(process->state->s == LTTV_STATE_ZOMBIE) {
306 prop_line.color = drawing_colors[COL_ZOMBIE];
307 } else if(process->state->s == LTTV_STATE_WAIT_FORK) {
308 prop_line.color = drawing_colors[COL_WAIT_FORK];
309 } else if(process->state->s == LTTV_STATE_EXIT) {
310 prop_line.color = drawing_colors[COL_EXIT];
311 } else if(process->state->s == LTTV_STATE_UNNAMED) {
312 prop_line.color = drawing_colors[COL_UNNAMED];
313 } else
314 g_assert(FALSE); /* UNKNOWN STATE */
315
316 return prop_line;
317
318 }
319
320 #if 0
321 static inline PropertiesLine prepare_status_line(LttvProcessState *process)
322 {
323 PropertiesLine prop_line;
324 prop_line.line_width = 2;
325 prop_line.style = GDK_LINE_SOLID;
326 prop_line.y = MIDDLE;
327 //GdkColormap *colormap = gdk_colormap_get_system();
328
329 g_debug("prepare_status_line for state : %s",
330 g_quark_to_string(process->state->s));
331
332 /* color of line : status of the process */
333 if(process->state->s == LTTV_STATE_UNNAMED)
334 prop_line.color = drawing_colors[COL_WHITE];
335 else if(process->state->s == LTTV_STATE_WAIT_FORK)
336 prop_line.color = drawing_colors[COL_WAIT_FORK];
337 else if(process->state->s == LTTV_STATE_WAIT_CPU)
338 prop_line.color = drawing_colors[COL_WAIT_CPU];
339 else if(process->state->s == LTTV_STATE_EXIT)
340 prop_line.color = drawing_colors[COL_EXIT];
341 else if(process->state->s == LTTV_STATE_ZOMBIE)
342 prop_line.color = drawing_colors[COL_ZOMBIE];
343 else if(process->state->s == LTTV_STATE_WAIT)
344 prop_line.color = drawing_colors[COL_WAIT];
345 else if(process->state->s == LTTV_STATE_RUN)
346 prop_line.color = drawing_colors[COL_RUN];
347 else
348 prop_line.color = drawing_colors[COL_WHITE];
349
350 //gdk_colormap_alloc_color(colormap,
351 // prop_line.color,
352 // FALSE,
353 // TRUE);
354
355 return prop_line;
356
357 }
358 #endif //0
359
360
361 /* before_schedchange_hook
362 *
363 * This function basically draw lines and icons. Two types of lines are drawn :
364 * one small (3 pixels?) representing the state of the process and the second
365 * type is thicker (10 pixels?) representing on which CPU a process is running
366 * (and this only in running state).
367 *
368 * Extremums of the lines :
369 * x_min : time of the last event context for this process kept in memory.
370 * x_max : time of the current event.
371 * y : middle of the process in the process list. The process is found in the
372 * list, therefore is it's position in pixels.
373 *
374 * The choice of lines'color is defined by the context of the last event for this
375 * process.
376 */
377
378
379 int before_schedchange_hook(void *hook_data, void *call_data)
380 {
381 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
382 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
383 ControlFlowData *control_flow_data = events_request->viewer_data;
384
385 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
386
387 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
388 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
389
390 LttEvent *e;
391 e = ltt_tracefile_get_event(tfc->tf);
392
393 LttTime evtime = ltt_event_time(e);
394
395 /* we are in a schedchange, before the state update. We must draw the
396 * items corresponding to the state before it changes : now is the right
397 * time to do it.
398 */
399
400 guint pid_out;
401 guint pid_in;
402 {
403 pid_out = ltt_event_get_long_unsigned(e, thf->f1);
404 pid_in = ltt_event_get_long_unsigned(e, thf->f2);
405 }
406
407 {
408 /* For the pid_out */
409 /* First, check if the current process is in the state computation
410 * process list. If it is there, that means we must add it right now and
411 * draw items from the beginning of the read for it. If it is not
412 * present, it's a new process and it was not present : it will
413 * be added after the state update. */
414 guint cpu = ltt_tracefile_num(tfc->tf);
415 LttvProcessState *process = ts->running_process[cpu];
416 /* unknown state, bad current pid */
417 if(process->pid != pid_out)
418 process = lttv_state_find_process(ts, ANY_CPU, pid_out);
419
420 if(process != NULL) {
421 /* Well, the process_out existed : we must get it in the process hash
422 * or add it, and draw its items.
423 */
424 /* Add process to process list (if not present) */
425 guint pl_height = 0;
426 HashedProcessData *hashed_process_data = NULL;
427 ProcessList *process_list = control_flow_data->process_list;
428 LttTime birth = process->creation_time;
429
430 hashed_process_data = processlist_get_process_data(process_list,
431 pid_out,
432 process->cpu,
433 &birth,
434 tfc->t_context->index);
435 if(hashed_process_data == NULL)
436 {
437 g_assert(pid_out == 0 || pid_out != process->ppid);
438 const gchar *name = g_quark_to_string(process->name);
439 /* Process not present */
440 ProcessInfo *process_info;
441 Drawing_t *drawing = control_flow_data->drawing;
442 processlist_add(process_list,
443 drawing,
444 pid_out,
445 process->cpu,
446 process->ppid,
447 &birth,
448 tfc->t_context->index,
449 name,
450 &pl_height,
451 &process_info,
452 &hashed_process_data);
453 gtk_widget_set_size_request(drawing->drawing_area,
454 -1,
455 pl_height);
456 gtk_widget_queue_draw(drawing->drawing_area);
457
458 }
459
460 /* Now, the process is in the state hash and our own process hash.
461 * We definitely can draw the items related to the ending state.
462 */
463
464 if(ltt_time_compare(hashed_process_data->next_good_time,
465 evtime) > 0)
466 {
467 if(hashed_process_data->x.middle_marked == FALSE) {
468
469 TimeWindow time_window =
470 lttvwindow_get_time_window(control_flow_data->tab);
471 #ifdef EXTRA_CHECK
472 if(ltt_time_compare(evtime, time_window.start_time) == -1
473 || ltt_time_compare(evtime, time_window.end_time) == 1)
474 return;
475 #endif //EXTRA_CHECK
476 Drawing_t *drawing = control_flow_data->drawing;
477 guint width = drawing->width;
478 guint x;
479 convert_time_to_pixels(
480 time_window,
481 evtime,
482 width,
483 &x);
484
485 /* Draw collision indicator */
486 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
487 gdk_draw_point(hashed_process_data->pixmap,
488 drawing->gc,
489 x,
490 (hashed_process_data->height/2)-3);
491 hashed_process_data->x.middle_marked = TRUE;
492 }
493 } else {
494 TimeWindow time_window =
495 lttvwindow_get_time_window(control_flow_data->tab);
496 #ifdef EXTRA_CHECK
497 if(ltt_time_compare(evtime, time_window.start_time) == -1
498 || ltt_time_compare(evtime, time_window.end_time) == 1)
499 return;
500 #endif //EXTRA_CHECK
501 Drawing_t *drawing = control_flow_data->drawing;
502 guint width = drawing->width;
503 guint x;
504 convert_time_to_pixels(
505 time_window,
506 evtime,
507 width,
508 &x);
509
510
511 /* Jump over draw if we are at the same x position */
512 if(x == hashed_process_data->x.middle &&
513 hashed_process_data->x.middle_used)
514 {
515 if(hashed_process_data->x.middle_marked == FALSE) {
516 /* Draw collision indicator */
517 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
518 gdk_draw_point(hashed_process_data->pixmap,
519 drawing->gc,
520 x,
521 (hashed_process_data->height/2)-3);
522 hashed_process_data->x.middle_marked = TRUE;
523 }
524 /* jump */
525 } else {
526 DrawContext draw_context;
527
528 /* Now create the drawing context that will be used to draw
529 * items related to the last state. */
530 draw_context.drawable = hashed_process_data->pixmap;
531 draw_context.gc = drawing->gc;
532 draw_context.pango_layout = drawing->pango_layout;
533 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
534 draw_context.drawinfo.end.x = x;
535
536 draw_context.drawinfo.y.over = 1;
537 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
538 draw_context.drawinfo.y.under = hashed_process_data->height;
539
540 draw_context.drawinfo.start.offset.over = 0;
541 draw_context.drawinfo.start.offset.middle = 0;
542 draw_context.drawinfo.start.offset.under = 0;
543 draw_context.drawinfo.end.offset.over = 0;
544 draw_context.drawinfo.end.offset.middle = 0;
545 draw_context.drawinfo.end.offset.under = 0;
546
547 {
548 /* Draw the line */
549 PropertiesLine prop_line = prepare_s_e_line(process);
550 draw_line((void*)&prop_line, (void*)&draw_context);
551
552 }
553 /* become the last x position */
554 hashed_process_data->x.middle = x;
555 hashed_process_data->x.middle_used = TRUE;
556 hashed_process_data->x.middle_marked = FALSE;
557
558 /* Calculate the next good time */
559 convert_pixels_to_time(width, x+1, time_window,
560 &hashed_process_data->next_good_time);
561 }
562 }
563 }
564 }
565
566 {
567 /* For the pid_in */
568 /* First, check if the current process is in the state computation
569 * process list. If it is there, that means we must add it right now and
570 * draw items from the beginning of the read for it. If it is not
571 * present, it's a new process and it was not present : it will
572 * be added after the state update. */
573 LttvProcessState *process;
574 process = lttv_state_find_process(ts, ANY_CPU, pid_in);
575
576 if(process != NULL) {
577 /* Well, the process_out existed : we must get it in the process hash
578 * or add it, and draw its items.
579 */
580 /* Add process to process list (if not present) */
581 guint pl_height = 0;
582 HashedProcessData *hashed_process_data = NULL;
583 ProcessList *process_list = control_flow_data->process_list;
584 LttTime birth = process->creation_time;
585
586 hashed_process_data = processlist_get_process_data(process_list,
587 pid_in,
588 process->cpu,
589 &birth,
590 tfc->t_context->index);
591 if(hashed_process_data == NULL)
592 {
593 g_assert(pid_in == 0 || pid_in != process->ppid);
594 const gchar *name = g_quark_to_string(process->name);
595 /* Process not present */
596 ProcessInfo *process_info;
597 Drawing_t *drawing = control_flow_data->drawing;
598 processlist_add(process_list,
599 drawing,
600 pid_in,
601 process->cpu,
602 process->ppid,
603 &birth,
604 tfc->t_context->index,
605 name,
606 &pl_height,
607 &process_info,
608 &hashed_process_data);
609 gtk_widget_set_size_request(drawing->drawing_area,
610 -1,
611 pl_height);
612 gtk_widget_queue_draw(drawing->drawing_area);
613
614 }
615 //We could set the current process and hash here, but will be done
616 //by after schedchange hook
617
618 /* Now, the process is in the state hash and our own process hash.
619 * We definitely can draw the items related to the ending state.
620 */
621
622 if(ltt_time_compare(hashed_process_data->next_good_time,
623 evtime) > 0)
624 {
625 if(hashed_process_data->x.middle_marked == FALSE) {
626
627 TimeWindow time_window =
628 lttvwindow_get_time_window(control_flow_data->tab);
629 #ifdef EXTRA_CHECK
630 if(ltt_time_compare(evtime, time_window.start_time) == -1
631 || ltt_time_compare(evtime, time_window.end_time) == 1)
632 return;
633 #endif //EXTRA_CHECK
634 Drawing_t *drawing = control_flow_data->drawing;
635 guint width = drawing->width;
636 guint x;
637 convert_time_to_pixels(
638 time_window,
639 evtime,
640 width,
641 &x);
642
643 /* Draw collision indicator */
644 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
645 gdk_draw_point(hashed_process_data->pixmap,
646 drawing->gc,
647 x,
648 (hashed_process_data->height/2)-3);
649 hashed_process_data->x.middle_marked = TRUE;
650 }
651 } else {
652 TimeWindow time_window =
653 lttvwindow_get_time_window(control_flow_data->tab);
654 #ifdef EXTRA_CHECK
655 if(ltt_time_compare(evtime, time_window.start_time) == -1
656 || ltt_time_compare(evtime, time_window.end_time) == 1)
657 return;
658 #endif //EXTRA_CHECK
659 Drawing_t *drawing = control_flow_data->drawing;
660 guint width = drawing->width;
661 guint x;
662
663 convert_time_to_pixels(
664 time_window,
665 evtime,
666 width,
667 &x);
668
669
670 /* Jump over draw if we are at the same x position */
671 if(x == hashed_process_data->x.middle &&
672 hashed_process_data->x.middle_used)
673 {
674 if(hashed_process_data->x.middle_marked == FALSE) {
675 /* Draw collision indicator */
676 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
677 gdk_draw_point(hashed_process_data->pixmap,
678 drawing->gc,
679 x,
680 (hashed_process_data->height/2)-3);
681 hashed_process_data->x.middle_marked = TRUE;
682 }
683 /* jump */
684 } else {
685 DrawContext draw_context;
686
687 /* Now create the drawing context that will be used to draw
688 * items related to the last state. */
689 draw_context.drawable = hashed_process_data->pixmap;
690 draw_context.gc = drawing->gc;
691 draw_context.pango_layout = drawing->pango_layout;
692 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
693 draw_context.drawinfo.end.x = x;
694
695 draw_context.drawinfo.y.over = 1;
696 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
697 draw_context.drawinfo.y.under = hashed_process_data->height;
698
699 draw_context.drawinfo.start.offset.over = 0;
700 draw_context.drawinfo.start.offset.middle = 0;
701 draw_context.drawinfo.start.offset.under = 0;
702 draw_context.drawinfo.end.offset.over = 0;
703 draw_context.drawinfo.end.offset.middle = 0;
704 draw_context.drawinfo.end.offset.under = 0;
705
706 {
707 /* Draw the line */
708 PropertiesLine prop_line = prepare_s_e_line(process);
709 draw_line((void*)&prop_line, (void*)&draw_context);
710 }
711
712
713 /* become the last x position */
714 hashed_process_data->x.middle = x;
715 hashed_process_data->x.middle_used = TRUE;
716 hashed_process_data->x.middle_marked = FALSE;
717
718 /* Calculate the next good time */
719 convert_pixels_to_time(width, x+1, time_window,
720 &hashed_process_data->next_good_time);
721 }
722 }
723 }
724 }
725 return 0;
726
727
728 #if 0
729 EventsRequest *events_request = (EventsRequest*)hook_data;
730 ControlFlowData *control_flow_data =
731 (ControlFlowData*)events_request->viewer_data;
732 Tab *tab = control_flow_data->tab;
733
734 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
735
736 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
737 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
738
739 LttEvent *e;
740 e = tfc->e;
741
742 LttTime evtime = ltt_event_time(e);
743 TimeWindow time_window =
744 lttvwindow_get_time_window(tab);
745
746 LttTime time_window.end_time = time_window.time_window.end_time;
747
748 //if(time < time_beg || time > time_end) return;
749 if(ltt_time_compare(evtime, time_window.start_time) == -1
750 || ltt_time_compare(evtime, time_window.end_time) == 1)
751 return;
752
753 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
754 {
755 g_debug("schedchange!");
756
757 /* Add process to process list (if not present) and get drawing "y" from
758 * process position */
759 guint pid_out, pid_in;
760 LttvProcessState *process_out, *process_in;
761 LttTime birth;
762 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
763
764 ProcessList *process_list = control_flow_data->process_list;
765
766
767 LttField *f = ltt_event_field(e);
768 LttField *element;
769 element = ltt_field_member(f,0);
770 pid_out = ltt_event_get_long_unsigned(e,element);
771 element = ltt_field_member(f,1);
772 pid_in = ltt_event_get_long_unsigned(e,element);
773 g_debug("out : %u in : %u", pid_out, pid_in);
774
775
776 /* Find process pid_out in the list... */
777 process_out = lttv_state_find_process(tfs, pid_out);
778 if(process_out == NULL) return 0;
779 g_debug("out : %s",g_quark_to_string(process_out->state->s));
780
781 birth = process_out->creation_time;
782 const gchar *name = g_quark_to_string(process_out->name);
783 HashedProcessData *hashed_process_data_out = NULL;
784
785 if(processlist_get_process_pixels(process_list,
786 pid_out,
787 &birth,
788 tfc->t_context->index,
789 &y_out,
790 &height,
791 &hashed_process_data_out) == 1)
792 {
793 /* Process not present */
794 processlist_add(process_list,
795 pid_out,
796 &birth,
797 tfc->t_context->index,
798 name,
799 &pl_height,
800 &hashed_process_data_out);
801 g_assert(processlist_get_process_pixels(process_list,
802 pid_out,
803 &birth,
804 tfc->t_context->index,
805 &y_out,
806 &height,
807 &hashed_process_data_out)==0);
808 drawing_insert_square( control_flow_data->drawing, y_out, height);
809 }
810 //g_free(name);
811
812 /* Find process pid_in in the list... */
813 process_in = lttv_state_find_process(tfs, pid_in);
814 if(process_in == NULL) return 0;
815 g_debug("in : %s",g_quark_to_string(process_in->state->s));
816
817 birth = process_in->creation_time;
818 name = g_quark_to_string(process_in->name);
819 HashedProcessData *hashed_process_data_in = NULL;
820
821 if(processlist_get_process_pixels(process_list,
822 pid_in,
823 &birth,
824 tfc->t_context->index,
825 &y_in,
826 &height,
827 &hashed_process_data_in) == 1)
828 {
829 /* Process not present */
830 processlist_add(process_list,
831 pid_in,
832 &birth,
833 tfc->t_context->index,
834 name,
835 &pl_height,
836 &hashed_process_data_in);
837 processlist_get_process_pixels(process_list,
838 pid_in,
839 &birth,
840 tfc->t_context->index,
841 &y_in,
842 &height,
843 &hashed_process_data_in);
844
845 drawing_insert_square( control_flow_data->drawing, y_in, height);
846 }
847 //g_free(name);
848
849
850 /* Find pixels corresponding to time of the event. If the time does
851 * not fit in the window, show a warning, not supposed to happend. */
852 guint x = 0;
853 guint width = control_flow_data->drawing->width;
854
855 LttTime time = ltt_event_time(e);
856
857 LttTime window_end = time_window.time_window.end_time;
858
859 convert_time_to_pixels(
860 time_window,
861 time,
862 width,
863 &x);
864 //assert(x <= width);
865 //
866 /* draw what represents the event for outgoing process. */
867
868 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
869 draw_context_out->current->modify_over->x = x;
870 draw_context_out->current->modify_under->x = x;
871 draw_context_out->current->modify_over->y = y_out;
872 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
873 draw_context_out->drawable = control_flow_data->drawing->pixmap;
874 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
875 GtkWidget *widget = control_flow_data->drawing->drawing_area;
876 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
877 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
878 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
879 //draw_context_out->gc = widget->style->black_gc;
880
881 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
882 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
883
884 /* Draw the line/background of the out process */
885 if(draw_context_out->previous->middle->x == -1)
886 {
887 draw_context_out->previous->over->x =
888 control_flow_data->drawing->damage_begin;
889 draw_context_out->previous->middle->x =
890 control_flow_data->drawing->damage_begin;
891 draw_context_out->previous->under->x =
892 control_flow_data->drawing->damage_begin;
893 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
894 }
895
896 draw_context_out->current->middle->x = x;
897 draw_context_out->current->over->x = x;
898 draw_context_out->current->under->x = x;
899 draw_context_out->current->middle->y = y_out + height/2;
900 draw_context_out->current->over->y = y_out;
901 draw_context_out->current->under->y = y_out + height;
902 draw_context_out->previous->middle->y = y_out + height/2;
903 draw_context_out->previous->over->y = y_out;
904 draw_context_out->previous->under->y = y_out + height;
905
906 draw_context_out->drawable = control_flow_data->drawing->pixmap;
907 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
908
909 if(process_out->state->s == LTTV_STATE_RUN)
910 {
911 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
912 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
913 draw_context_out->gc = control_flow_data->drawing->gc;
914
915 PropertiesBG prop_bg;
916 prop_bg.color = g_new(GdkColor,1);
917
918 switch(ltt_tracefile_num(tfc->tf)) {
919 case 0:
920 prop_bg.color->red = 0x1515;
921 prop_bg.color->green = 0x1515;
922 prop_bg.color->blue = 0x8c8c;
923 break;
924 case 1:
925 prop_bg.color->red = 0x4e4e;
926 prop_bg.color->green = 0xa9a9;
927 prop_bg.color->blue = 0xa4a4;
928 break;
929 case 2:
930 prop_bg.color->red = 0x7a7a;
931 prop_bg.color->green = 0x4a4a;
932 prop_bg.color->blue = 0x8b8b;
933 break;
934 case 3:
935 prop_bg.color->red = 0x8080;
936 prop_bg.color->green = 0x7777;
937 prop_bg.color->blue = 0x4747;
938 break;
939 default:
940 prop_bg.color->red = 0xe7e7;
941 prop_bg.color->green = 0xe7e7;
942 prop_bg.color->blue = 0xe7e7;
943 }
944
945 g_debug("calling from draw_event");
946 draw_bg((void*)&prop_bg, (void*)draw_context_out);
947 g_free(prop_bg.color);
948 //gdk_gc_unref(draw_context_out->gc);
949 }
950
951 draw_context_out->gc = widget->style->black_gc;
952
953 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
954 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
955 PropertiesText prop_text_out;
956 prop_text_out.foreground = &colorfg_out;
957 prop_text_out.background = &colorbg_out;
958 prop_text_out.size = 6;
959 prop_text_out.position = OVER;
960
961 /* color of text : status of the process */
962 if(process_out->state->s == LTTV_STATE_UNNAMED)
963 {
964 prop_text_out.foreground->red = 0xffff;
965 prop_text_out.foreground->green = 0xffff;
966 prop_text_out.foreground->blue = 0xffff;
967 }
968 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
969 {
970 prop_text_out.foreground->red = 0x0fff;
971 prop_text_out.foreground->green = 0xffff;
972 prop_text_out.foreground->blue = 0xfff0;
973 }
974 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
975 {
976 prop_text_out.foreground->red = 0xffff;
977 prop_text_out.foreground->green = 0xffff;
978 prop_text_out.foreground->blue = 0x0000;
979 }
980 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
981 {
982 prop_text_out.foreground->red = 0xffff;
983 prop_text_out.foreground->green = 0x0000;
984 prop_text_out.foreground->blue = 0xffff;
985 }
986 else if(process_out->state->s == LTTV_STATE_WAIT)
987 {
988 prop_text_out.foreground->red = 0xffff;
989 prop_text_out.foreground->green = 0x0000;
990 prop_text_out.foreground->blue = 0x0000;
991 }
992 else if(process_out->state->s == LTTV_STATE_RUN)
993 {
994 prop_text_out.foreground->red = 0x0000;
995 prop_text_out.foreground->green = 0xffff;
996 prop_text_out.foreground->blue = 0x0000;
997 }
998 else
999 {
1000 prop_text_out.foreground->red = 0xffff;
1001 prop_text_out.foreground->green = 0xffff;
1002 prop_text_out.foreground->blue = 0xffff;
1003 }
1004
1005
1006 /* Print status of the process : U, WF, WC, E, W, R */
1007 if(process_out->state->s == LTTV_STATE_UNNAMED)
1008 prop_text_out.text = "U->";
1009 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1010 prop_text_out.text = "WF->";
1011 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1012 prop_text_out.text = "WC->";
1013 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1014 prop_text_out.text = "E->";
1015 else if(process_out->state->s == LTTV_STATE_WAIT)
1016 prop_text_out.text = "W->";
1017 else if(process_out->state->s == LTTV_STATE_RUN)
1018 prop_text_out.text = "R->";
1019 else
1020 prop_text_out.text = "U";
1021
1022 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1023 //gdk_gc_unref(draw_context_out->gc);
1024
1025 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1026 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1027 draw_context_out->gc = control_flow_data->drawing->gc;
1028
1029 PropertiesLine prop_line_out;
1030 prop_line_out.color = g_new(GdkColor,1);
1031 prop_line_out.line_width = 2;
1032 prop_line_out.style = GDK_LINE_SOLID;
1033 prop_line_out.position = MIDDLE;
1034
1035 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
1036
1037 /* color of line : status of the process */
1038 if(process_out->state->s == LTTV_STATE_UNNAMED)
1039 {
1040 prop_line_out.color->red = 0xffff;
1041 prop_line_out.color->green = 0xffff;
1042 prop_line_out.color->blue = 0xffff;
1043 }
1044 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1045 {
1046 prop_line_out.color->red = 0x0fff;
1047 prop_line_out.color->green = 0xffff;
1048 prop_line_out.color->blue = 0xfff0;
1049 }
1050 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1051 {
1052 prop_line_out.color->red = 0xffff;
1053 prop_line_out.color->green = 0xffff;
1054 prop_line_out.color->blue = 0x0000;
1055 }
1056 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1057 {
1058 prop_line_out.color->red = 0xffff;
1059 prop_line_out.color->green = 0x0000;
1060 prop_line_out.color->blue = 0xffff;
1061 }
1062 else if(process_out->state->s == LTTV_STATE_WAIT)
1063 {
1064 prop_line_out.color->red = 0xffff;
1065 prop_line_out.color->green = 0x0000;
1066 prop_line_out.color->blue = 0x0000;
1067 }
1068 else if(process_out->state->s == LTTV_STATE_RUN)
1069 {
1070 prop_line_out.color->red = 0x0000;
1071 prop_line_out.color->green = 0xffff;
1072 prop_line_out.color->blue = 0x0000;
1073 }
1074 else
1075 {
1076 prop_line_out.color->red = 0xffff;
1077 prop_line_out.color->green = 0xffff;
1078 prop_line_out.color->blue = 0xffff;
1079 }
1080
1081 draw_line((void*)&prop_line_out, (void*)draw_context_out);
1082 g_free(prop_line_out.color);
1083 //gdk_gc_unref(draw_context_out->gc);
1084 /* Note : finishing line will have to be added when trace read over. */
1085
1086 /* Finally, update the drawing context of the pid_in. */
1087
1088 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1089 draw_context_in->current->modify_over->x = x;
1090 draw_context_in->current->modify_under->x = x;
1091 draw_context_in->current->modify_over->y = y_in;
1092 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1093 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1094 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1095 widget = control_flow_data->drawing->drawing_area;
1096 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1097 //draw_context_in->gc = widget->style->black_gc;
1098 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1099 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1100
1101 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1102 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1103
1104 /* Draw the line/bg of the in process */
1105 if(draw_context_in->previous->middle->x == -1)
1106 {
1107 draw_context_in->previous->over->x =
1108 control_flow_data->drawing->damage_begin;
1109 draw_context_in->previous->middle->x =
1110 control_flow_data->drawing->damage_begin;
1111 draw_context_in->previous->under->x =
1112 control_flow_data->drawing->damage_begin;
1113
1114 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
1115
1116 }
1117
1118 draw_context_in->current->middle->x = x;
1119 draw_context_in->current->over->x = x;
1120 draw_context_in->current->under->x = x;
1121 draw_context_in->current->middle->y = y_in + height/2;
1122 draw_context_in->current->over->y = y_in;
1123 draw_context_in->current->under->y = y_in + height;
1124 draw_context_in->previous->middle->y = y_in + height/2;
1125 draw_context_in->previous->over->y = y_in;
1126 draw_context_in->previous->under->y = y_in + height;
1127
1128 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1129 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1130
1131
1132 if(process_in->state->s == LTTV_STATE_RUN)
1133 {
1134 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1135 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1136 draw_context_in->gc = control_flow_data->drawing->gc;
1137
1138 PropertiesBG prop_bg;
1139 prop_bg.color = g_new(GdkColor,1);
1140
1141 switcht(ltt_tracefile_num(tfc->tf)) {
1142 case 0:
1143 prop_bg.color->red = 0x1515;
1144 prop_bg.color->green = 0x1515;
1145 prop_bg.color->blue = 0x8c8c;
1146 break;
1147 case 1:
1148 prop_bg.color->red = 0x4e4e;
1149 prop_bg.color->green = 0xa9a9;
1150 prop_bg.color->blue = 0xa4a4;
1151 break;
1152 case 2:
1153 prop_bg.color->red = 0x7a7a;
1154 prop_bg.color->green = 0x4a4a;
1155 prop_bg.color->blue = 0x8b8b;
1156 break;
1157 case 3:
1158 prop_bg.color->red = 0x8080;
1159 prop_bg.color->green = 0x7777;
1160 prop_bg.color->blue = 0x4747;
1161 break;
1162 default:
1163 prop_bg.color->red = 0xe7e7;
1164 prop_bg.color->green = 0xe7e7;
1165 prop_bg.color->blue = 0xe7e7;
1166 }
1167
1168
1169 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1170 g_free(prop_bg.color);
1171 //gdk_gc_unref(draw_context_in->gc);
1172 }
1173
1174 draw_context_in->gc = widget->style->black_gc;
1175
1176 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1177 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1178 PropertiesText prop_text_in;
1179 prop_text_in.foreground = &colorfg_in;
1180 prop_text_in.background = &colorbg_in;
1181 prop_text_in.size = 6;
1182 prop_text_in.position = OVER;
1183
1184 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
1185 /* foreground of text : status of the process */
1186 if(process_in->state->s == LTTV_STATE_UNNAMED)
1187 {
1188 prop_text_in.foreground->red = 0xffff;
1189 prop_text_in.foreground->green = 0xffff;
1190 prop_text_in.foreground->blue = 0xffff;
1191 }
1192 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1193 {
1194 prop_text_in.foreground->red = 0x0fff;
1195 prop_text_in.foreground->green = 0xffff;
1196 prop_text_in.foreground->blue = 0xfff0;
1197 }
1198 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1199 {
1200 prop_text_in.foreground->red = 0xffff;
1201 prop_text_in.foreground->green = 0xffff;
1202 prop_text_in.foreground->blue = 0x0000;
1203 }
1204 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1205 {
1206 prop_text_in.foreground->red = 0xffff;
1207 prop_text_in.foreground->green = 0x0000;
1208 prop_text_in.foreground->blue = 0xffff;
1209 }
1210 else if(process_in->state->s == LTTV_STATE_WAIT)
1211 {
1212 prop_text_in.foreground->red = 0xffff;
1213 prop_text_in.foreground->green = 0x0000;
1214 prop_text_in.foreground->blue = 0x0000;
1215 }
1216 else if(process_in->state->s == LTTV_STATE_RUN)
1217 {
1218 prop_text_in.foreground->red = 0x0000;
1219 prop_text_in.foreground->green = 0xffff;
1220 prop_text_in.foreground->blue = 0x0000;
1221 }
1222 else
1223 {
1224 prop_text_in.foreground->red = 0xffff;
1225 prop_text_in.foreground->green = 0xffff;
1226 prop_text_in.foreground->blue = 0xffff;
1227 }
1228
1229
1230
1231 /* Print status of the process : U, WF, WC, E, W, R */
1232 if(process_in->state->s == LTTV_STATE_UNNAMED)
1233 prop_text_in.text = "U->";
1234 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1235 prop_text_in.text = "WF->";
1236 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1237 prop_text_in.text = "WC->";
1238 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1239 prop_text_in.text = "E->";
1240 else if(process_in->state->s == LTTV_STATE_WAIT)
1241 prop_text_in.text = "W->";
1242 else if(process_in->state->s == LTTV_STATE_RUN)
1243 prop_text_in.text = "R->";
1244 else
1245 prop_text_in.text = "U";
1246
1247 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1248 //gdk_gc_unref(draw_context_in->gc);
1249
1250 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1251 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1252 draw_context_in->gc = control_flow_data->drawing->gc;
1253
1254 PropertiesLine prop_line_in;
1255 prop_line_in.color = g_new(GdkColor,1);
1256 prop_line_in.line_width = 2;
1257 prop_line_in.style = GDK_LINE_SOLID;
1258 prop_line_in.position = MIDDLE;
1259
1260 /* color of line : status of the process */
1261 if(process_in->state->s == LTTV_STATE_UNNAMED)
1262 {
1263 prop_line_in.color->red = 0xffff;
1264 prop_line_in.color->green = 0xffff;
1265 prop_line_in.color->blue = 0xffff;
1266 }
1267 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1268 {
1269 prop_line_in.color->red = 0x0fff;
1270 prop_line_in.color->green = 0xffff;
1271 prop_line_in.color->blue = 0xfff0;
1272 }
1273 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1274 {
1275 prop_line_in.color->red = 0xffff;
1276 prop_line_in.color->green = 0xffff;
1277 prop_line_in.color->blue = 0x0000;
1278 }
1279 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1280 {
1281 prop_line_in.color->red = 0xffff;
1282 prop_line_in.color->green = 0x0000;
1283 prop_line_in.color->blue = 0xffff;
1284 }
1285 else if(process_in->state->s == LTTV_STATE_WAIT)
1286 {
1287 prop_line_in.color->red = 0xffff;
1288 prop_line_in.color->green = 0x0000;
1289 prop_line_in.color->blue = 0x0000;
1290 }
1291 else if(process_in->state->s == LTTV_STATE_RUN)
1292 {
1293 prop_line_in.color->red = 0x0000;
1294 prop_line_in.color->green = 0xffff;
1295 prop_line_in.color->blue = 0x0000;
1296 }
1297 else
1298 {
1299 prop_line_in.color->red = 0xffff;
1300 prop_line_in.color->green = 0xffff;
1301 prop_line_in.color->blue = 0xffff;
1302 }
1303
1304 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1305 g_free(prop_line_in.color);
1306 //gdk_gc_unref(draw_context_in->gc);
1307 }
1308
1309 return 0;
1310 #endif //0
1311
1312
1313
1314 /* Text dump */
1315 #ifdef DONTSHOW
1316 GString *string = g_string_new("");;
1317 gboolean field_names = TRUE, state = TRUE;
1318
1319 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1320 g_string_append_printf(string,"\n");
1321
1322 if(state) {
1323 g_string_append_printf(string, " %s",
1324 g_quark_to_string(tfs->process->state->s));
1325 }
1326
1327 g_info("%s",string->str);
1328
1329 g_string_free(string, TRUE);
1330
1331 /* End of text dump */
1332 #endif //DONTSHOW
1333
1334 }
1335
1336 /* after_schedchange_hook
1337 *
1338 * The draw after hook is called by the reading API to have a
1339 * particular event drawn on the screen.
1340 * @param hook_data ControlFlowData structure of the viewer.
1341 * @param call_data Event context.
1342 *
1343 * This function adds items to be drawn in a queue for each process.
1344 *
1345 */
1346 int after_schedchange_hook(void *hook_data, void *call_data)
1347 {
1348 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1349 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1350 ControlFlowData *control_flow_data = events_request->viewer_data;
1351
1352 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1353
1354 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1355
1356 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1357
1358 LttEvent *e;
1359 e = ltt_tracefile_get_event(tfc->tf);
1360
1361 LttTime evtime = ltt_event_time(e);
1362
1363 /* Add process to process list (if not present) */
1364 LttvProcessState *process_in;
1365 LttTime birth;
1366 guint pl_height = 0;
1367 HashedProcessData *hashed_process_data_in = NULL;
1368
1369 ProcessList *process_list = control_flow_data->process_list;
1370
1371 guint pid_in;
1372 {
1373 guint pid_out;
1374 pid_out = ltt_event_get_long_unsigned(e, thf->f1);
1375 pid_in = ltt_event_get_long_unsigned(e, thf->f2);
1376 }
1377
1378
1379 /* Find process pid_in in the list... */
1380 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
1381 //process_in = tfs->process;
1382 guint cpu = ltt_tracefile_num(tfc->tf);
1383 process_in = ts->running_process[cpu];
1384 /* It should exist, because we are after the state update. */
1385 #ifdef EXTRA_CHECK
1386 g_assert(process_in != NULL);
1387 #endif //EXTRA_CHECK
1388 birth = process_in->creation_time;
1389
1390 hashed_process_data_in = processlist_get_process_data(process_list,
1391 pid_in,
1392 process_in->cpu,
1393 &birth,
1394 tfc->t_context->index);
1395 if(hashed_process_data_in == NULL)
1396 {
1397 g_assert(pid_in == 0 || pid_in != process_in->ppid);
1398 const gchar *name = g_quark_to_string(process_in->name);
1399 ProcessInfo *process_info;
1400 Drawing_t *drawing = control_flow_data->drawing;
1401 /* Process not present */
1402 processlist_add(process_list,
1403 drawing,
1404 pid_in,
1405 process_in->cpu,
1406 process_in->ppid,
1407 &birth,
1408 tfc->t_context->index,
1409 name,
1410 &pl_height,
1411 &process_info,
1412 &hashed_process_data_in);
1413 gtk_widget_set_size_request(drawing->drawing_area,
1414 -1,
1415 pl_height);
1416 gtk_widget_queue_draw(drawing->drawing_area);
1417 }
1418 /* Set the current process */
1419 process_list->current_hash_data[process_in->cpu] =
1420 hashed_process_data_in;
1421
1422 if(ltt_time_compare(hashed_process_data_in->next_good_time,
1423 evtime) <= 0)
1424 {
1425 TimeWindow time_window =
1426 lttvwindow_get_time_window(control_flow_data->tab);
1427
1428 #ifdef EXTRA_CHECK
1429 if(ltt_time_compare(evtime, time_window.start_time) == -1
1430 || ltt_time_compare(evtime, time_window.end_time) == 1)
1431 return;
1432 #endif //EXTRA_CHECK
1433 Drawing_t *drawing = control_flow_data->drawing;
1434 guint width = drawing->width;
1435 guint new_x;
1436
1437 convert_time_to_pixels(
1438 time_window,
1439 evtime,
1440 width,
1441 &new_x);
1442
1443 if(hashed_process_data_in->x.middle != new_x) {
1444 hashed_process_data_in->x.middle = new_x;
1445 hashed_process_data_in->x.middle_used = FALSE;
1446 hashed_process_data_in->x.middle_marked = FALSE;
1447 }
1448 }
1449 return 0;
1450
1451
1452
1453
1454
1455 #if 0
1456 EventsRequest *events_request = (EventsRequest*)hook_data;
1457 ControlFlowData *control_flow_data = events_request->viewer_data;
1458
1459 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1460
1461 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1462 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1463
1464
1465 LttEvent *e;
1466 e = tfc->e;
1467
1468 LttTime evtime = ltt_event_time(e);
1469 TimeWindow time_window =
1470 lttvwindow_get_time_window(control_flow_data->tab);
1471
1472 LttTime time_window.end_time = time_window.time_window.end_time;
1473
1474 //if(time < time_beg || time > time_end) return;
1475 if(ltt_time_compare(evtime, time_window.start_time) == -1
1476 || ltt_time_compare(evtime, time_window.end_time) == 1)
1477 return;
1478
1479
1480 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1481 {
1482 g_debug("schedchange!");
1483
1484 /* Add process to process list (if not present) and get drawing "y" from
1485 * process position */
1486 guint pid_out, pid_in;
1487 LttvProcessState *process_out, *process_in;
1488 LttTime birth;
1489 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1490
1491 ProcessList *process_list = control_flow_data->process_list;
1492
1493
1494 LttField *f = ltt_event_field(e);
1495 LttField *element;
1496 element = ltt_field_member(f,0);
1497 pid_out = ltt_event_get_long_unsigned(e,element);
1498 element = ltt_field_member(f,1);
1499 pid_in = ltt_event_get_long_unsigned(e,element);
1500 //g_debug("out : %u in : %u", pid_out, pid_in);
1501
1502
1503 /* Find process pid_out in the list... */
1504 process_out = lttv_state_find_process(tfs, pid_out);
1505 if(process_out == NULL) return 0;
1506 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1507
1508 birth = process_out->creation_time;
1509 gchar *name = strdup(g_quark_to_string(process_out->name));
1510 HashedProcessData *hashed_process_data_out = NULL;
1511
1512 if(processlist_get_process_pixels(process_list,
1513 pid_out,
1514 &birth,
1515 tfc->t_context->index,
1516 &y_out,
1517 &height,
1518 &hashed_process_data_out) == 1)
1519 {
1520 /* Process not present */
1521 processlist_add(process_list,
1522 pid_out,
1523 &birth,
1524 tfc->t_context->index,
1525 name,
1526 &pl_height,
1527 &hashed_process_data_out);
1528 processlist_get_process_pixels(process_list,
1529 pid_out,
1530 &birth,
1531 tfc->t_context->index,
1532 &y_out,
1533 &height,
1534 &hashed_process_data_out);
1535 drawing_insert_square( control_flow_data->drawing, y_out, height);
1536 }
1537
1538 g_free(name);
1539
1540 /* Find process pid_in in the list... */
1541 process_in = lttv_state_find_process(tfs, pid_in);
1542 if(process_in == NULL) return 0;
1543 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1544
1545 birth = process_in->creation_time;
1546 name = strdup(g_quark_to_string(process_in->name));
1547 HashedProcessData *hashed_process_data_in = NULL;
1548
1549 if(processlist_get_process_pixels(process_list,
1550 pid_in,
1551 &birth,
1552 tfc->t_context->index,
1553 &y_in,
1554 &height,
1555 &hashed_process_data_in) == 1)
1556 {
1557 /* Process not present */
1558 processlist_add(process_list,
1559 pid_in,
1560 &birth,
1561 tfc->t_context->index,
1562 name,
1563 &pl_height,
1564 &hashed_process_data_in);
1565 processlist_get_process_pixels(process_list,
1566 pid_in,
1567 &birth,
1568 tfc->t_context->index,
1569 &y_in,
1570 &height,
1571 &hashed_process_data_in);
1572
1573 drawing_insert_square( control_flow_data->drawing, y_in, height);
1574 }
1575 g_free(name);
1576
1577
1578 /* Find pixels corresponding to time of the event. If the time does
1579 * not fit in the window, show a warning, not supposed to happend. */
1580 //guint x = 0;
1581 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1582
1583 //LttTime time = ltt_event_time(e);
1584
1585 //LttTime window_end = time_window->time_window.end_time;
1586
1587
1588 //convert_time_to_pixels(
1589 // *time_window,
1590 // time,
1591 // width,
1592 // &x);
1593
1594 //assert(x <= width);
1595
1596 /* draw what represents the event for outgoing process. */
1597
1598 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
1599 //draw_context_out->current->modify_over->x = x;
1600 draw_context_out->current->modify_over->y = y_out;
1601 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
1602 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1603 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1604 GtkWidget *widget = control_flow_data->drawing->drawing_area;
1605 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1606
1607 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1608 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1609
1610 /*if(process_out->state->s == LTTV_STATE_RUN)
1611 {
1612 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1613 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1614 PropertiesBG prop_bg;
1615 prop_bg.color = g_new(GdkColor,1);
1616
1617 prop_bg.color->red = 0xffff;
1618 prop_bg.color->green = 0xffff;
1619 prop_bg.color->blue = 0xffff;
1620
1621 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1622 g_free(prop_bg.color);
1623 gdk_gc_unref(draw_context_out->gc);
1624 }*/
1625
1626 draw_context_out->gc = widget->style->black_gc;
1627
1628 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
1629 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
1630 PropertiesText prop_text_out;
1631 prop_text_out.foreground = &colorfg_out;
1632 prop_text_out.background = &colorbg_out;
1633 prop_text_out.size = 6;
1634 prop_text_out.position = OVER;
1635
1636 /* color of text : status of the process */
1637 if(process_out->state->s == LTTV_STATE_UNNAMED)
1638 {
1639 prop_text_out.foreground->red = 0xffff;
1640 prop_text_out.foreground->green = 0xffff;
1641 prop_text_out.foreground->blue = 0xffff;
1642 }
1643 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1644 {
1645 prop_text_out.foreground->red = 0x0fff;
1646 prop_text_out.foreground->green = 0xffff;
1647 prop_text_out.foreground->blue = 0xfff0;
1648 }
1649 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1650 {
1651 prop_text_out.foreground->red = 0xffff;
1652 prop_text_out.foreground->green = 0xffff;
1653 prop_text_out.foreground->blue = 0x0000;
1654 }
1655 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1656 {
1657 prop_text_out.foreground->red = 0xffff;
1658 prop_text_out.foreground->green = 0x0000;
1659 prop_text_out.foreground->blue = 0xffff;
1660 }
1661 else if(process_out->state->s == LTTV_STATE_WAIT)
1662 {
1663 prop_text_out.foreground->red = 0xffff;
1664 prop_text_out.foreground->green = 0x0000;
1665 prop_text_out.foreground->blue = 0x0000;
1666 }
1667 else if(process_out->state->s == LTTV_STATE_RUN)
1668 {
1669 prop_text_out.foreground->red = 0x0000;
1670 prop_text_out.foreground->green = 0xffff;
1671 prop_text_out.foreground->blue = 0x0000;
1672 }
1673 else
1674 {
1675 prop_text_out.foreground->red = 0xffff;
1676 prop_text_out.foreground->green = 0xffff;
1677 prop_text_out.foreground->blue = 0xffff;
1678 }
1679
1680 /* Print status of the process : U, WF, WC, E, W, R */
1681 if(process_out->state->s == LTTV_STATE_UNNAMED)
1682 prop_text_out.text = "U";
1683 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1684 prop_text_out.text = "WF";
1685 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1686 prop_text_out.text = "WC";
1687 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1688 prop_text_out.text = "E";
1689 else if(process_out->state->s == LTTV_STATE_WAIT)
1690 prop_text_out.text = "W";
1691 else if(process_out->state->s == LTTV_STATE_RUN)
1692 prop_text_out.text = "R";
1693 else
1694 prop_text_out.text = "U";
1695
1696 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1697
1698 //gdk_gc_unref(draw_context_out->gc);
1699
1700 draw_context_out->current->middle->y = y_out+height/2;
1701 draw_context_out->current->over->y = y_out;
1702 draw_context_out->current->under->y = y_out+height;
1703 draw_context_out->current->status = process_out->state->s;
1704
1705 /* for pid_out : remove previous, Prev = current, new current (default) */
1706 g_free(draw_context_out->previous->modify_under);
1707 g_free(draw_context_out->previous->modify_middle);
1708 g_free(draw_context_out->previous->modify_over);
1709 g_free(draw_context_out->previous->under);
1710 g_free(draw_context_out->previous->middle);
1711 g_free(draw_context_out->previous->over);
1712 g_free(draw_context_out->previous);
1713
1714 draw_context_out->previous = draw_context_out->current;
1715
1716 draw_context_out->current = g_new(DrawInfo,1);
1717 draw_context_out->current->over = g_new(ItemInfo,1);
1718 draw_context_out->current->over->x = -1;
1719 draw_context_out->current->over->y = -1;
1720 draw_context_out->current->middle = g_new(ItemInfo,1);
1721 draw_context_out->current->middle->x = -1;
1722 draw_context_out->current->middle->y = -1;
1723 draw_context_out->current->under = g_new(ItemInfo,1);
1724 draw_context_out->current->under->x = -1;
1725 draw_context_out->current->under->y = -1;
1726 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1727 draw_context_out->current->modify_over->x = -1;
1728 draw_context_out->current->modify_over->y = -1;
1729 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1730 draw_context_out->current->modify_middle->x = -1;
1731 draw_context_out->current->modify_middle->y = -1;
1732 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1733 draw_context_out->current->modify_under->x = -1;
1734 draw_context_out->current->modify_under->y = -1;
1735 draw_context_out->current->status = LTTV_STATE_UNNAMED;
1736
1737 /* Finally, update the drawing context of the pid_in. */
1738
1739 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1740 //draw_context_in->current->modify_over->x = x;
1741 draw_context_in->current->modify_over->y = y_in;
1742 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1743 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1744 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1745 widget = control_flow_data->drawing->drawing_area;
1746 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1747
1748 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1749 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1750
1751 /*if(process_in->state->s == LTTV_STATE_RUN)
1752 {
1753 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1754 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1755 PropertiesBG prop_bg;
1756 prop_bg.color = g_new(GdkColor,1);
1757
1758 prop_bg.color->red = 0xffff;
1759 prop_bg.color->green = 0xffff;
1760 prop_bg.color->blue = 0xffff;
1761
1762 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1763 g_free(prop_bg.color);
1764 gdk_gc_unref(draw_context_in->gc);
1765 }*/
1766
1767 draw_context_in->gc = widget->style->black_gc;
1768
1769 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1770 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1771 PropertiesText prop_text_in;
1772 prop_text_in.foreground = &colorfg_in;
1773 prop_text_in.background = &colorbg_in;
1774 prop_text_in.size = 6;
1775 prop_text_in.position = OVER;
1776
1777 /* foreground of text : status of the process */
1778 if(process_in->state->s == LTTV_STATE_UNNAMED)
1779 {
1780 prop_text_in.foreground->red = 0xffff;
1781 prop_text_in.foreground->green = 0xffff;
1782 prop_text_in.foreground->blue = 0xffff;
1783 }
1784 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1785 {
1786 prop_text_in.foreground->red = 0x0fff;
1787 prop_text_in.foreground->green = 0xffff;
1788 prop_text_in.foreground->blue = 0xfff0;
1789 }
1790 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1791 {
1792 prop_text_in.foreground->red = 0xffff;
1793 prop_text_in.foreground->green = 0xffff;
1794 prop_text_in.foreground->blue = 0x0000;
1795 }
1796 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1797 {
1798 prop_text_in.foreground->red = 0xffff;
1799 prop_text_in.foreground->green = 0x0000;
1800 prop_text_in.foreground->blue = 0xffff;
1801 }
1802 else if(process_in->state->s == LTTV_STATE_WAIT)
1803 {
1804 prop_text_in.foreground->red = 0xffff;
1805 prop_text_in.foreground->green = 0x0000;
1806 prop_text_in.foreground->blue = 0x0000;
1807 }
1808 else if(process_in->state->s == LTTV_STATE_RUN)
1809 {
1810 prop_text_in.foreground->red = 0x0000;
1811 prop_text_in.foreground->green = 0xffff;
1812 prop_text_in.foreground->blue = 0x0000;
1813 }
1814 else
1815 {
1816 prop_text_in.foreground->red = 0xffff;
1817 prop_text_in.foreground->green = 0xffff;
1818 prop_text_in.foreground->blue = 0xffff;
1819 }
1820
1821
1822 /* Print status of the process : U, WF, WC, E, W, R */
1823 if(process_in->state->s == LTTV_STATE_UNNAMED)
1824 prop_text_in.text = "U";
1825 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1826 prop_text_in.text = "WF";
1827 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1828 prop_text_in.text = "WC";
1829 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1830 prop_text_in.text = "E";
1831 else if(process_in->state->s == LTTV_STATE_WAIT)
1832 prop_text_in.text = "W";
1833 else if(process_in->state->s == LTTV_STATE_RUN)
1834 prop_text_in.text = "R";
1835 else
1836 prop_text_in.text = "U";
1837
1838 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1839
1840
1841 if(process_in->state->s == LTTV_STATE_RUN)
1842 {
1843 gchar tmp[255];
1844 prop_text_in.foreground = &colorfg_in;
1845 prop_text_in.background = &colorbg_in;
1846 prop_text_in.foreground->red = 0xffff;
1847 prop_text_in.foreground->green = 0xffff;
1848 prop_text_in.foreground->blue = 0xffff;
1849 prop_text_in.size = 6;
1850 prop_text_in.position = UNDER;
1851
1852 prop_text_in.text = g_new(gchar, 260);
1853 strcpy(prop_text_in.text, "CPU ");
1854 snprintf(tmp, 255, "%u", ltt_tracefile_num(tfc->tf));
1855 strcat(prop_text_in.text, tmp);
1856
1857 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1858 g_free(prop_text_in.text);
1859 }
1860
1861
1862 draw_context_in->current->middle->y = y_in+height/2;
1863 draw_context_in->current->over->y = y_in;
1864 draw_context_in->current->under->y = y_in+height;
1865 draw_context_in->current->status = process_in->state->s;
1866
1867 /* for pid_in : remove previous, Prev = current, new current (default) */
1868 g_free(draw_context_in->previous->modify_under);
1869 g_free(draw_context_in->previous->modify_middle);
1870 g_free(draw_context_in->previous->modify_over);
1871 g_free(draw_context_in->previous->under);
1872 g_free(draw_context_in->previous->middle);
1873 g_free(draw_context_in->previous->over);
1874 g_free(draw_context_in->previous);
1875
1876 draw_context_in->previous = draw_context_in->current;
1877
1878 draw_context_in->current = g_new(DrawInfo,1);
1879 draw_context_in->current->over = g_new(ItemInfo,1);
1880 draw_context_in->current->over->x = -1;
1881 draw_context_in->current->over->y = -1;
1882 draw_context_in->current->middle = g_new(ItemInfo,1);
1883 draw_context_in->current->middle->x = -1;
1884 draw_context_in->current->middle->y = -1;
1885 draw_context_in->current->under = g_new(ItemInfo,1);
1886 draw_context_in->current->under->x = -1;
1887 draw_context_in->current->under->y = -1;
1888 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1889 draw_context_in->current->modify_over->x = -1;
1890 draw_context_in->current->modify_over->y = -1;
1891 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1892 draw_context_in->current->modify_middle->x = -1;
1893 draw_context_in->current->modify_middle->y = -1;
1894 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1895 draw_context_in->current->modify_under->x = -1;
1896 draw_context_in->current->modify_under->y = -1;
1897 draw_context_in->current->status = LTTV_STATE_UNNAMED;
1898
1899 }
1900
1901 return 0;
1902 #endif //0
1903 }
1904
1905 #if 0
1906 static inline PropertiesLine prepare_execmode_line(LttvProcessState *process)
1907 {
1908 PropertiesLine prop_line;
1909 prop_line.line_width = 1;
1910 prop_line.style = GDK_LINE_SOLID;
1911 prop_line.y = OVER;
1912 //GdkColormap *colormap = gdk_colormap_get_system();
1913
1914 /* color of line : execution mode of the process */
1915 if(process->state->t == LTTV_STATE_USER_MODE)
1916 prop_line.color = drawing_colors[COL_USER_MODE];
1917 else if(process->state->t == LTTV_STATE_SYSCALL)
1918 prop_line.color = drawing_colors[COL_SYSCALL];
1919 else if(process->state->t == LTTV_STATE_TRAP)
1920 prop_line.color = drawing_colors[COL_TRAP];
1921 else if(process->state->t == LTTV_STATE_IRQ)
1922 prop_line.color = drawing_colors[COL_IRQ];
1923 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
1924 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
1925 else
1926 prop_line.color = drawing_colors[COL_WHITE];
1927
1928 //gdk_colormap_alloc_color(colormap,
1929 // prop_line.color,
1930 // FALSE,
1931 // TRUE);
1932
1933 return prop_line;
1934
1935 }
1936 #endif //0
1937
1938
1939 /* before_execmode_hook
1940 *
1941 * This function basically draw lines and icons. Two types of lines are drawn :
1942 * one small (3 pixels?) representing the state of the process and the second
1943 * type is thicker (10 pixels?) representing on which CPU a process is running
1944 * (and this only in running state).
1945 *
1946 * Extremums of the lines :
1947 * x_min : time of the last event context for this process kept in memory.
1948 * x_max : time of the current event.
1949 * y : middle of the process in the process list. The process is found in the
1950 * list, therefore is it's position in pixels.
1951 *
1952 * The choice of lines'color is defined by the context of the last event for this
1953 * process.
1954 */
1955
1956
1957 int before_execmode_hook(void *hook_data, void *call_data)
1958 {
1959 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1960 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1961 ControlFlowData *control_flow_data = events_request->viewer_data;
1962
1963 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1964
1965 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1966
1967 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1968
1969 LttEvent *e;
1970 e = ltt_tracefile_get_event(tfc->tf);
1971
1972 LttTime evtime = ltt_event_time(e);
1973
1974 /* we are in a execmode, before the state update. We must draw the
1975 * items corresponding to the state before it changes : now is the right
1976 * time to do it.
1977 */
1978 /* For the pid */
1979 //LttvProcessState *process = tfs->process;
1980 guint cpu = ltt_tracefile_num(tfc->tf);
1981 LttvProcessState *process = ts->running_process[cpu];
1982 g_assert(process != NULL);
1983
1984 guint pid = process->pid;
1985
1986 /* Well, the process_out existed : we must get it in the process hash
1987 * or add it, and draw its items.
1988 */
1989 /* Add process to process list (if not present) */
1990 guint pl_height = 0;
1991 HashedProcessData *hashed_process_data = NULL;
1992 ProcessList *process_list = control_flow_data->process_list;
1993 LttTime birth = process->creation_time;
1994
1995 if(likely(process_list->current_hash_data[cpu] != NULL)) {
1996 hashed_process_data = process_list->current_hash_data[cpu];
1997 } else {
1998 hashed_process_data = processlist_get_process_data(process_list,
1999 pid,
2000 process->cpu,
2001 &birth,
2002 tfc->t_context->index);
2003 if(unlikely(hashed_process_data == NULL))
2004 {
2005 g_assert(pid == 0 || pid != process->ppid);
2006 ProcessInfo *process_info;
2007 /* Process not present */
2008 Drawing_t *drawing = control_flow_data->drawing;
2009 const gchar *name = g_quark_to_string(process->name);
2010 processlist_add(process_list,
2011 drawing,
2012 pid,
2013 process->cpu,
2014 process->ppid,
2015 &birth,
2016 tfc->t_context->index,
2017 name,
2018 &pl_height,
2019 &process_info,
2020 &hashed_process_data);
2021 gtk_widget_set_size_request(drawing->drawing_area,
2022 -1,
2023 pl_height);
2024 gtk_widget_queue_draw(drawing->drawing_area);
2025 }
2026 /* Set the current process */
2027 process_list->current_hash_data[process->cpu] =
2028 hashed_process_data;
2029 }
2030
2031 /* Now, the process is in the state hash and our own process hash.
2032 * We definitely can draw the items related to the ending state.
2033 */
2034
2035 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2036 evtime) > 0))
2037 {
2038 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2039 TimeWindow time_window =
2040 lttvwindow_get_time_window(control_flow_data->tab);
2041
2042 #ifdef EXTRA_CHECK
2043 if(ltt_time_compare(evtime, time_window.start_time) == -1
2044 || ltt_time_compare(evtime, time_window.end_time) == 1)
2045 return;
2046 #endif //EXTRA_CHECK
2047 Drawing_t *drawing = control_flow_data->drawing;
2048 guint width = drawing->width;
2049 guint x;
2050 convert_time_to_pixels(
2051 time_window,
2052 evtime,
2053 width,
2054 &x);
2055
2056 /* Draw collision indicator */
2057 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2058 gdk_draw_point(hashed_process_data->pixmap,
2059 drawing->gc,
2060 x,
2061 (hashed_process_data->height/2)-3);
2062 hashed_process_data->x.middle_marked = TRUE;
2063 }
2064 } else {
2065 TimeWindow time_window =
2066 lttvwindow_get_time_window(control_flow_data->tab);
2067
2068 #ifdef EXTRA_CHECK
2069 if(ltt_time_compare(evtime, time_window.start_time) == -1
2070 || ltt_time_compare(evtime, time_window.end_time) == 1)
2071 return;
2072 #endif //EXTRA_CHECK
2073 Drawing_t *drawing = control_flow_data->drawing;
2074 guint width = drawing->width;
2075 guint x;
2076
2077 convert_time_to_pixels(
2078 time_window,
2079 evtime,
2080 width,
2081 &x);
2082
2083
2084 /* Jump over draw if we are at the same x position */
2085 if(unlikely(x == hashed_process_data->x.middle &&
2086 hashed_process_data->x.middle_used))
2087 {
2088 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2089 /* Draw collision indicator */
2090 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2091 gdk_draw_point(hashed_process_data->pixmap,
2092 drawing->gc,
2093 x,
2094 (hashed_process_data->height/2)-3);
2095 hashed_process_data->x.middle_marked = TRUE;
2096 }
2097 /* jump */
2098 } else {
2099
2100 DrawContext draw_context;
2101 /* Now create the drawing context that will be used to draw
2102 * items related to the last state. */
2103 draw_context.drawable = hashed_process_data->pixmap;
2104 draw_context.gc = drawing->gc;
2105 draw_context.pango_layout = drawing->pango_layout;
2106 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2107 draw_context.drawinfo.end.x = x;
2108
2109 draw_context.drawinfo.y.over = 1;
2110 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2111 draw_context.drawinfo.y.under = hashed_process_data->height;
2112
2113 draw_context.drawinfo.start.offset.over = 0;
2114 draw_context.drawinfo.start.offset.middle = 0;
2115 draw_context.drawinfo.start.offset.under = 0;
2116 draw_context.drawinfo.end.offset.over = 0;
2117 draw_context.drawinfo.end.offset.middle = 0;
2118 draw_context.drawinfo.end.offset.under = 0;
2119
2120 {
2121 /* Draw the line */
2122 PropertiesLine prop_line = prepare_s_e_line(process);
2123 draw_line((void*)&prop_line, (void*)&draw_context);
2124
2125 }
2126 /* become the last x position */
2127 hashed_process_data->x.middle = x;
2128 hashed_process_data->x.middle_used = TRUE;
2129 hashed_process_data->x.middle_marked = FALSE;
2130
2131 /* Calculate the next good time */
2132 convert_pixels_to_time(width, x+1, time_window,
2133 &hashed_process_data->next_good_time);
2134 }
2135 }
2136
2137 return 0;
2138 }
2139
2140 /* after_execmode_hook
2141 *
2142 * The draw after hook is called by the reading API to have a
2143 * particular event drawn on the screen.
2144 * @param hook_data ControlFlowData structure of the viewer.
2145 * @param call_data Event context.
2146 *
2147 * This function adds items to be drawn in a queue for each process.
2148 *
2149 */
2150 #if 0
2151 int after_execmode_hook(void *hook_data, void *call_data)
2152 {
2153 /**************** DOES NOTHING!! *************/
2154 /* hook desactivated in drawing.c */
2155 return 0;
2156
2157
2158 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2159 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2160 ControlFlowData *control_flow_data = events_request->viewer_data;
2161
2162 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2163
2164 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2165
2166 LttEvent *e;
2167 e = ltt_tracefile_get_event(tfc->tf);
2168
2169 LttTime evtime = ltt_event_time(e);
2170
2171 /* Add process to process list (if not present) */
2172 LttvProcessState *process;
2173 LttTime birth;
2174 guint pl_height = 0;
2175 HashedProcessData *hashed_process_data = NULL;
2176
2177 ProcessList *process_list = control_flow_data->process_list;
2178
2179 /* Find process pid_in in the list... */
2180 process = tfs->process;
2181 /* It should exist, because we are after the state update. */
2182 g_assert(process != NULL);
2183
2184 guint pid = process->pid;
2185
2186 birth = process->creation_time;
2187
2188 if(likely(process_list->current_hash_data[ltt_tracefile_num(tfc->tf)] != NULL)) {
2189 hashed_process_data = process_list->current_hash_data[ltt_tracefile_num(tfc->tf)];
2190 } else {
2191 hashed_process_data = processlist_get_process_data(process_list,
2192 pid,
2193 process->last_cpu_index,
2194 &birth,
2195 tfc->t_context->index);
2196 if(unlikely(hashed_process_data == NULL))
2197 {
2198 g_assert(pid == 0 || pid != process->ppid);
2199 /* Process not present */
2200 Drawing_t *drawing = control_flow_data->drawing;
2201 const gchar *name = g_quark_to_string(process->name);
2202 ProcessInfo *process_info;
2203 processlist_add(process_list,
2204 drawing,
2205 pid,
2206 process->last_cpu_index,
2207 process->ppid,
2208 &birth,
2209 tfc->t_context->index,
2210 name,
2211 &pl_height,
2212 &process_info,
2213 &hashed_process_data);
2214 gtk_widget_set_size_request(drawing->drawing_area,
2215 -1,
2216 pl_height);
2217 gtk_widget_queue_draw(drawing->drawing_area);
2218 }
2219 /* Set the current process */
2220 process_list->current_hash_data[process->last_cpu_index] =
2221 hashed_process_data;
2222 }
2223
2224 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
2225 evtime) <= 0))
2226 {
2227 TimeWindow time_window =
2228 lttvwindow_get_time_window(control_flow_data->tab);
2229
2230 #ifdef EXTRA_CHECK
2231 if(ltt_time_compare(evtime, time_window.start_time) == -1
2232 || ltt_time_compare(evtime, time_window.end_time) == 1)
2233 return;
2234 #endif //EXTRA_CHECK
2235 Drawing_t *drawing = control_flow_data->drawing;
2236 guint width = drawing->width;
2237 guint new_x;
2238
2239 convert_time_to_pixels(
2240 time_window,
2241 evtime,
2242 width,
2243 &new_x);
2244
2245 if(hashed_process_data->x.middle != new_x) {
2246 hashed_process_data->x.middle = new_x;
2247 hashed_process_data->x.middle_used = FALSE;
2248 hashed_process_data->x.middle_marked = FALSE;
2249 }
2250 }
2251 return 0;
2252 }
2253 #endif //0
2254
2255
2256
2257 /* before_process_exit_hook
2258 *
2259 * Draw lines for process event.
2260 *
2261 * @param hook_data ControlFlowData structure of the viewer.
2262 * @param call_data Event context.
2263 *
2264 * This function adds items to be drawn in a queue for each process.
2265 *
2266 */
2267
2268
2269 int before_process_exit_hook(void *hook_data, void *call_data)
2270 {
2271 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2272 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2273
2274 ControlFlowData *control_flow_data = events_request->viewer_data;
2275
2276 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2277
2278 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2279
2280 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2281
2282 LttEvent *e;
2283 e = ltt_tracefile_get_event(tfc->tf);
2284
2285 LttTime evtime = ltt_event_time(e);
2286
2287 /* Add process to process list (if not present) */
2288 //LttvProcessState *process = tfs->process;
2289 guint cpu = ltt_tracefile_num(tfc->tf);
2290 LttvProcessState *process = ts->running_process[cpu];
2291 guint pid = process->pid;
2292 LttTime birth;
2293 guint pl_height = 0;
2294 HashedProcessData *hashed_process_data = NULL;
2295
2296 ProcessList *process_list = control_flow_data->process_list;
2297
2298 g_assert(process != NULL);
2299
2300 birth = process->creation_time;
2301
2302 if(likely(process_list->current_hash_data[cpu] != NULL)) {
2303 hashed_process_data = process_list->current_hash_data[cpu];
2304 } else {
2305 hashed_process_data = processlist_get_process_data(process_list,
2306 pid,
2307 process->cpu,
2308 &birth,
2309 tfc->t_context->index);
2310 if(unlikely(hashed_process_data == NULL))
2311 {
2312 g_assert(pid == 0 || pid != process->ppid);
2313 /* Process not present */
2314 Drawing_t *drawing = control_flow_data->drawing;
2315 const gchar *name = g_quark_to_string(process->name);
2316 ProcessInfo *process_info;
2317 processlist_add(process_list,
2318 drawing,
2319 pid,
2320 process->cpu,
2321 process->ppid,
2322 &birth,
2323 tfc->t_context->index,
2324 name,
2325 &pl_height,
2326 &process_info,
2327 &hashed_process_data);
2328 gtk_widget_set_size_request(drawing->drawing_area,
2329 -1,
2330 pl_height);
2331 gtk_widget_queue_draw(drawing->drawing_area);
2332 }
2333 }
2334
2335 /* Now, the process is in the state hash and our own process hash.
2336 * We definitely can draw the items related to the ending state.
2337 */
2338
2339 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2340 evtime) > 0))
2341 {
2342 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2343 TimeWindow time_window =
2344 lttvwindow_get_time_window(control_flow_data->tab);
2345
2346 #ifdef EXTRA_CHECK
2347 if(ltt_time_compare(evtime, time_window.start_time) == -1
2348 || ltt_time_compare(evtime, time_window.end_time) == 1)
2349 return;
2350 #endif //EXTRA_CHECK
2351 Drawing_t *drawing = control_flow_data->drawing;
2352 guint width = drawing->width;
2353 guint x;
2354 convert_time_to_pixels(
2355 time_window,
2356 evtime,
2357 width,
2358 &x);
2359
2360 /* Draw collision indicator */
2361 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2362 gdk_draw_point(hashed_process_data->pixmap,
2363 drawing->gc,
2364 x,
2365 (hashed_process_data->height/2)-3);
2366 hashed_process_data->x.middle_marked = TRUE;
2367 }
2368 } else {
2369 TimeWindow time_window =
2370 lttvwindow_get_time_window(control_flow_data->tab);
2371
2372 #ifdef EXTRA_CHECK
2373 if(ltt_time_compare(evtime, time_window.start_time) == -1
2374 || ltt_time_compare(evtime, time_window.end_time) == 1)
2375 return;
2376 #endif //EXTRA_CHECK
2377 Drawing_t *drawing = control_flow_data->drawing;
2378 guint width = drawing->width;
2379 guint x;
2380
2381 convert_time_to_pixels(
2382 time_window,
2383 evtime,
2384 width,
2385 &x);
2386
2387
2388 /* Jump over draw if we are at the same x position */
2389 if(unlikely(x == hashed_process_data->x.middle &&
2390 hashed_process_data->x.middle_used))
2391 {
2392 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2393 /* Draw collision indicator */
2394 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2395 gdk_draw_point(hashed_process_data->pixmap,
2396 drawing->gc,
2397 x,
2398 (hashed_process_data->height/2)-3);
2399 hashed_process_data->x.middle_marked = TRUE;
2400 }
2401 /* jump */
2402 } else {
2403 DrawContext draw_context;
2404
2405 /* Now create the drawing context that will be used to draw
2406 * items related to the last state. */
2407 draw_context.drawable = hashed_process_data->pixmap;
2408 draw_context.gc = drawing->gc;
2409 draw_context.pango_layout = drawing->pango_layout;
2410 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2411 draw_context.drawinfo.end.x = x;
2412
2413 draw_context.drawinfo.y.over = 1;
2414 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2415 draw_context.drawinfo.y.under = hashed_process_data->height;
2416
2417 draw_context.drawinfo.start.offset.over = 0;
2418 draw_context.drawinfo.start.offset.middle = 0;
2419 draw_context.drawinfo.start.offset.under = 0;
2420 draw_context.drawinfo.end.offset.over = 0;
2421 draw_context.drawinfo.end.offset.middle = 0;
2422 draw_context.drawinfo.end.offset.under = 0;
2423
2424 {
2425 /* Draw the line */
2426 PropertiesLine prop_line = prepare_s_e_line(process);
2427 draw_line((void*)&prop_line, (void*)&draw_context);
2428
2429 }
2430 /* become the last x position */
2431 hashed_process_data->x.middle = x;
2432 hashed_process_data->x.middle_used = TRUE;
2433 hashed_process_data->x.middle_marked = FALSE;
2434
2435 /* Calculate the next good time */
2436 convert_pixels_to_time(width, x+1, time_window,
2437 &hashed_process_data->next_good_time);
2438 }
2439 }
2440
2441 return 0;
2442
2443 }
2444
2445
2446
2447 /* before_process_release_hook
2448 *
2449 * Draw lines for process event.
2450 *
2451 * @param hook_data ControlFlowData structure of the viewer.
2452 * @param call_data Event context.
2453 *
2454 * This function adds items to be drawn in a queue for each process.
2455 *
2456 */
2457
2458
2459 int before_process_release_hook(void *hook_data, void *call_data)
2460 {
2461 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2462 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2463
2464 ControlFlowData *control_flow_data = events_request->viewer_data;
2465
2466 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2467
2468 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2469
2470 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2471
2472 LttEvent *e;
2473 e = ltt_tracefile_get_event(tfc->tf);
2474
2475 LttTime evtime = ltt_event_time(e);
2476
2477
2478 guint pid;
2479 {
2480 pid = ltt_event_get_long_unsigned(e, thf->f1);
2481 }
2482
2483 /* Add process to process list (if not present) */
2484 /* Don't care about the process if it's not in the state hash already :
2485 * that means a process that has never done anything in the trace and
2486 * unknown suddently gets destroyed : no state meaningful to show. */
2487 LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
2488
2489 if(process != NULL) {
2490 LttTime birth;
2491 guint pl_height = 0;
2492 HashedProcessData *hashed_process_data = NULL;
2493
2494 ProcessList *process_list = control_flow_data->process_list;
2495
2496 birth = process->creation_time;
2497
2498 /* Cannot use current process : this event happens on another process,
2499 * action done by the parent. */
2500 hashed_process_data = processlist_get_process_data(process_list,
2501 pid,
2502 process->cpu,
2503 &birth,
2504 tfc->t_context->index);
2505 if(unlikely(hashed_process_data == NULL))
2506 {
2507 g_assert(pid == 0 || pid != process->ppid);
2508 /* Process not present */
2509 Drawing_t *drawing = control_flow_data->drawing;
2510 const gchar *name = g_quark_to_string(process->name);
2511 ProcessInfo *process_info;
2512 processlist_add(process_list,
2513 drawing,
2514 pid,
2515 process->cpu,
2516 process->ppid,
2517 &birth,
2518 tfc->t_context->index,
2519 name,
2520 &pl_height,
2521 &process_info,
2522 &hashed_process_data);
2523 gtk_widget_set_size_request(drawing->drawing_area,
2524 -1,
2525 pl_height);
2526 gtk_widget_queue_draw(drawing->drawing_area);
2527 }
2528
2529 /* Now, the process is in the state hash and our own process hash.
2530 * We definitely can draw the items related to the ending state.
2531 */
2532
2533 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2534 evtime) > 0))
2535 {
2536 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2537 TimeWindow time_window =
2538 lttvwindow_get_time_window(control_flow_data->tab);
2539
2540 #ifdef EXTRA_CHECK
2541 if(ltt_time_compare(evtime, time_window.start_time) == -1
2542 || ltt_time_compare(evtime, time_window.end_time) == 1)
2543 return;
2544 #endif //EXTRA_CHECK
2545 Drawing_t *drawing = control_flow_data->drawing;
2546 guint width = drawing->width;
2547 guint x;
2548 convert_time_to_pixels(
2549 time_window,
2550 evtime,
2551 width,
2552 &x);
2553
2554 /* Draw collision indicator */
2555 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2556 gdk_draw_point(hashed_process_data->pixmap,
2557 drawing->gc,
2558 x,
2559 (hashed_process_data->height/2)-3);
2560 hashed_process_data->x.middle_marked = TRUE;
2561 }
2562 } else {
2563 TimeWindow time_window =
2564 lttvwindow_get_time_window(control_flow_data->tab);
2565
2566 #ifdef EXTRA_CHECK
2567 if(ltt_time_compare(evtime, time_window.start_time) == -1
2568 || ltt_time_compare(evtime, time_window.end_time) == 1)
2569 return;
2570 #endif //EXTRA_CHECK
2571 Drawing_t *drawing = control_flow_data->drawing;
2572 guint width = drawing->width;
2573 guint x;
2574
2575 convert_time_to_pixels(
2576 time_window,
2577 evtime,
2578 width,
2579 &x);
2580
2581
2582 /* Jump over draw if we are at the same x position */
2583 if(unlikely(x == hashed_process_data->x.middle &&
2584 hashed_process_data->x.middle_used))
2585 {
2586 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2587 /* Draw collision indicator */
2588 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2589 gdk_draw_point(hashed_process_data->pixmap,
2590 drawing->gc,
2591 x,
2592 (hashed_process_data->height/2)-3);
2593 hashed_process_data->x.middle_marked = TRUE;
2594 }
2595 /* jump */
2596 } else {
2597 DrawContext draw_context;
2598
2599 /* Now create the drawing context that will be used to draw
2600 * items related to the last state. */
2601 draw_context.drawable = hashed_process_data->pixmap;
2602 draw_context.gc = drawing->gc;
2603 draw_context.pango_layout = drawing->pango_layout;
2604 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2605 draw_context.drawinfo.end.x = x;
2606
2607 draw_context.drawinfo.y.over = 1;
2608 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2609 draw_context.drawinfo.y.under = hashed_process_data->height;
2610
2611 draw_context.drawinfo.start.offset.over = 0;
2612 draw_context.drawinfo.start.offset.middle = 0;
2613 draw_context.drawinfo.start.offset.under = 0;
2614 draw_context.drawinfo.end.offset.over = 0;
2615 draw_context.drawinfo.end.offset.middle = 0;
2616 draw_context.drawinfo.end.offset.under = 0;
2617
2618 {
2619 /* Draw the line */
2620 PropertiesLine prop_line = prepare_s_e_line(process);
2621 draw_line((void*)&prop_line, (void*)&draw_context);
2622
2623 }
2624 /* become the last x position */
2625 hashed_process_data->x.middle = x;
2626 hashed_process_data->x.middle_used = TRUE;
2627 hashed_process_data->x.middle_marked = FALSE;
2628
2629 /* Calculate the next good time */
2630 convert_pixels_to_time(width, x+1, time_window,
2631 &hashed_process_data->next_good_time);
2632 }
2633 }
2634 }
2635
2636 return 0;
2637 }
2638
2639
2640
2641
2642
2643
2644
2645
2646 #if 0
2647 /* before_process_hook
2648 *
2649 * Draw lines for process event.
2650 *
2651 * @param hook_data ControlFlowData structure of the viewer.
2652 * @param call_data Event context.
2653 *
2654 * This function adds items to be drawn in a queue for each process.
2655 *
2656 */
2657 int before_process_hook(void *hook_data, void *call_data)
2658 {
2659 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2660 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2661 ControlFlowData *control_flow_data = events_request->viewer_data;
2662
2663 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2664
2665 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2666
2667 LttEvent *e;
2668 e = ltt_tracefile_get_event(tfc->tf);
2669
2670 LttTime evtime = ltt_event_time(e);
2671
2672 guint sub_id;
2673 {
2674 LttField *f = ltt_event_field(e);
2675 LttField *element;
2676 element = ltt_field_member(f,0);
2677 sub_id = ltt_event_get_long_unsigned(e,element);
2678 }
2679
2680 if(sub_id == 3) { /* exit */
2681
2682 /* Add process to process list (if not present) */
2683 LttvProcessState *process = tfs->process;
2684 guint pid = process->pid;
2685 LttTime birth;
2686 guint pl_height = 0;
2687 HashedProcessData *hashed_process_data = NULL;
2688
2689 ProcessList *process_list = control_flow_data->process_list;
2690
2691 g_assert(process != NULL);
2692
2693 birth = process->creation_time;
2694
2695 if(likely(process_list->current_hash_data[tfc->index] != NULL)) {
2696 hashed_process_data = process_list->current_hash_data[tfc->index];
2697 } else {
2698 hashed_process_data = processlist_get_process_data(process_list,
2699 pid,
2700 process->last_cpu_index,
2701 &birth,
2702 tfc->t_context->index);
2703 if(unlikely(hashed_process_data == NULL))
2704 {
2705 g_assert(pid == 0 || pid != process->ppid);
2706 /* Process not present */
2707 Drawing_t *drawing = control_flow_data->drawing;
2708 const gchar *name = g_quark_to_string(process->name);
2709 ProcessInfo *process_info;
2710 processlist_add(process_list,
2711 drawing,
2712 pid,
2713 process->last_cpu_index,
2714 process->ppid,
2715 &birth,
2716 tfc->t_context->index,
2717 name,
2718 &pl_height,
2719 &process_info,
2720 &hashed_process_data);
2721 gtk_widget_set_size_request(drawing->drawing_area,
2722 -1,
2723 pl_height);
2724 gtk_widget_queue_draw(drawing->drawing_area);
2725 }
2726 }
2727
2728 /* Now, the process is in the state hash and our own process hash.
2729 * We definitely can draw the items related to the ending state.
2730 */
2731
2732 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2733 evtime) > 0))
2734 {
2735 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2736 TimeWindow time_window =
2737 lttvwindow_get_time_window(control_flow_data->tab);
2738
2739 #ifdef EXTRA_CHECK
2740 if(ltt_time_compare(evtime, time_window.start_time) == -1
2741 || ltt_time_compare(evtime, time_window.end_time) == 1)
2742 return;
2743 #endif //EXTRA_CHECK
2744 Drawing_t *drawing = control_flow_data->drawing;
2745 guint width = drawing->width;
2746 guint x;
2747 convert_time_to_pixels(
2748 time_window,
2749 evtime,
2750 width,
2751 &x);
2752
2753 /* Draw collision indicator */
2754 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2755 gdk_draw_point(hashed_process_data->pixmap,
2756 drawing->gc,
2757 x,
2758 (hashed_process_data->height/2)-3);
2759 hashed_process_data->x.middle_marked = TRUE;
2760 }
2761 } else {
2762 TimeWindow time_window =
2763 lttvwindow_get_time_window(control_flow_data->tab);
2764
2765 #ifdef EXTRA_CHECK
2766 if(ltt_time_compare(evtime, time_window.start_time) == -1
2767 || ltt_time_compare(evtime, time_window.end_time) == 1)
2768 return;
2769 #endif //EXTRA_CHECK
2770 Drawing_t *drawing = control_flow_data->drawing;
2771 guint width = drawing->width;
2772 guint x;
2773
2774 convert_time_to_pixels(
2775 time_window,
2776 evtime,
2777 width,
2778 &x);
2779
2780
2781 /* Jump over draw if we are at the same x position */
2782 if(unlikely(x == hashed_process_data->x.middle &&
2783 hashed_process_data->x.middle_used))
2784 {
2785 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2786 /* Draw collision indicator */
2787 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2788 gdk_draw_point(hashed_process_data->pixmap,
2789 drawing->gc,
2790 x,
2791 (hashed_process_data->height/2)-3);
2792 hashed_process_data->x.middle_marked = TRUE;
2793 }
2794 /* jump */
2795 } else {
2796 DrawContext draw_context;
2797
2798 /* Now create the drawing context that will be used to draw
2799 * items related to the last state. */
2800 draw_context.drawable = hashed_process_data->pixmap;
2801 draw_context.gc = drawing->gc;
2802 draw_context.pango_layout = drawing->pango_layout;
2803 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2804 draw_context.drawinfo.end.x = x;
2805
2806 draw_context.drawinfo.y.over = 1;
2807 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2808 draw_context.drawinfo.y.under = hashed_process_data->height;
2809
2810 draw_context.drawinfo.start.offset.over = 0;
2811 draw_context.drawinfo.start.offset.middle = 0;
2812 draw_context.drawinfo.start.offset.under = 0;
2813 draw_context.drawinfo.end.offset.over = 0;
2814 draw_context.drawinfo.end.offset.middle = 0;
2815 draw_context.drawinfo.end.offset.under = 0;
2816
2817 {
2818 /* Draw the line */
2819 PropertiesLine prop_line = prepare_s_e_line(process);
2820 draw_line((void*)&prop_line, (void*)&draw_context);
2821
2822 }
2823 /* become the last x position */
2824 hashed_process_data->x.middle = x;
2825 hashed_process_data->x.middle_used = TRUE;
2826 hashed_process_data->x.middle_marked = FALSE;
2827
2828 /* Calculate the next good time */
2829 convert_pixels_to_time(width, x+1, time_window,
2830 &hashed_process_data->next_good_time);
2831 }
2832 }
2833
2834 } else if(sub_id == 7) /* release */ {
2835
2836 guint pid;
2837 {
2838 LttField *f = ltt_event_field(e);
2839 LttField *element;
2840 element = ltt_field_member(f,1);
2841 pid = ltt_event_get_long_unsigned(e,element);
2842 }
2843
2844 /* Add process to process list (if not present) */
2845 /* Don't care about the process if it's not in the state hash already :
2846 * that means a process that has never done anything in the trace and
2847 * unknown suddently gets destroyed : no state meaningful to show. */
2848 LttvProcessState *process = lttv_state_find_process(tfs, pid);
2849
2850 if(process != NULL) {
2851 LttTime birth;
2852 guint pl_height = 0;
2853 HashedProcessData *hashed_process_data = NULL;
2854
2855 ProcessList *process_list = control_flow_data->process_list;
2856
2857 birth = process->creation_time;
2858
2859 /* Cannot use current process : this event happens on another process,
2860 * action done by the parent. */
2861 hashed_process_data = processlist_get_process_data(process_list,
2862 pid,
2863 process->last_cpu_index,
2864 &birth,
2865 tfc->t_context->index);
2866 if(unlikely(hashed_process_data == NULL))
2867 {
2868 g_assert(pid == 0 || pid != process->ppid);
2869 /* Process not present */
2870 Drawing_t *drawing = control_flow_data->drawing;
2871 const gchar *name = g_quark_to_string(process->name);
2872 ProcessInfo *process_info;
2873 processlist_add(process_list,
2874 drawing,
2875 pid,
2876 process->last_cpu_index,
2877 process->ppid,
2878 &birth,
2879 tfc->t_context->index,
2880 name,
2881 &pl_height,
2882 &process_info,
2883 &hashed_process_data);
2884 gtk_widget_set_size_request(drawing->drawing_area,
2885 -1,
2886 pl_height);
2887 gtk_widget_queue_draw(drawing->drawing_area);
2888 }
2889
2890 /* Now, the process is in the state hash and our own process hash.
2891 * We definitely can draw the items related to the ending state.
2892 */
2893
2894 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2895 evtime) > 0))
2896 {
2897 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2898 TimeWindow time_window =
2899 lttvwindow_get_time_window(control_flow_data->tab);
2900
2901 #ifdef EXTRA_CHECK
2902 if(ltt_time_compare(evtime, time_window.start_time) == -1
2903 || ltt_time_compare(evtime, time_window.end_time) == 1)
2904 return;
2905 #endif //EXTRA_CHECK
2906 Drawing_t *drawing = control_flow_data->drawing;
2907 guint width = drawing->width;
2908 guint x;
2909 convert_time_to_pixels(
2910 time_window,
2911 evtime,
2912 width,
2913 &x);
2914
2915 /* Draw collision indicator */
2916 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2917 gdk_draw_point(hashed_process_data->pixmap,
2918 drawing->gc,
2919 x,
2920 (hashed_process_data->height/2)-3);
2921 hashed_process_data->x.middle_marked = TRUE;
2922 }
2923 } else {
2924 TimeWindow time_window =
2925 lttvwindow_get_time_window(control_flow_data->tab);
2926
2927 #ifdef EXTRA_CHECK
2928 if(ltt_time_compare(evtime, time_window.start_time) == -1
2929 || ltt_time_compare(evtime, time_window.end_time) == 1)
2930 return;
2931 #endif //EXTRA_CHECK
2932 Drawing_t *drawing = control_flow_data->drawing;
2933 guint width = drawing->width;
2934 guint x;
2935
2936 convert_time_to_pixels(
2937 time_window,
2938 evtime,
2939 width,
2940 &x);
2941
2942
2943 /* Jump over draw if we are at the same x position */
2944 if(unlikely(x == hashed_process_data->x.middle &&
2945 hashed_process_data->x.middle_used))
2946 {
2947 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2948 /* Draw collision indicator */
2949 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2950 gdk_draw_point(hashed_process_data->pixmap,
2951 drawing->gc,
2952 x,
2953 (hashed_process_data->height/2)-3);
2954 hashed_process_data->x.middle_marked = TRUE;
2955 }
2956 /* jump */
2957 } else {
2958 DrawContext draw_context;
2959
2960 /* Now create the drawing context that will be used to draw
2961 * items related to the last state. */
2962 draw_context.drawable = hashed_process_data->pixmap;
2963 draw_context.gc = drawing->gc;
2964 draw_context.pango_layout = drawing->pango_layout;
2965 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2966 draw_context.drawinfo.end.x = x;
2967
2968 draw_context.drawinfo.y.over = 1;
2969 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2970 draw_context.drawinfo.y.under = hashed_process_data->height;
2971
2972 draw_context.drawinfo.start.offset.over = 0;
2973 draw_context.drawinfo.start.offset.middle = 0;
2974 draw_context.drawinfo.start.offset.under = 0;
2975 draw_context.drawinfo.end.offset.over = 0;
2976 draw_context.drawinfo.end.offset.middle = 0;
2977 draw_context.drawinfo.end.offset.under = 0;
2978
2979 {
2980 /* Draw the line */
2981 PropertiesLine prop_line = prepare_s_e_line(process);
2982 draw_line((void*)&prop_line, (void*)&draw_context);
2983
2984 }
2985 /* become the last x position */
2986 hashed_process_data->x.middle = x;
2987 hashed_process_data->x.middle_used = TRUE;
2988 hashed_process_data->x.middle_marked = FALSE;
2989
2990 /* Calculate the next good time */
2991 convert_pixels_to_time(width, x+1, time_window,
2992 &hashed_process_data->next_good_time);
2993 }
2994 }
2995 }
2996
2997 }
2998 return 0;
2999
3000 }
3001
3002 #endif //0
3003
3004
3005
3006 /* after_process_fork_hook
3007 *
3008 * Create the processlist entry for the child process. Put the last
3009 * position in x at the current time value.
3010 *
3011 * @param hook_data ControlFlowData structure of the viewer.
3012 * @param call_data Event context.
3013 *
3014 * This function adds items to be drawn in a queue for each process.
3015 *
3016 */
3017 int after_process_fork_hook(void *hook_data, void *call_data)
3018 {
3019 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3020 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3021 ControlFlowData *control_flow_data = events_request->viewer_data;
3022
3023 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3024
3025 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3026
3027 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3028
3029 LttEvent *e;
3030 e = ltt_tracefile_get_event(tfc->tf);
3031
3032 LttTime evtime = ltt_event_time(e);
3033
3034 guint child_pid;
3035 {
3036 child_pid = ltt_event_get_long_unsigned(e, thf->f2);
3037 }
3038
3039 /* Add process to process list (if not present) */
3040 LttvProcessState *process_child;
3041 LttTime birth;
3042 guint pl_height = 0;
3043 HashedProcessData *hashed_process_data_child = NULL;
3044
3045 ProcessList *process_list = control_flow_data->process_list;
3046
3047 /* Find child in the list... */
3048 process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
3049 /* It should exist, because we are after the state update. */
3050 g_assert(process_child != NULL);
3051
3052 birth = process_child->creation_time;
3053
3054 /* Cannot use current process, because this action is done by the parent
3055 * on its child. */
3056 hashed_process_data_child = processlist_get_process_data(process_list,
3057 child_pid,
3058 process_child->cpu,
3059 &birth,
3060 tfc->t_context->index);
3061 if(likely(hashed_process_data_child == NULL))
3062 {
3063 g_assert(child_pid == 0 || child_pid != process_child->ppid);
3064 /* Process not present */
3065 Drawing_t *drawing = control_flow_data->drawing;
3066 const gchar *name = g_quark_to_string(process_child->name);
3067 ProcessInfo *process_info;
3068 processlist_add(process_list,
3069 drawing,
3070 child_pid,
3071 process_child->cpu,
3072 process_child->ppid,
3073 &birth,
3074 tfc->t_context->index,
3075 name,
3076 &pl_height,
3077 &process_info,
3078 &hashed_process_data_child);
3079 gtk_widget_set_size_request(drawing->drawing_area,
3080 -1,
3081 pl_height);
3082 gtk_widget_queue_draw(drawing->drawing_area);
3083 }
3084
3085
3086 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
3087 evtime) <= 0))
3088 {
3089 TimeWindow time_window =
3090 lttvwindow_get_time_window(control_flow_data->tab);
3091
3092 #ifdef EXTRA_CHECK
3093 if(ltt_time_compare(evtime, time_window.start_time) == -1
3094 || ltt_time_compare(evtime, time_window.end_time) == 1)
3095 return;
3096 #endif //EXTRA_CHECK
3097 Drawing_t *drawing = control_flow_data->drawing;
3098 guint width = drawing->width;
3099 guint new_x;
3100 convert_time_to_pixels(
3101 time_window,
3102 evtime,
3103 width,
3104 &new_x);
3105
3106 if(likely(hashed_process_data_child->x.over != new_x)) {
3107 hashed_process_data_child->x.over = new_x;
3108 hashed_process_data_child->x.over_used = FALSE;
3109 hashed_process_data_child->x.over_marked = FALSE;
3110 }
3111 if(likely(hashed_process_data_child->x.middle != new_x)) {
3112 hashed_process_data_child->x.middle = new_x;
3113 hashed_process_data_child->x.middle_used = FALSE;
3114 hashed_process_data_child->x.middle_marked = FALSE;
3115 }
3116 if(likely(hashed_process_data_child->x.under != new_x)) {
3117 hashed_process_data_child->x.under = new_x;
3118 hashed_process_data_child->x.under_used = FALSE;
3119 hashed_process_data_child->x.under_marked = FALSE;
3120 }
3121 }
3122 return 0;
3123 }
3124
3125
3126
3127 /* after_process_exit_hook
3128 *
3129 * Create the processlist entry for the child process. Put the last
3130 * position in x at the current time value.
3131 *
3132 * @param hook_data ControlFlowData structure of the viewer.
3133 * @param call_data Event context.
3134 *
3135 * This function adds items to be drawn in a queue for each process.
3136 *
3137 */
3138 int after_process_exit_hook(void *hook_data, void *call_data)
3139 {
3140 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3141 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3142 ControlFlowData *control_flow_data = events_request->viewer_data;
3143
3144 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3145
3146 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3147
3148 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3149
3150 LttEvent *e;
3151 e = ltt_tracefile_get_event(tfc->tf);
3152
3153 LttTime evtime = ltt_event_time(e);
3154
3155 /* Add process to process list (if not present) */
3156 //LttvProcessState *process = tfs->process;
3157 guint cpu = ltt_tracefile_num(tfc->tf);
3158 LttvProcessState *process = ts->running_process[cpu];
3159
3160 /* It should exist, because we are after the state update. */
3161 g_assert(process != NULL);
3162
3163 guint pid = process->pid;
3164 LttTime birth;
3165 guint pl_height = 0;
3166 HashedProcessData *hashed_process_data = NULL;
3167
3168 ProcessList *process_list = control_flow_data->process_list;
3169
3170 birth = process->creation_time;
3171
3172 if(likely(process_list->current_hash_data[cpu] != NULL) ){
3173 hashed_process_data = process_list->current_hash_data[cpu];
3174 } else {
3175 hashed_process_data = processlist_get_process_data(process_list,
3176 pid,
3177 process->cpu,
3178 &birth,
3179 tfc->t_context->index);
3180 if(unlikely(hashed_process_data == NULL))
3181 {
3182 g_assert(pid == 0 || pid != process->ppid);
3183 /* Process not present */
3184 Drawing_t *drawing = control_flow_data->drawing;
3185 const gchar *name = g_quark_to_string(process->name);
3186 ProcessInfo *process_info;
3187 processlist_add(process_list,
3188 drawing,
3189 pid,
3190 process->cpu,
3191 process->ppid,
3192 &birth,
3193 tfc->t_context->index,
3194 name,
3195 &pl_height,
3196 &process_info,
3197 &hashed_process_data);
3198 gtk_widget_set_size_request(drawing->drawing_area,
3199 -1,
3200 pl_height);
3201 gtk_widget_queue_draw(drawing->drawing_area);
3202 }
3203
3204 /* Set the current process */
3205 process_list->current_hash_data[process->cpu] =
3206 hashed_process_data;
3207 }
3208
3209 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3210 evtime) <= 0))
3211 {
3212 TimeWindow time_window =
3213 lttvwindow_get_time_window(control_flow_data->tab);
3214
3215 #ifdef EXTRA_CHECK
3216 if(ltt_time_compare(evtime, time_window.start_time) == -1
3217 || ltt_time_compare(evtime, time_window.end_time) == 1)
3218 return;
3219 #endif //EXTRA_CHECK
3220 Drawing_t *drawing = control_flow_data->drawing;
3221 guint width = drawing->width;
3222 guint new_x;
3223 convert_time_to_pixels(
3224 time_window,
3225 evtime,
3226 width,
3227 &new_x);
3228 if(unlikely(hashed_process_data->x.middle != new_x)) {
3229 hashed_process_data->x.middle = new_x;
3230 hashed_process_data->x.middle_used = FALSE;
3231 hashed_process_data->x.middle_marked = FALSE;
3232 }
3233 }
3234
3235 return 0;
3236 }
3237
3238
3239 #if 0
3240
3241 /* after_process_hook
3242 *
3243 * Create the processlist entry for the child process. Put the last
3244 * position in x at the current time value.
3245 *
3246 * @param hook_data ControlFlowData structure of the viewer.
3247 * @param call_data Event context.
3248 *
3249 * This function adds items to be drawn in a queue for each process.
3250 *
3251 */
3252 int after_process_hook(void *hook_data, void *call_data)
3253 {
3254 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3255 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3256 ControlFlowData *control_flow_data = events_request->viewer_data;
3257
3258 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3259
3260 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3261
3262 LttEvent *e;
3263 e = ltt_tracefile_get_event(tfc->tf);
3264
3265 LttTime evtime = ltt_event_time(e);
3266
3267 guint sub_id;
3268 guint param1;
3269 {
3270 LttField *f = ltt_event_field(e);
3271 LttField *element;
3272 element = ltt_field_member(f,0);
3273 sub_id = ltt_event_get_long_unsigned(e,element);
3274 element = ltt_field_member(f,1);
3275 param1 = ltt_event_get_long_unsigned(e,element);
3276 }
3277
3278 if(sub_id == 2) { /* fork */
3279
3280 guint child_pid = param1;
3281 /* Add process to process list (if not present) */
3282 LttvProcessState *process_child;
3283 LttTime birth;
3284 guint pl_height = 0;
3285 HashedProcessData *hashed_process_data_child = NULL;
3286
3287 ProcessList *process_list = control_flow_data->process_list;
3288
3289 /* Find child in the list... */
3290 process_child = lttv_state_find_process(tfs, child_pid);
3291 /* It should exist, because we are after the state update. */
3292 g_assert(process_child != NULL);
3293
3294 birth = process_child->creation_time;
3295
3296 /* Cannot use current process, because this action is done by the parent
3297 * on its child. */
3298 hashed_process_data_child = processlist_get_process_data(process_list,
3299 child_pid,
3300 process_child->last_cpu_index,
3301 &birth,
3302 tfc->t_context->index);
3303 if(likely(hashed_process_data_child == NULL))
3304 {
3305 g_assert(child_pid == 0 || child_pid != process_child->ppid);
3306 /* Process not present */
3307 Drawing_t *drawing = control_flow_data->drawing;
3308 const gchar *name = g_quark_to_string(process_child->name);
3309 ProcessInfo *process_info;
3310 processlist_add(process_list,
3311 drawing,
3312 child_pid,
3313 process_child->last_cpu_index,
3314 process_child->ppid,
3315 &birth,
3316 tfc->t_context->index,
3317 name,
3318 &pl_height,
3319 &process_info,
3320 &hashed_process_data_child);
3321 gtk_widget_set_size_request(drawing->drawing_area,
3322 -1,
3323 pl_height);
3324 gtk_widget_queue_draw(drawing->drawing_area);
3325 }
3326
3327
3328 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
3329 evtime) <= 0))
3330 {
3331 TimeWindow time_window =
3332 lttvwindow_get_time_window(control_flow_data->tab);
3333
3334 #ifdef EXTRA_CHECK
3335 if(ltt_time_compare(evtime, time_window.start_time) == -1
3336 || ltt_time_compare(evtime, time_window.end_time) == 1)
3337 return;
3338 #endif //EXTRA_CHECK
3339 Drawing_t *drawing = control_flow_data->drawing;
3340 guint width = drawing->width;
3341 guint new_x;
3342 convert_time_to_pixels(
3343 time_window,
3344 evtime,
3345 width,
3346 &new_x);
3347
3348 if(likely(hashed_process_data_child->x.over != new_x)) {
3349 hashed_process_data_child->x.over = new_x;
3350 hashed_process_data_child->x.over_used = FALSE;
3351 hashed_process_data_child->x.over_marked = FALSE;
3352 }
3353 if(likely(hashed_process_data_child->x.middle != new_x)) {
3354 hashed_process_data_child->x.middle = new_x;
3355 hashed_process_data_child->x.middle_used = FALSE;
3356 hashed_process_data_child->x.middle_marked = FALSE;
3357 }
3358 if(likely(hashed_process_data_child->x.under != new_x)) {
3359 hashed_process_data_child->x.under = new_x;
3360 hashed_process_data_child->x.under_used = FALSE;
3361 hashed_process_data_child->x.under_marked = FALSE;
3362 }
3363 }
3364
3365 } else if(sub_id == 3) { /* exit */
3366
3367 /* Add process to process list (if not present) */
3368 LttvProcessState *process = tfs->process;
3369 guint pid = process->pid;
3370 LttTime birth;
3371 guint pl_height = 0;
3372 HashedProcessData *hashed_process_data = NULL;
3373
3374 ProcessList *process_list = control_flow_data->process_list;
3375
3376 /* It should exist, because we are after the state update. */
3377 g_assert(process != NULL);
3378
3379 birth = process->creation_time;
3380
3381 if(likely(process_list->current_hash_data[ltt_tracefile_num(tfc->tf)] != NULL) ){
3382 hashed_process_data = process_list->current_hash_data[ltt_tracefile_num(tfc->tf)];
3383 } else {
3384 hashed_process_data = processlist_get_process_data(process_list,
3385 pid,
3386 process->last_cpu_index,
3387 &birth,
3388 tfc->t_context->index);
3389 if(unlikely(hashed_process_data == NULL))
3390 {
3391 g_assert(pid == 0 || pid != process->ppid);
3392 /* Process not present */
3393 Drawing_t *drawing = control_flow_data->drawing;
3394 const gchar *name = g_quark_to_string(process->name);
3395 ProcessInfo *process_info;
3396 processlist_add(process_list,
3397 drawing,
3398 pid,
3399 process->last_cpu_index,
3400 process->ppid,
3401 &birth,
3402 tfc->t_context->index,
3403 name,
3404 &pl_height,
3405 &process_info,
3406 &hashed_process_data);
3407 gtk_widget_set_size_request(drawing->drawing_area,
3408 -1,
3409 pl_height);
3410 gtk_widget_queue_draw(drawing->drawing_area);
3411 }
3412
3413 /* Set the current process */
3414 process_list->current_hash_data[process->last_cpu_index] =
3415 hashed_process_data;
3416 }
3417
3418 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3419 evtime) <= 0))
3420 {
3421 TimeWindow time_window =
3422 lttvwindow_get_time_window(control_flow_data->tab);
3423
3424 #ifdef EXTRA_CHECK
3425 if(ltt_time_compare(evtime, time_window.start_time) == -1
3426 || ltt_time_compare(evtime, time_window.end_time) == 1)
3427 return;
3428 #endif //EXTRA_CHECK
3429 Drawing_t *drawing = control_flow_data->drawing;
3430 guint width = drawing->width;
3431 guint new_x;
3432 convert_time_to_pixels(
3433 time_window,
3434 evtime,
3435 width,
3436 &new_x);
3437 if(unlikely(hashed_process_data->x.middle != new_x)) {
3438 hashed_process_data->x.middle = new_x;
3439 hashed_process_data->x.middle_used = FALSE;
3440 hashed_process_data->x.middle_marked = FALSE;
3441 }
3442 }
3443
3444 }
3445 return 0;
3446
3447 }
3448 #endif //0
3449
3450 gint update_time_window_hook(void *hook_data, void *call_data)
3451 {
3452 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3453 Drawing_t *drawing = control_flow_data->drawing;
3454 ProcessList *process_list = control_flow_data->process_list;
3455
3456 const TimeWindowNotifyData *time_window_nofify_data =
3457 ((const TimeWindowNotifyData *)call_data);
3458
3459 TimeWindow *old_time_window =
3460 time_window_nofify_data->old_time_window;
3461 TimeWindow *new_time_window =
3462 time_window_nofify_data->new_time_window;
3463
3464 /* Update the ruler */
3465 drawing_update_ruler(control_flow_data->drawing,
3466 new_time_window);
3467
3468
3469 /* Two cases : zoom in/out or scrolling */
3470
3471 /* In order to make sure we can reuse the old drawing, the scale must
3472 * be the same and the new time interval being partly located in the
3473 * currently shown time interval. (reuse is only for scrolling)
3474 */
3475
3476 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
3477 old_time_window->start_time.tv_sec,
3478 old_time_window->start_time.tv_nsec,
3479 old_time_window->time_width.tv_sec,
3480 old_time_window->time_width.tv_nsec);
3481
3482 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
3483 new_time_window->start_time.tv_sec,
3484 new_time_window->start_time.tv_nsec,
3485 new_time_window->time_width.tv_sec,
3486 new_time_window->time_width.tv_nsec);
3487
3488 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
3489 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
3490 {
3491 /* Same scale (scrolling) */
3492 g_info("scrolling");
3493 LttTime *ns = &new_time_window->start_time;
3494 LttTime *nw = &new_time_window->time_width;
3495 LttTime *os = &old_time_window->start_time;
3496 LttTime *ow = &old_time_window->time_width;
3497 LttTime old_end = old_time_window->end_time;
3498 LttTime new_end = new_time_window->end_time;
3499 //if(ns<os+w<ns+w)
3500 //if(ns<os+w && os+w<ns+w)
3501 //if(ns<old_end && os<ns)
3502 if(ltt_time_compare(*ns, old_end) == -1
3503 && ltt_time_compare(*os, *ns) == -1)
3504 {
3505 g_info("scrolling near right");
3506 /* Scroll right, keep right part of the screen */
3507 guint x = 0;
3508 guint width = control_flow_data->drawing->width;
3509 convert_time_to_pixels(
3510 *old_time_window,
3511 *ns,
3512 width,
3513 &x);
3514
3515 /* Copy old data to new location */
3516 copy_pixmap_region(process_list,
3517 NULL,
3518 control_flow_data->drawing->drawing_area->style->black_gc,
3519 NULL,
3520 x, 0,
3521 0, 0,
3522 control_flow_data->drawing->width-x+SAFETY, -1);
3523
3524 if(drawing->damage_begin == drawing->damage_end)
3525 drawing->damage_begin = control_flow_data->drawing->width-x;
3526 else
3527 drawing->damage_begin = 0;
3528
3529 drawing->damage_end = control_flow_data->drawing->width;
3530
3531 /* Clear the data request background, but not SAFETY */
3532 rectangle_pixmap(process_list,
3533 control_flow_data->drawing->drawing_area->style->black_gc,
3534 TRUE,
3535 drawing->damage_begin+SAFETY, 0,
3536 drawing->damage_end - drawing->damage_begin, // do not overlap
3537 -1);
3538 gtk_widget_queue_draw(drawing->drawing_area);
3539 //gtk_widget_queue_draw_area (drawing->drawing_area,
3540 // 0,0,
3541 // control_flow_data->drawing->width,
3542 // control_flow_data->drawing->height);
3543
3544 /* Get new data for the rest. */
3545 drawing_data_request(control_flow_data->drawing,
3546 drawing->damage_begin, 0,
3547 drawing->damage_end - drawing->damage_begin,
3548 control_flow_data->drawing->height);
3549 } else {
3550 //if(ns<os<ns+w)
3551 //if(ns<os && os<ns+w)
3552 //if(ns<os && os<new_end)
3553 if(ltt_time_compare(*ns,*os) == -1
3554 && ltt_time_compare(*os,new_end) == -1)
3555 {
3556 g_info("scrolling near left");
3557 /* Scroll left, keep left part of the screen */
3558 guint x = 0;
3559 guint width = control_flow_data->drawing->width;
3560 convert_time_to_pixels(
3561 *new_time_window,
3562 *os,
3563 width,
3564 &x);
3565
3566 /* Copy old data to new location */
3567 copy_pixmap_region (process_list,
3568 NULL,
3569 control_flow_data->drawing->drawing_area->style->black_gc,
3570 NULL,
3571 0, 0,
3572 x, 0,
3573 -1, -1);
3574
3575 if(drawing->damage_begin == drawing->damage_end)
3576 drawing->damage_end = x;
3577 else
3578 drawing->damage_end =
3579 control_flow_data->drawing->width;
3580
3581 drawing->damage_begin = 0;
3582
3583 rectangle_pixmap (process_list,
3584 control_flow_data->drawing->drawing_area->style->black_gc,
3585 TRUE,
3586 drawing->damage_begin, 0,
3587 drawing->damage_end - drawing->damage_begin, // do not overlap
3588 -1);
3589
3590 gtk_widget_queue_draw(drawing->drawing_area);
3591 //gtk_widget_queue_draw_area (drawing->drawing_area,
3592 // 0,0,
3593 // control_flow_data->drawing->width,
3594 // control_flow_data->drawing->height);
3595
3596
3597 /* Get new data for the rest. */
3598 drawing_data_request(control_flow_data->drawing,
3599 drawing->damage_begin, 0,
3600 drawing->damage_end - drawing->damage_begin,
3601 control_flow_data->drawing->height);
3602
3603 } else {
3604 if(ltt_time_compare(*ns,*os) == 0)
3605 {
3606 g_info("not scrolling");
3607 } else {
3608 g_info("scrolling far");
3609 /* Cannot reuse any part of the screen : far jump */
3610
3611
3612 rectangle_pixmap (process_list,
3613 control_flow_data->drawing->drawing_area->style->black_gc,
3614 TRUE,
3615 0, 0,
3616 control_flow_data->drawing->width+SAFETY, // do not overlap
3617 -1);
3618
3619 //gtk_widget_queue_draw_area (drawing->drawing_area,
3620 // 0,0,
3621 // control_flow_data->drawing->width,
3622 // control_flow_data->drawing->height);
3623 gtk_widget_queue_draw(drawing->drawing_area);
3624
3625 drawing->damage_begin = 0;
3626 drawing->damage_end = control_flow_data->drawing->width;
3627
3628 drawing_data_request(control_flow_data->drawing,
3629 0, 0,
3630 control_flow_data->drawing->width,
3631 control_flow_data->drawing->height);
3632
3633 }
3634 }
3635 }
3636 } else {
3637 /* Different scale (zoom) */
3638 g_info("zoom");
3639
3640 rectangle_pixmap (process_list,
3641 control_flow_data->drawing->drawing_area->style->black_gc,
3642 TRUE,
3643 0, 0,
3644 control_flow_data->drawing->width+SAFETY, // do not overlap
3645 -1);
3646
3647 //gtk_widget_queue_draw_area (drawing->drawing_area,
3648 // 0,0,
3649 // control_flow_data->drawing->width,
3650 // control_flow_data->drawing->height);
3651 gtk_widget_queue_draw(drawing->drawing_area);
3652
3653 drawing->damage_begin = 0;
3654 drawing->damage_end = control_flow_data->drawing->width;
3655
3656 drawing_data_request(control_flow_data->drawing,
3657 0, 0,
3658 control_flow_data->drawing->width,
3659 control_flow_data->drawing->height);
3660 }
3661
3662
3663
3664 return 0;
3665 }
3666
3667 gint traceset_notify(void *hook_data, void *call_data)
3668 {
3669 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3670 Drawing_t *drawing = control_flow_data->drawing;
3671
3672
3673 drawing_clear(control_flow_data->drawing);
3674 processlist_clear(control_flow_data->process_list);
3675 gtk_widget_set_size_request(
3676 control_flow_data->drawing->drawing_area,
3677 -1, processlist_get_height(control_flow_data->process_list));
3678 redraw_notify(control_flow_data, NULL);
3679
3680 request_background_data(control_flow_data);
3681
3682 return FALSE;
3683 }
3684
3685 gint redraw_notify(void *hook_data, void *call_data)
3686 {
3687 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3688 Drawing_t *drawing = control_flow_data->drawing;
3689 GtkWidget *widget = drawing->drawing_area;
3690
3691 drawing->damage_begin = 0;
3692 drawing->damage_end = drawing->width;
3693
3694 /* fun feature, to be separated someday... */
3695 drawing_clear(control_flow_data->drawing);
3696 processlist_clear(control_flow_data->process_list);
3697 gtk_widget_set_size_request(
3698 control_flow_data->drawing->drawing_area,
3699 -1, processlist_get_height(control_flow_data->process_list));
3700 // Clear the images
3701 rectangle_pixmap (control_flow_data->process_list,
3702 widget->style->black_gc,
3703 TRUE,
3704 0, 0,
3705 drawing->alloc_width,
3706 -1);
3707
3708 gtk_widget_queue_draw(drawing->drawing_area);
3709
3710 if(drawing->damage_begin < drawing->damage_end)
3711 {
3712 drawing_data_request(drawing,
3713 drawing->damage_begin,
3714 0,
3715 drawing->damage_end-drawing->damage_begin,
3716 drawing->height);
3717 }
3718
3719 //gtk_widget_queue_draw_area(drawing->drawing_area,
3720 // 0,0,
3721 // drawing->width,
3722 // drawing->height);
3723 return FALSE;
3724
3725 }
3726
3727
3728 gint continue_notify(void *hook_data, void *call_data)
3729 {
3730 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3731 Drawing_t *drawing = control_flow_data->drawing;
3732
3733 //g_assert(widget->allocation.width == drawing->damage_end);
3734
3735 if(drawing->damage_begin < drawing->damage_end)
3736 {
3737 drawing_data_request(drawing,
3738 drawing->damage_begin,
3739 0,
3740 drawing->damage_end-drawing->damage_begin,
3741 drawing->height);
3742 }
3743
3744 return FALSE;
3745 }
3746
3747
3748 gint update_current_time_hook(void *hook_data, void *call_data)
3749 {
3750 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
3751 Drawing_t *drawing = control_flow_data->drawing;
3752
3753 LttTime current_time = *((LttTime*)call_data);
3754
3755 TimeWindow time_window =
3756 lttvwindow_get_time_window(control_flow_data->tab);
3757
3758 LttTime time_begin = time_window.start_time;
3759 LttTime width = time_window.time_width;
3760 LttTime half_width;
3761 {
3762 guint64 time_ll = ltt_time_to_uint64(width);
3763 time_ll = time_ll >> 1; /* divide by two */
3764 half_width = ltt_time_from_uint64(time_ll);
3765 }
3766 LttTime time_end = ltt_time_add(time_begin, width);
3767
3768 LttvTracesetContext * tsc =
3769 lttvwindow_get_traceset_context(control_flow_data->tab);
3770
3771 LttTime trace_start = tsc->time_span.start_time;
3772 LttTime trace_end = tsc->time_span.end_time;
3773
3774 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
3775 current_time.tv_nsec);
3776
3777
3778
3779 /* If current time is inside time interval, just move the highlight
3780 * bar */
3781
3782 /* Else, we have to change the time interval. We have to tell it
3783 * to the main window. */
3784 /* The time interval change will take care of placing the current
3785 * time at the center of the visible area, or nearest possible if we are
3786 * at one end of the trace. */
3787
3788
3789 if(ltt_time_compare(current_time, time_begin) < 0)
3790 {
3791 TimeWindow new_time_window;
3792
3793 if(ltt_time_compare(current_time,
3794 ltt_time_add(trace_start,half_width)) < 0)
3795 time_begin = trace_start;
3796 else
3797 time_begin = ltt_time_sub(current_time,half_width);
3798
3799 new_time_window.start_time = time_begin;
3800 new_time_window.time_width = width;
3801 new_time_window.time_width_double = ltt_time_to_double(width);
3802 new_time_window.end_time = ltt_time_add(time_begin, width);
3803
3804 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3805 }
3806 else if(ltt_time_compare(current_time, time_end) > 0)
3807 {
3808 TimeWindow new_time_window;
3809
3810 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
3811 time_begin = ltt_time_sub(trace_end,width);
3812 else
3813 time_begin = ltt_time_sub(current_time,half_width);
3814
3815 new_time_window.start_time = time_begin;
3816 new_time_window.time_width = width;
3817 new_time_window.time_width_double = ltt_time_to_double(width);
3818 new_time_window.end_time = ltt_time_add(time_begin, width);
3819
3820 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3821
3822 }
3823 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
3824
3825
3826 return 0;
3827 }
3828
3829 typedef struct _ClosureData {
3830 EventsRequest *events_request;
3831 LttvTracesetState *tss;
3832 LttTime end_time;
3833 guint x_end;
3834 } ClosureData;
3835
3836
3837 void draw_closure(gpointer key, gpointer value, gpointer user_data)
3838 {
3839 ProcessInfo *process_info = (ProcessInfo*)key;
3840 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
3841 ClosureData *closure_data = (ClosureData*)user_data;
3842
3843 EventsRequest *events_request = closure_data->events_request;
3844 ControlFlowData *control_flow_data = events_request->viewer_data;
3845
3846 LttvTracesetState *tss = closure_data->tss;
3847 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
3848
3849 LttTime evtime = closure_data->end_time;
3850
3851 {
3852 /* For the process */
3853 /* First, check if the current process is in the state computation
3854 * process list. If it is there, that means we must add it right now and
3855 * draw items from the beginning of the read for it. If it is not
3856 * present, it's a new process and it was not present : it will
3857 * be added after the state update. */
3858 #ifdef EXTRA_CHECK
3859 g_assert(lttv_traceset_number(tsc->ts) > 0);
3860 #endif //EXTRA_CHECK
3861 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
3862 LttvTraceState *ts = (LttvTraceState*)tc;
3863
3864 #if 0
3865 //FIXME : optimize data structures.
3866 LttvTracefileState *tfs;
3867 LttvTracefileContext *tfc;
3868 guint i;
3869 for(i=0;i<tc->tracefiles->len;i++) {
3870 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
3871 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
3872 && ltt_tracefile_num(tfc->tf) == process_info->cpu)
3873 break;
3874
3875 }
3876 g_assert(i<tc->tracefiles->len);
3877 tfs = LTTV_TRACEFILE_STATE(tfc);
3878 #endif //0
3879 // LttvTracefileState *tfs =
3880 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
3881 // tracefiles[process_info->cpu];
3882
3883 LttvProcessState *process;
3884 process = lttv_state_find_process(ts, process_info->cpu,
3885 process_info->pid);
3886
3887 if(unlikely(process != NULL)) {
3888
3889 /* Only draw for processes that are currently in the trace states */
3890
3891 ProcessList *process_list = control_flow_data->process_list;
3892 #ifdef EXTRA_CHECK
3893 /* Should be alike when background info is ready */
3894 if(control_flow_data->background_info_waiting==0)
3895 g_assert(ltt_time_compare(process->creation_time,
3896 process_info->birth) == 0);
3897 #endif //EXTRA_CHECK
3898
3899 /* Now, the process is in the state hash and our own process hash.
3900 * We definitely can draw the items related to the ending state.
3901 */
3902
3903 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3904 evtime) <= 0))
3905 {
3906 TimeWindow time_window =
3907 lttvwindow_get_time_window(control_flow_data->tab);
3908
3909 #ifdef EXTRA_CHECK
3910 if(ltt_time_compare(evtime, time_window.start_time) == -1
3911 || ltt_time_compare(evtime, time_window.end_time) == 1)
3912 return;
3913 #endif //EXTRA_CHECK
3914 Drawing_t *drawing = control_flow_data->drawing;
3915 guint width = drawing->width;
3916
3917 guint x = closure_data->x_end;
3918
3919 DrawContext draw_context;
3920
3921 /* Now create the drawing context that will be used to draw
3922 * items related to the last state. */
3923 draw_context.drawable = hashed_process_data->pixmap;
3924 draw_context.gc = drawing->gc;
3925 draw_context.pango_layout = drawing->pango_layout;
3926 draw_context.drawinfo.end.x = x;
3927
3928 draw_context.drawinfo.y.over = 1;
3929 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
3930 draw_context.drawinfo.y.under = hashed_process_data->height;
3931
3932 draw_context.drawinfo.start.offset.over = 0;
3933 draw_context.drawinfo.start.offset.middle = 0;
3934 draw_context.drawinfo.start.offset.under = 0;
3935 draw_context.drawinfo.end.offset.over = 0;
3936 draw_context.drawinfo.end.offset.middle = 0;
3937 draw_context.drawinfo.end.offset.under = 0;
3938 #if 0
3939 /* Jump over draw if we are at the same x position */
3940 if(x == hashed_process_data->x.over)
3941 {
3942 /* jump */
3943 } else {
3944 draw_context.drawinfo.start.x = hashed_process_data->x.over;
3945 /* Draw the line */
3946 PropertiesLine prop_line = prepare_execmode_line(process);
3947 draw_line((void*)&prop_line, (void*)&draw_context);
3948
3949 hashed_process_data->x.over = x;
3950 }
3951 #endif //0
3952
3953 if(unlikely(x == hashed_process_data->x.middle &&
3954 hashed_process_data->x.middle_used)) {
3955 #if 0 /* do not mark closure : not missing information */
3956 if(hashed_process_data->x.middle_marked == FALSE) {
3957 /* Draw collision indicator */
3958 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
3959 gdk_draw_point(drawing->pixmap,
3960 drawing->gc,
3961 x,
3962 y+(height/2)-3);
3963 hashed_process_data->x.middle_marked = TRUE;
3964 }
3965 #endif //0
3966 /* Jump */
3967 } else {
3968 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
3969 /* Draw the line */
3970 PropertiesLine prop_line = prepare_s_e_line(process);
3971 draw_line((void*)&prop_line, (void*)&draw_context);
3972
3973 /* become the last x position */
3974 if(likely(x != hashed_process_data->x.middle)) {
3975 hashed_process_data->x.middle = x;
3976 /* but don't use the pixel */
3977 hashed_process_data->x.middle_used = FALSE;
3978
3979 /* Calculate the next good time */
3980 convert_pixels_to_time(width, x+1, time_window,
3981 &hashed_process_data->next_good_time);
3982 }
3983 }
3984 }
3985 }
3986 }
3987 return;
3988 }
3989
3990 int before_chunk(void *hook_data, void *call_data)
3991 {
3992 EventsRequest *events_request = (EventsRequest*)hook_data;
3993 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3994 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
3995 #if 0
3996 /* Desactivate sort */
3997 gtk_tree_sortable_set_sort_column_id(
3998 GTK_TREE_SORTABLE(cfd->process_list->list_store),
3999 TRACE_COLUMN,
4000 GTK_SORT_ASCENDING);
4001 #endif //0
4002 drawing_chunk_begin(events_request, tss);
4003
4004 return 0;
4005 }
4006
4007 int before_request(void *hook_data, void *call_data)
4008 {
4009 EventsRequest *events_request = (EventsRequest*)hook_data;
4010 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4011
4012 drawing_data_request_begin(events_request, tss);
4013
4014 return 0;
4015 }
4016
4017
4018 /*
4019 * after request is necessary in addition of after chunk in order to draw
4020 * lines until the end of the screen. after chunk just draws lines until
4021 * the last event.
4022 *
4023 * for each process
4024 * draw closing line
4025 * expose
4026 */
4027 int after_request(void *hook_data, void *call_data)
4028 {
4029 EventsRequest *events_request = (EventsRequest*)hook_data;
4030 ControlFlowData *control_flow_data = events_request->viewer_data;
4031 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4032
4033 ProcessList *process_list = control_flow_data->process_list;
4034 LttTime end_time = events_request->end_time;
4035
4036 ClosureData closure_data;
4037 closure_data.events_request = (EventsRequest*)hook_data;
4038 closure_data.tss = tss;
4039 closure_data.end_time = end_time;
4040
4041 TimeWindow time_window =
4042 lttvwindow_get_time_window(control_flow_data->tab);
4043 guint width = control_flow_data->drawing->width;
4044 convert_time_to_pixels(
4045 time_window,
4046 end_time,
4047 width,
4048 &closure_data.x_end);
4049
4050
4051 /* Draw last items */
4052 g_hash_table_foreach(process_list->process_hash, draw_closure,
4053 (void*)&closure_data);
4054
4055
4056 /* Request expose */
4057 drawing_request_expose(events_request, tss, end_time);
4058 return 0;
4059 }
4060
4061 /*
4062 * for each process
4063 * draw closing line
4064 * expose
4065 */
4066 int after_chunk(void *hook_data, void *call_data)
4067 {
4068 EventsRequest *events_request = (EventsRequest*)hook_data;
4069 ControlFlowData *control_flow_data = events_request->viewer_data;
4070 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4071 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
4072 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
4073 LttTime end_time;
4074
4075 ProcessList *process_list = control_flow_data->process_list;
4076
4077 g_free(process_list->current_hash_data);
4078 process_list->current_hash_data = NULL;
4079
4080 if(tfc != NULL)
4081 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
4082 else /* end of traceset, or position now out of request : end */
4083 end_time = events_request->end_time;
4084
4085 ClosureData closure_data;
4086 closure_data.events_request = (EventsRequest*)hook_data;
4087 closure_data.tss = tss;
4088 closure_data.end_time = end_time;
4089
4090 TimeWindow time_window =
4091 lttvwindow_get_time_window(control_flow_data->tab);
4092 guint width = control_flow_data->drawing->width;
4093 convert_time_to_pixels(
4094 time_window,
4095 end_time,
4096 width,
4097 &closure_data.x_end);
4098
4099 /* Draw last items */
4100 g_hash_table_foreach(process_list->process_hash, draw_closure,
4101 (void*)&closure_data);
4102 #if 0
4103 /* Reactivate sort */
4104 gtk_tree_sortable_set_sort_column_id(
4105 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
4106 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
4107 GTK_SORT_ASCENDING);
4108
4109 update_index_to_pixmap(control_flow_data->process_list);
4110 /* Request a full expose : drawing scrambled */
4111 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
4112 #endif //0
4113 /* Request expose (updates damages zone also) */
4114 drawing_request_expose(events_request, tss, end_time);
4115
4116 return 0;
4117 }
4118
This page took 0.11742 seconds and 4 git commands to generate.