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