fix bug in current process
[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
49//#define PANGO_ENABLE_BACKEND
50#include <gtk/gtk.h>
51#include <gdk/gdk.h>
52#include <glib.h>
53#include <assert.h>
54#include <string.h>
55#include <stdio.h>
56
57//#include <pango/pango.h>
58
59#include <ltt/event.h>
60#include <ltt/time.h>
61#include <ltt/type.h>
62
63#include <lttv/lttv.h>
64#include <lttv/hook.h>
65#include <lttv/state.h>
66#include <lttvwindow/lttvwindow.h>
67#include <lttvwindow/lttvwindowtraces.h>
68
69
70#include "eventhooks.h"
71#include "cfv.h"
72#include "processlist.h"
73#include "drawing.h"
74#include "cfv-private.h"
75
76
77#define MAX_PATH_LEN 256
78
79
80#if 0
81typedef struct _ProcessAddClosure {
82 ControlFlowData *cfd;
83 guint trace_num;
84} ProcessAddClosure;
85
86static void process_add(gpointer key,
87 gpointer value,
88 gpointer user_data)
89{
90 LttvProcessState *process = (LttvProcessState*)value;
91 ProcessAddClosure *closure = (ProcessAddClosure*)user_data;
92 ControlFlowData *control_flow_data = closure->cfd;
93 guint trace_num = closure->trace_num;
94
95 /* Add process to process list (if not present) */
96 guint pid;
97 LttTime birth;
98 guint y = 0, height = 0, pl_height = 0;
99
100 ProcessList *process_list = control_flow_data->process_list;
101
102 pid = process->pid;
103 birth = process->creation_time;
104 const gchar *name = g_quark_to_string(process->name);
105 HashedProcessData *hashed_process_data = NULL;
106
107 if(processlist_get_process_pixels(process_list,
108 pid,
109 &birth,
110 trace_num,
111 &y,
112 &height,
113 &hashed_process_data) == 1)
114 {
115 /* Process not present */
116 processlist_add(process_list,
117 pid,
118 &birth,
119 trace_num,
120 name,
121 &pl_height,
122 &hashed_process_data);
123 processlist_get_process_pixels(process_list,
124 pid,
125 &birth,
126 trace_num,
127 &y,
128 &height,
129 &hashed_process_data);
130 drawing_insert_square( control_flow_data->drawing, y, height);
131 }
132}
133#endif //0
134
135
136/* Action to do when background computation completed.
137 *
138 * Wait for all the awaited computations to be over.
139 */
140
141gint background_ready(void *hook_data, void *call_data)
142{
143 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
144 LttvTrace *trace = (LttvTrace*)call_data;
145 LttvTracesetContext *tsc =
146 lttvwindow_get_traceset_context(control_flow_data->tab);
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 redraw_notify(control_flow_data, NULL);
156 }
157
158 return 0;
159}
160
161
162/* Request background computation. Verify if it is in progress or ready first.
163 * Only for each trace in the tab's traceset.
164 */
165void request_background_data(ControlFlowData *control_flow_data)
166{
167 LttvTracesetContext * tsc =
168 lttvwindow_get_traceset_context(control_flow_data->tab);
169 gint num_traces = lttv_traceset_number(tsc->ts);
170 gint i;
171 LttvTrace *trace;
172
173 LttvHooks *background_ready_hook =
174 lttv_hooks_new();
175 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
176 LTTV_PRIO_DEFAULT);
177 control_flow_data->background_info_waiting = 0;
178
179 for(i=0;i<num_traces;i++) {
180 trace = lttv_traceset_get(tsc->ts, i);
181
182 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) {
183
184 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
185 trace) == FALSE) {
186 /* We first remove requests that could have been done for the same
187 * information. Happens when two viewers ask for it before servicing
188 * starts.
189 */
190 lttvwindowtraces_background_request_remove(trace, "state");
191 lttvwindowtraces_background_request_queue(trace,
192 "state");
193 lttvwindowtraces_background_notify_queue(control_flow_data,
194 trace,
195 ltt_time_infinite,
196 NULL,
197 background_ready_hook);
198 control_flow_data->background_info_waiting++;
199 } else { /* in progress */
200
201 lttvwindowtraces_background_notify_current(control_flow_data,
202 trace,
203 ltt_time_infinite,
204 NULL,
205 background_ready_hook);
206 control_flow_data->background_info_waiting++;
207 }
208 } else {
209 /* Data ready. Be its nature, this viewer doesn't need to have
210 * its data ready hook called htere, because a background
211 * request is always linked with a redraw.
212 */
213 }
214
215 }
216
217 lttv_hooks_destroy(background_ready_hook);
218}
219
220
221
222
223/**
224 * Event Viewer's constructor hook
225 *
226 * This constructor is given as a parameter to the menuitem and toolbar button
227 * registration. It creates the list.
228 * @param tab A pointer to the parent tab.
229 * @return The widget created.
230 */
231GtkWidget *
232h_guicontrolflow(Tab *tab)
233{
234 g_info("h_guicontrolflow, %p", tab);
235 ControlFlowData *control_flow_data = guicontrolflow() ;
236
237 control_flow_data->tab = tab;
238
239 //g_debug("time width2 : %u",time_window->time_width);
240 // Unreg done in the GuiControlFlow_Destructor
241 lttvwindow_register_traceset_notify(tab,
242 traceset_notify,
243 control_flow_data);
244
245 lttvwindow_register_time_window_notify(tab,
246 update_time_window_hook,
247 control_flow_data);
248 lttvwindow_register_current_time_notify(tab,
249 update_current_time_hook,
250 control_flow_data);
251 lttvwindow_register_redraw_notify(tab,
252 redraw_notify,
253 control_flow_data);
254 lttvwindow_register_continue_notify(tab,
255 continue_notify,
256 control_flow_data);
257 request_background_data(control_flow_data);
258
259
260 return guicontrolflow_get_widget(control_flow_data) ;
261
262}
263
264int event_selected_hook(void *hook_data, void *call_data)
265{
266 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
267 guint *event_number = (guint*) call_data;
268
269 g_debug("DEBUG : event selected by main window : %u", *event_number);
270
271}
272
273/* Function that selects the color of status&exemode line */
274static __inline__ PropertiesLine prepare_s_e_line(LttvProcessState *process)
275{
276 PropertiesLine prop_line;
277 prop_line.line_width = 2;
278 prop_line.style = GDK_LINE_SOLID;
279 prop_line.y = MIDDLE;
280 //GdkColormap *colormap = gdk_colormap_get_system();
281
282 g_debug("prepare_status_line for state : %s",
283 g_quark_to_string(process->state->s));
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 EventsRequest *events_request = (EventsRequest*)hook_data;
382 ControlFlowData *control_flow_data = events_request->viewer_data;
383 Drawing_t *drawing = control_flow_data->drawing;
384
385 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
386
387 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
388 LttvTraceState *ts =(LttvTraceState *)((LttvTracefileContext*)tfs)->t_context;
389
390 LttEvent *e;
391 e = tfc->e;
392
393 LttTime evtime = ltt_event_time(e);
394
395 guint width = drawing->width;
396
397 /* we are in a schedchange, before the state update. We must draw the
398 * items corresponding to the state before it changes : now is the right
399 * time to do it.
400 */
401
402 guint pid_out;
403 guint pid_in;
404 {
405 LttField *f = ltt_event_field(e);
406 LttField *element;
407 element = ltt_field_member(f,0);
408 pid_out = ltt_event_get_long_unsigned(e,element);
409 element = ltt_field_member(f,1);
410 pid_in = ltt_event_get_long_unsigned(e,element);
411 g_debug("out : %u in : %u", pid_out, pid_in);
412 }
413
414 {
415 /* For the pid_out */
416 /* First, check if the current process is in the state computation
417 * process list. If it is there, that means we must add it right now and
418 * draw items from the beginning of the read for it. If it is not
419 * present, it's a new process and it was not present : it will
420 * be added after the state update. */
421 LttvProcessState *process;
422 /* unknown state, bad current pid */
423 if(tfs->process->pid != pid_out)
424 process = lttv_state_find_process(tfs, pid_out);
425 else
426 process = tfs->process;
427
428 if(process != NULL) {
429 /* Well, the process_out existed : we must get it in the process hash
430 * or add it, and draw its items.
431 */
432 /* Add process to process list (if not present) */
433 guint y = 0, height = 0, pl_height = 0;
434 HashedProcessData *hashed_process_data = NULL;
435 ProcessList *process_list = control_flow_data->process_list;
436 LttTime birth = process->creation_time;
437
438 if(processlist_get_process_pixels(process_list,
439 pid_out,
440 process->last_cpu_index,
441 &birth,
442 tfc->t_context->index,
443 &y,
444 &height,
445 &hashed_process_data) == 1)
446 {
447 g_assert(pid_out == 0 || pid_out != process->ppid);
448 const gchar *name = g_quark_to_string(process->name);
449 /* Process not present */
450 ProcessInfo *process_info;
451 processlist_add(process_list,
452 pid_out,
453 process->last_cpu_index,
454 process->ppid,
455 &birth,
456 tfc->t_context->index,
457 name,
458 &pl_height,
459 &process_info,
460 &hashed_process_data);
461 processlist_get_pixels_from_data(process_list,
462 hashed_process_data,
463 &y,
464 &height);
465 drawing_insert_square( drawing, y, height);
466 }
467
468 /* Now, the process is in the state hash and our own process hash.
469 * We definitely can draw the items related to the ending state.
470 */
471
472 /* Check if the x position is unset. In can have been left unset by
473 * a draw closure from a after chunk hook. This should never happen,
474 * because it must be set by before chunk hook to the damage_begin
475 * value.
476 */
477 g_assert(hashed_process_data->x.middle != -1);
478 if(ltt_time_compare(hashed_process_data->next_good_time,
479 evtime) > 0)
480 {
481 if(hashed_process_data->x.middle_marked == FALSE) {
482 TimeWindow time_window =
483 lttvwindow_get_time_window(control_flow_data->tab);
484#ifdef EXTRA_CHECK
485 if(ltt_time_compare(evtime, time_window.start_time) == -1
486 || ltt_time_compare(evtime, time_window.end_time) == 1)
487 return;
488#endif //EXTRA_CHECK
489
490 guint x;
491 convert_time_to_pixels(
492 time_window,
493 evtime,
494 width,
495 &x);
496
497 /* Draw collision indicator */
498 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
499 gdk_draw_point(drawing->pixmap,
500 drawing->gc,
501 x,
502 y+(height/2)-3);
503 hashed_process_data->x.middle_marked = TRUE;
504 }
505 } else {
506 TimeWindow time_window =
507 lttvwindow_get_time_window(control_flow_data->tab);
508#ifdef EXTRA_CHECK
509 if(ltt_time_compare(evtime, time_window.start_time) == -1
510 || ltt_time_compare(evtime, time_window.end_time) == 1)
511 return;
512#endif //EXTRA_CHECK
513
514 guint x;
515 convert_time_to_pixels(
516 time_window,
517 evtime,
518 width,
519 &x);
520
521
522 /* Jump over draw if we are at the same x position */
523 if(x == hashed_process_data->x.middle &&
524 hashed_process_data->x.middle_used)
525 {
526 if(hashed_process_data->x.middle_marked == FALSE) {
527 /* Draw collision indicator */
528 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
529 gdk_draw_point(drawing->pixmap,
530 drawing->gc,
531 x,
532 y+(height/2)-3);
533 hashed_process_data->x.middle_marked = TRUE;
534 }
535 /* jump */
536 } else {
537 DrawContext draw_context;
538
539 /* Now create the drawing context that will be used to draw
540 * items related to the last state. */
541 draw_context.drawable = drawing->pixmap;
542 draw_context.gc = drawing->gc;
543 draw_context.pango_layout = drawing->pango_layout;
544 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
545 draw_context.drawinfo.end.x = x;
546
547 draw_context.drawinfo.y.over = y+1;
548 draw_context.drawinfo.y.middle = y+(height/2);
549 draw_context.drawinfo.y.under = y+height;
550
551 draw_context.drawinfo.start.offset.over = 0;
552 draw_context.drawinfo.start.offset.middle = 0;
553 draw_context.drawinfo.start.offset.under = 0;
554 draw_context.drawinfo.end.offset.over = 0;
555 draw_context.drawinfo.end.offset.middle = 0;
556 draw_context.drawinfo.end.offset.under = 0;
557
558 {
559 /* Draw the line */
560 PropertiesLine prop_line = prepare_s_e_line(process);
561 draw_line((void*)&prop_line, (void*)&draw_context);
562
563 }
564 /* become the last x position */
565 hashed_process_data->x.middle = x;
566 hashed_process_data->x.middle_used = TRUE;
567 hashed_process_data->x.middle_marked = FALSE;
568
569 /* Calculate the next good time */
570 convert_pixels_to_time(width, x+1, time_window,
571 &hashed_process_data->next_good_time);
572 }
573 }
574 }
575 }
576
577 {
578 /* For the pid_in */
579 /* First, check if the current process is in the state computation
580 * process list. If it is there, that means we must add it right now and
581 * draw items from the beginning of the read for it. If it is not
582 * present, it's a new process and it was not present : it will
583 * be added after the state update. */
584 LttvProcessState *process;
585 process = lttv_state_find_process(tfs, pid_in);
586
587 if(process != NULL) {
588 /* Well, the process_out existed : we must get it in the process hash
589 * or add it, and draw its items.
590 */
591 /* Add process to process list (if not present) */
592 guint y = 0, height = 0, pl_height = 0;
593 HashedProcessData *hashed_process_data = NULL;
594 ProcessList *process_list = control_flow_data->process_list;
595 LttTime birth = process->creation_time;
596
597 if(processlist_get_process_pixels(process_list,
598 pid_in,
599 process->last_cpu_index,
600 &birth,
601 tfc->t_context->index,
602 &y,
603 &height,
604 &hashed_process_data) == 1)
605 {
606 g_assert(pid_in == 0 || pid_in != process->ppid);
607 const gchar *name = g_quark_to_string(process->name);
608 /* Process not present */
609 ProcessInfo *process_info;
610 processlist_add(process_list,
611 pid_in,
612 process->last_cpu_index,
613 process->ppid,
614 &birth,
615 tfc->t_context->index,
616 name,
617 &pl_height,
618 &process_info,
619 &hashed_process_data);
620 processlist_get_pixels_from_data(process_list,
621 hashed_process_data,
622 &y,
623 &height);
624 drawing_insert_square( drawing, y, height);
625 }
626 //We could set the current process and hash here, but will be done
627 //by after schedchange hook
628
629 /* Now, the process is in the state hash and our own process hash.
630 * We definitely can draw the items related to the ending state.
631 */
632
633 /* Check if the x position is unset. In can have been left unset by
634 * a draw closure from a after chunk hook. This should never happen,
635 * because it must be set by before chunk hook to the damage_begin
636 * value.
637 */
638 g_assert(hashed_process_data->x.middle != -1);
639
640 if(ltt_time_compare(hashed_process_data->next_good_time,
641 evtime) > 0)
642 {
643 if(hashed_process_data->x.middle_marked == FALSE) {
644 TimeWindow time_window =
645 lttvwindow_get_time_window(control_flow_data->tab);
646#ifdef EXTRA_CHECK
647 if(ltt_time_compare(evtime, time_window.start_time) == -1
648 || ltt_time_compare(evtime, time_window.end_time) == 1)
649 return;
650#endif //EXTRA_CHECK
651 guint x;
652 convert_time_to_pixels(
653 time_window,
654 evtime,
655 width,
656 &x);
657
658 /* Draw collision indicator */
659 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
660 gdk_draw_point(drawing->pixmap,
661 drawing->gc,
662 x,
663 y+(height/2)-3);
664 hashed_process_data->x.middle_marked = TRUE;
665 }
666 } else {
667 TimeWindow time_window =
668 lttvwindow_get_time_window(control_flow_data->tab);
669#ifdef EXTRA_CHECK
670 if(ltt_time_compare(evtime, time_window.start_time) == -1
671 || ltt_time_compare(evtime, time_window.end_time) == 1)
672 return;
673#endif //EXTRA_CHECK
674 guint x;
675
676 convert_time_to_pixels(
677 time_window,
678 evtime,
679 width,
680 &x);
681
682
683 /* Jump over draw if we are at the same x position */
684 if(x == hashed_process_data->x.middle &&
685 hashed_process_data->x.middle_used)
686 {
687 if(hashed_process_data->x.middle_marked == FALSE) {
688 /* Draw collision indicator */
689 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
690 gdk_draw_point(drawing->pixmap,
691 drawing->gc,
692 x,
693 y+(height/2)-3);
694 hashed_process_data->x.middle_marked = TRUE;
695 }
696 /* jump */
697 } else {
698 DrawContext draw_context;
699
700 /* Now create the drawing context that will be used to draw
701 * items related to the last state. */
702 draw_context.drawable = drawing->pixmap;
703 draw_context.gc = drawing->gc;
704 draw_context.pango_layout = drawing->pango_layout;
705 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
706 draw_context.drawinfo.end.x = x;
707
708 draw_context.drawinfo.y.over = y+1;
709 draw_context.drawinfo.y.middle = y+(height/2);
710 draw_context.drawinfo.y.under = y+height;
711
712 draw_context.drawinfo.start.offset.over = 0;
713 draw_context.drawinfo.start.offset.middle = 0;
714 draw_context.drawinfo.start.offset.under = 0;
715 draw_context.drawinfo.end.offset.over = 0;
716 draw_context.drawinfo.end.offset.middle = 0;
717 draw_context.drawinfo.end.offset.under = 0;
718
719 {
720 /* Draw the line */
721 PropertiesLine prop_line = prepare_s_e_line(process);
722 draw_line((void*)&prop_line, (void*)&draw_context);
723 }
724
725
726 /* become the last x position */
727 hashed_process_data->x.middle = x;
728 hashed_process_data->x.middle_used = TRUE;
729 hashed_process_data->x.middle_marked = FALSE;
730
731 /* Calculate the next good time */
732 convert_pixels_to_time(width, x+1, time_window,
733 &hashed_process_data->next_good_time);
734 }
735 }
736 }
737 }
738 return 0;
739
740
741#if 0
742 EventsRequest *events_request = (EventsRequest*)hook_data;
743 ControlFlowData *control_flow_data =
744 (ControlFlowData*)events_request->viewer_data;
745 Tab *tab = control_flow_data->tab;
746
747 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
748
749 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
750 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
751
752 LttEvent *e;
753 e = tfc->e;
754
755 LttTime evtime = ltt_event_time(e);
756 TimeWindow time_window =
757 lttvwindow_get_time_window(tab);
758
759 LttTime time_window.end_time = time_window.time_window.end_time;
760
761 //if(time < time_beg || time > time_end) return;
762 if(ltt_time_compare(evtime, time_window.start_time) == -1
763 || ltt_time_compare(evtime, time_window.end_time) == 1)
764 return;
765
766 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
767 {
768 g_debug("schedchange!");
769
770 /* Add process to process list (if not present) and get drawing "y" from
771 * process position */
772 guint pid_out, pid_in;
773 LttvProcessState *process_out, *process_in;
774 LttTime birth;
775 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
776
777 ProcessList *process_list = control_flow_data->process_list;
778
779
780 LttField *f = ltt_event_field(e);
781 LttField *element;
782 element = ltt_field_member(f,0);
783 pid_out = ltt_event_get_long_unsigned(e,element);
784 element = ltt_field_member(f,1);
785 pid_in = ltt_event_get_long_unsigned(e,element);
786 g_debug("out : %u in : %u", pid_out, pid_in);
787
788
789 /* Find process pid_out in the list... */
790 process_out = lttv_state_find_process(tfs, pid_out);
791 if(process_out == NULL) return 0;
792 g_debug("out : %s",g_quark_to_string(process_out->state->s));
793
794 birth = process_out->creation_time;
795 const gchar *name = g_quark_to_string(process_out->name);
796 HashedProcessData *hashed_process_data_out = NULL;
797
798 if(processlist_get_process_pixels(process_list,
799 pid_out,
800 &birth,
801 tfc->t_context->index,
802 &y_out,
803 &height,
804 &hashed_process_data_out) == 1)
805 {
806 /* Process not present */
807 processlist_add(process_list,
808 pid_out,
809 &birth,
810 tfc->t_context->index,
811 name,
812 &pl_height,
813 &hashed_process_data_out);
814 g_assert(processlist_get_process_pixels(process_list,
815 pid_out,
816 &birth,
817 tfc->t_context->index,
818 &y_out,
819 &height,
820 &hashed_process_data_out)==0);
821 drawing_insert_square( control_flow_data->drawing, y_out, height);
822 }
823 //g_free(name);
824
825 /* Find process pid_in in the list... */
826 process_in = lttv_state_find_process(tfs, pid_in);
827 if(process_in == NULL) return 0;
828 g_debug("in : %s",g_quark_to_string(process_in->state->s));
829
830 birth = process_in->creation_time;
831 name = g_quark_to_string(process_in->name);
832 HashedProcessData *hashed_process_data_in = NULL;
833
834 if(processlist_get_process_pixels(process_list,
835 pid_in,
836 &birth,
837 tfc->t_context->index,
838 &y_in,
839 &height,
840 &hashed_process_data_in) == 1)
841 {
842 /* Process not present */
843 processlist_add(process_list,
844 pid_in,
845 &birth,
846 tfc->t_context->index,
847 name,
848 &pl_height,
849 &hashed_process_data_in);
850 processlist_get_process_pixels(process_list,
851 pid_in,
852 &birth,
853 tfc->t_context->index,
854 &y_in,
855 &height,
856 &hashed_process_data_in);
857
858 drawing_insert_square( control_flow_data->drawing, y_in, height);
859 }
860 //g_free(name);
861
862
863 /* Find pixels corresponding to time of the event. If the time does
864 * not fit in the window, show a warning, not supposed to happend. */
865 guint x = 0;
866 guint width = control_flow_data->drawing->width;
867
868 LttTime time = ltt_event_time(e);
869
870 LttTime window_end = time_window.time_window.end_time;
871
872 convert_time_to_pixels(
873 time_window,
874 time,
875 width,
876 &x);
877 //assert(x <= width);
878 //
879 /* draw what represents the event for outgoing process. */
880
881 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
882 draw_context_out->current->modify_over->x = x;
883 draw_context_out->current->modify_under->x = x;
884 draw_context_out->current->modify_over->y = y_out;
885 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
886 draw_context_out->drawable = control_flow_data->drawing->pixmap;
887 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
888 GtkWidget *widget = control_flow_data->drawing->drawing_area;
889 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
890 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
891 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
892 //draw_context_out->gc = widget->style->black_gc;
893
894 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
895 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
896
897 /* Draw the line/background of the out process */
898 if(draw_context_out->previous->middle->x == -1)
899 {
900 draw_context_out->previous->over->x =
901 control_flow_data->drawing->damage_begin;
902 draw_context_out->previous->middle->x =
903 control_flow_data->drawing->damage_begin;
904 draw_context_out->previous->under->x =
905 control_flow_data->drawing->damage_begin;
906
907 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
908 }
909
910 draw_context_out->current->middle->x = x;
911 draw_context_out->current->over->x = x;
912 draw_context_out->current->under->x = x;
913 draw_context_out->current->middle->y = y_out + height/2;
914 draw_context_out->current->over->y = y_out;
915 draw_context_out->current->under->y = y_out + height;
916 draw_context_out->previous->middle->y = y_out + height/2;
917 draw_context_out->previous->over->y = y_out;
918 draw_context_out->previous->under->y = y_out + height;
919
920 draw_context_out->drawable = control_flow_data->drawing->pixmap;
921 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
922
923 if(process_out->state->s == LTTV_STATE_RUN)
924 {
925 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
926 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
927 draw_context_out->gc = control_flow_data->drawing->gc;
928
929 PropertiesBG prop_bg;
930 prop_bg.color = g_new(GdkColor,1);
931
932 switch(tfc->index) {
933 case 0:
934 prop_bg.color->red = 0x1515;
935 prop_bg.color->green = 0x1515;
936 prop_bg.color->blue = 0x8c8c;
937 break;
938 case 1:
939 prop_bg.color->red = 0x4e4e;
940 prop_bg.color->green = 0xa9a9;
941 prop_bg.color->blue = 0xa4a4;
942 break;
943 case 2:
944 prop_bg.color->red = 0x7a7a;
945 prop_bg.color->green = 0x4a4a;
946 prop_bg.color->blue = 0x8b8b;
947 break;
948 case 3:
949 prop_bg.color->red = 0x8080;
950 prop_bg.color->green = 0x7777;
951 prop_bg.color->blue = 0x4747;
952 break;
953 default:
954 prop_bg.color->red = 0xe7e7;
955 prop_bg.color->green = 0xe7e7;
956 prop_bg.color->blue = 0xe7e7;
957 }
958
959 g_debug("calling from draw_event");
960 draw_bg((void*)&prop_bg, (void*)draw_context_out);
961 g_free(prop_bg.color);
962 //gdk_gc_unref(draw_context_out->gc);
963 }
964
965 draw_context_out->gc = widget->style->black_gc;
966
967 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
968 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
969 PropertiesText prop_text_out;
970 prop_text_out.foreground = &colorfg_out;
971 prop_text_out.background = &colorbg_out;
972 prop_text_out.size = 6;
973 prop_text_out.position = OVER;
974
975 /* color of text : status of the process */
976 if(process_out->state->s == LTTV_STATE_UNNAMED)
977 {
978 prop_text_out.foreground->red = 0xffff;
979 prop_text_out.foreground->green = 0xffff;
980 prop_text_out.foreground->blue = 0xffff;
981 }
982 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
983 {
984 prop_text_out.foreground->red = 0x0fff;
985 prop_text_out.foreground->green = 0xffff;
986 prop_text_out.foreground->blue = 0xfff0;
987 }
988 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
989 {
990 prop_text_out.foreground->red = 0xffff;
991 prop_text_out.foreground->green = 0xffff;
992 prop_text_out.foreground->blue = 0x0000;
993 }
994 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
995 {
996 prop_text_out.foreground->red = 0xffff;
997 prop_text_out.foreground->green = 0x0000;
998 prop_text_out.foreground->blue = 0xffff;
999 }
1000 else if(process_out->state->s == LTTV_STATE_WAIT)
1001 {
1002 prop_text_out.foreground->red = 0xffff;
1003 prop_text_out.foreground->green = 0x0000;
1004 prop_text_out.foreground->blue = 0x0000;
1005 }
1006 else if(process_out->state->s == LTTV_STATE_RUN)
1007 {
1008 prop_text_out.foreground->red = 0x0000;
1009 prop_text_out.foreground->green = 0xffff;
1010 prop_text_out.foreground->blue = 0x0000;
1011 }
1012 else
1013 {
1014 prop_text_out.foreground->red = 0xffff;
1015 prop_text_out.foreground->green = 0xffff;
1016 prop_text_out.foreground->blue = 0xffff;
1017 }
1018
1019
1020 /* Print status of the process : U, WF, WC, E, W, R */
1021 if(process_out->state->s == LTTV_STATE_UNNAMED)
1022 prop_text_out.text = "U->";
1023 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1024 prop_text_out.text = "WF->";
1025 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1026 prop_text_out.text = "WC->";
1027 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1028 prop_text_out.text = "E->";
1029 else if(process_out->state->s == LTTV_STATE_WAIT)
1030 prop_text_out.text = "W->";
1031 else if(process_out->state->s == LTTV_STATE_RUN)
1032 prop_text_out.text = "R->";
1033 else
1034 prop_text_out.text = "U";
1035
1036 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1037 //gdk_gc_unref(draw_context_out->gc);
1038
1039 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1040 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1041 draw_context_out->gc = control_flow_data->drawing->gc;
1042
1043 PropertiesLine prop_line_out;
1044 prop_line_out.color = g_new(GdkColor,1);
1045 prop_line_out.line_width = 2;
1046 prop_line_out.style = GDK_LINE_SOLID;
1047 prop_line_out.position = MIDDLE;
1048
1049 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
1050
1051 /* color of line : status of the process */
1052 if(process_out->state->s == LTTV_STATE_UNNAMED)
1053 {
1054 prop_line_out.color->red = 0xffff;
1055 prop_line_out.color->green = 0xffff;
1056 prop_line_out.color->blue = 0xffff;
1057 }
1058 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1059 {
1060 prop_line_out.color->red = 0x0fff;
1061 prop_line_out.color->green = 0xffff;
1062 prop_line_out.color->blue = 0xfff0;
1063 }
1064 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1065 {
1066 prop_line_out.color->red = 0xffff;
1067 prop_line_out.color->green = 0xffff;
1068 prop_line_out.color->blue = 0x0000;
1069 }
1070 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1071 {
1072 prop_line_out.color->red = 0xffff;
1073 prop_line_out.color->green = 0x0000;
1074 prop_line_out.color->blue = 0xffff;
1075 }
1076 else if(process_out->state->s == LTTV_STATE_WAIT)
1077 {
1078 prop_line_out.color->red = 0xffff;
1079 prop_line_out.color->green = 0x0000;
1080 prop_line_out.color->blue = 0x0000;
1081 }
1082 else if(process_out->state->s == LTTV_STATE_RUN)
1083 {
1084 prop_line_out.color->red = 0x0000;
1085 prop_line_out.color->green = 0xffff;
1086 prop_line_out.color->blue = 0x0000;
1087 }
1088 else
1089 {
1090 prop_line_out.color->red = 0xffff;
1091 prop_line_out.color->green = 0xffff;
1092 prop_line_out.color->blue = 0xffff;
1093 }
1094
1095 draw_line((void*)&prop_line_out, (void*)draw_context_out);
1096 g_free(prop_line_out.color);
1097 //gdk_gc_unref(draw_context_out->gc);
1098 /* Note : finishing line will have to be added when trace read over. */
1099
1100 /* Finally, update the drawing context of the pid_in. */
1101
1102 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1103 draw_context_in->current->modify_over->x = x;
1104 draw_context_in->current->modify_under->x = x;
1105 draw_context_in->current->modify_over->y = y_in;
1106 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1107 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1108 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1109 widget = control_flow_data->drawing->drawing_area;
1110 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1111 //draw_context_in->gc = widget->style->black_gc;
1112 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1113 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1114
1115 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1116 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1117
1118 /* Draw the line/bg of the in process */
1119 if(draw_context_in->previous->middle->x == -1)
1120 {
1121 draw_context_in->previous->over->x =
1122 control_flow_data->drawing->damage_begin;
1123 draw_context_in->previous->middle->x =
1124 control_flow_data->drawing->damage_begin;
1125 draw_context_in->previous->under->x =
1126 control_flow_data->drawing->damage_begin;
1127
1128 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
1129
1130 }
1131
1132 draw_context_in->current->middle->x = x;
1133 draw_context_in->current->over->x = x;
1134 draw_context_in->current->under->x = x;
1135 draw_context_in->current->middle->y = y_in + height/2;
1136 draw_context_in->current->over->y = y_in;
1137 draw_context_in->current->under->y = y_in + height;
1138 draw_context_in->previous->middle->y = y_in + height/2;
1139 draw_context_in->previous->over->y = y_in;
1140 draw_context_in->previous->under->y = y_in + height;
1141
1142 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1143 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1144
1145
1146 if(process_in->state->s == LTTV_STATE_RUN)
1147 {
1148 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1149 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1150 draw_context_in->gc = control_flow_data->drawing->gc;
1151
1152 PropertiesBG prop_bg;
1153 prop_bg.color = g_new(GdkColor,1);
1154
1155 switch(tfc->index) {
1156 case 0:
1157 prop_bg.color->red = 0x1515;
1158 prop_bg.color->green = 0x1515;
1159 prop_bg.color->blue = 0x8c8c;
1160 break;
1161 case 1:
1162 prop_bg.color->red = 0x4e4e;
1163 prop_bg.color->green = 0xa9a9;
1164 prop_bg.color->blue = 0xa4a4;
1165 break;
1166 case 2:
1167 prop_bg.color->red = 0x7a7a;
1168 prop_bg.color->green = 0x4a4a;
1169 prop_bg.color->blue = 0x8b8b;
1170 break;
1171 case 3:
1172 prop_bg.color->red = 0x8080;
1173 prop_bg.color->green = 0x7777;
1174 prop_bg.color->blue = 0x4747;
1175 break;
1176 default:
1177 prop_bg.color->red = 0xe7e7;
1178 prop_bg.color->green = 0xe7e7;
1179 prop_bg.color->blue = 0xe7e7;
1180 }
1181
1182
1183 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1184 g_free(prop_bg.color);
1185 //gdk_gc_unref(draw_context_in->gc);
1186 }
1187
1188 draw_context_in->gc = widget->style->black_gc;
1189
1190 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1191 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1192 PropertiesText prop_text_in;
1193 prop_text_in.foreground = &colorfg_in;
1194 prop_text_in.background = &colorbg_in;
1195 prop_text_in.size = 6;
1196 prop_text_in.position = OVER;
1197
1198 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
1199 /* foreground of text : status of the process */
1200 if(process_in->state->s == LTTV_STATE_UNNAMED)
1201 {
1202 prop_text_in.foreground->red = 0xffff;
1203 prop_text_in.foreground->green = 0xffff;
1204 prop_text_in.foreground->blue = 0xffff;
1205 }
1206 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1207 {
1208 prop_text_in.foreground->red = 0x0fff;
1209 prop_text_in.foreground->green = 0xffff;
1210 prop_text_in.foreground->blue = 0xfff0;
1211 }
1212 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1213 {
1214 prop_text_in.foreground->red = 0xffff;
1215 prop_text_in.foreground->green = 0xffff;
1216 prop_text_in.foreground->blue = 0x0000;
1217 }
1218 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1219 {
1220 prop_text_in.foreground->red = 0xffff;
1221 prop_text_in.foreground->green = 0x0000;
1222 prop_text_in.foreground->blue = 0xffff;
1223 }
1224 else if(process_in->state->s == LTTV_STATE_WAIT)
1225 {
1226 prop_text_in.foreground->red = 0xffff;
1227 prop_text_in.foreground->green = 0x0000;
1228 prop_text_in.foreground->blue = 0x0000;
1229 }
1230 else if(process_in->state->s == LTTV_STATE_RUN)
1231 {
1232 prop_text_in.foreground->red = 0x0000;
1233 prop_text_in.foreground->green = 0xffff;
1234 prop_text_in.foreground->blue = 0x0000;
1235 }
1236 else
1237 {
1238 prop_text_in.foreground->red = 0xffff;
1239 prop_text_in.foreground->green = 0xffff;
1240 prop_text_in.foreground->blue = 0xffff;
1241 }
1242
1243
1244
1245 /* Print status of the process : U, WF, WC, E, W, R */
1246 if(process_in->state->s == LTTV_STATE_UNNAMED)
1247 prop_text_in.text = "U->";
1248 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1249 prop_text_in.text = "WF->";
1250 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1251 prop_text_in.text = "WC->";
1252 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1253 prop_text_in.text = "E->";
1254 else if(process_in->state->s == LTTV_STATE_WAIT)
1255 prop_text_in.text = "W->";
1256 else if(process_in->state->s == LTTV_STATE_RUN)
1257 prop_text_in.text = "R->";
1258 else
1259 prop_text_in.text = "U";
1260
1261 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1262 //gdk_gc_unref(draw_context_in->gc);
1263
1264 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1265 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1266 draw_context_in->gc = control_flow_data->drawing->gc;
1267
1268 PropertiesLine prop_line_in;
1269 prop_line_in.color = g_new(GdkColor,1);
1270 prop_line_in.line_width = 2;
1271 prop_line_in.style = GDK_LINE_SOLID;
1272 prop_line_in.position = MIDDLE;
1273
1274 /* color of line : status of the process */
1275 if(process_in->state->s == LTTV_STATE_UNNAMED)
1276 {
1277 prop_line_in.color->red = 0xffff;
1278 prop_line_in.color->green = 0xffff;
1279 prop_line_in.color->blue = 0xffff;
1280 }
1281 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1282 {
1283 prop_line_in.color->red = 0x0fff;
1284 prop_line_in.color->green = 0xffff;
1285 prop_line_in.color->blue = 0xfff0;
1286 }
1287 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1288 {
1289 prop_line_in.color->red = 0xffff;
1290 prop_line_in.color->green = 0xffff;
1291 prop_line_in.color->blue = 0x0000;
1292 }
1293 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1294 {
1295 prop_line_in.color->red = 0xffff;
1296 prop_line_in.color->green = 0x0000;
1297 prop_line_in.color->blue = 0xffff;
1298 }
1299 else if(process_in->state->s == LTTV_STATE_WAIT)
1300 {
1301 prop_line_in.color->red = 0xffff;
1302 prop_line_in.color->green = 0x0000;
1303 prop_line_in.color->blue = 0x0000;
1304 }
1305 else if(process_in->state->s == LTTV_STATE_RUN)
1306 {
1307 prop_line_in.color->red = 0x0000;
1308 prop_line_in.color->green = 0xffff;
1309 prop_line_in.color->blue = 0x0000;
1310 }
1311 else
1312 {
1313 prop_line_in.color->red = 0xffff;
1314 prop_line_in.color->green = 0xffff;
1315 prop_line_in.color->blue = 0xffff;
1316 }
1317
1318 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1319 g_free(prop_line_in.color);
1320 //gdk_gc_unref(draw_context_in->gc);
1321 }
1322
1323 return 0;
1324#endif //0
1325
1326
1327
1328 /* Text dump */
1329#ifdef DONTSHOW
1330 GString *string = g_string_new("");;
1331 gboolean field_names = TRUE, state = TRUE;
1332
1333 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1334 g_string_append_printf(string,"\n");
1335
1336 if(state) {
1337 g_string_append_printf(string, " %s",
1338 g_quark_to_string(tfs->process->state->s));
1339 }
1340
1341 g_info("%s",string->str);
1342
1343 g_string_free(string, TRUE);
1344
1345 /* End of text dump */
1346#endif //DONTSHOW
1347
1348}
1349
1350/* after_schedchange_hook
1351 *
1352 * The draw after hook is called by the reading API to have a
1353 * particular event drawn on the screen.
1354 * @param hook_data ControlFlowData structure of the viewer.
1355 * @param call_data Event context.
1356 *
1357 * This function adds items to be drawn in a queue for each process.
1358 *
1359 */
1360int after_schedchange_hook(void *hook_data, void *call_data)
1361{
1362 EventsRequest *events_request = (EventsRequest*)hook_data;
1363 ControlFlowData *control_flow_data = events_request->viewer_data;
1364
1365 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1366
1367 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1368 LttvTraceState *ts =(LttvTraceState *)((LttvTracefileContext*)tfs)->t_context;
1369
1370 LttEvent *e;
1371 e = tfc->e;
1372
1373 LttTime evtime = ltt_event_time(e);
1374
1375 guint width = control_flow_data->drawing->width;
1376
1377 /* Add process to process list (if not present) */
1378 LttvProcessState *process_out, *process_in;
1379 LttTime birth;
1380 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1381 HashedProcessData *hashed_process_data_in = NULL;
1382
1383 ProcessList *process_list = control_flow_data->process_list;
1384
1385 guint pid_in;
1386 {
1387 guint pid_out;
1388 LttField *f = ltt_event_field(e);
1389 LttField *element;
1390 element = ltt_field_member(f,0);
1391 pid_out = ltt_event_get_long_unsigned(e,element);
1392 element = ltt_field_member(f,1);
1393 pid_in = ltt_event_get_long_unsigned(e,element);
1394 g_debug("out : %u in : %u", pid_out, pid_in);
1395 }
1396
1397
1398 /* Find process pid_in in the list... */
1399 //process_in = lttv_state_find_process(tfs, pid_in);
1400 process_in = tfs->process;
1401 /* It should exist, because we are after the state update. */
1402 g_assert(process_in != NULL);
1403
1404 birth = process_in->creation_time;
1405
1406 if(processlist_get_process_pixels(process_list,
1407 pid_in,
1408 process_in->last_cpu_index,
1409 &birth,
1410 tfc->t_context->index,
1411 &y_in,
1412 &height,
1413 &hashed_process_data_in) == 1)
1414 {
1415 g_assert(pid_in == 0 || pid_in != process_in->ppid);
1416 const gchar *name = g_quark_to_string(process_in->name);
1417 ProcessInfo *process_info;
1418 /* Process not present */
1419 processlist_add(process_list,
1420 pid_in,
1421 process_in->last_cpu_index,
1422 process_in->ppid,
1423 &birth,
1424 tfc->t_context->index,
1425 name,
1426 &pl_height,
1427 &process_info,
1428 &hashed_process_data_in);
1429 processlist_get_pixels_from_data(process_list,
1430 hashed_process_data_in,
1431 &y_in,
1432 &height);
1433 drawing_insert_square( control_flow_data->drawing, y_in, height);
1434 }
1435 /* Set the current process */
1436 process_list->current_hash_data[process_in->last_cpu_index] =
1437 hashed_process_data_in;
1438
1439 if(ltt_time_compare(hashed_process_data_in->next_good_time,
1440 evtime) <= 0)
1441 {
1442 TimeWindow time_window =
1443 lttvwindow_get_time_window(control_flow_data->tab);
1444
1445#ifdef EXTRA_CHECK
1446 if(ltt_time_compare(evtime, time_window.start_time) == -1
1447 || ltt_time_compare(evtime, time_window.end_time) == 1)
1448 return;
1449#endif //EXTRA_CHECK
1450
1451 guint new_x;
1452
1453 convert_time_to_pixels(
1454 time_window,
1455 evtime,
1456 width,
1457 &new_x);
1458
1459 if(hashed_process_data_in->x.middle != new_x) {
1460 hashed_process_data_in->x.middle = new_x;
1461 hashed_process_data_in->x.middle_used = FALSE;
1462 hashed_process_data_in->x.middle_marked = FALSE;
1463 }
1464 }
1465 return 0;
1466
1467
1468
1469
1470
1471#if 0
1472 EventsRequest *events_request = (EventsRequest*)hook_data;
1473 ControlFlowData *control_flow_data = events_request->viewer_data;
1474
1475 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1476
1477 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1478 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1479
1480
1481 LttEvent *e;
1482 e = tfc->e;
1483
1484 LttTime evtime = ltt_event_time(e);
1485 TimeWindow time_window =
1486 lttvwindow_get_time_window(control_flow_data->tab);
1487
1488 LttTime time_window.end_time = time_window.time_window.end_time;
1489
1490 //if(time < time_beg || time > time_end) return;
1491 if(ltt_time_compare(evtime, time_window.start_time) == -1
1492 || ltt_time_compare(evtime, time_window.end_time) == 1)
1493 return;
1494
1495
1496 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1497 {
1498 g_debug("schedchange!");
1499
1500 /* Add process to process list (if not present) and get drawing "y" from
1501 * process position */
1502 guint pid_out, pid_in;
1503 LttvProcessState *process_out, *process_in;
1504 LttTime birth;
1505 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1506
1507 ProcessList *process_list = control_flow_data->process_list;
1508
1509
1510 LttField *f = ltt_event_field(e);
1511 LttField *element;
1512 element = ltt_field_member(f,0);
1513 pid_out = ltt_event_get_long_unsigned(e,element);
1514 element = ltt_field_member(f,1);
1515 pid_in = ltt_event_get_long_unsigned(e,element);
1516 //g_debug("out : %u in : %u", pid_out, pid_in);
1517
1518
1519 /* Find process pid_out in the list... */
1520 process_out = lttv_state_find_process(tfs, pid_out);
1521 if(process_out == NULL) return 0;
1522 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1523
1524 birth = process_out->creation_time;
1525 gchar *name = strdup(g_quark_to_string(process_out->name));
1526 HashedProcessData *hashed_process_data_out = NULL;
1527
1528 if(processlist_get_process_pixels(process_list,
1529 pid_out,
1530 &birth,
1531 tfc->t_context->index,
1532 &y_out,
1533 &height,
1534 &hashed_process_data_out) == 1)
1535 {
1536 /* Process not present */
1537 processlist_add(process_list,
1538 pid_out,
1539 &birth,
1540 tfc->t_context->index,
1541 name,
1542 &pl_height,
1543 &hashed_process_data_out);
1544 processlist_get_process_pixels(process_list,
1545 pid_out,
1546 &birth,
1547 tfc->t_context->index,
1548 &y_out,
1549 &height,
1550 &hashed_process_data_out);
1551 drawing_insert_square( control_flow_data->drawing, y_out, height);
1552 }
1553
1554 g_free(name);
1555
1556 /* Find process pid_in in the list... */
1557 process_in = lttv_state_find_process(tfs, pid_in);
1558 if(process_in == NULL) return 0;
1559 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1560
1561 birth = process_in->creation_time;
1562 name = strdup(g_quark_to_string(process_in->name));
1563 HashedProcessData *hashed_process_data_in = NULL;
1564
1565 if(processlist_get_process_pixels(process_list,
1566 pid_in,
1567 &birth,
1568 tfc->t_context->index,
1569 &y_in,
1570 &height,
1571 &hashed_process_data_in) == 1)
1572 {
1573 /* Process not present */
1574 processlist_add(process_list,
1575 pid_in,
1576 &birth,
1577 tfc->t_context->index,
1578 name,
1579 &pl_height,
1580 &hashed_process_data_in);
1581 processlist_get_process_pixels(process_list,
1582 pid_in,
1583 &birth,
1584 tfc->t_context->index,
1585 &y_in,
1586 &height,
1587 &hashed_process_data_in);
1588
1589 drawing_insert_square( control_flow_data->drawing, y_in, height);
1590 }
1591 g_free(name);
1592
1593
1594 /* Find pixels corresponding to time of the event. If the time does
1595 * not fit in the window, show a warning, not supposed to happend. */
1596 //guint x = 0;
1597 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1598
1599 //LttTime time = ltt_event_time(e);
1600
1601 //LttTime window_end = time_window->time_window.end_time;
1602
1603
1604 //convert_time_to_pixels(
1605 // *time_window,
1606 // time,
1607 // width,
1608 // &x);
1609
1610 //assert(x <= width);
1611
1612 /* draw what represents the event for outgoing process. */
1613
1614 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
1615 //draw_context_out->current->modify_over->x = x;
1616 draw_context_out->current->modify_over->y = y_out;
1617 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
1618 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1619 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1620 GtkWidget *widget = control_flow_data->drawing->drawing_area;
1621 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1622
1623 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1624 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1625
1626 /*if(process_out->state->s == LTTV_STATE_RUN)
1627 {
1628 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1629 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1630 PropertiesBG prop_bg;
1631 prop_bg.color = g_new(GdkColor,1);
1632
1633 prop_bg.color->red = 0xffff;
1634 prop_bg.color->green = 0xffff;
1635 prop_bg.color->blue = 0xffff;
1636
1637 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1638 g_free(prop_bg.color);
1639 gdk_gc_unref(draw_context_out->gc);
1640 }*/
1641
1642 draw_context_out->gc = widget->style->black_gc;
1643
1644 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
1645 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
1646 PropertiesText prop_text_out;
1647 prop_text_out.foreground = &colorfg_out;
1648 prop_text_out.background = &colorbg_out;
1649 prop_text_out.size = 6;
1650 prop_text_out.position = OVER;
1651
1652 /* color of text : status of the process */
1653 if(process_out->state->s == LTTV_STATE_UNNAMED)
1654 {
1655 prop_text_out.foreground->red = 0xffff;
1656 prop_text_out.foreground->green = 0xffff;
1657 prop_text_out.foreground->blue = 0xffff;
1658 }
1659 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1660 {
1661 prop_text_out.foreground->red = 0x0fff;
1662 prop_text_out.foreground->green = 0xffff;
1663 prop_text_out.foreground->blue = 0xfff0;
1664 }
1665 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1666 {
1667 prop_text_out.foreground->red = 0xffff;
1668 prop_text_out.foreground->green = 0xffff;
1669 prop_text_out.foreground->blue = 0x0000;
1670 }
1671 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1672 {
1673 prop_text_out.foreground->red = 0xffff;
1674 prop_text_out.foreground->green = 0x0000;
1675 prop_text_out.foreground->blue = 0xffff;
1676 }
1677 else if(process_out->state->s == LTTV_STATE_WAIT)
1678 {
1679 prop_text_out.foreground->red = 0xffff;
1680 prop_text_out.foreground->green = 0x0000;
1681 prop_text_out.foreground->blue = 0x0000;
1682 }
1683 else if(process_out->state->s == LTTV_STATE_RUN)
1684 {
1685 prop_text_out.foreground->red = 0x0000;
1686 prop_text_out.foreground->green = 0xffff;
1687 prop_text_out.foreground->blue = 0x0000;
1688 }
1689 else
1690 {
1691 prop_text_out.foreground->red = 0xffff;
1692 prop_text_out.foreground->green = 0xffff;
1693 prop_text_out.foreground->blue = 0xffff;
1694 }
1695
1696 /* Print status of the process : U, WF, WC, E, W, R */
1697 if(process_out->state->s == LTTV_STATE_UNNAMED)
1698 prop_text_out.text = "U";
1699 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1700 prop_text_out.text = "WF";
1701 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1702 prop_text_out.text = "WC";
1703 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1704 prop_text_out.text = "E";
1705 else if(process_out->state->s == LTTV_STATE_WAIT)
1706 prop_text_out.text = "W";
1707 else if(process_out->state->s == LTTV_STATE_RUN)
1708 prop_text_out.text = "R";
1709 else
1710 prop_text_out.text = "U";
1711
1712 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1713
1714 //gdk_gc_unref(draw_context_out->gc);
1715
1716 draw_context_out->current->middle->y = y_out+height/2;
1717 draw_context_out->current->over->y = y_out;
1718 draw_context_out->current->under->y = y_out+height;
1719 draw_context_out->current->status = process_out->state->s;
1720
1721 /* for pid_out : remove previous, Prev = current, new current (default) */
1722 g_free(draw_context_out->previous->modify_under);
1723 g_free(draw_context_out->previous->modify_middle);
1724 g_free(draw_context_out->previous->modify_over);
1725 g_free(draw_context_out->previous->under);
1726 g_free(draw_context_out->previous->middle);
1727 g_free(draw_context_out->previous->over);
1728 g_free(draw_context_out->previous);
1729
1730 draw_context_out->previous = draw_context_out->current;
1731
1732 draw_context_out->current = g_new(DrawInfo,1);
1733 draw_context_out->current->over = g_new(ItemInfo,1);
1734 draw_context_out->current->over->x = -1;
1735 draw_context_out->current->over->y = -1;
1736 draw_context_out->current->middle = g_new(ItemInfo,1);
1737 draw_context_out->current->middle->x = -1;
1738 draw_context_out->current->middle->y = -1;
1739 draw_context_out->current->under = g_new(ItemInfo,1);
1740 draw_context_out->current->under->x = -1;
1741 draw_context_out->current->under->y = -1;
1742 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1743 draw_context_out->current->modify_over->x = -1;
1744 draw_context_out->current->modify_over->y = -1;
1745 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1746 draw_context_out->current->modify_middle->x = -1;
1747 draw_context_out->current->modify_middle->y = -1;
1748 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1749 draw_context_out->current->modify_under->x = -1;
1750 draw_context_out->current->modify_under->y = -1;
1751 draw_context_out->current->status = LTTV_STATE_UNNAMED;
1752
1753 /* Finally, update the drawing context of the pid_in. */
1754
1755 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1756 //draw_context_in->current->modify_over->x = x;
1757 draw_context_in->current->modify_over->y = y_in;
1758 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1759 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1760 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1761 widget = control_flow_data->drawing->drawing_area;
1762 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1763
1764 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1765 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1766
1767 /*if(process_in->state->s == LTTV_STATE_RUN)
1768 {
1769 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1770 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1771 PropertiesBG prop_bg;
1772 prop_bg.color = g_new(GdkColor,1);
1773
1774 prop_bg.color->red = 0xffff;
1775 prop_bg.color->green = 0xffff;
1776 prop_bg.color->blue = 0xffff;
1777
1778 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1779 g_free(prop_bg.color);
1780 gdk_gc_unref(draw_context_in->gc);
1781 }*/
1782
1783 draw_context_in->gc = widget->style->black_gc;
1784
1785 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1786 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1787 PropertiesText prop_text_in;
1788 prop_text_in.foreground = &colorfg_in;
1789 prop_text_in.background = &colorbg_in;
1790 prop_text_in.size = 6;
1791 prop_text_in.position = OVER;
1792
1793 /* foreground of text : status of the process */
1794 if(process_in->state->s == LTTV_STATE_UNNAMED)
1795 {
1796 prop_text_in.foreground->red = 0xffff;
1797 prop_text_in.foreground->green = 0xffff;
1798 prop_text_in.foreground->blue = 0xffff;
1799 }
1800 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1801 {
1802 prop_text_in.foreground->red = 0x0fff;
1803 prop_text_in.foreground->green = 0xffff;
1804 prop_text_in.foreground->blue = 0xfff0;
1805 }
1806 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1807 {
1808 prop_text_in.foreground->red = 0xffff;
1809 prop_text_in.foreground->green = 0xffff;
1810 prop_text_in.foreground->blue = 0x0000;
1811 }
1812 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1813 {
1814 prop_text_in.foreground->red = 0xffff;
1815 prop_text_in.foreground->green = 0x0000;
1816 prop_text_in.foreground->blue = 0xffff;
1817 }
1818 else if(process_in->state->s == LTTV_STATE_WAIT)
1819 {
1820 prop_text_in.foreground->red = 0xffff;
1821 prop_text_in.foreground->green = 0x0000;
1822 prop_text_in.foreground->blue = 0x0000;
1823 }
1824 else if(process_in->state->s == LTTV_STATE_RUN)
1825 {
1826 prop_text_in.foreground->red = 0x0000;
1827 prop_text_in.foreground->green = 0xffff;
1828 prop_text_in.foreground->blue = 0x0000;
1829 }
1830 else
1831 {
1832 prop_text_in.foreground->red = 0xffff;
1833 prop_text_in.foreground->green = 0xffff;
1834 prop_text_in.foreground->blue = 0xffff;
1835 }
1836
1837
1838 /* Print status of the process : U, WF, WC, E, W, R */
1839 if(process_in->state->s == LTTV_STATE_UNNAMED)
1840 prop_text_in.text = "U";
1841 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1842 prop_text_in.text = "WF";
1843 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1844 prop_text_in.text = "WC";
1845 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1846 prop_text_in.text = "E";
1847 else if(process_in->state->s == LTTV_STATE_WAIT)
1848 prop_text_in.text = "W";
1849 else if(process_in->state->s == LTTV_STATE_RUN)
1850 prop_text_in.text = "R";
1851 else
1852 prop_text_in.text = "U";
1853
1854 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1855
1856
1857 if(process_in->state->s == LTTV_STATE_RUN)
1858 {
1859 gchar tmp[255];
1860 prop_text_in.foreground = &colorfg_in;
1861 prop_text_in.background = &colorbg_in;
1862 prop_text_in.foreground->red = 0xffff;
1863 prop_text_in.foreground->green = 0xffff;
1864 prop_text_in.foreground->blue = 0xffff;
1865 prop_text_in.size = 6;
1866 prop_text_in.position = UNDER;
1867
1868 prop_text_in.text = g_new(gchar, 260);
1869 strcpy(prop_text_in.text, "CPU ");
1870 snprintf(tmp, 255, "%u", tfc->index);
1871 strcat(prop_text_in.text, tmp);
1872
1873 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1874 g_free(prop_text_in.text);
1875 }
1876
1877
1878 draw_context_in->current->middle->y = y_in+height/2;
1879 draw_context_in->current->over->y = y_in;
1880 draw_context_in->current->under->y = y_in+height;
1881 draw_context_in->current->status = process_in->state->s;
1882
1883 /* for pid_in : remove previous, Prev = current, new current (default) */
1884 g_free(draw_context_in->previous->modify_under);
1885 g_free(draw_context_in->previous->modify_middle);
1886 g_free(draw_context_in->previous->modify_over);
1887 g_free(draw_context_in->previous->under);
1888 g_free(draw_context_in->previous->middle);
1889 g_free(draw_context_in->previous->over);
1890 g_free(draw_context_in->previous);
1891
1892 draw_context_in->previous = draw_context_in->current;
1893
1894 draw_context_in->current = g_new(DrawInfo,1);
1895 draw_context_in->current->over = g_new(ItemInfo,1);
1896 draw_context_in->current->over->x = -1;
1897 draw_context_in->current->over->y = -1;
1898 draw_context_in->current->middle = g_new(ItemInfo,1);
1899 draw_context_in->current->middle->x = -1;
1900 draw_context_in->current->middle->y = -1;
1901 draw_context_in->current->under = g_new(ItemInfo,1);
1902 draw_context_in->current->under->x = -1;
1903 draw_context_in->current->under->y = -1;
1904 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1905 draw_context_in->current->modify_over->x = -1;
1906 draw_context_in->current->modify_over->y = -1;
1907 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1908 draw_context_in->current->modify_middle->x = -1;
1909 draw_context_in->current->modify_middle->y = -1;
1910 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1911 draw_context_in->current->modify_under->x = -1;
1912 draw_context_in->current->modify_under->y = -1;
1913 draw_context_in->current->status = LTTV_STATE_UNNAMED;
1914
1915 }
1916
1917 return 0;
1918#endif //0
1919}
1920
1921#if 0
1922static __inline__ PropertiesLine prepare_execmode_line(LttvProcessState *process)
1923{
1924 PropertiesLine prop_line;
1925 prop_line.line_width = 1;
1926 prop_line.style = GDK_LINE_SOLID;
1927 prop_line.y = OVER;
1928 //GdkColormap *colormap = gdk_colormap_get_system();
1929
1930 /* color of line : execution mode of the process */
1931 if(process->state->t == LTTV_STATE_USER_MODE)
1932 prop_line.color = drawing_colors[COL_USER_MODE];
1933 else if(process->state->t == LTTV_STATE_SYSCALL)
1934 prop_line.color = drawing_colors[COL_SYSCALL];
1935 else if(process->state->t == LTTV_STATE_TRAP)
1936 prop_line.color = drawing_colors[COL_TRAP];
1937 else if(process->state->t == LTTV_STATE_IRQ)
1938 prop_line.color = drawing_colors[COL_IRQ];
1939 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
1940 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
1941 else
1942 prop_line.color = drawing_colors[COL_WHITE];
1943
1944 //gdk_colormap_alloc_color(colormap,
1945 // prop_line.color,
1946 // FALSE,
1947 // TRUE);
1948
1949 return prop_line;
1950
1951}
1952#endif //0
1953
1954
1955/* before_execmode_hook
1956 *
1957 * This function basically draw lines and icons. Two types of lines are drawn :
1958 * one small (3 pixels?) representing the state of the process and the second
1959 * type is thicker (10 pixels?) representing on which CPU a process is running
1960 * (and this only in running state).
1961 *
1962 * Extremums of the lines :
1963 * x_min : time of the last event context for this process kept in memory.
1964 * x_max : time of the current event.
1965 * y : middle of the process in the process list. The process is found in the
1966 * list, therefore is it's position in pixels.
1967 *
1968 * The choice of lines'color is defined by the context of the last event for this
1969 * process.
1970 */
1971
1972
1973int before_execmode_hook(void *hook_data, void *call_data)
1974{
1975 EventsRequest *events_request = (EventsRequest*)hook_data;
1976 ControlFlowData *control_flow_data = events_request->viewer_data;
1977 Drawing_t *drawing = control_flow_data->drawing;
1978
1979 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1980
1981 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1982 LttvTraceState *ts =(LttvTraceState *)((LttvTracefileContext*)tfs)->t_context;
1983
1984 LttEvent *e;
1985 e = tfc->e;
1986
1987 LttTime evtime = ltt_event_time(e);
1988 guint width = drawing->width;
1989
1990 /* we are in a execmode, before the state update. We must draw the
1991 * items corresponding to the state before it changes : now is the right
1992 * time to do it.
1993 */
1994 /* For the pid */
1995 LttvProcessState *process = tfs->process;
1996 g_assert(process != NULL);
1997
1998 guint pid = process->pid;
1999
2000 /* Well, the process_out existed : we must get it in the process hash
2001 * or add it, and draw its items.
2002 */
2003 /* Add process to process list (if not present) */
2004 guint y = 0, height = 0, pl_height = 0;
2005 HashedProcessData *hashed_process_data = NULL;
2006 ProcessList *process_list = control_flow_data->process_list;
2007 LttTime birth = process->creation_time;
2008
2009 if(process_list->current_hash_data[tfc->index] != NULL) {
2010 hashed_process_data = process_list->current_hash_data[tfc->index];
2011 processlist_get_pixels_from_data(process_list,
2012 hashed_process_data,
2013 &y,
2014 &height);
2015 } else {
2016 if(processlist_get_process_pixels(process_list,
2017 pid,
2018 process->last_cpu_index,
2019 &birth,
2020 tfc->t_context->index,
2021 &y,
2022 &height,
2023 &hashed_process_data) == 1)
2024 {
2025 g_assert(pid == 0 || pid != process->ppid);
2026 ProcessInfo *process_info;
2027 /* Process not present */
2028 const gchar *name = g_quark_to_string(process->name);
2029 processlist_add(process_list,
2030 pid,
2031 process->last_cpu_index,
2032 process->ppid,
2033 &birth,
2034 tfc->t_context->index,
2035 name,
2036 &pl_height,
2037 &process_info,
2038 &hashed_process_data);
2039 processlist_get_pixels_from_data(process_list,
2040 hashed_process_data,
2041 &y,
2042 &height);
2043 drawing_insert_square( drawing, y, height);
2044 }
2045 /* Set the current process */
2046 process_list->current_hash_data[process->last_cpu_index] =
2047 hashed_process_data;
2048 }
2049
2050 /* Now, the process is in the state hash and our own process hash.
2051 * We definitely can draw the items related to the ending state.
2052 */
2053
2054 /* Check if the x position is unset. In can have been left unset by
2055 * a draw closure from a after chunk hook. This should never happen,
2056 * because it must be set by before chunk hook to the damage_begin
2057 * value.
2058 */
2059 g_assert(hashed_process_data->x.over != -1);
2060
2061 if(ltt_time_compare(hashed_process_data->next_good_time,
2062 evtime) > 0)
2063 {
2064 if(hashed_process_data->x.middle_marked == FALSE) {
2065 TimeWindow time_window =
2066 lttvwindow_get_time_window(control_flow_data->tab);
2067
2068#ifdef EXTRA_CHECK
2069 if(ltt_time_compare(evtime, time_window.start_time) == -1
2070 || ltt_time_compare(evtime, time_window.end_time) == 1)
2071 return;
2072#endif //EXTRA_CHECK
2073 guint x;
2074 convert_time_to_pixels(
2075 time_window,
2076 evtime,
2077 width,
2078 &x);
2079
2080 /* Draw collision indicator */
2081 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2082 gdk_draw_point(drawing->pixmap,
2083 drawing->gc,
2084 x,
2085 y+(height/2)-3);
2086 hashed_process_data->x.middle_marked = TRUE;
2087 }
2088 } else {
2089 TimeWindow time_window =
2090 lttvwindow_get_time_window(control_flow_data->tab);
2091
2092#ifdef EXTRA_CHECK
2093 if(ltt_time_compare(evtime, time_window.start_time) == -1
2094 || ltt_time_compare(evtime, time_window.end_time) == 1)
2095 return;
2096#endif //EXTRA_CHECK
2097 guint x;
2098
2099 convert_time_to_pixels(
2100 time_window,
2101 evtime,
2102 width,
2103 &x);
2104
2105
2106 /* Jump over draw if we are at the same x position */
2107 if(x == hashed_process_data->x.middle &&
2108 hashed_process_data->x.middle_used)
2109 {
2110 if(hashed_process_data->x.middle_marked == FALSE) {
2111 /* Draw collision indicator */
2112 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2113 gdk_draw_point(drawing->pixmap,
2114 drawing->gc,
2115 x,
2116 y+(height/2)-3);
2117 hashed_process_data->x.middle_marked = TRUE;
2118 }
2119 /* jump */
2120 } else {
2121
2122 DrawContext draw_context;
2123 /* Now create the drawing context that will be used to draw
2124 * items related to the last state. */
2125 draw_context.drawable = drawing->pixmap;
2126 draw_context.gc = drawing->gc;
2127 draw_context.pango_layout = drawing->pango_layout;
2128 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2129 draw_context.drawinfo.end.x = x;
2130
2131 draw_context.drawinfo.y.over = y+1;
2132 draw_context.drawinfo.y.middle = y+(height/2);
2133 draw_context.drawinfo.y.under = y+height;
2134
2135 draw_context.drawinfo.start.offset.over = 0;
2136 draw_context.drawinfo.start.offset.middle = 0;
2137 draw_context.drawinfo.start.offset.under = 0;
2138 draw_context.drawinfo.end.offset.over = 0;
2139 draw_context.drawinfo.end.offset.middle = 0;
2140 draw_context.drawinfo.end.offset.under = 0;
2141
2142 {
2143 /* Draw the line */
2144 PropertiesLine prop_line = prepare_s_e_line(process);
2145 draw_line((void*)&prop_line, (void*)&draw_context);
2146
2147 }
2148 /* become the last x position */
2149 hashed_process_data->x.middle = x;
2150 hashed_process_data->x.middle_used = TRUE;
2151 hashed_process_data->x.middle_marked = FALSE;
2152
2153 /* Calculate the next good time */
2154 convert_pixels_to_time(width, x+1, time_window,
2155 &hashed_process_data->next_good_time);
2156 }
2157 }
2158
2159 return 0;
2160}
2161
2162/* after_execmode_hook
2163 *
2164 * The draw after hook is called by the reading API to have a
2165 * particular event drawn on the screen.
2166 * @param hook_data ControlFlowData structure of the viewer.
2167 * @param call_data Event context.
2168 *
2169 * This function adds items to be drawn in a queue for each process.
2170 *
2171 */
2172int after_execmode_hook(void *hook_data, void *call_data)
2173{
2174 EventsRequest *events_request = (EventsRequest*)hook_data;
2175 ControlFlowData *control_flow_data = events_request->viewer_data;
2176
2177 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2178
2179 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2180 LttvTraceState *ts =(LttvTraceState *)((LttvTracefileContext*)tfs)->t_context;
2181
2182 LttEvent *e;
2183 e = tfc->e;
2184
2185 LttTime evtime = ltt_event_time(e);
2186 guint width = control_flow_data->drawing->width;
2187
2188 /* Add process to process list (if not present) */
2189 LttvProcessState *process;
2190 LttTime birth;
2191 guint y = 0, height = 0, pl_height = 0;
2192 HashedProcessData *hashed_process_data = NULL;
2193
2194 ProcessList *process_list = control_flow_data->process_list;
2195
2196 /* Find process pid_in in the list... */
2197 process = tfs->process;
2198 /* It should exist, because we are after the state update. */
2199 g_assert(process != NULL);
2200
2201 guint pid = process->pid;
2202
2203 birth = process->creation_time;
2204
2205 if(process_list->current_hash_data[tfc->index] != NULL) {
2206 hashed_process_data = process_list->current_hash_data[tfc->index];
2207 processlist_get_pixels_from_data(process_list,
2208 hashed_process_data,
2209 &y,
2210 &height);
2211 } else {
2212 if(processlist_get_process_pixels(process_list,
2213 pid,
2214 process->last_cpu_index,
2215 &birth,
2216 tfc->t_context->index,
2217 &y,
2218 &height,
2219 &hashed_process_data) == 1)
2220 {
2221 g_assert(pid == 0 || pid != process->ppid);
2222 /* Process not present */
2223 const gchar *name = g_quark_to_string(process->name);
2224 ProcessInfo *process_info;
2225 processlist_add(process_list,
2226 pid,
2227 process->last_cpu_index,
2228 process->ppid,
2229 &birth,
2230 tfc->t_context->index,
2231 name,
2232 &pl_height,
2233 &process_info,
2234 &hashed_process_data);
2235 processlist_get_pixels_from_data(process_list,
2236 hashed_process_data,
2237 &y,
2238 &height);
2239 drawing_insert_square( control_flow_data->drawing, y, height);
2240 }
2241 /* Set the current process */
2242 process_list->current_hash_data[process->last_cpu_index] =
2243 hashed_process_data;
2244 }
2245
2246 if(ltt_time_compare(hashed_process_data->next_good_time,
2247 evtime) <= 0)
2248 {
2249 TimeWindow time_window =
2250 lttvwindow_get_time_window(control_flow_data->tab);
2251
2252#ifdef EXTRA_CHECK
2253 if(ltt_time_compare(evtime, time_window.start_time) == -1
2254 || ltt_time_compare(evtime, time_window.end_time) == 1)
2255 return;
2256#endif //EXTRA_CHECK
2257
2258
2259 guint new_x;
2260
2261 convert_time_to_pixels(
2262 time_window,
2263 evtime,
2264 width,
2265 &new_x);
2266
2267 if(hashed_process_data->x.middle != new_x) {
2268 hashed_process_data->x.middle = new_x;
2269 hashed_process_data->x.middle_used = FALSE;
2270 hashed_process_data->x.middle_marked = FALSE;
2271 }
2272 }
2273 return 0;
2274}
2275
2276
2277
2278/* before_process_hook
2279 *
2280 * Draw lines for process event.
2281 *
2282 * @param hook_data ControlFlowData structure of the viewer.
2283 * @param call_data Event context.
2284 *
2285 * This function adds items to be drawn in a queue for each process.
2286 *
2287 */
2288int before_process_hook(void *hook_data, void *call_data)
2289{
2290 EventsRequest *events_request = (EventsRequest*)hook_data;
2291 ControlFlowData *control_flow_data = events_request->viewer_data;
2292 Drawing_t *drawing = control_flow_data->drawing;
2293
2294 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2295
2296 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2297 LttvTraceState *ts =(LttvTraceState *)((LttvTracefileContext*)tfs)->t_context;
2298
2299 LttEvent *e;
2300 e = tfc->e;
2301
2302 LttTime evtime = ltt_event_time(e);
2303 guint width = control_flow_data->drawing->width;
2304
2305 guint sub_id;
2306 {
2307 LttField *f = ltt_event_field(e);
2308 LttField *element;
2309 element = ltt_field_member(f,0);
2310 sub_id = ltt_event_get_long_unsigned(e,element);
2311 }
2312
2313 if(sub_id == 3) { /* exit */
2314
2315 /* Add process to process list (if not present) */
2316 LttvProcessState *process = tfs->process;
2317 guint pid = process->pid;
2318 LttTime birth;
2319 guint y = 0, height = 0, pl_height = 0;
2320 HashedProcessData *hashed_process_data = NULL;
2321
2322 ProcessList *process_list = control_flow_data->process_list;
2323
2324 g_assert(process != NULL);
2325
2326 birth = process->creation_time;
2327
2328 if(process_list->current_hash_data[tfc->index] != NULL) {
2329 hashed_process_data = process_list->current_hash_data[tfc->index];
2330 processlist_get_pixels_from_data(process_list,
2331 hashed_process_data,
2332 &y,
2333 &height);
2334 } else if(processlist_get_process_pixels(process_list,
2335 pid,
2336 process->last_cpu_index,
2337 &birth,
2338 tfc->t_context->index,
2339 &y,
2340 &height,
2341 &hashed_process_data) == 1)
2342 {
2343 g_assert(pid == 0 || pid != process->ppid);
2344 /* Process not present */
2345 const gchar *name = g_quark_to_string(process->name);
2346 ProcessInfo *process_info;
2347 processlist_add(process_list,
2348 pid,
2349 process->last_cpu_index,
2350 process->ppid,
2351 &birth,
2352 tfc->t_context->index,
2353 name,
2354 &pl_height,
2355 &process_info,
2356 &hashed_process_data);
2357 processlist_get_pixels_from_data(process_list,
2358 hashed_process_data,
2359 &y,
2360 &height);
2361 drawing_insert_square( control_flow_data->drawing, y, height);
2362 }
2363
2364 /* Now, the process is in the state hash and our own process hash.
2365 * We definitely can draw the items related to the ending state.
2366 */
2367
2368 /* Check if the x position is unset. In can have been left unset by
2369 * a draw closure from a after chunk hook. This should never happen,
2370 * because it must be set by before chunk hook to the damage_begin
2371 * value.
2372 */
2373 g_assert(hashed_process_data->x.over != -1);
2374
2375 if(ltt_time_compare(hashed_process_data->next_good_time,
2376 evtime) > 0)
2377 {
2378 if(hashed_process_data->x.middle_marked == FALSE) {
2379 TimeWindow time_window =
2380 lttvwindow_get_time_window(control_flow_data->tab);
2381
2382#ifdef EXTRA_CHECK
2383 if(ltt_time_compare(evtime, time_window.start_time) == -1
2384 || ltt_time_compare(evtime, time_window.end_time) == 1)
2385 return;
2386#endif //EXTRA_CHECK
2387
2388 guint x;
2389 convert_time_to_pixels(
2390 time_window,
2391 evtime,
2392 width,
2393 &x);
2394
2395 /* Draw collision indicator */
2396 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2397 gdk_draw_point(drawing->pixmap,
2398 drawing->gc,
2399 x,
2400 y+(height/2)-3);
2401 hashed_process_data->x.middle_marked = TRUE;
2402 }
2403 } else {
2404 TimeWindow time_window =
2405 lttvwindow_get_time_window(control_flow_data->tab);
2406
2407#ifdef EXTRA_CHECK
2408 if(ltt_time_compare(evtime, time_window.start_time) == -1
2409 || ltt_time_compare(evtime, time_window.end_time) == 1)
2410 return;
2411#endif //EXTRA_CHECK
2412
2413 guint x;
2414
2415 convert_time_to_pixels(
2416 time_window,
2417 evtime,
2418 width,
2419 &x);
2420
2421
2422 /* Jump over draw if we are at the same x position */
2423 if(x == hashed_process_data->x.middle &&
2424 hashed_process_data->x.middle_used)
2425 {
2426 if(hashed_process_data->x.middle_marked == FALSE) {
2427 /* Draw collision indicator */
2428 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2429 gdk_draw_point(drawing->pixmap,
2430 drawing->gc,
2431 x,
2432 y+(height/2)-3);
2433 hashed_process_data->x.middle_marked = TRUE;
2434 }
2435 /* jump */
2436 } else {
2437 DrawContext draw_context;
2438
2439 /* Now create the drawing context that will be used to draw
2440 * items related to the last state. */
2441 draw_context.drawable = drawing->pixmap;
2442 draw_context.gc = drawing->gc;
2443 draw_context.pango_layout = drawing->pango_layout;
2444 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2445 draw_context.drawinfo.end.x = x;
2446
2447 draw_context.drawinfo.y.over = y+1;
2448 draw_context.drawinfo.y.middle = y+(height/2);
2449 draw_context.drawinfo.y.under = y+height;
2450
2451 draw_context.drawinfo.start.offset.over = 0;
2452 draw_context.drawinfo.start.offset.middle = 0;
2453 draw_context.drawinfo.start.offset.under = 0;
2454 draw_context.drawinfo.end.offset.over = 0;
2455 draw_context.drawinfo.end.offset.middle = 0;
2456 draw_context.drawinfo.end.offset.under = 0;
2457
2458 {
2459 /* Draw the line */
2460 PropertiesLine prop_line = prepare_s_e_line(process);
2461 draw_line((void*)&prop_line, (void*)&draw_context);
2462
2463 }
2464 /* become the last x position */
2465 hashed_process_data->x.middle = x;
2466 hashed_process_data->x.middle_used = TRUE;
2467 hashed_process_data->x.middle_marked = FALSE;
2468
2469 /* Calculate the next good time */
2470 convert_pixels_to_time(width, x+1, time_window,
2471 &hashed_process_data->next_good_time);
2472 }
2473 }
2474
2475 }
2476 return 0;
2477
2478}
2479
2480
2481
2482
2483
2484
2485/* after_process_hook
2486 *
2487 * Create the processlist entry for the child process. Put the last
2488 * position in x at the current time value.
2489 *
2490 * @param hook_data ControlFlowData structure of the viewer.
2491 * @param call_data Event context.
2492 *
2493 * This function adds items to be drawn in a queue for each process.
2494 *
2495 */
2496int after_process_hook(void *hook_data, void *call_data)
2497{
2498 EventsRequest *events_request = (EventsRequest*)hook_data;
2499 ControlFlowData *control_flow_data = events_request->viewer_data;
2500
2501 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2502
2503 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2504 LttvTraceState *ts =(LttvTraceState *)((LttvTracefileContext*)tfs)->t_context;
2505
2506 LttEvent *e;
2507 e = tfc->e;
2508
2509 LttTime evtime = ltt_event_time(e);
2510 guint width = control_flow_data->drawing->width;
2511
2512 guint sub_id;
2513 guint param1;
2514 {
2515 LttField *f = ltt_event_field(e);
2516 LttField *element;
2517 element = ltt_field_member(f,0);
2518 sub_id = ltt_event_get_long_unsigned(e,element);
2519 element = ltt_field_member(f,1);
2520 param1 = ltt_event_get_long_unsigned(e,element);
2521 }
2522
2523 if(sub_id == 2) { /* fork */
2524
2525 guint child_pid = param1;
2526 /* Add process to process list (if not present) */
2527 LttvProcessState *process_child;
2528 LttTime birth;
2529 guint y_child = 0, height = 0, pl_height = 0;
2530 HashedProcessData *hashed_process_data_child = NULL;
2531
2532 ProcessList *process_list = control_flow_data->process_list;
2533
2534 /* Find child in the list... */
2535 process_child = lttv_state_find_process(tfs, child_pid);
2536 /* It should exist, because we are after the state update. */
2537 g_assert(process_child != NULL);
2538
2539 birth = process_child->creation_time;
2540
2541 if(processlist_get_process_pixels(process_list,
2542 child_pid,
2543 process_child->last_cpu_index,
2544 &birth,
2545 tfc->t_context->index,
2546 &y_child,
2547 &height,
2548 &hashed_process_data_child) == 1)
2549 {
2550 g_assert(child_pid == 0 || child_pid != process_child->ppid);
2551 /* Process not present */
2552 const gchar *name = g_quark_to_string(process_child->name);
2553 ProcessInfo *process_info;
2554 processlist_add(process_list,
2555 child_pid,
2556 process_child->last_cpu_index,
2557 process_child->ppid,
2558 &birth,
2559 tfc->t_context->index,
2560 name,
2561 &pl_height,
2562 &process_info,
2563 &hashed_process_data_child);
2564 processlist_get_pixels_from_data(process_list,
2565 hashed_process_data_child,
2566 &y_child,
2567 &height);
2568 drawing_insert_square( control_flow_data->drawing, y_child, height);
2569 }
2570
2571
2572 if(ltt_time_compare(hashed_process_data_child->next_good_time,
2573 evtime) <= 0)
2574 {
2575 TimeWindow time_window =
2576 lttvwindow_get_time_window(control_flow_data->tab);
2577
2578#ifdef EXTRA_CHECK
2579 if(ltt_time_compare(evtime, time_window.start_time) == -1
2580 || ltt_time_compare(evtime, time_window.end_time) == 1)
2581 return;
2582#endif //EXTRA_CHECK
2583
2584 guint new_x;
2585 convert_time_to_pixels(
2586 time_window,
2587 evtime,
2588 width,
2589 &new_x);
2590
2591 if(hashed_process_data_child->x.over != new_x) {
2592 hashed_process_data_child->x.over = new_x;
2593 hashed_process_data_child->x.over_used = FALSE;
2594 hashed_process_data_child->x.over_marked = FALSE;
2595 }
2596 if(hashed_process_data_child->x.middle != new_x) {
2597 hashed_process_data_child->x.middle = new_x;
2598 hashed_process_data_child->x.middle_used = FALSE;
2599 hashed_process_data_child->x.middle_marked = FALSE;
2600 }
2601 if(hashed_process_data_child->x.under != new_x) {
2602 hashed_process_data_child->x.under = new_x;
2603 hashed_process_data_child->x.under_used = FALSE;
2604 hashed_process_data_child->x.under_marked = FALSE;
2605 }
2606 }
2607
2608 } else if(sub_id == 3) { /* exit */
2609
2610 /* Add process to process list (if not present) */
2611 LttvProcessState *process = tfs->process;
2612 guint pid = process->pid;
2613 LttTime birth;
2614 guint y = 0, height = 0, pl_height = 0;
2615 HashedProcessData *hashed_process_data = NULL;
2616
2617 ProcessList *process_list = control_flow_data->process_list;
2618
2619 /* It should exist, because we are after the state update. */
2620 g_assert(process != NULL);
2621
2622 birth = process->creation_time;
2623
2624 if(process_list->current_hash_data[tfc->index] != NULL) {
2625 hashed_process_data = process_list->current_hash_data[tfc->index];
2626 processlist_get_pixels_from_data(process_list,
2627 hashed_process_data,
2628 &y,
2629 &height);
2630
2631 } else {
2632 if(processlist_get_process_pixels(process_list,
2633 pid,
2634 process->last_cpu_index,
2635 &birth,
2636 tfc->t_context->index,
2637 &y,
2638 &height,
2639 &hashed_process_data) == 1)
2640 {
2641 g_assert(pid == 0 || pid != process->ppid);
2642 /* Process not present */
2643 const gchar *name = g_quark_to_string(process->name);
2644 ProcessInfo *process_info;
2645 processlist_add(process_list,
2646 pid,
2647 process->last_cpu_index,
2648 process->ppid,
2649 &birth,
2650 tfc->t_context->index,
2651 name,
2652 &pl_height,
2653 &process_info,
2654 &hashed_process_data);
2655 processlist_get_pixels_from_data(process_list,
2656 hashed_process_data,
2657 &y,
2658 &height);
2659 drawing_insert_square( control_flow_data->drawing, y, height);
2660 }
2661
2662 /* Set the current process */
2663 process_list->current_hash_data[process->last_cpu_index] =
2664 hashed_process_data;
2665 }
2666
2667 if(ltt_time_compare(hashed_process_data->next_good_time,
2668 evtime) <= 0)
2669 {
2670 TimeWindow time_window =
2671 lttvwindow_get_time_window(control_flow_data->tab);
2672
2673#ifdef EXTRA_CHECK
2674 if(ltt_time_compare(evtime, time_window.start_time) == -1
2675 || ltt_time_compare(evtime, time_window.end_time) == 1)
2676 return;
2677#endif //EXTRA_CHECK
2678
2679 guint new_x;
2680 convert_time_to_pixels(
2681 time_window,
2682 evtime,
2683 width,
2684 &new_x);
2685 if(hashed_process_data->x.middle != new_x) {
2686 hashed_process_data->x.middle = new_x;
2687 hashed_process_data->x.middle_used = FALSE;
2688 hashed_process_data->x.middle_marked = FALSE;
2689 }
2690 }
2691
2692 }
2693 return 0;
2694
2695}
2696
2697
2698gint update_time_window_hook(void *hook_data, void *call_data)
2699{
2700 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2701 Drawing_t *drawing = control_flow_data->drawing;
2702
2703 const TimeWindowNotifyData *time_window_nofify_data =
2704 ((const TimeWindowNotifyData *)call_data);
2705
2706 TimeWindow *old_time_window =
2707 time_window_nofify_data->old_time_window;
2708 TimeWindow *new_time_window =
2709 time_window_nofify_data->new_time_window;
2710
2711 /* Update the ruler */
2712 drawing_update_ruler(control_flow_data->drawing,
2713 new_time_window);
2714
2715
2716 /* Two cases : zoom in/out or scrolling */
2717
2718 /* In order to make sure we can reuse the old drawing, the scale must
2719 * be the same and the new time interval being partly located in the
2720 * currently shown time interval. (reuse is only for scrolling)
2721 */
2722
2723 g_info("Old time window HOOK : %u, %u to %u, %u",
2724 old_time_window->start_time.tv_sec,
2725 old_time_window->start_time.tv_nsec,
2726 old_time_window->time_width.tv_sec,
2727 old_time_window->time_width.tv_nsec);
2728
2729 g_info("New time window HOOK : %u, %u to %u, %u",
2730 new_time_window->start_time.tv_sec,
2731 new_time_window->start_time.tv_nsec,
2732 new_time_window->time_width.tv_sec,
2733 new_time_window->time_width.tv_nsec);
2734
2735 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
2736 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
2737 {
2738 /* Same scale (scrolling) */
2739 g_info("scrolling");
2740 LttTime *ns = &new_time_window->start_time;
2741 LttTime *nw = &new_time_window->time_width;
2742 LttTime *os = &old_time_window->start_time;
2743 LttTime *ow = &old_time_window->time_width;
2744 LttTime old_end = old_time_window->end_time;
2745 LttTime new_end = new_time_window->end_time;
2746 //if(ns<os+w<ns+w)
2747 //if(ns<os+w && os+w<ns+w)
2748 //if(ns<old_end && os<ns)
2749 if(ltt_time_compare(*ns, old_end) == -1
2750 && ltt_time_compare(*os, *ns) == -1)
2751 {
2752 g_info("scrolling near right");
2753 /* Scroll right, keep right part of the screen */
2754 guint x = 0;
2755 guint width = control_flow_data->drawing->width;
2756 convert_time_to_pixels(
2757 *old_time_window,
2758 *ns,
2759 width,
2760 &x);
2761
2762 /* Copy old data to new location */
2763 gdk_draw_drawable (control_flow_data->drawing->pixmap,
2764 control_flow_data->drawing->drawing_area->style->black_gc,
2765 control_flow_data->drawing->pixmap,
2766 x, 0,
2767 0, 0,
2768 control_flow_data->drawing->width-x+SAFETY, -1);
2769
2770 if(drawing->damage_begin == drawing->damage_end)
2771 drawing->damage_begin = control_flow_data->drawing->width-x;
2772 else
2773 drawing->damage_begin = 0;
2774
2775 drawing->damage_end = control_flow_data->drawing->width;
2776
2777 /* Clear the data request background, but not SAFETY */
2778 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2779 //control_flow_data->drawing->drawing_area->style->black_gc,
2780 control_flow_data->drawing->drawing_area->style->black_gc,
2781 TRUE,
2782 drawing->damage_begin+SAFETY, 0,
2783 drawing->damage_end - drawing->damage_begin, // do not overlap
2784 control_flow_data->drawing->height);
2785
2786 gtk_widget_queue_draw_area (drawing->drawing_area,
2787 0,0,
2788 control_flow_data->drawing->width,
2789 control_flow_data->drawing->height);
2790
2791 /* Get new data for the rest. */
2792 drawing_data_request(control_flow_data->drawing,
2793 &control_flow_data->drawing->pixmap,
2794 drawing->damage_begin, 0,
2795 drawing->damage_end - drawing->damage_begin,
2796 control_flow_data->drawing->height);
2797 } else {
2798 //if(ns<os<ns+w)
2799 //if(ns<os && os<ns+w)
2800 //if(ns<os && os<new_end)
2801 if(ltt_time_compare(*ns,*os) == -1
2802 && ltt_time_compare(*os,new_end) == -1)
2803 {
2804 g_info("scrolling near left");
2805 /* Scroll left, keep left part of the screen */
2806 guint x = 0;
2807 guint width = control_flow_data->drawing->width;
2808 convert_time_to_pixels(
2809 *new_time_window,
2810 *os,
2811 width,
2812 &x);
2813
2814
2815 /* Copy old data to new location */
2816 gdk_draw_drawable (control_flow_data->drawing->pixmap,
2817 control_flow_data->drawing->drawing_area->style->black_gc,
2818 control_flow_data->drawing->pixmap,
2819 0, 0,
2820 x, 0,
2821 -1, -1);
2822
2823 if(drawing->damage_begin == drawing->damage_end)
2824 drawing->damage_end = x;
2825 else
2826 drawing->damage_end =
2827 control_flow_data->drawing->width;
2828
2829 drawing->damage_begin = 0;
2830
2831 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2832 control_flow_data->drawing->drawing_area->style->black_gc,
2833 TRUE,
2834 drawing->damage_begin, 0,
2835 drawing->damage_end - drawing->damage_begin, // do not overlap
2836 control_flow_data->drawing->height);
2837
2838 gtk_widget_queue_draw_area (drawing->drawing_area,
2839 0,0,
2840 control_flow_data->drawing->width,
2841 control_flow_data->drawing->height);
2842
2843
2844 /* Get new data for the rest. */
2845 drawing_data_request(control_flow_data->drawing,
2846 &control_flow_data->drawing->pixmap,
2847 drawing->damage_begin, 0,
2848 drawing->damage_end - drawing->damage_begin,
2849 control_flow_data->drawing->height);
2850
2851 } else {
2852 if(ltt_time_compare(*ns,*os) == 0)
2853 {
2854 g_info("not scrolling");
2855 } else {
2856 g_info("scrolling far");
2857 /* Cannot reuse any part of the screen : far jump */
2858
2859
2860 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2861 control_flow_data->drawing->drawing_area->style->black_gc,
2862 TRUE,
2863 0, 0,
2864 control_flow_data->drawing->width+SAFETY, // do not overlap
2865 control_flow_data->drawing->height);
2866
2867 gtk_widget_queue_draw_area (drawing->drawing_area,
2868 0,0,
2869 control_flow_data->drawing->width,
2870 control_flow_data->drawing->height);
2871
2872 drawing->damage_begin = 0;
2873 drawing->damage_end = control_flow_data->drawing->width;
2874
2875 drawing_data_request(control_flow_data->drawing,
2876 &control_flow_data->drawing->pixmap,
2877 0, 0,
2878 control_flow_data->drawing->width,
2879 control_flow_data->drawing->height);
2880
2881 }
2882 }
2883 }
2884 } else {
2885 /* Different scale (zoom) */
2886 g_info("zoom");
2887
2888 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2889 control_flow_data->drawing->drawing_area->style->black_gc,
2890 TRUE,
2891 0, 0,
2892 control_flow_data->drawing->width+SAFETY, // do not overlap
2893 control_flow_data->drawing->height);
2894
2895 gtk_widget_queue_draw_area (drawing->drawing_area,
2896 0,0,
2897 control_flow_data->drawing->width,
2898 control_flow_data->drawing->height);
2899
2900 drawing->damage_begin = 0;
2901 drawing->damage_end = control_flow_data->drawing->width;
2902
2903 drawing_data_request(control_flow_data->drawing,
2904 &control_flow_data->drawing->pixmap,
2905 0, 0,
2906 control_flow_data->drawing->width,
2907 control_flow_data->drawing->height);
2908 }
2909
2910
2911
2912 return 0;
2913}
2914
2915gint traceset_notify(void *hook_data, void *call_data)
2916{
2917 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2918 Drawing_t *drawing = control_flow_data->drawing;
2919 GtkWidget *widget = drawing->drawing_area;
2920
2921
2922 drawing_clear(control_flow_data->drawing);
2923 processlist_clear(control_flow_data->process_list);
2924 redraw_notify(control_flow_data, NULL);
2925
2926 request_background_data(control_flow_data);
2927#if 0
2928 drawing->damage_begin = 0;
2929 drawing->damage_end = drawing->width;
2930 if(drawing->damage_begin < drawing->damage_end)
2931 {
2932 drawing_data_request(drawing,
2933 &drawing->pixmap,
2934 drawing->damage_begin,
2935 0,
2936 drawing->damage_end-drawing->damage_begin,
2937 drawing->height);
2938 }
2939
2940 gtk_widget_queue_draw_area(drawing->drawing_area,
2941 0,0,
2942 drawing->width,
2943 drawing->height);
2944#endif //0
2945
2946 return FALSE;
2947}
2948
2949gint redraw_notify(void *hook_data, void *call_data)
2950{
2951 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2952 Drawing_t *drawing = control_flow_data->drawing;
2953 GtkWidget *widget = drawing->drawing_area;
2954
2955 drawing->damage_begin = 0;
2956 drawing->damage_end = drawing->width;
2957
2958 /* fun feature, to be separated someday... */
2959 drawing_clear(control_flow_data->drawing);
2960 processlist_clear(control_flow_data->process_list);
2961
2962 // Clear the image
2963 gdk_draw_rectangle (drawing->pixmap,
2964 widget->style->black_gc,
2965 TRUE,
2966 0, 0,
2967 drawing->width+SAFETY,
2968 drawing->height);
2969
2970
2971 if(drawing->damage_begin < drawing->damage_end)
2972 {
2973 drawing_data_request(drawing,
2974 &drawing->pixmap,
2975 drawing->damage_begin,
2976 0,
2977 drawing->damage_end-drawing->damage_begin,
2978 drawing->height);
2979 }
2980
2981 gtk_widget_queue_draw_area(drawing->drawing_area,
2982 0,0,
2983 drawing->width,
2984 drawing->height);
2985 return FALSE;
2986
2987}
2988
2989
2990gint continue_notify(void *hook_data, void *call_data)
2991{
2992 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2993 Drawing_t *drawing = control_flow_data->drawing;
2994 GtkWidget *widget = drawing->drawing_area;
2995
2996 //g_assert(widget->allocation.width == drawing->damage_end);
2997
2998 if(drawing->damage_begin < drawing->damage_end)
2999 {
3000 drawing_data_request(drawing,
3001 &drawing->pixmap,
3002 drawing->damage_begin,
3003 0,
3004 drawing->damage_end-drawing->damage_begin,
3005 drawing->height);
3006 }
3007
3008 return FALSE;
3009}
3010
3011
3012gint update_current_time_hook(void *hook_data, void *call_data)
3013{
3014 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
3015 Drawing_t *drawing = control_flow_data->drawing;
3016
3017 LttTime current_time = *((LttTime*)call_data);
3018
3019 TimeWindow time_window =
3020 lttvwindow_get_time_window(control_flow_data->tab);
3021
3022 LttTime time_begin = time_window.start_time;
3023 LttTime width = time_window.time_width;
3024 LttTime half_width;
3025 {
3026 guint64 time_ll = ltt_time_to_uint64(width);
3027 time_ll = time_ll >> 1; /* divide by two */
3028 half_width = ltt_time_from_uint64(time_ll);
3029 }
3030 LttTime time_end = ltt_time_add(time_begin, width);
3031
3032 LttvTracesetContext * tsc =
3033 lttvwindow_get_traceset_context(control_flow_data->tab);
3034
3035 LttTime trace_start = tsc->time_span.start_time;
3036 LttTime trace_end = tsc->time_span.end_time;
3037
3038 g_info("New current time HOOK : %u, %u", current_time.tv_sec,
3039 current_time.tv_nsec);
3040
3041
3042
3043 /* If current time is inside time interval, just move the highlight
3044 * bar */
3045
3046 /* Else, we have to change the time interval. We have to tell it
3047 * to the main window. */
3048 /* The time interval change will take care of placing the current
3049 * time at the center of the visible area, or nearest possible if we are
3050 * at one end of the trace. */
3051
3052
3053 if(ltt_time_compare(current_time, time_begin) == -1)
3054 {
3055 TimeWindow new_time_window;
3056
3057 if(ltt_time_compare(current_time,
3058 ltt_time_add(trace_start,half_width)) == -1)
3059 time_begin = trace_start;
3060 else
3061 time_begin = ltt_time_sub(current_time,half_width);
3062
3063 new_time_window.start_time = time_begin;
3064 new_time_window.time_width = width;
3065 new_time_window.time_width_double = ltt_time_to_double(width);
3066 new_time_window.end_time = ltt_time_add(time_begin, width);
3067
3068 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3069 }
3070 else if(ltt_time_compare(current_time, time_end) == 1)
3071 {
3072 TimeWindow new_time_window;
3073
3074 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) == 1)
3075 time_begin = ltt_time_sub(trace_end,width);
3076 else
3077 time_begin = ltt_time_sub(current_time,half_width);
3078
3079 new_time_window.start_time = time_begin;
3080 new_time_window.time_width = width;
3081 new_time_window.time_width_double = ltt_time_to_double(width);
3082 new_time_window.end_time = ltt_time_add(time_begin, width);
3083
3084 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
3085
3086 }
3087 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
3088 gtk_widget_queue_draw_area(drawing->drawing_area,
3089 0,0,
3090 drawing->width,
3091 drawing->height);
3092
3093 return 0;
3094}
3095
3096typedef struct _ClosureData {
3097 EventsRequest *events_request;
3098 LttvTracesetState *tss;
3099 LttTime end_time;
3100} ClosureData;
3101
3102
3103void draw_closure(gpointer key, gpointer value, gpointer user_data)
3104{
3105 ProcessInfo *process_info = (ProcessInfo*)key;
3106 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
3107 ClosureData *closure_data = (ClosureData*)user_data;
3108
3109 EventsRequest *events_request = closure_data->events_request;
3110 ControlFlowData *control_flow_data = events_request->viewer_data;
3111 Drawing_t *drawing = control_flow_data->drawing;
3112
3113 LttvTracesetState *tss = closure_data->tss;
3114 LttvTracesetContext *tsc = (LttvTracesetContext*)closure_data->tss;
3115
3116 LttTime evtime = closure_data->end_time;
3117 guint width = drawing->width;
3118
3119 {
3120 /* For the process */
3121 /* First, check if the current process is in the state computation
3122 * process list. If it is there, that means we must add it right now and
3123 * draw items from the beginning of the read for it. If it is not
3124 * present, it's a new process and it was not present : it will
3125 * be added after the state update. */
3126#ifdef EXTRA_CHECK
3127 g_assert(lttv_traceset_number(tsc->ts) > 0);
3128#endif //EXTRA_CHECK
3129 /* tracefiles[0] is ok here, because we draw for every PID, and
3130 * assume CPU 0 for PID 0 //FIXME */
3131 LttvTracefileState *tfs =
3132 (LttvTracefileState*)tsc->traces[process_info->trace_num]->tracefiles[0];
3133
3134 LttvProcessState *process;
3135 process = lttv_state_find_process(tfs,
3136 process_info->pid);
3137
3138 if(process != NULL) {
3139
3140 /* Only draw for processes that are currently in the trace states */
3141
3142 guint y = 0, height = 0, pl_height = 0;
3143 ProcessList *process_list = control_flow_data->process_list;
3144 LttTime birth = process_info->birth;
3145
3146 /* Should be alike when background info is ready */
3147 if(control_flow_data->background_info_waiting==0)
3148 g_assert(ltt_time_compare(process->creation_time,
3149 process_info->birth) == 0);
3150 /* process HAS to be present */
3151 processlist_get_pixels_from_data(process_list,
3152 hashed_process_data,
3153 &y,
3154 &height);
3155
3156 /* Now, the process is in the state hash and our own process hash.
3157 * We definitely can draw the items related to the ending state.
3158 */
3159
3160 /* Check if the x position is unset. In can have been left unset by
3161 * a draw closure from a after chunk hook. This should never happen,
3162 * because it must be set by before chunk hook to the damage_begin
3163 * value.
3164 */
3165 g_assert(hashed_process_data->x.over != -1);
3166
3167 if(ltt_time_compare(hashed_process_data->next_good_time,
3168 evtime) <= 0)
3169 {
3170 TimeWindow time_window =
3171 lttvwindow_get_time_window(control_flow_data->tab);
3172
3173#ifdef EXTRA_CHECK
3174 if(ltt_time_compare(evtime, time_window.start_time) == -1
3175 || ltt_time_compare(evtime, time_window.end_time) == 1)
3176 return;
3177#endif //EXTRA_CHECK
3178 guint x;
3179
3180 convert_time_to_pixels(
3181 time_window,
3182 evtime,
3183 width,
3184 &x);
3185
3186 DrawContext draw_context;
3187
3188 /* Now create the drawing context that will be used to draw
3189 * items related to the last state. */
3190 draw_context.drawable = drawing->pixmap;
3191 draw_context.gc = drawing->gc;
3192 draw_context.pango_layout = drawing->pango_layout;
3193 draw_context.drawinfo.end.x = x;
3194
3195 draw_context.drawinfo.y.over = y+1;
3196 draw_context.drawinfo.y.middle = y+(height/2);
3197 draw_context.drawinfo.y.under = y+height;
3198
3199 draw_context.drawinfo.start.offset.over = 0;
3200 draw_context.drawinfo.start.offset.middle = 0;
3201 draw_context.drawinfo.start.offset.under = 0;
3202 draw_context.drawinfo.end.offset.over = 0;
3203 draw_context.drawinfo.end.offset.middle = 0;
3204 draw_context.drawinfo.end.offset.under = 0;
3205#if 0
3206 /* Jump over draw if we are at the same x position */
3207 if(x == hashed_process_data->x.over)
3208 {
3209 /* jump */
3210 } else {
3211 draw_context.drawinfo.start.x = hashed_process_data->x.over;
3212 /* Draw the line */
3213 PropertiesLine prop_line = prepare_execmode_line(process);
3214 draw_line((void*)&prop_line, (void*)&draw_context);
3215
3216 hashed_process_data->x.over = x;
3217 }
3218#endif //0
3219
3220 if(x == hashed_process_data->x.middle &&
3221 hashed_process_data->x.middle_used) {
3222#if 0 /* do not mark closure : not missing information */
3223 if(hashed_process_data->x.middle_marked == FALSE) {
3224 /* Draw collision indicator */
3225 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
3226 gdk_draw_point(drawing->pixmap,
3227 drawing->gc,
3228 x,
3229 y+(height/2)-3);
3230 hashed_process_data->x.middle_marked = TRUE;
3231 }
3232#endif //0
3233 /* Jump */
3234 } else {
3235 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
3236 /* Draw the line */
3237 PropertiesLine prop_line = prepare_s_e_line(process);
3238 draw_line((void*)&prop_line, (void*)&draw_context);
3239
3240 /* become the last x position */
3241 if(x != hashed_process_data->x.middle) {
3242 hashed_process_data->x.middle = x;
3243 /* but don't use the pixel */
3244 hashed_process_data->x.middle_used = FALSE;
3245
3246 /* Calculate the next good time */
3247 convert_pixels_to_time(width, x+1, time_window,
3248 &hashed_process_data->next_good_time);
3249 }
3250 }
3251 }
3252 }
3253 }
3254 return;
3255}
3256
3257int before_chunk(void *hook_data, void *call_data)
3258{
3259 EventsRequest *events_request = (EventsRequest*)hook_data;
3260 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3261
3262 drawing_chunk_begin(events_request, tss);
3263
3264 return 0;
3265}
3266
3267int before_request(void *hook_data, void *call_data)
3268{
3269 EventsRequest *events_request = (EventsRequest*)hook_data;
3270 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3271
3272 drawing_data_request_begin(events_request, tss);
3273
3274 return 0;
3275}
3276
3277
3278/*
3279 * after request is necessary in addition of after chunk in order to draw
3280 * lines until the end of the screen. after chunk just draws lines until
3281 * the last event.
3282 *
3283 * for each process
3284 * draw closing line
3285 * expose
3286 */
3287int after_request(void *hook_data, void *call_data)
3288{
3289 EventsRequest *events_request = (EventsRequest*)hook_data;
3290 ControlFlowData *control_flow_data = events_request->viewer_data;
3291 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3292 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
3293
3294 ProcessList *process_list = control_flow_data->process_list;
3295 LttTime end_time = events_request->end_time;
3296
3297 ClosureData closure_data;
3298 closure_data.events_request = (EventsRequest*)hook_data;
3299 closure_data.tss = tss;
3300 closure_data.end_time = end_time;
3301
3302 /* Draw last items */
3303 g_hash_table_foreach(process_list->process_hash, draw_closure,
3304 (void*)&closure_data);
3305
3306 /* Request expose */
3307 drawing_request_expose(events_request, tss, end_time);
3308 return 0;
3309}
3310
3311/*
3312 * for each process
3313 * draw closing line
3314 * expose
3315 */
3316int after_chunk(void *hook_data, void *call_data)
3317{
3318 EventsRequest *events_request = (EventsRequest*)hook_data;
3319 ControlFlowData *control_flow_data = events_request->viewer_data;
3320 LttvTracesetState *tss = (LttvTracesetState*)call_data;
3321 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
3322 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
3323 LttTime end_time;
3324
3325 ProcessList *process_list = control_flow_data->process_list;
3326
3327 g_free(process_list->current_hash_data);
3328 process_list->current_hash_data = NULL;
3329
3330 if(tfc != NULL)
3331 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
3332 else /* end of traceset, or position now out of request : end */
3333 end_time = events_request->end_time;
3334
3335 ClosureData closure_data;
3336 closure_data.events_request = (EventsRequest*)hook_data;
3337 closure_data.tss = tss;
3338 closure_data.end_time = end_time;
3339
3340 /* Draw last items */
3341 g_hash_table_foreach(process_list->process_hash, draw_closure,
3342 (void*)&closure_data);
3343
3344 /* Request expose */
3345 drawing_request_expose(events_request, tss, end_time);
3346
3347 return 0;
3348}
3349
This page took 0.032592 seconds and 4 git commands to generate.