statistics working : still must add stats per time feature to graphical view
[lttv.git] / ltt / branches / poly / lttv / modules / gui / controlflow / eventhooks.c
... / ...
CommitLineData
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
83typedef struct _ProcessAddClosure {
84 ControlFlowData *cfd;
85 guint trace_num;
86} ProcessAddClosure;
87
88static 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
143gint 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 */
168void 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 */
234GtkWidget *
235h_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
266int 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 */
277static 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
321static 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
379int 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,
419 ltt_tracefile_num(tfc->tf), pid_out);
420
421 if(process != NULL) {
422 /* Well, the process_out existed : we must get it in the process hash
423 * or add it, and draw its items.
424 */
425 /* Add process to process list (if not present) */
426 guint pl_height = 0;
427 HashedProcessData *hashed_process_data = NULL;
428 ProcessList *process_list = control_flow_data->process_list;
429 LttTime birth = process->creation_time;
430
431 hashed_process_data = processlist_get_process_data(process_list,
432 pid_out,
433 process->cpu,
434 &birth,
435 tfc->t_context->index);
436 if(hashed_process_data == NULL)
437 {
438 g_assert(pid_out == 0 || pid_out != process->ppid);
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 process->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,
575 ltt_tracefile_num(tfc->tf), pid_in);
576
577 if(process != NULL) {
578 /* Well, the process existed : we must get it in the process hash
579 * or add it, and draw its items.
580 */
581 /* Add process to process list (if not present) */
582 guint pl_height = 0;
583 HashedProcessData *hashed_process_data = NULL;
584 ProcessList *process_list = control_flow_data->process_list;
585 LttTime birth = process->creation_time;
586
587 hashed_process_data = processlist_get_process_data(process_list,
588 pid_in,
589 process->cpu,
590 &birth,
591 tfc->t_context->index);
592 if(hashed_process_data == NULL)
593 {
594 g_assert(pid_in == 0 || pid_in != process->ppid);
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 process->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 */
1346int 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 ProcessInfo *process_info;
1399 Drawing_t *drawing = control_flow_data->drawing;
1400 /* Process not present */
1401 processlist_add(process_list,
1402 drawing,
1403 pid_in,
1404 process_in->cpu,
1405 process_in->ppid,
1406 &birth,
1407 tfc->t_context->index,
1408 process_in->name,
1409 &pl_height,
1410 &process_info,
1411 &hashed_process_data_in);
1412 gtk_widget_set_size_request(drawing->drawing_area,
1413 -1,
1414 pl_height);
1415 gtk_widget_queue_draw(drawing->drawing_area);
1416 }
1417 /* Set the current process */
1418 process_list->current_hash_data[process_in->cpu] =
1419 hashed_process_data_in;
1420
1421 if(ltt_time_compare(hashed_process_data_in->next_good_time,
1422 evtime) <= 0)
1423 {
1424 TimeWindow time_window =
1425 lttvwindow_get_time_window(control_flow_data->tab);
1426
1427#ifdef EXTRA_CHECK
1428 if(ltt_time_compare(evtime, time_window.start_time) == -1
1429 || ltt_time_compare(evtime, time_window.end_time) == 1)
1430 return;
1431#endif //EXTRA_CHECK
1432 Drawing_t *drawing = control_flow_data->drawing;
1433 guint width = drawing->width;
1434 guint new_x;
1435
1436 convert_time_to_pixels(
1437 time_window,
1438 evtime,
1439 width,
1440 &new_x);
1441
1442 if(hashed_process_data_in->x.middle != new_x) {
1443 hashed_process_data_in->x.middle = new_x;
1444 hashed_process_data_in->x.middle_used = FALSE;
1445 hashed_process_data_in->x.middle_marked = FALSE;
1446 }
1447 }
1448 return 0;
1449
1450
1451
1452
1453
1454#if 0
1455 EventsRequest *events_request = (EventsRequest*)hook_data;
1456 ControlFlowData *control_flow_data = events_request->viewer_data;
1457
1458 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1459
1460 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1461 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1462
1463
1464 LttEvent *e;
1465 e = tfc->e;
1466
1467 LttTime evtime = ltt_event_time(e);
1468 TimeWindow time_window =
1469 lttvwindow_get_time_window(control_flow_data->tab);
1470
1471 LttTime time_window.end_time = time_window.time_window.end_time;
1472
1473 //if(time < time_beg || time > time_end) return;
1474 if(ltt_time_compare(evtime, time_window.start_time) == -1
1475 || ltt_time_compare(evtime, time_window.end_time) == 1)
1476 return;
1477
1478
1479 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1480 {
1481 g_debug("schedchange!");
1482
1483 /* Add process to process list (if not present) and get drawing "y" from
1484 * process position */
1485 guint pid_out, pid_in;
1486 LttvProcessState *process_out, *process_in;
1487 LttTime birth;
1488 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1489
1490 ProcessList *process_list = control_flow_data->process_list;
1491
1492
1493 LttField *f = ltt_event_field(e);
1494 LttField *element;
1495 element = ltt_field_member(f,0);
1496 pid_out = ltt_event_get_long_unsigned(e,element);
1497 element = ltt_field_member(f,1);
1498 pid_in = ltt_event_get_long_unsigned(e,element);
1499 //g_debug("out : %u in : %u", pid_out, pid_in);
1500
1501
1502 /* Find process pid_out in the list... */
1503 process_out = lttv_state_find_process(tfs, pid_out);
1504 if(process_out == NULL) return 0;
1505 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1506
1507 birth = process_out->creation_time;
1508 gchar *name = strdup(g_quark_to_string(process_out->name));
1509 HashedProcessData *hashed_process_data_out = NULL;
1510
1511 if(processlist_get_process_pixels(process_list,
1512 pid_out,
1513 &birth,
1514 tfc->t_context->index,
1515 &y_out,
1516 &height,
1517 &hashed_process_data_out) == 1)
1518 {
1519 /* Process not present */
1520 processlist_add(process_list,
1521 pid_out,
1522 &birth,
1523 tfc->t_context->index,
1524 name,
1525 &pl_height,
1526 &hashed_process_data_out);
1527 processlist_get_process_pixels(process_list,
1528 pid_out,
1529 &birth,
1530 tfc->t_context->index,
1531 &y_out,
1532 &height,
1533 &hashed_process_data_out);
1534 drawing_insert_square( control_flow_data->drawing, y_out, height);
1535 }
1536
1537 g_free(name);
1538
1539 /* Find process pid_in in the list... */
1540 process_in = lttv_state_find_process(tfs, pid_in);
1541 if(process_in == NULL) return 0;
1542 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1543
1544 birth = process_in->creation_time;
1545 name = strdup(g_quark_to_string(process_in->name));
1546 HashedProcessData *hashed_process_data_in = NULL;
1547
1548 if(processlist_get_process_pixels(process_list,
1549 pid_in,
1550 &birth,
1551 tfc->t_context->index,
1552 &y_in,
1553 &height,
1554 &hashed_process_data_in) == 1)
1555 {
1556 /* Process not present */
1557 processlist_add(process_list,
1558 pid_in,
1559 &birth,
1560 tfc->t_context->index,
1561 name,
1562 &pl_height,
1563 &hashed_process_data_in);
1564 processlist_get_process_pixels(process_list,
1565 pid_in,
1566 &birth,
1567 tfc->t_context->index,
1568 &y_in,
1569 &height,
1570 &hashed_process_data_in);
1571
1572 drawing_insert_square( control_flow_data->drawing, y_in, height);
1573 }
1574 g_free(name);
1575
1576
1577 /* Find pixels corresponding to time of the event. If the time does
1578 * not fit in the window, show a warning, not supposed to happend. */
1579 //guint x = 0;
1580 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1581
1582 //LttTime time = ltt_event_time(e);
1583
1584 //LttTime window_end = time_window->time_window.end_time;
1585
1586
1587 //convert_time_to_pixels(
1588 // *time_window,
1589 // time,
1590 // width,
1591 // &x);
1592
1593 //assert(x <= width);
1594
1595 /* draw what represents the event for outgoing process. */
1596
1597 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
1598 //draw_context_out->current->modify_over->x = x;
1599 draw_context_out->current->modify_over->y = y_out;
1600 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
1601 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1602 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1603 GtkWidget *widget = control_flow_data->drawing->drawing_area;
1604 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1605
1606 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1607 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1608
1609 /*if(process_out->state->s == LTTV_STATE_RUN)
1610 {
1611 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1612 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1613 PropertiesBG prop_bg;
1614 prop_bg.color = g_new(GdkColor,1);
1615
1616 prop_bg.color->red = 0xffff;
1617 prop_bg.color->green = 0xffff;
1618 prop_bg.color->blue = 0xffff;
1619
1620 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1621 g_free(prop_bg.color);
1622 gdk_gc_unref(draw_context_out->gc);
1623 }*/
1624
1625 draw_context_out->gc = widget->style->black_gc;
1626
1627 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
1628 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
1629 PropertiesText prop_text_out;
1630 prop_text_out.foreground = &colorfg_out;
1631 prop_text_out.background = &colorbg_out;
1632 prop_text_out.size = 6;
1633 prop_text_out.position = OVER;
1634
1635 /* color of text : status of the process */
1636 if(process_out->state->s == LTTV_STATE_UNNAMED)
1637 {
1638 prop_text_out.foreground->red = 0xffff;
1639 prop_text_out.foreground->green = 0xffff;
1640 prop_text_out.foreground->blue = 0xffff;
1641 }
1642 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1643 {
1644 prop_text_out.foreground->red = 0x0fff;
1645 prop_text_out.foreground->green = 0xffff;
1646 prop_text_out.foreground->blue = 0xfff0;
1647 }
1648 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1649 {
1650 prop_text_out.foreground->red = 0xffff;
1651 prop_text_out.foreground->green = 0xffff;
1652 prop_text_out.foreground->blue = 0x0000;
1653 }
1654 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1655 {
1656 prop_text_out.foreground->red = 0xffff;
1657 prop_text_out.foreground->green = 0x0000;
1658 prop_text_out.foreground->blue = 0xffff;
1659 }
1660 else if(process_out->state->s == LTTV_STATE_WAIT)
1661 {
1662 prop_text_out.foreground->red = 0xffff;
1663 prop_text_out.foreground->green = 0x0000;
1664 prop_text_out.foreground->blue = 0x0000;
1665 }
1666 else if(process_out->state->s == LTTV_STATE_RUN)
1667 {
1668 prop_text_out.foreground->red = 0x0000;
1669 prop_text_out.foreground->green = 0xffff;
1670 prop_text_out.foreground->blue = 0x0000;
1671 }
1672 else
1673 {
1674 prop_text_out.foreground->red = 0xffff;
1675 prop_text_out.foreground->green = 0xffff;
1676 prop_text_out.foreground->blue = 0xffff;
1677 }
1678
1679 /* Print status of the process : U, WF, WC, E, W, R */
1680 if(process_out->state->s == LTTV_STATE_UNNAMED)
1681 prop_text_out.text = "U";
1682 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1683 prop_text_out.text = "WF";
1684 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1685 prop_text_out.text = "WC";
1686 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1687 prop_text_out.text = "E";
1688 else if(process_out->state->s == LTTV_STATE_WAIT)
1689 prop_text_out.text = "W";
1690 else if(process_out->state->s == LTTV_STATE_RUN)
1691 prop_text_out.text = "R";
1692 else
1693 prop_text_out.text = "U";
1694
1695 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1696
1697 //gdk_gc_unref(draw_context_out->gc);
1698
1699 draw_context_out->current->middle->y = y_out+height/2;
1700 draw_context_out->current->over->y = y_out;
1701 draw_context_out->current->under->y = y_out+height;
1702 draw_context_out->current->status = process_out->state->s;
1703
1704 /* for pid_out : remove previous, Prev = current, new current (default) */
1705 g_free(draw_context_out->previous->modify_under);
1706 g_free(draw_context_out->previous->modify_middle);
1707 g_free(draw_context_out->previous->modify_over);
1708 g_free(draw_context_out->previous->under);
1709 g_free(draw_context_out->previous->middle);
1710 g_free(draw_context_out->previous->over);
1711 g_free(draw_context_out->previous);
1712
1713 draw_context_out->previous = draw_context_out->current;
1714
1715 draw_context_out->current = g_new(DrawInfo,1);
1716 draw_context_out->current->over = g_new(ItemInfo,1);
1717 draw_context_out->current->over->x = -1;
1718 draw_context_out->current->over->y = -1;
1719 draw_context_out->current->middle = g_new(ItemInfo,1);
1720 draw_context_out->current->middle->x = -1;
1721 draw_context_out->current->middle->y = -1;
1722 draw_context_out->current->under = g_new(ItemInfo,1);
1723 draw_context_out->current->under->x = -1;
1724 draw_context_out->current->under->y = -1;
1725 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1726 draw_context_out->current->modify_over->x = -1;
1727 draw_context_out->current->modify_over->y = -1;
1728 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1729 draw_context_out->current->modify_middle->x = -1;
1730 draw_context_out->current->modify_middle->y = -1;
1731 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1732 draw_context_out->current->modify_under->x = -1;
1733 draw_context_out->current->modify_under->y = -1;
1734 draw_context_out->current->status = LTTV_STATE_UNNAMED;
1735
1736 /* Finally, update the drawing context of the pid_in. */
1737
1738 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1739 //draw_context_in->current->modify_over->x = x;
1740 draw_context_in->current->modify_over->y = y_in;
1741 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1742 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1743 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1744 widget = control_flow_data->drawing->drawing_area;
1745 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1746
1747 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1748 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1749
1750 /*if(process_in->state->s == LTTV_STATE_RUN)
1751 {
1752 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1753 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1754 PropertiesBG prop_bg;
1755 prop_bg.color = g_new(GdkColor,1);
1756
1757 prop_bg.color->red = 0xffff;
1758 prop_bg.color->green = 0xffff;
1759 prop_bg.color->blue = 0xffff;
1760
1761 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1762 g_free(prop_bg.color);
1763 gdk_gc_unref(draw_context_in->gc);
1764 }*/
1765
1766 draw_context_in->gc = widget->style->black_gc;
1767
1768 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1769 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1770 PropertiesText prop_text_in;
1771 prop_text_in.foreground = &colorfg_in;
1772 prop_text_in.background = &colorbg_in;
1773 prop_text_in.size = 6;
1774 prop_text_in.position = OVER;
1775
1776 /* foreground of text : status of the process */
1777 if(process_in->state->s == LTTV_STATE_UNNAMED)
1778 {
1779 prop_text_in.foreground->red = 0xffff;
1780 prop_text_in.foreground->green = 0xffff;
1781 prop_text_in.foreground->blue = 0xffff;
1782 }
1783 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1784 {
1785 prop_text_in.foreground->red = 0x0fff;
1786 prop_text_in.foreground->green = 0xffff;
1787 prop_text_in.foreground->blue = 0xfff0;
1788 }
1789 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1790 {
1791 prop_text_in.foreground->red = 0xffff;
1792 prop_text_in.foreground->green = 0xffff;
1793 prop_text_in.foreground->blue = 0x0000;
1794 }
1795 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1796 {
1797 prop_text_in.foreground->red = 0xffff;
1798 prop_text_in.foreground->green = 0x0000;
1799 prop_text_in.foreground->blue = 0xffff;
1800 }
1801 else if(process_in->state->s == LTTV_STATE_WAIT)
1802 {
1803 prop_text_in.foreground->red = 0xffff;
1804 prop_text_in.foreground->green = 0x0000;
1805 prop_text_in.foreground->blue = 0x0000;
1806 }
1807 else if(process_in->state->s == LTTV_STATE_RUN)
1808 {
1809 prop_text_in.foreground->red = 0x0000;
1810 prop_text_in.foreground->green = 0xffff;
1811 prop_text_in.foreground->blue = 0x0000;
1812 }
1813 else
1814 {
1815 prop_text_in.foreground->red = 0xffff;
1816 prop_text_in.foreground->green = 0xffff;
1817 prop_text_in.foreground->blue = 0xffff;
1818 }
1819
1820
1821 /* Print status of the process : U, WF, WC, E, W, R */
1822 if(process_in->state->s == LTTV_STATE_UNNAMED)
1823 prop_text_in.text = "U";
1824 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1825 prop_text_in.text = "WF";
1826 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1827 prop_text_in.text = "WC";
1828 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1829 prop_text_in.text = "E";
1830 else if(process_in->state->s == LTTV_STATE_WAIT)
1831 prop_text_in.text = "W";
1832 else if(process_in->state->s == LTTV_STATE_RUN)
1833 prop_text_in.text = "R";
1834 else
1835 prop_text_in.text = "U";
1836
1837 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1838
1839
1840 if(process_in->state->s == LTTV_STATE_RUN)
1841 {
1842 gchar tmp[255];
1843 prop_text_in.foreground = &colorfg_in;
1844 prop_text_in.background = &colorbg_in;
1845 prop_text_in.foreground->red = 0xffff;
1846 prop_text_in.foreground->green = 0xffff;
1847 prop_text_in.foreground->blue = 0xffff;
1848 prop_text_in.size = 6;
1849 prop_text_in.position = UNDER;
1850
1851 prop_text_in.text = g_new(gchar, 260);
1852 strcpy(prop_text_in.text, "CPU ");
1853 snprintf(tmp, 255, "%u", ltt_tracefile_num(tfc->tf));
1854 strcat(prop_text_in.text, tmp);
1855
1856 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1857 g_free(prop_text_in.text);
1858 }
1859
1860
1861 draw_context_in->current->middle->y = y_in+height/2;
1862 draw_context_in->current->over->y = y_in;
1863 draw_context_in->current->under->y = y_in+height;
1864 draw_context_in->current->status = process_in->state->s;
1865
1866 /* for pid_in : remove previous, Prev = current, new current (default) */
1867 g_free(draw_context_in->previous->modify_under);
1868 g_free(draw_context_in->previous->modify_middle);
1869 g_free(draw_context_in->previous->modify_over);
1870 g_free(draw_context_in->previous->under);
1871 g_free(draw_context_in->previous->middle);
1872 g_free(draw_context_in->previous->over);
1873 g_free(draw_context_in->previous);
1874
1875 draw_context_in->previous = draw_context_in->current;
1876
1877 draw_context_in->current = g_new(DrawInfo,1);
1878 draw_context_in->current->over = g_new(ItemInfo,1);
1879 draw_context_in->current->over->x = -1;
1880 draw_context_in->current->over->y = -1;
1881 draw_context_in->current->middle = g_new(ItemInfo,1);
1882 draw_context_in->current->middle->x = -1;
1883 draw_context_in->current->middle->y = -1;
1884 draw_context_in->current->under = g_new(ItemInfo,1);
1885 draw_context_in->current->under->x = -1;
1886 draw_context_in->current->under->y = -1;
1887 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1888 draw_context_in->current->modify_over->x = -1;
1889 draw_context_in->current->modify_over->y = -1;
1890 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1891 draw_context_in->current->modify_middle->x = -1;
1892 draw_context_in->current->modify_middle->y = -1;
1893 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1894 draw_context_in->current->modify_under->x = -1;
1895 draw_context_in->current->modify_under->y = -1;
1896 draw_context_in->current->status = LTTV_STATE_UNNAMED;
1897
1898 }
1899
1900 return 0;
1901#endif //0
1902}
1903
1904#if 0
1905static inline PropertiesLine prepare_execmode_line(LttvProcessState *process)
1906{
1907 PropertiesLine prop_line;
1908 prop_line.line_width = 1;
1909 prop_line.style = GDK_LINE_SOLID;
1910 prop_line.y = OVER;
1911 //GdkColormap *colormap = gdk_colormap_get_system();
1912
1913 /* color of line : execution mode of the process */
1914 if(process->state->t == LTTV_STATE_USER_MODE)
1915 prop_line.color = drawing_colors[COL_USER_MODE];
1916 else if(process->state->t == LTTV_STATE_SYSCALL)
1917 prop_line.color = drawing_colors[COL_SYSCALL];
1918 else if(process->state->t == LTTV_STATE_TRAP)
1919 prop_line.color = drawing_colors[COL_TRAP];
1920 else if(process->state->t == LTTV_STATE_IRQ)
1921 prop_line.color = drawing_colors[COL_IRQ];
1922 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
1923 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
1924 else
1925 prop_line.color = drawing_colors[COL_WHITE];
1926
1927 //gdk_colormap_alloc_color(colormap,
1928 // prop_line.color,
1929 // FALSE,
1930 // TRUE);
1931
1932 return prop_line;
1933
1934}
1935#endif //0
1936
1937
1938/* before_execmode_hook
1939 *
1940 * This function basically draw lines and icons. Two types of lines are drawn :
1941 * one small (3 pixels?) representing the state of the process and the second
1942 * type is thicker (10 pixels?) representing on which CPU a process is running
1943 * (and this only in running state).
1944 *
1945 * Extremums of the lines :
1946 * x_min : time of the last event context for this process kept in memory.
1947 * x_max : time of the current event.
1948 * y : middle of the process in the process list. The process is found in the
1949 * list, therefore is it's position in pixels.
1950 *
1951 * The choice of lines'color is defined by the context of the last event for this
1952 * process.
1953 */
1954
1955
1956int before_execmode_hook(void *hook_data, void *call_data)
1957{
1958 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
1959 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
1960 ControlFlowData *control_flow_data = events_request->viewer_data;
1961
1962 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1963
1964 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1965
1966 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1967
1968 LttEvent *e;
1969 e = ltt_tracefile_get_event(tfc->tf);
1970
1971 LttTime evtime = ltt_event_time(e);
1972
1973 /* we are in a execmode, before the state update. We must draw the
1974 * items corresponding to the state before it changes : now is the right
1975 * time to do it.
1976 */
1977 /* For the pid */
1978 //LttvProcessState *process = tfs->process;
1979 guint cpu = ltt_tracefile_num(tfc->tf);
1980 LttvProcessState *process = ts->running_process[cpu];
1981 g_assert(process != NULL);
1982
1983 guint pid = process->pid;
1984
1985 /* Well, the process_out existed : we must get it in the process hash
1986 * or add it, and draw its items.
1987 */
1988 /* Add process to process list (if not present) */
1989 guint pl_height = 0;
1990 HashedProcessData *hashed_process_data = NULL;
1991 ProcessList *process_list = control_flow_data->process_list;
1992 LttTime birth = process->creation_time;
1993
1994 if(likely(process_list->current_hash_data[cpu] != NULL)) {
1995 hashed_process_data = process_list->current_hash_data[cpu];
1996 } else {
1997 hashed_process_data = processlist_get_process_data(process_list,
1998 pid,
1999 process->cpu,
2000 &birth,
2001 tfc->t_context->index);
2002 if(unlikely(hashed_process_data == NULL))
2003 {
2004 g_assert(pid == 0 || pid != process->ppid);
2005 ProcessInfo *process_info;
2006 /* Process not present */
2007 Drawing_t *drawing = control_flow_data->drawing;
2008 processlist_add(process_list,
2009 drawing,
2010 pid,
2011 process->cpu,
2012 process->ppid,
2013 &birth,
2014 tfc->t_context->index,
2015 process->name,
2016 &pl_height,
2017 &process_info,
2018 &hashed_process_data);
2019 gtk_widget_set_size_request(drawing->drawing_area,
2020 -1,
2021 pl_height);
2022 gtk_widget_queue_draw(drawing->drawing_area);
2023 }
2024 /* Set the current process */
2025 process_list->current_hash_data[process->cpu] =
2026 hashed_process_data;
2027 }
2028
2029 /* Now, the process is in the state hash and our own process hash.
2030 * We definitely can draw the items related to the ending state.
2031 */
2032
2033 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2034 evtime) > 0))
2035 {
2036 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2037 TimeWindow time_window =
2038 lttvwindow_get_time_window(control_flow_data->tab);
2039
2040#ifdef EXTRA_CHECK
2041 if(ltt_time_compare(evtime, time_window.start_time) == -1
2042 || ltt_time_compare(evtime, time_window.end_time) == 1)
2043 return;
2044#endif //EXTRA_CHECK
2045 Drawing_t *drawing = control_flow_data->drawing;
2046 guint width = drawing->width;
2047 guint x;
2048 convert_time_to_pixels(
2049 time_window,
2050 evtime,
2051 width,
2052 &x);
2053
2054 /* Draw collision indicator */
2055 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2056 gdk_draw_point(hashed_process_data->pixmap,
2057 drawing->gc,
2058 x,
2059 (hashed_process_data->height/2)-3);
2060 hashed_process_data->x.middle_marked = TRUE;
2061 }
2062 } else {
2063 TimeWindow time_window =
2064 lttvwindow_get_time_window(control_flow_data->tab);
2065
2066#ifdef EXTRA_CHECK
2067 if(ltt_time_compare(evtime, time_window.start_time) == -1
2068 || ltt_time_compare(evtime, time_window.end_time) == 1)
2069 return;
2070#endif //EXTRA_CHECK
2071 Drawing_t *drawing = control_flow_data->drawing;
2072 guint width = drawing->width;
2073 guint x;
2074
2075 convert_time_to_pixels(
2076 time_window,
2077 evtime,
2078 width,
2079 &x);
2080
2081
2082 /* Jump over draw if we are at the same x position */
2083 if(unlikely(x == hashed_process_data->x.middle &&
2084 hashed_process_data->x.middle_used))
2085 {
2086 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2087 /* Draw collision indicator */
2088 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2089 gdk_draw_point(hashed_process_data->pixmap,
2090 drawing->gc,
2091 x,
2092 (hashed_process_data->height/2)-3);
2093 hashed_process_data->x.middle_marked = TRUE;
2094 }
2095 /* jump */
2096 } else {
2097
2098 DrawContext draw_context;
2099 /* Now create the drawing context that will be used to draw
2100 * items related to the last state. */
2101 draw_context.drawable = hashed_process_data->pixmap;
2102 draw_context.gc = drawing->gc;
2103 draw_context.pango_layout = drawing->pango_layout;
2104 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2105 draw_context.drawinfo.end.x = x;
2106
2107 draw_context.drawinfo.y.over = 1;
2108 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2109 draw_context.drawinfo.y.under = hashed_process_data->height;
2110
2111 draw_context.drawinfo.start.offset.over = 0;
2112 draw_context.drawinfo.start.offset.middle = 0;
2113 draw_context.drawinfo.start.offset.under = 0;
2114 draw_context.drawinfo.end.offset.over = 0;
2115 draw_context.drawinfo.end.offset.middle = 0;
2116 draw_context.drawinfo.end.offset.under = 0;
2117
2118 {
2119 /* Draw the line */
2120 PropertiesLine prop_line = prepare_s_e_line(process);
2121 draw_line((void*)&prop_line, (void*)&draw_context);
2122
2123 }
2124 /* become the last x position */
2125 hashed_process_data->x.middle = x;
2126 hashed_process_data->x.middle_used = TRUE;
2127 hashed_process_data->x.middle_marked = FALSE;
2128
2129 /* Calculate the next good time */
2130 convert_pixels_to_time(width, x+1, time_window,
2131 &hashed_process_data->next_good_time);
2132 }
2133 }
2134
2135 return 0;
2136}
2137
2138/* after_execmode_hook
2139 *
2140 * The draw after hook is called by the reading API to have a
2141 * particular event drawn on the screen.
2142 * @param hook_data ControlFlowData structure of the viewer.
2143 * @param call_data Event context.
2144 *
2145 * This function adds items to be drawn in a queue for each process.
2146 *
2147 */
2148#if 0
2149int after_execmode_hook(void *hook_data, void *call_data)
2150{
2151 /**************** DOES NOTHING!! *************/
2152 /* hook desactivated in drawing.c */
2153 return 0;
2154
2155
2156 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2157 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2158 ControlFlowData *control_flow_data = events_request->viewer_data;
2159
2160 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2161
2162 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2163
2164 LttEvent *e;
2165 e = ltt_tracefile_get_event(tfc->tf);
2166
2167 LttTime evtime = ltt_event_time(e);
2168
2169 /* Add process to process list (if not present) */
2170 LttvProcessState *process;
2171 LttTime birth;
2172 guint pl_height = 0;
2173 HashedProcessData *hashed_process_data = NULL;
2174
2175 ProcessList *process_list = control_flow_data->process_list;
2176
2177 /* Find process pid_in in the list... */
2178 process = tfs->process;
2179 /* It should exist, because we are after the state update. */
2180 g_assert(process != NULL);
2181
2182 guint pid = process->pid;
2183
2184 birth = process->creation_time;
2185
2186 if(likely(process_list->current_hash_data[ltt_tracefile_num(tfc->tf)] != NULL)) {
2187 hashed_process_data = process_list->current_hash_data[ltt_tracefile_num(tfc->tf)];
2188 } else {
2189 hashed_process_data = processlist_get_process_data(process_list,
2190 pid,
2191 process->last_cpu_index,
2192 &birth,
2193 tfc->t_context->index);
2194 if(unlikely(hashed_process_data == NULL))
2195 {
2196 g_assert(pid == 0 || pid != process->ppid);
2197 /* Process not present */
2198 Drawing_t *drawing = control_flow_data->drawing;
2199 const gchar *name = g_quark_to_string(process->name);
2200 ProcessInfo *process_info;
2201 processlist_add(process_list,
2202 drawing,
2203 pid,
2204 process->last_cpu_index,
2205 process->ppid,
2206 &birth,
2207 tfc->t_context->index,
2208 name,
2209 &pl_height,
2210 &process_info,
2211 &hashed_process_data);
2212 gtk_widget_set_size_request(drawing->drawing_area,
2213 -1,
2214 pl_height);
2215 gtk_widget_queue_draw(drawing->drawing_area);
2216 }
2217 /* Set the current process */
2218 process_list->current_hash_data[process->last_cpu_index] =
2219 hashed_process_data;
2220 }
2221
2222 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
2223 evtime) <= 0))
2224 {
2225 TimeWindow time_window =
2226 lttvwindow_get_time_window(control_flow_data->tab);
2227
2228#ifdef EXTRA_CHECK
2229 if(ltt_time_compare(evtime, time_window.start_time) == -1
2230 || ltt_time_compare(evtime, time_window.end_time) == 1)
2231 return;
2232#endif //EXTRA_CHECK
2233 Drawing_t *drawing = control_flow_data->drawing;
2234 guint width = drawing->width;
2235 guint new_x;
2236
2237 convert_time_to_pixels(
2238 time_window,
2239 evtime,
2240 width,
2241 &new_x);
2242
2243 if(hashed_process_data->x.middle != new_x) {
2244 hashed_process_data->x.middle = new_x;
2245 hashed_process_data->x.middle_used = FALSE;
2246 hashed_process_data->x.middle_marked = FALSE;
2247 }
2248 }
2249 return 0;
2250}
2251#endif //0
2252
2253
2254
2255/* before_process_exit_hook
2256 *
2257 * Draw lines for process event.
2258 *
2259 * @param hook_data ControlFlowData structure of the viewer.
2260 * @param call_data Event context.
2261 *
2262 * This function adds items to be drawn in a queue for each process.
2263 *
2264 */
2265
2266
2267int before_process_exit_hook(void *hook_data, void *call_data)
2268{
2269 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2270 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2271
2272 ControlFlowData *control_flow_data = events_request->viewer_data;
2273
2274 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2275
2276 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2277
2278 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2279
2280 LttEvent *e;
2281 e = ltt_tracefile_get_event(tfc->tf);
2282
2283 LttTime evtime = ltt_event_time(e);
2284
2285 /* Add process to process list (if not present) */
2286 //LttvProcessState *process = tfs->process;
2287 guint cpu = ltt_tracefile_num(tfc->tf);
2288 LttvProcessState *process = ts->running_process[cpu];
2289 guint pid = process->pid;
2290 LttTime birth;
2291 guint pl_height = 0;
2292 HashedProcessData *hashed_process_data = NULL;
2293
2294 ProcessList *process_list = control_flow_data->process_list;
2295
2296 g_assert(process != NULL);
2297
2298 birth = process->creation_time;
2299
2300 if(likely(process_list->current_hash_data[cpu] != NULL)) {
2301 hashed_process_data = process_list->current_hash_data[cpu];
2302 } else {
2303 hashed_process_data = processlist_get_process_data(process_list,
2304 pid,
2305 process->cpu,
2306 &birth,
2307 tfc->t_context->index);
2308 if(unlikely(hashed_process_data == NULL))
2309 {
2310 g_assert(pid == 0 || pid != process->ppid);
2311 /* Process not present */
2312 Drawing_t *drawing = control_flow_data->drawing;
2313 ProcessInfo *process_info;
2314 processlist_add(process_list,
2315 drawing,
2316 pid,
2317 process->cpu,
2318 process->ppid,
2319 &birth,
2320 tfc->t_context->index,
2321 process->name,
2322 &pl_height,
2323 &process_info,
2324 &hashed_process_data);
2325 gtk_widget_set_size_request(drawing->drawing_area,
2326 -1,
2327 pl_height);
2328 gtk_widget_queue_draw(drawing->drawing_area);
2329 }
2330 }
2331
2332 /* Now, the process is in the state hash and our own process hash.
2333 * We definitely can draw the items related to the ending state.
2334 */
2335
2336 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2337 evtime) > 0))
2338 {
2339 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2340 TimeWindow time_window =
2341 lttvwindow_get_time_window(control_flow_data->tab);
2342
2343#ifdef EXTRA_CHECK
2344 if(ltt_time_compare(evtime, time_window.start_time) == -1
2345 || ltt_time_compare(evtime, time_window.end_time) == 1)
2346 return;
2347#endif //EXTRA_CHECK
2348 Drawing_t *drawing = control_flow_data->drawing;
2349 guint width = drawing->width;
2350 guint x;
2351 convert_time_to_pixels(
2352 time_window,
2353 evtime,
2354 width,
2355 &x);
2356
2357 /* Draw collision indicator */
2358 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2359 gdk_draw_point(hashed_process_data->pixmap,
2360 drawing->gc,
2361 x,
2362 (hashed_process_data->height/2)-3);
2363 hashed_process_data->x.middle_marked = TRUE;
2364 }
2365 } else {
2366 TimeWindow time_window =
2367 lttvwindow_get_time_window(control_flow_data->tab);
2368
2369#ifdef EXTRA_CHECK
2370 if(ltt_time_compare(evtime, time_window.start_time) == -1
2371 || ltt_time_compare(evtime, time_window.end_time) == 1)
2372 return;
2373#endif //EXTRA_CHECK
2374 Drawing_t *drawing = control_flow_data->drawing;
2375 guint width = drawing->width;
2376 guint x;
2377
2378 convert_time_to_pixels(
2379 time_window,
2380 evtime,
2381 width,
2382 &x);
2383
2384
2385 /* Jump over draw if we are at the same x position */
2386 if(unlikely(x == hashed_process_data->x.middle &&
2387 hashed_process_data->x.middle_used))
2388 {
2389 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2390 /* Draw collision indicator */
2391 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2392 gdk_draw_point(hashed_process_data->pixmap,
2393 drawing->gc,
2394 x,
2395 (hashed_process_data->height/2)-3);
2396 hashed_process_data->x.middle_marked = TRUE;
2397 }
2398 /* jump */
2399 } else {
2400 DrawContext draw_context;
2401
2402 /* Now create the drawing context that will be used to draw
2403 * items related to the last state. */
2404 draw_context.drawable = hashed_process_data->pixmap;
2405 draw_context.gc = drawing->gc;
2406 draw_context.pango_layout = drawing->pango_layout;
2407 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2408 draw_context.drawinfo.end.x = x;
2409
2410 draw_context.drawinfo.y.over = 1;
2411 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2412 draw_context.drawinfo.y.under = hashed_process_data->height;
2413
2414 draw_context.drawinfo.start.offset.over = 0;
2415 draw_context.drawinfo.start.offset.middle = 0;
2416 draw_context.drawinfo.start.offset.under = 0;
2417 draw_context.drawinfo.end.offset.over = 0;
2418 draw_context.drawinfo.end.offset.middle = 0;
2419 draw_context.drawinfo.end.offset.under = 0;
2420
2421 {
2422 /* Draw the line */
2423 PropertiesLine prop_line = prepare_s_e_line(process);
2424 draw_line((void*)&prop_line, (void*)&draw_context);
2425
2426 }
2427 /* become the last x position */
2428 hashed_process_data->x.middle = x;
2429 hashed_process_data->x.middle_used = TRUE;
2430 hashed_process_data->x.middle_marked = FALSE;
2431
2432 /* Calculate the next good time */
2433 convert_pixels_to_time(width, x+1, time_window,
2434 &hashed_process_data->next_good_time);
2435 }
2436 }
2437
2438 return 0;
2439
2440}
2441
2442
2443
2444/* before_process_release_hook
2445 *
2446 * Draw lines for process event.
2447 *
2448 * @param hook_data ControlFlowData structure of the viewer.
2449 * @param call_data Event context.
2450 *
2451 * This function adds items to be drawn in a queue for each process.
2452 *
2453 */
2454
2455
2456int before_process_release_hook(void *hook_data, void *call_data)
2457{
2458 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2459 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2460
2461 ControlFlowData *control_flow_data = events_request->viewer_data;
2462
2463 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2464
2465 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2466
2467 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2468
2469 LttEvent *e;
2470 e = ltt_tracefile_get_event(tfc->tf);
2471
2472 LttTime evtime = ltt_event_time(e);
2473
2474
2475 guint pid;
2476 {
2477 pid = ltt_event_get_long_unsigned(e, thf->f1);
2478 }
2479
2480 /* Add process to process list (if not present) */
2481 /* Don't care about the process if it's not in the state hash already :
2482 * that means a process that has never done anything in the trace and
2483 * unknown suddently gets destroyed : no state meaningful to show. */
2484 LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
2485
2486 if(process != NULL) {
2487 LttTime birth;
2488 guint pl_height = 0;
2489 HashedProcessData *hashed_process_data = NULL;
2490
2491 ProcessList *process_list = control_flow_data->process_list;
2492
2493 birth = process->creation_time;
2494
2495 /* Cannot use current process : this event happens on another process,
2496 * action done by the parent. */
2497 hashed_process_data = processlist_get_process_data(process_list,
2498 pid,
2499 process->cpu,
2500 &birth,
2501 tfc->t_context->index);
2502 if(unlikely(hashed_process_data == NULL))
2503 {
2504 g_assert(pid == 0 || pid != process->ppid);
2505 /* Process not present */
2506 Drawing_t *drawing = control_flow_data->drawing;
2507 ProcessInfo *process_info;
2508 processlist_add(process_list,
2509 drawing,
2510 pid,
2511 process->cpu,
2512 process->ppid,
2513 &birth,
2514 tfc->t_context->index,
2515 process->name,
2516 &pl_height,
2517 &process_info,
2518 &hashed_process_data);
2519 gtk_widget_set_size_request(drawing->drawing_area,
2520 -1,
2521 pl_height);
2522 gtk_widget_queue_draw(drawing->drawing_area);
2523 }
2524
2525 /* Now, the process is in the state hash and our own process hash.
2526 * We definitely can draw the items related to the ending state.
2527 */
2528
2529 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2530 evtime) > 0))
2531 {
2532 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2533 TimeWindow time_window =
2534 lttvwindow_get_time_window(control_flow_data->tab);
2535
2536#ifdef EXTRA_CHECK
2537 if(ltt_time_compare(evtime, time_window.start_time) == -1
2538 || ltt_time_compare(evtime, time_window.end_time) == 1)
2539 return;
2540#endif //EXTRA_CHECK
2541 Drawing_t *drawing = control_flow_data->drawing;
2542 guint width = drawing->width;
2543 guint x;
2544 convert_time_to_pixels(
2545 time_window,
2546 evtime,
2547 width,
2548 &x);
2549
2550 /* Draw collision indicator */
2551 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2552 gdk_draw_point(hashed_process_data->pixmap,
2553 drawing->gc,
2554 x,
2555 (hashed_process_data->height/2)-3);
2556 hashed_process_data->x.middle_marked = TRUE;
2557 }
2558 } else {
2559 TimeWindow time_window =
2560 lttvwindow_get_time_window(control_flow_data->tab);
2561
2562#ifdef EXTRA_CHECK
2563 if(ltt_time_compare(evtime, time_window.start_time) == -1
2564 || ltt_time_compare(evtime, time_window.end_time) == 1)
2565 return;
2566#endif //EXTRA_CHECK
2567 Drawing_t *drawing = control_flow_data->drawing;
2568 guint width = drawing->width;
2569 guint x;
2570
2571 convert_time_to_pixels(
2572 time_window,
2573 evtime,
2574 width,
2575 &x);
2576
2577
2578 /* Jump over draw if we are at the same x position */
2579 if(unlikely(x == hashed_process_data->x.middle &&
2580 hashed_process_data->x.middle_used))
2581 {
2582 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2583 /* Draw collision indicator */
2584 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2585 gdk_draw_point(hashed_process_data->pixmap,
2586 drawing->gc,
2587 x,
2588 (hashed_process_data->height/2)-3);
2589 hashed_process_data->x.middle_marked = TRUE;
2590 }
2591 /* jump */
2592 } else {
2593 DrawContext draw_context;
2594
2595 /* Now create the drawing context that will be used to draw
2596 * items related to the last state. */
2597 draw_context.drawable = hashed_process_data->pixmap;
2598 draw_context.gc = drawing->gc;
2599 draw_context.pango_layout = drawing->pango_layout;
2600 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2601 draw_context.drawinfo.end.x = x;
2602
2603 draw_context.drawinfo.y.over = 1;
2604 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2605 draw_context.drawinfo.y.under = hashed_process_data->height;
2606
2607 draw_context.drawinfo.start.offset.over = 0;
2608 draw_context.drawinfo.start.offset.middle = 0;
2609 draw_context.drawinfo.start.offset.under = 0;
2610 draw_context.drawinfo.end.offset.over = 0;
2611 draw_context.drawinfo.end.offset.middle = 0;
2612 draw_context.drawinfo.end.offset.under = 0;
2613
2614 {
2615 /* Draw the line */
2616 PropertiesLine prop_line = prepare_s_e_line(process);
2617 draw_line((void*)&prop_line, (void*)&draw_context);
2618
2619 }
2620 /* become the last x position */
2621 hashed_process_data->x.middle = x;
2622 hashed_process_data->x.middle_used = TRUE;
2623 hashed_process_data->x.middle_marked = FALSE;
2624
2625 /* Calculate the next good time */
2626 convert_pixels_to_time(width, x+1, time_window,
2627 &hashed_process_data->next_good_time);
2628 }
2629 }
2630 }
2631
2632 return 0;
2633}
2634
2635
2636
2637
2638
2639
2640
2641
2642#if 0
2643/* before_process_hook
2644 *
2645 * Draw lines for process event.
2646 *
2647 * @param hook_data ControlFlowData structure of the viewer.
2648 * @param call_data Event context.
2649 *
2650 * This function adds items to be drawn in a queue for each process.
2651 *
2652 */
2653int before_process_hook(void *hook_data, void *call_data)
2654{
2655 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
2656 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
2657 ControlFlowData *control_flow_data = events_request->viewer_data;
2658
2659 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2660
2661 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2662
2663 LttEvent *e;
2664 e = ltt_tracefile_get_event(tfc->tf);
2665
2666 LttTime evtime = ltt_event_time(e);
2667
2668 guint sub_id;
2669 {
2670 LttField *f = ltt_event_field(e);
2671 LttField *element;
2672 element = ltt_field_member(f,0);
2673 sub_id = ltt_event_get_long_unsigned(e,element);
2674 }
2675
2676 if(sub_id == 3) { /* exit */
2677
2678 /* Add process to process list (if not present) */
2679 LttvProcessState *process = tfs->process;
2680 guint pid = process->pid;
2681 LttTime birth;
2682 guint pl_height = 0;
2683 HashedProcessData *hashed_process_data = NULL;
2684
2685 ProcessList *process_list = control_flow_data->process_list;
2686
2687 g_assert(process != NULL);
2688
2689 birth = process->creation_time;
2690
2691 if(likely(process_list->current_hash_data[tfc->index] != NULL)) {
2692 hashed_process_data = process_list->current_hash_data[tfc->index];
2693 } else {
2694 hashed_process_data = processlist_get_process_data(process_list,
2695 pid,
2696 process->last_cpu_index,
2697 &birth,
2698 tfc->t_context->index);
2699 if(unlikely(hashed_process_data == NULL))
2700 {
2701 g_assert(pid == 0 || pid != process->ppid);
2702 /* Process not present */
2703 Drawing_t *drawing = control_flow_data->drawing;
2704 const gchar *name = g_quark_to_string(process->name);
2705 ProcessInfo *process_info;
2706 processlist_add(process_list,
2707 drawing,
2708 pid,
2709 process->last_cpu_index,
2710 process->ppid,
2711 &birth,
2712 tfc->t_context->index,
2713 name,
2714 &pl_height,
2715 &process_info,
2716 &hashed_process_data);
2717 gtk_widget_set_size_request(drawing->drawing_area,
2718 -1,
2719 pl_height);
2720 gtk_widget_queue_draw(drawing->drawing_area);
2721 }
2722 }
2723
2724 /* Now, the process is in the state hash and our own process hash.
2725 * We definitely can draw the items related to the ending state.
2726 */
2727
2728 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2729 evtime) > 0))
2730 {
2731 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2732 TimeWindow time_window =
2733 lttvwindow_get_time_window(control_flow_data->tab);
2734
2735#ifdef EXTRA_CHECK
2736 if(ltt_time_compare(evtime, time_window.start_time) == -1
2737 || ltt_time_compare(evtime, time_window.end_time) == 1)
2738 return;
2739#endif //EXTRA_CHECK
2740 Drawing_t *drawing = control_flow_data->drawing;
2741 guint width = drawing->width;
2742 guint x;
2743 convert_time_to_pixels(
2744 time_window,
2745 evtime,
2746 width,
2747 &x);
2748
2749 /* Draw collision indicator */
2750 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2751 gdk_draw_point(hashed_process_data->pixmap,
2752 drawing->gc,
2753 x,
2754 (hashed_process_data->height/2)-3);
2755 hashed_process_data->x.middle_marked = TRUE;
2756 }
2757 } else {
2758 TimeWindow time_window =
2759 lttvwindow_get_time_window(control_flow_data->tab);
2760
2761#ifdef EXTRA_CHECK
2762 if(ltt_time_compare(evtime, time_window.start_time) == -1
2763 || ltt_time_compare(evtime, time_window.end_time) == 1)
2764 return;
2765#endif //EXTRA_CHECK
2766 Drawing_t *drawing = control_flow_data->drawing;
2767 guint width = drawing->width;
2768 guint x;
2769
2770 convert_time_to_pixels(
2771 time_window,
2772 evtime,
2773 width,
2774 &x);
2775
2776
2777 /* Jump over draw if we are at the same x position */
2778 if(unlikely(x == hashed_process_data->x.middle &&
2779 hashed_process_data->x.middle_used))
2780 {
2781 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2782 /* Draw collision indicator */
2783 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2784 gdk_draw_point(hashed_process_data->pixmap,
2785 drawing->gc,
2786 x,
2787 (hashed_process_data->height/2)-3);
2788 hashed_process_data->x.middle_marked = TRUE;
2789 }
2790 /* jump */
2791 } else {
2792 DrawContext draw_context;
2793
2794 /* Now create the drawing context that will be used to draw
2795 * items related to the last state. */
2796 draw_context.drawable = hashed_process_data->pixmap;
2797 draw_context.gc = drawing->gc;
2798 draw_context.pango_layout = drawing->pango_layout;
2799 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2800 draw_context.drawinfo.end.x = x;
2801
2802 draw_context.drawinfo.y.over = 1;
2803 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2804 draw_context.drawinfo.y.under = hashed_process_data->height;
2805
2806 draw_context.drawinfo.start.offset.over = 0;
2807 draw_context.drawinfo.start.offset.middle = 0;
2808 draw_context.drawinfo.start.offset.under = 0;
2809 draw_context.drawinfo.end.offset.over = 0;
2810 draw_context.drawinfo.end.offset.middle = 0;
2811 draw_context.drawinfo.end.offset.under = 0;
2812
2813 {
2814 /* Draw the line */
2815 PropertiesLine prop_line = prepare_s_e_line(process);
2816 draw_line((void*)&prop_line, (void*)&draw_context);
2817
2818 }
2819 /* become the last x position */
2820 hashed_process_data->x.middle = x;
2821 hashed_process_data->x.middle_used = TRUE;
2822 hashed_process_data->x.middle_marked = FALSE;
2823
2824 /* Calculate the next good time */
2825 convert_pixels_to_time(width, x+1, time_window,
2826 &hashed_process_data->next_good_time);
2827 }
2828 }
2829
2830 } else if(sub_id == 7) /* release */ {
2831
2832 guint pid;
2833 {
2834 LttField *f = ltt_event_field(e);
2835 LttField *element;
2836 element = ltt_field_member(f,1);
2837 pid = ltt_event_get_long_unsigned(e,element);
2838 }
2839
2840 /* Add process to process list (if not present) */
2841 /* Don't care about the process if it's not in the state hash already :
2842 * that means a process that has never done anything in the trace and
2843 * unknown suddently gets destroyed : no state meaningful to show. */
2844 LttvProcessState *process = lttv_state_find_process(tfs, pid);
2845
2846 if(process != NULL) {
2847 LttTime birth;
2848 guint pl_height = 0;
2849 HashedProcessData *hashed_process_data = NULL;
2850
2851 ProcessList *process_list = control_flow_data->process_list;
2852
2853 birth = process->creation_time;
2854
2855 /* Cannot use current process : this event happens on another process,
2856 * action done by the parent. */
2857 hashed_process_data = processlist_get_process_data(process_list,
2858 pid,
2859 process->last_cpu_index,
2860 &birth,
2861 tfc->t_context->index);
2862 if(unlikely(hashed_process_data == NULL))
2863 {
2864 g_assert(pid == 0 || pid != process->ppid);
2865 /* Process not present */
2866 Drawing_t *drawing = control_flow_data->drawing;
2867 ProcessInfo *process_info;
2868 processlist_add(process_list,
2869 drawing,
2870 pid,
2871 process->last_cpu_index,
2872 process->ppid,
2873 &birth,
2874 tfc->t_context->index,
2875 process->name,
2876 &pl_height,
2877 &process_info,
2878 &hashed_process_data);
2879 gtk_widget_set_size_request(drawing->drawing_area,
2880 -1,
2881 pl_height);
2882 gtk_widget_queue_draw(drawing->drawing_area);
2883 }
2884
2885 /* Now, the process is in the state hash and our own process hash.
2886 * We definitely can draw the items related to the ending state.
2887 */
2888
2889 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
2890 evtime) > 0))
2891 {
2892 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2893 TimeWindow time_window =
2894 lttvwindow_get_time_window(control_flow_data->tab);
2895
2896#ifdef EXTRA_CHECK
2897 if(ltt_time_compare(evtime, time_window.start_time) == -1
2898 || ltt_time_compare(evtime, time_window.end_time) == 1)
2899 return;
2900#endif //EXTRA_CHECK
2901 Drawing_t *drawing = control_flow_data->drawing;
2902 guint width = drawing->width;
2903 guint x;
2904 convert_time_to_pixels(
2905 time_window,
2906 evtime,
2907 width,
2908 &x);
2909
2910 /* Draw collision indicator */
2911 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2912 gdk_draw_point(hashed_process_data->pixmap,
2913 drawing->gc,
2914 x,
2915 (hashed_process_data->height/2)-3);
2916 hashed_process_data->x.middle_marked = TRUE;
2917 }
2918 } else {
2919 TimeWindow time_window =
2920 lttvwindow_get_time_window(control_flow_data->tab);
2921
2922#ifdef EXTRA_CHECK
2923 if(ltt_time_compare(evtime, time_window.start_time) == -1
2924 || ltt_time_compare(evtime, time_window.end_time) == 1)
2925 return;
2926#endif //EXTRA_CHECK
2927 Drawing_t *drawing = control_flow_data->drawing;
2928 guint width = drawing->width;
2929 guint x;
2930
2931 convert_time_to_pixels(
2932 time_window,
2933 evtime,
2934 width,
2935 &x);
2936
2937
2938 /* Jump over draw if we are at the same x position */
2939 if(unlikely(x == hashed_process_data->x.middle &&
2940 hashed_process_data->x.middle_used))
2941 {
2942 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2943 /* Draw collision indicator */
2944 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2945 gdk_draw_point(hashed_process_data->pixmap,
2946 drawing->gc,
2947 x,
2948 (hashed_process_data->height/2)-3);
2949 hashed_process_data->x.middle_marked = TRUE;
2950 }
2951 /* jump */
2952 } else {
2953 DrawContext draw_context;
2954
2955 /* Now create the drawing context that will be used to draw
2956 * items related to the last state. */
2957 draw_context.drawable = hashed_process_data->pixmap;
2958 draw_context.gc = drawing->gc;
2959 draw_context.pango_layout = drawing->pango_layout;
2960 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2961 draw_context.drawinfo.end.x = x;
2962
2963 draw_context.drawinfo.y.over = 1;
2964 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2965 draw_context.drawinfo.y.under = hashed_process_data->height;
2966
2967 draw_context.drawinfo.start.offset.over = 0;
2968 draw_context.drawinfo.start.offset.middle = 0;
2969 draw_context.drawinfo.start.offset.under = 0;
2970 draw_context.drawinfo.end.offset.over = 0;
2971 draw_context.drawinfo.end.offset.middle = 0;
2972 draw_context.drawinfo.end.offset.under = 0;
2973
2974 {
2975 /* Draw the line */
2976 PropertiesLine prop_line = prepare_s_e_line(process);
2977 draw_line((void*)&prop_line, (void*)&draw_context);
2978
2979 }
2980 /* become the last x position */
2981 hashed_process_data->x.middle = x;
2982 hashed_process_data->x.middle_used = TRUE;
2983 hashed_process_data->x.middle_marked = FALSE;
2984
2985 /* Calculate the next good time */
2986 convert_pixels_to_time(width, x+1, time_window,
2987 &hashed_process_data->next_good_time);
2988 }
2989 }
2990 }
2991
2992 }
2993 return 0;
2994
2995}
2996
2997#endif //0
2998
2999
3000
3001/* after_process_fork_hook
3002 *
3003 * Create the processlist entry for the child process. Put the last
3004 * position in x at the current time value.
3005 *
3006 * @param hook_data ControlFlowData structure of the viewer.
3007 * @param call_data Event context.
3008 *
3009 * This function adds items to be drawn in a queue for each process.
3010 *
3011 */
3012int after_process_fork_hook(void *hook_data, void *call_data)
3013{
3014 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3015 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3016 ControlFlowData *control_flow_data = events_request->viewer_data;
3017
3018 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3019
3020 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3021
3022 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3023
3024 LttEvent *e;
3025 e = ltt_tracefile_get_event(tfc->tf);
3026
3027 LttTime evtime = ltt_event_time(e);
3028
3029 guint child_pid;
3030 {
3031 child_pid = ltt_event_get_long_unsigned(e, thf->f2);
3032 }
3033
3034 /* Add process to process list (if not present) */
3035 LttvProcessState *process_child;
3036 LttTime birth;
3037 guint pl_height = 0;
3038 HashedProcessData *hashed_process_data_child = NULL;
3039
3040 ProcessList *process_list = control_flow_data->process_list;
3041
3042 /* Find child in the list... */
3043 process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
3044 /* It should exist, because we are after the state update. */
3045 g_assert(process_child != NULL);
3046
3047 birth = process_child->creation_time;
3048
3049 /* Cannot use current process, because this action is done by the parent
3050 * on its child. */
3051 hashed_process_data_child = processlist_get_process_data(process_list,
3052 child_pid,
3053 process_child->cpu,
3054 &birth,
3055 tfc->t_context->index);
3056 if(likely(hashed_process_data_child == NULL))
3057 {
3058 g_assert(child_pid == 0 || child_pid != process_child->ppid);
3059 /* Process not present */
3060 Drawing_t *drawing = control_flow_data->drawing;
3061 ProcessInfo *process_info;
3062 processlist_add(process_list,
3063 drawing,
3064 child_pid,
3065 process_child->cpu,
3066 process_child->ppid,
3067 &birth,
3068 tfc->t_context->index,
3069 process_child->name,
3070 &pl_height,
3071 &process_info,
3072 &hashed_process_data_child);
3073 gtk_widget_set_size_request(drawing->drawing_area,
3074 -1,
3075 pl_height);
3076 gtk_widget_queue_draw(drawing->drawing_area);
3077 }
3078
3079
3080 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
3081 evtime) <= 0))
3082 {
3083 TimeWindow time_window =
3084 lttvwindow_get_time_window(control_flow_data->tab);
3085
3086#ifdef EXTRA_CHECK
3087 if(ltt_time_compare(evtime, time_window.start_time) == -1
3088 || ltt_time_compare(evtime, time_window.end_time) == 1)
3089 return;
3090#endif //EXTRA_CHECK
3091 Drawing_t *drawing = control_flow_data->drawing;
3092 guint width = drawing->width;
3093 guint new_x;
3094 convert_time_to_pixels(
3095 time_window,
3096 evtime,
3097 width,
3098 &new_x);
3099
3100 if(likely(hashed_process_data_child->x.over != new_x)) {
3101 hashed_process_data_child->x.over = new_x;
3102 hashed_process_data_child->x.over_used = FALSE;
3103 hashed_process_data_child->x.over_marked = FALSE;
3104 }
3105 if(likely(hashed_process_data_child->x.middle != new_x)) {
3106 hashed_process_data_child->x.middle = new_x;
3107 hashed_process_data_child->x.middle_used = FALSE;
3108 hashed_process_data_child->x.middle_marked = FALSE;
3109 }
3110 if(likely(hashed_process_data_child->x.under != new_x)) {
3111 hashed_process_data_child->x.under = new_x;
3112 hashed_process_data_child->x.under_used = FALSE;
3113 hashed_process_data_child->x.under_marked = FALSE;
3114 }
3115 }
3116 return 0;
3117}
3118
3119
3120
3121/* after_process_exit_hook
3122 *
3123 * Create the processlist entry for the child process. Put the last
3124 * position in x at the current time value.
3125 *
3126 * @param hook_data ControlFlowData structure of the viewer.
3127 * @param call_data Event context.
3128 *
3129 * This function adds items to be drawn in a queue for each process.
3130 *
3131 */
3132int after_process_exit_hook(void *hook_data, void *call_data)
3133{
3134 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3135 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3136 ControlFlowData *control_flow_data = events_request->viewer_data;
3137
3138 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3139
3140 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3141
3142 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3143
3144 LttEvent *e;
3145 e = ltt_tracefile_get_event(tfc->tf);
3146
3147 LttTime evtime = ltt_event_time(e);
3148
3149 /* Add process to process list (if not present) */
3150 //LttvProcessState *process = tfs->process;
3151 guint cpu = ltt_tracefile_num(tfc->tf);
3152 LttvProcessState *process = ts->running_process[cpu];
3153
3154 /* It should exist, because we are after the state update. */
3155 g_assert(process != NULL);
3156
3157 guint pid = process->pid;
3158 LttTime birth;
3159 guint pl_height = 0;
3160 HashedProcessData *hashed_process_data = NULL;
3161
3162 ProcessList *process_list = control_flow_data->process_list;
3163
3164 birth = process->creation_time;
3165
3166 if(likely(process_list->current_hash_data[cpu] != NULL) ){
3167 hashed_process_data = process_list->current_hash_data[cpu];
3168 } else {
3169 hashed_process_data = processlist_get_process_data(process_list,
3170 pid,
3171 process->cpu,
3172 &birth,
3173 tfc->t_context->index);
3174 if(unlikely(hashed_process_data == NULL))
3175 {
3176 g_assert(pid == 0 || pid != process->ppid);
3177 /* Process not present */
3178 Drawing_t *drawing = control_flow_data->drawing;
3179 ProcessInfo *process_info;
3180 processlist_add(process_list,
3181 drawing,
3182 pid,
3183 process->cpu,
3184 process->ppid,
3185 &birth,
3186 tfc->t_context->index,
3187 process->name,
3188 &pl_height,
3189 &process_info,
3190 &hashed_process_data);
3191 gtk_widget_set_size_request(drawing->drawing_area,
3192 -1,
3193 pl_height);
3194 gtk_widget_queue_draw(drawing->drawing_area);
3195 }
3196
3197 /* Set the current process */
3198 process_list->current_hash_data[process->cpu] =
3199 hashed_process_data;
3200 }
3201
3202 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3203 evtime) <= 0))
3204 {
3205 TimeWindow time_window =
3206 lttvwindow_get_time_window(control_flow_data->tab);
3207
3208#ifdef EXTRA_CHECK
3209 if(ltt_time_compare(evtime, time_window.start_time) == -1
3210 || ltt_time_compare(evtime, time_window.end_time) == 1)
3211 return;
3212#endif //EXTRA_CHECK
3213 Drawing_t *drawing = control_flow_data->drawing;
3214 guint width = drawing->width;
3215 guint new_x;
3216 convert_time_to_pixels(
3217 time_window,
3218 evtime,
3219 width,
3220 &new_x);
3221 if(unlikely(hashed_process_data->x.middle != new_x)) {
3222 hashed_process_data->x.middle = new_x;
3223 hashed_process_data->x.middle_used = FALSE;
3224 hashed_process_data->x.middle_marked = FALSE;
3225 }
3226 }
3227
3228 return 0;
3229}
3230
3231
3232#if 0
3233
3234/* after_process_hook
3235 *
3236 * Create the processlist entry for the child process. Put the last
3237 * position in x at the current time value.
3238 *
3239 * @param hook_data ControlFlowData structure of the viewer.
3240 * @param call_data Event context.
3241 *
3242 * This function adds items to be drawn in a queue for each process.
3243 *
3244 */
3245int after_process_hook(void *hook_data, void *call_data)
3246{
3247 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3248 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3249 ControlFlowData *control_flow_data = events_request->viewer_data;
3250
3251 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3252
3253 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3254
3255 LttEvent *e;
3256 e = ltt_tracefile_get_event(tfc->tf);
3257
3258 LttTime evtime = ltt_event_time(e);
3259
3260 guint sub_id;
3261 guint param1;
3262 {
3263 LttField *f = ltt_event_field(e);
3264 LttField *element;
3265 element = ltt_field_member(f,0);
3266 sub_id = ltt_event_get_long_unsigned(e,element);
3267 element = ltt_field_member(f,1);
3268 param1 = ltt_event_get_long_unsigned(e,element);
3269 }
3270
3271 if(sub_id == 2) { /* fork */
3272
3273 guint child_pid = param1;
3274 /* Add process to process list (if not present) */
3275 LttvProcessState *process_child;
3276 LttTime birth;
3277 guint pl_height = 0;
3278 HashedProcessData *hashed_process_data_child = NULL;
3279
3280 ProcessList *process_list = control_flow_data->process_list;
3281
3282 /* Find child in the list... */
3283 process_child = lttv_state_find_process(tfs, child_pid);
3284 /* It should exist, because we are after the state update. */
3285 g_assert(process_child != NULL);
3286
3287 birth = process_child->creation_time;
3288
3289 /* Cannot use current process, because this action is done by the parent
3290 * on its child. */
3291 hashed_process_data_child = processlist_get_process_data(process_list,
3292 child_pid,
3293 process_child->last_cpu_index,
3294 &birth,
3295 tfc->t_context->index);
3296 if(likely(hashed_process_data_child == NULL))
3297 {
3298 g_assert(child_pid == 0 || child_pid != process_child->ppid);
3299 /* Process not present */
3300 Drawing_t *drawing = control_flow_data->drawing;
3301 const gchar *name = g_quark_to_string(process_child->name);
3302 ProcessInfo *process_info;
3303 processlist_add(process_list,
3304 drawing,
3305 child_pid,
3306 process_child->last_cpu_index,
3307 process_child->ppid,
3308 &birth,
3309 tfc->t_context->index,
3310 name,
3311 &pl_height,
3312 &process_info,
3313 &hashed_process_data_child);
3314 gtk_widget_set_size_request(drawing->drawing_area,
3315 -1,
3316 pl_height);
3317 gtk_widget_queue_draw(drawing->drawing_area);
3318 }
3319
3320
3321 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
3322 evtime) <= 0))
3323 {
3324 TimeWindow time_window =
3325 lttvwindow_get_time_window(control_flow_data->tab);
3326
3327#ifdef EXTRA_CHECK
3328 if(ltt_time_compare(evtime, time_window.start_time) == -1
3329 || ltt_time_compare(evtime, time_window.end_time) == 1)
3330 return;
3331#endif //EXTRA_CHECK
3332 Drawing_t *drawing = control_flow_data->drawing;
3333 guint width = drawing->width;
3334 guint new_x;
3335 convert_time_to_pixels(
3336 time_window,
3337 evtime,
3338 width,
3339 &new_x);
3340
3341 if(likely(hashed_process_data_child->x.over != new_x)) {
3342 hashed_process_data_child->x.over = new_x;
3343 hashed_process_data_child->x.over_used = FALSE;
3344 hashed_process_data_child->x.over_marked = FALSE;
3345 }
3346 if(likely(hashed_process_data_child->x.middle != new_x)) {
3347 hashed_process_data_child->x.middle = new_x;
3348 hashed_process_data_child->x.middle_used = FALSE;
3349 hashed_process_data_child->x.middle_marked = FALSE;
3350 }
3351 if(likely(hashed_process_data_child->x.under != new_x)) {
3352 hashed_process_data_child->x.under = new_x;
3353 hashed_process_data_child->x.under_used = FALSE;
3354 hashed_process_data_child->x.under_marked = FALSE;
3355 }
3356 }
3357
3358 } else if(sub_id == 3) { /* exit */
3359
3360 /* Add process to process list (if not present) */
3361 LttvProcessState *process = tfs->process;
3362 guint pid = process->pid;
3363 LttTime birth;
3364 guint pl_height = 0;
3365 HashedProcessData *hashed_process_data = NULL;
3366
3367 ProcessList *process_list = control_flow_data->process_list;
3368
3369 /* It should exist, because we are after the state update. */
3370 g_assert(process != NULL);
3371
3372 birth = process->creation_time;
3373
3374 if(likely(process_list->current_hash_data[ltt_tracefile_num(tfc->tf)] != NULL) ){
3375 hashed_process_data = process_list->current_hash_data[ltt_tracefile_num(tfc->tf)];
3376 } else {
3377 hashed_process_data = processlist_get_process_data(process_list,
3378 pid,
3379 process->last_cpu_index,
3380 &birth,
3381 tfc->t_context->index);
3382 if(unlikely(hashed_process_data == NULL))
3383 {
3384 g_assert(pid == 0 || pid != process->ppid);
3385 /* Process not present */
3386 Drawing_t *drawing = control_flow_data->drawing;
3387 const gchar *name = g_quark_to_string(process->name);
3388 ProcessInfo *process_info;
3389 processlist_add(process_list,
3390 drawing,
3391 pid,
3392 process->last_cpu_index,
3393 process->ppid,
3394 &birth,
3395 tfc->t_context->index,
3396 name,
3397 &pl_height,
3398 &process_info,
3399 &hashed_process_data);
3400 gtk_widget_set_size_request(drawing->drawing_area,
3401 -1,
3402 pl_height);
3403 gtk_widget_queue_draw(drawing->drawing_area);
3404 }
3405
3406 /* Set the current process */
3407 process_list->current_hash_data[process->last_cpu_index] =
3408 hashed_process_data;
3409 }
3410
3411 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3412 evtime) <= 0))
3413 {
3414 TimeWindow time_window =
3415 lttvwindow_get_time_window(control_flow_data->tab);
3416
3417#ifdef EXTRA_CHECK
3418 if(ltt_time_compare(evtime, time_window.start_time) == -1
3419 || ltt_time_compare(evtime, time_window.end_time) == 1)
3420 return;
3421#endif //EXTRA_CHECK
3422 Drawing_t *drawing = control_flow_data->drawing;
3423 guint width = drawing->width;
3424 guint new_x;
3425 convert_time_to_pixels(
3426 time_window,
3427 evtime,
3428 width,
3429 &new_x);
3430 if(unlikely(hashed_process_data->x.middle != new_x)) {
3431 hashed_process_data->x.middle = new_x;
3432 hashed_process_data->x.middle_used = FALSE;
3433 hashed_process_data->x.middle_marked = FALSE;
3434 }
3435 }
3436
3437 }
3438 return 0;
3439
3440}
3441#endif //0
3442
3443/* Get the filename of the process to print */
3444int after_fs_exec_hook(void *hook_data, void *call_data)
3445{
3446 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
3447 EventsRequest *events_request = (EventsRequest*)thf->hook_data;
3448 ControlFlowData *control_flow_data = events_request->viewer_data;
3449
3450 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
3451
3452 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
3453
3454 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
3455
3456 guint cpu = ltt_tracefile_num(tfc->tf);
3457 LttvProcessState *process = ts->running_process[cpu];
3458 g_assert(process != NULL);
3459
3460 guint pid = process->pid;
3461
3462 /* Well, the process_out existed : we must get it in the process hash
3463 * or add it, and draw its items.
3464 */
3465 /* Add process to process list (if not present) */
3466 guint pl_height = 0;
3467 HashedProcessData *hashed_process_data = NULL;
3468 ProcessList *process_list = control_flow_data->process_list;
3469 LttTime birth = process->creation_time;
3470
3471 if(likely(process_list->current_hash_data[cpu] != NULL)) {
3472 hashed_process_data = process_list->current_hash_data[cpu];
3473 } else {
3474 hashed_process_data = processlist_get_process_data(process_list,
3475 pid,
3476 process->cpu,
3477 &birth,
3478 tfc->t_context->index);
3479 if(unlikely(hashed_process_data == NULL))
3480 {
3481 g_assert(pid == 0 || pid != process->ppid);
3482 ProcessInfo *process_info;
3483 /* Process not present */
3484 Drawing_t *drawing = control_flow_data->drawing;
3485 processlist_add(process_list,
3486 drawing,
3487 pid,
3488 process->cpu,
3489 process->ppid,
3490 &birth,
3491 tfc->t_context->index,
3492 process->name,
3493 &pl_height,
3494 &process_info,
3495 &hashed_process_data);
3496 gtk_widget_set_size_request(drawing->drawing_area,
3497 -1,
3498 pl_height);
3499 gtk_widget_queue_draw(drawing->drawing_area);
3500 }
3501 /* Set the current process */
3502 process_list->current_hash_data[process->cpu] =
3503 hashed_process_data;
3504 }
3505
3506 processlist_set_name(process_list, process->name, hashed_process_data);
3507
3508 return 0;
3509
3510}
3511
3512
3513
3514
3515gint update_time_window_hook(void *hook_data, void *call_data)
3516{
3517 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3518 Drawing_t *drawing = control_flow_data->drawing;
3519 ProcessList *process_list = control_flow_data->process_list;
3520
3521 const TimeWindowNotifyData *time_window_nofify_data =
3522 ((const TimeWindowNotifyData *)call_data);
3523
3524 TimeWindow *old_time_window =
3525 time_window_nofify_data->old_time_window;
3526 TimeWindow *new_time_window =
3527 time_window_nofify_data->new_time_window;
3528
3529 /* Update the ruler */
3530 drawing_update_ruler(control_flow_data->drawing,
3531 new_time_window);
3532
3533
3534 /* Two cases : zoom in/out or scrolling */
3535
3536 /* In order to make sure we can reuse the old drawing, the scale must
3537 * be the same and the new time interval being partly located in the
3538 * currently shown time interval. (reuse is only for scrolling)
3539 */
3540
3541 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
3542 old_time_window->start_time.tv_sec,
3543 old_time_window->start_time.tv_nsec,
3544 old_time_window->time_width.tv_sec,
3545 old_time_window->time_width.tv_nsec);
3546
3547 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
3548 new_time_window->start_time.tv_sec,
3549 new_time_window->start_time.tv_nsec,
3550 new_time_window->time_width.tv_sec,
3551 new_time_window->time_width.tv_nsec);
3552
3553 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
3554 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
3555 {
3556 /* Same scale (scrolling) */
3557 g_info("scrolling");
3558 LttTime *ns = &new_time_window->start_time;
3559 LttTime *nw = &new_time_window->time_width;
3560 LttTime *os = &old_time_window->start_time;
3561 LttTime *ow = &old_time_window->time_width;
3562 LttTime old_end = old_time_window->end_time;
3563 LttTime new_end = new_time_window->end_time;
3564 //if(ns<os+w<ns+w)
3565 //if(ns<os+w && os+w<ns+w)
3566 //if(ns<old_end && os<ns)
3567 if(ltt_time_compare(*ns, old_end) == -1
3568 && ltt_time_compare(*os, *ns) == -1)
3569 {
3570 g_info("scrolling near right");
3571 /* Scroll right, keep right part of the screen */
3572 guint x = 0;
3573 guint width = control_flow_data->drawing->width;
3574 convert_time_to_pixels(
3575 *old_time_window,
3576 *ns,
3577 width,
3578 &x);
3579
3580 /* Copy old data to new location */
3581 copy_pixmap_region(process_list,
3582 NULL,
3583 control_flow_data->drawing->drawing_area->style->black_gc,
3584 NULL,
3585 x, 0,
3586 0, 0,
3587 control_flow_data->drawing->width-x+SAFETY, -1);
3588
3589 if(drawing->damage_begin == drawing->damage_end)
3590 drawing->damage_begin = control_flow_data->drawing->width-x;
3591 else
3592 drawing->damage_begin = 0;
3593
3594 drawing->damage_end = control_flow_data->drawing->width;
3595
3596 /* Clear the data request background, but not SAFETY */
3597 rectangle_pixmap(process_list,
3598 control_flow_data->drawing->drawing_area->style->black_gc,
3599 TRUE,
3600 drawing->damage_begin+SAFETY, 0,
3601 drawing->damage_end - drawing->damage_begin, // do not overlap
3602 -1);
3603 gtk_widget_queue_draw(drawing->drawing_area);
3604 //gtk_widget_queue_draw_area (drawing->drawing_area,
3605 // 0,0,
3606 // control_flow_data->drawing->width,
3607 // control_flow_data->drawing->height);
3608
3609 /* Get new data for the rest. */
3610 drawing_data_request(control_flow_data->drawing,
3611 drawing->damage_begin, 0,
3612 drawing->damage_end - drawing->damage_begin,
3613 control_flow_data->drawing->height);
3614 } else {
3615 //if(ns<os<ns+w)
3616 //if(ns<os && os<ns+w)
3617 //if(ns<os && os<new_end)
3618 if(ltt_time_compare(*ns,*os) == -1
3619 && ltt_time_compare(*os,new_end) == -1)
3620 {
3621 g_info("scrolling near left");
3622 /* Scroll left, keep left part of the screen */
3623 guint x = 0;
3624 guint width = control_flow_data->drawing->width;
3625 convert_time_to_pixels(
3626 *new_time_window,
3627 *os,
3628 width,
3629 &x);
3630
3631 /* Copy old data to new location */
3632 copy_pixmap_region (process_list,
3633 NULL,
3634 control_flow_data->drawing->drawing_area->style->black_gc,
3635 NULL,
3636 0, 0,
3637 x, 0,
3638 -1, -1);
3639
3640 if(drawing->damage_begin == drawing->damage_end)
3641 drawing->damage_end = x;
3642 else
3643 drawing->damage_end =
3644 control_flow_data->drawing->width;
3645
3646 drawing->damage_begin = 0;
3647
3648 rectangle_pixmap (process_list,
3649 control_flow_data->drawing->drawing_area->style->black_gc,
3650 TRUE,
3651 drawing->damage_begin, 0,
3652 drawing->damage_end - drawing->damage_begin, // do not overlap
3653 -1);
3654
3655 gtk_widget_queue_draw(drawing->drawing_area);
3656 //gtk_widget_queue_draw_area (drawing->drawing_area,
3657 // 0,0,
3658 // control_flow_data->drawing->width,
3659 // control_flow_data->drawing->height);
3660
3661
3662 /* Get new data for the rest. */
3663 drawing_data_request(control_flow_data->drawing,
3664 drawing->damage_begin, 0,
3665 drawing->damage_end - drawing->damage_begin,
3666 control_flow_data->drawing->height);
3667
3668 } else {
3669 if(ltt_time_compare(*ns,*os) == 0)
3670 {
3671 g_info("not scrolling");
3672 } else {
3673 g_info("scrolling far");
3674 /* Cannot reuse any part of the screen : far jump */
3675
3676
3677 rectangle_pixmap (process_list,
3678 control_flow_data->drawing->drawing_area->style->black_gc,
3679 TRUE,
3680 0, 0,
3681 control_flow_data->drawing->width+SAFETY, // do not overlap
3682 -1);
3683
3684 //gtk_widget_queue_draw_area (drawing->drawing_area,
3685 // 0,0,
3686 // control_flow_data->drawing->width,
3687 // control_flow_data->drawing->height);
3688 gtk_widget_queue_draw(drawing->drawing_area);
3689
3690 drawing->damage_begin = 0;
3691 drawing->damage_end = control_flow_data->drawing->width;
3692
3693 drawing_data_request(control_flow_data->drawing,
3694 0, 0,
3695 control_flow_data->drawing->width,
3696 control_flow_data->drawing->height);
3697
3698 }
3699 }
3700 }
3701 } else {
3702 /* Different scale (zoom) */
3703 g_info("zoom");
3704
3705 rectangle_pixmap (process_list,
3706 control_flow_data->drawing->drawing_area->style->black_gc,
3707 TRUE,
3708 0, 0,
3709 control_flow_data->drawing->width+SAFETY, // do not overlap
3710 -1);
3711
3712 //gtk_widget_queue_draw_area (drawing->drawing_area,
3713 // 0,0,
3714 // control_flow_data->drawing->width,
3715 // control_flow_data->drawing->height);
3716 gtk_widget_queue_draw(drawing->drawing_area);
3717
3718 drawing->damage_begin = 0;
3719 drawing->damage_end = control_flow_data->drawing->width;
3720
3721 drawing_data_request(control_flow_data->drawing,
3722 0, 0,
3723 control_flow_data->drawing->width,
3724 control_flow_data->drawing->height);
3725 }
3726
3727
3728
3729 return 0;
3730}
3731
3732gint traceset_notify(void *hook_data, void *call_data)
3733{
3734 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3735 Drawing_t *drawing = control_flow_data->drawing;
3736
3737
3738 drawing_clear(control_flow_data->drawing);
3739 processlist_clear(control_flow_data->process_list);
3740 gtk_widget_set_size_request(
3741 control_flow_data->drawing->drawing_area,
3742 -1, processlist_get_height(control_flow_data->process_list));
3743 redraw_notify(control_flow_data, NULL);
3744
3745 request_background_data(control_flow_data);
3746
3747 return FALSE;
3748}
3749
3750gint redraw_notify(void *hook_data, void *call_data)
3751{
3752 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3753 Drawing_t *drawing = control_flow_data->drawing;
3754 GtkWidget *widget = drawing->drawing_area;
3755
3756 drawing->damage_begin = 0;
3757 drawing->damage_end = drawing->width;
3758
3759 /* fun feature, to be separated someday... */
3760 drawing_clear(control_flow_data->drawing);
3761 processlist_clear(control_flow_data->process_list);
3762 gtk_widget_set_size_request(
3763 control_flow_data->drawing->drawing_area,
3764 -1, processlist_get_height(control_flow_data->process_list));
3765 // Clear the images
3766 rectangle_pixmap (control_flow_data->process_list,
3767 widget->style->black_gc,
3768 TRUE,
3769 0, 0,
3770 drawing->alloc_width,
3771 -1);
3772
3773 gtk_widget_queue_draw(drawing->drawing_area);
3774
3775 if(drawing->damage_begin < drawing->damage_end)
3776 {
3777 drawing_data_request(drawing,
3778 drawing->damage_begin,
3779 0,
3780 drawing->damage_end-drawing->damage_begin,
3781 drawing->height);
3782 }
3783
3784 //gtk_widget_queue_draw_area(drawing->drawing_area,
3785 // 0,0,
3786 // drawing->width,
3787 // drawing->height);
3788 return FALSE;
3789
3790}
3791
3792
3793gint continue_notify(void *hook_data, void *call_data)
3794{
3795 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
3796 Drawing_t *drawing = control_flow_data->drawing;
3797
3798 //g_assert(widget->allocation.width == drawing->damage_end);
3799
3800 if(drawing->damage_begin < drawing->damage_end)
3801 {
3802 drawing_data_request(drawing,
3803 drawing->damage_begin,
3804 0,
3805 drawing->damage_end-drawing->damage_begin,
3806 drawing->height);
3807 }
3808
3809 return FALSE;
3810}
3811
3812
3813gint update_current_time_hook(void *hook_data, void *call_data)
3814{
3815 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
3816 Drawing_t *drawing = control_flow_data->drawing;
3817
3818 LttTime current_time = *((LttTime*)call_data);
3819
3820 TimeWindow time_window =
3821 lttvwindow_get_time_window(control_flow_data->tab);
3822
3823 LttTime time_begin = time_window.start_time;
3824 LttTime width = time_window.time_width;
3825 LttTime half_width;
3826 {
3827 guint64 time_ll = ltt_time_to_uint64(width);
3828 time_ll = time_ll >> 1; /* divide by two */
3829 half_width = ltt_time_from_uint64(time_ll);
3830 }
3831 LttTime time_end = ltt_time_add(time_begin, width);
3832
3833 LttvTracesetContext * tsc =
3834 lttvwindow_get_traceset_context(control_flow_data->tab);
3835
3836 LttTime trace_start = tsc->time_span.start_time;
3837 LttTime trace_end = tsc->time_span.end_time;
3838
3839 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
3840 current_time.tv_nsec);
3841
3842
3843
3844 /* If current time is inside time interval, just move the highlight
3845 * bar */
3846
3847 /* Else, we have to change the time interval. We have to tell it
3848 * to the main window. */
3849 /* The time interval change will take care of placing the current
3850 * time at the center of the visible area, or nearest possible if we are
3851 * at one end of the trace. */
3852
3853
3854 if(ltt_time_compare(current_time, time_begin) < 0)
3855 {
3856 TimeWindow new_time_window;
3857
3858 if(ltt_time_compare(current_time,
3859 ltt_time_add(trace_start,half_width)) < 0)
3860 time_begin = trace_start;
3861 else
3862 time_begin = ltt_time_sub(current_time,half_width);
3863
3864 new_time_window.start_time = time_begin;
3865 new_time_window.time_width = width;
3866 new_time_window.time_width_double = ltt_time_to_double(width);
3867 new_time_window.end_time = ltt_time_add(time_begin, width);
3868
3869 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3870 }
3871 else if(ltt_time_compare(current_time, time_end) > 0)
3872 {
3873 TimeWindow new_time_window;
3874
3875 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
3876 time_begin = ltt_time_sub(trace_end,width);
3877 else
3878 time_begin = ltt_time_sub(current_time,half_width);
3879
3880 new_time_window.start_time = time_begin;
3881 new_time_window.time_width = width;
3882 new_time_window.time_width_double = ltt_time_to_double(width);
3883 new_time_window.end_time = ltt_time_add(time_begin, width);
3884
3885 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3886
3887 }
3888 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
3889
3890
3891 return 0;
3892}
3893
3894typedef struct _ClosureData {
3895 EventsRequest *events_request;
3896 LttvTracesetState *tss;
3897 LttTime end_time;
3898 guint x_end;
3899} ClosureData;
3900
3901
3902void draw_closure(gpointer key, gpointer value, gpointer user_data)
3903{
3904 ProcessInfo *process_info = (ProcessInfo*)key;
3905 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
3906 ClosureData *closure_data = (ClosureData*)user_data;
3907
3908 EventsRequest *events_request = closure_data->events_request;
3909 ControlFlowData *control_flow_data = events_request->viewer_data;
3910
3911 LttvTracesetState *tss = closure_data->tss;
3912 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
3913
3914 LttTime evtime = closure_data->end_time;
3915
3916 {
3917 /* For the process */
3918 /* First, check if the current process is in the state computation
3919 * process list. If it is there, that means we must add it right now and
3920 * draw items from the beginning of the read for it. If it is not
3921 * present, it's a new process and it was not present : it will
3922 * be added after the state update. */
3923#ifdef EXTRA_CHECK
3924 g_assert(lttv_traceset_number(tsc->ts) > 0);
3925#endif //EXTRA_CHECK
3926 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
3927 LttvTraceState *ts = (LttvTraceState*)tc;
3928
3929#if 0
3930 //FIXME : optimize data structures.
3931 LttvTracefileState *tfs;
3932 LttvTracefileContext *tfc;
3933 guint i;
3934 for(i=0;i<tc->tracefiles->len;i++) {
3935 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
3936 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
3937 && ltt_tracefile_num(tfc->tf) == process_info->cpu)
3938 break;
3939
3940 }
3941 g_assert(i<tc->tracefiles->len);
3942 tfs = LTTV_TRACEFILE_STATE(tfc);
3943#endif //0
3944 // LttvTracefileState *tfs =
3945 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
3946 // tracefiles[process_info->cpu];
3947
3948 LttvProcessState *process;
3949 process = lttv_state_find_process(ts, process_info->cpu,
3950 process_info->pid);
3951
3952 if(unlikely(process != NULL)) {
3953
3954 /* Only draw for processes that are currently in the trace states */
3955
3956 ProcessList *process_list = control_flow_data->process_list;
3957#ifdef EXTRA_CHECK
3958 /* Should be alike when background info is ready */
3959 if(control_flow_data->background_info_waiting==0)
3960 g_assert(ltt_time_compare(process->creation_time,
3961 process_info->birth) == 0);
3962#endif //EXTRA_CHECK
3963
3964 /* Now, the process is in the state hash and our own process hash.
3965 * We definitely can draw the items related to the ending state.
3966 */
3967
3968 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
3969 evtime) <= 0))
3970 {
3971 TimeWindow time_window =
3972 lttvwindow_get_time_window(control_flow_data->tab);
3973
3974#ifdef EXTRA_CHECK
3975 if(ltt_time_compare(evtime, time_window.start_time) == -1
3976 || ltt_time_compare(evtime, time_window.end_time) == 1)
3977 return;
3978#endif //EXTRA_CHECK
3979 Drawing_t *drawing = control_flow_data->drawing;
3980 guint width = drawing->width;
3981
3982 guint x = closure_data->x_end;
3983
3984 DrawContext draw_context;
3985
3986 /* Now create the drawing context that will be used to draw
3987 * items related to the last state. */
3988 draw_context.drawable = hashed_process_data->pixmap;
3989 draw_context.gc = drawing->gc;
3990 draw_context.pango_layout = drawing->pango_layout;
3991 draw_context.drawinfo.end.x = x;
3992
3993 draw_context.drawinfo.y.over = 1;
3994 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
3995 draw_context.drawinfo.y.under = hashed_process_data->height;
3996
3997 draw_context.drawinfo.start.offset.over = 0;
3998 draw_context.drawinfo.start.offset.middle = 0;
3999 draw_context.drawinfo.start.offset.under = 0;
4000 draw_context.drawinfo.end.offset.over = 0;
4001 draw_context.drawinfo.end.offset.middle = 0;
4002 draw_context.drawinfo.end.offset.under = 0;
4003#if 0
4004 /* Jump over draw if we are at the same x position */
4005 if(x == hashed_process_data->x.over)
4006 {
4007 /* jump */
4008 } else {
4009 draw_context.drawinfo.start.x = hashed_process_data->x.over;
4010 /* Draw the line */
4011 PropertiesLine prop_line = prepare_execmode_line(process);
4012 draw_line((void*)&prop_line, (void*)&draw_context);
4013
4014 hashed_process_data->x.over = x;
4015 }
4016#endif //0
4017
4018 if(unlikely(x == hashed_process_data->x.middle &&
4019 hashed_process_data->x.middle_used)) {
4020#if 0 /* do not mark closure : not missing information */
4021 if(hashed_process_data->x.middle_marked == FALSE) {
4022 /* Draw collision indicator */
4023 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
4024 gdk_draw_point(drawing->pixmap,
4025 drawing->gc,
4026 x,
4027 y+(height/2)-3);
4028 hashed_process_data->x.middle_marked = TRUE;
4029 }
4030#endif //0
4031 /* Jump */
4032 } else {
4033 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
4034 /* Draw the line */
4035 PropertiesLine prop_line = prepare_s_e_line(process);
4036 draw_line((void*)&prop_line, (void*)&draw_context);
4037
4038 /* become the last x position */
4039 if(likely(x != hashed_process_data->x.middle)) {
4040 hashed_process_data->x.middle = x;
4041 /* but don't use the pixel */
4042 hashed_process_data->x.middle_used = FALSE;
4043
4044 /* Calculate the next good time */
4045 convert_pixels_to_time(width, x+1, time_window,
4046 &hashed_process_data->next_good_time);
4047 }
4048 }
4049 }
4050 }
4051 }
4052 return;
4053}
4054
4055int before_chunk(void *hook_data, void *call_data)
4056{
4057 EventsRequest *events_request = (EventsRequest*)hook_data;
4058 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4059 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
4060#if 0
4061 /* Desactivate sort */
4062 gtk_tree_sortable_set_sort_column_id(
4063 GTK_TREE_SORTABLE(cfd->process_list->list_store),
4064 TRACE_COLUMN,
4065 GTK_SORT_ASCENDING);
4066#endif //0
4067 drawing_chunk_begin(events_request, tss);
4068
4069 return 0;
4070}
4071
4072int before_request(void *hook_data, void *call_data)
4073{
4074 EventsRequest *events_request = (EventsRequest*)hook_data;
4075 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4076
4077 drawing_data_request_begin(events_request, tss);
4078
4079 return 0;
4080}
4081
4082
4083/*
4084 * after request is necessary in addition of after chunk in order to draw
4085 * lines until the end of the screen. after chunk just draws lines until
4086 * the last event.
4087 *
4088 * for each process
4089 * draw closing line
4090 * expose
4091 */
4092int after_request(void *hook_data, void *call_data)
4093{
4094 EventsRequest *events_request = (EventsRequest*)hook_data;
4095 ControlFlowData *control_flow_data = events_request->viewer_data;
4096 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4097
4098 ProcessList *process_list = control_flow_data->process_list;
4099 LttTime end_time = events_request->end_time;
4100
4101 ClosureData closure_data;
4102 closure_data.events_request = (EventsRequest*)hook_data;
4103 closure_data.tss = tss;
4104 closure_data.end_time = end_time;
4105
4106 TimeWindow time_window =
4107 lttvwindow_get_time_window(control_flow_data->tab);
4108 guint width = control_flow_data->drawing->width;
4109 convert_time_to_pixels(
4110 time_window,
4111 end_time,
4112 width,
4113 &closure_data.x_end);
4114
4115
4116 /* Draw last items */
4117 g_hash_table_foreach(process_list->process_hash, draw_closure,
4118 (void*)&closure_data);
4119
4120
4121 /* Request expose */
4122 drawing_request_expose(events_request, tss, end_time);
4123 return 0;
4124}
4125
4126/*
4127 * for each process
4128 * draw closing line
4129 * expose
4130 */
4131int after_chunk(void *hook_data, void *call_data)
4132{
4133 EventsRequest *events_request = (EventsRequest*)hook_data;
4134 ControlFlowData *control_flow_data = events_request->viewer_data;
4135 LttvTracesetState *tss = (LttvTracesetState*)call_data;
4136 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
4137 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
4138 LttTime end_time;
4139
4140 ProcessList *process_list = control_flow_data->process_list;
4141
4142 g_free(process_list->current_hash_data);
4143 process_list->current_hash_data = NULL;
4144
4145 if(tfc != NULL)
4146 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
4147 else /* end of traceset, or position now out of request : end */
4148 end_time = events_request->end_time;
4149
4150 ClosureData closure_data;
4151 closure_data.events_request = (EventsRequest*)hook_data;
4152 closure_data.tss = tss;
4153 closure_data.end_time = end_time;
4154
4155 TimeWindow time_window =
4156 lttvwindow_get_time_window(control_flow_data->tab);
4157 guint width = control_flow_data->drawing->width;
4158 convert_time_to_pixels(
4159 time_window,
4160 end_time,
4161 width,
4162 &closure_data.x_end);
4163
4164 /* Draw last items */
4165 g_hash_table_foreach(process_list->process_hash, draw_closure,
4166 (void*)&closure_data);
4167#if 0
4168 /* Reactivate sort */
4169 gtk_tree_sortable_set_sort_column_id(
4170 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
4171 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
4172 GTK_SORT_ASCENDING);
4173
4174 update_index_to_pixmap(control_flow_data->process_list);
4175 /* Request a full expose : drawing scrambled */
4176 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
4177#endif //0
4178 /* Request expose (updates damages zone also) */
4179 drawing_request_expose(events_request, tss, end_time);
4180
4181 return 0;
4182}
4183
This page took 0.034473 seconds and 4 git commands to generate.