wait fork state now ok
[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 #include "cfv-private.h"
75
76
77 #define MAX_PATH_LEN 256
78
79
80 #if 0
81 typedef struct _ProcessAddClosure {
82 ControlFlowData *cfd;
83 guint trace_num;
84 } ProcessAddClosure;
85
86 static void process_add(gpointer key,
87 gpointer value,
88 gpointer user_data)
89 {
90 LttvProcessState *process = (LttvProcessState*)value;
91 ProcessAddClosure *closure = (ProcessAddClosure*)user_data;
92 ControlFlowData *control_flow_data = closure->cfd;
93 guint trace_num = closure->trace_num;
94
95 /* Add process to process list (if not present) */
96 guint pid;
97 LttTime birth;
98 guint y = 0, height = 0, pl_height = 0;
99
100 ProcessList *process_list =
101 guicontrolflow_get_process_list(control_flow_data);
102
103 pid = process->pid;
104 birth = process->creation_time;
105 const gchar *name = g_quark_to_string(process->name);
106 HashedProcessData *hashed_process_data = NULL;
107
108 if(processlist_get_process_pixels(process_list,
109 pid,
110 &birth,
111 trace_num,
112 &y,
113 &height,
114 &hashed_process_data) == 1)
115 {
116 /* Process not present */
117 processlist_add(process_list,
118 pid,
119 &birth,
120 trace_num,
121 name,
122 &pl_height,
123 &hashed_process_data);
124 processlist_get_process_pixels(process_list,
125 pid,
126 &birth,
127 trace_num,
128 &y,
129 &height,
130 &hashed_process_data);
131 drawing_insert_square( control_flow_data->drawing, y, height);
132 }
133 }
134 #endif //0
135
136
137 /* Action to do when background computation completed.
138 *
139 * Wait for all the awaited computations to be over.
140 */
141
142 gint background_ready(void *hook_data, void *call_data)
143 {
144 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
145 LttvTrace *trace = (LttvTrace*)call_data;
146 LttvTracesetContext *tsc =
147 lttvwindow_get_traceset_context(control_flow_data->tab);
148
149 control_flow_data->background_info_waiting--;
150
151 if(control_flow_data->background_info_waiting == 0) {
152 g_debug("control flow viewer : background computation data ready.");
153
154 drawing_clear(control_flow_data->drawing);
155 processlist_clear(control_flow_data->process_list);
156 redraw_notify(control_flow_data, NULL);
157 }
158
159 return 0;
160 }
161
162
163 /* Request background computation. Verify if it is in progress or ready first.
164 * Only for each trace in the tab's traceset.
165 */
166 void request_background_data(ControlFlowData *control_flow_data)
167 {
168 LttvTracesetContext * tsc =
169 lttvwindow_get_traceset_context(control_flow_data->tab);
170 gint num_traces = lttv_traceset_number(tsc->ts);
171 gint i;
172 LttvTrace *trace;
173
174 LttvHooks *background_ready_hook =
175 lttv_hooks_new();
176 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
177 LTTV_PRIO_DEFAULT);
178 control_flow_data->background_info_waiting = 0;
179
180 for(i=0;i<num_traces;i++) {
181 trace = lttv_traceset_get(tsc->ts, i);
182
183 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) {
184
185 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
186 trace) == FALSE) {
187 /* We first remove requests that could have been done for the same
188 * information. Happens when two viewers ask for it before servicing
189 * starts.
190 */
191 lttvwindowtraces_background_request_remove(trace, "state");
192 lttvwindowtraces_background_request_queue(trace,
193 "state");
194 lttvwindowtraces_background_notify_queue(control_flow_data,
195 trace,
196 ltt_time_infinite,
197 NULL,
198 background_ready_hook);
199 control_flow_data->background_info_waiting++;
200 } else { /* in progress */
201
202 lttvwindowtraces_background_notify_current(control_flow_data,
203 trace,
204 ltt_time_infinite,
205 NULL,
206 background_ready_hook);
207 control_flow_data->background_info_waiting++;
208 }
209 }
210 }
211
212 lttv_hooks_destroy(background_ready_hook);
213 }
214
215
216
217
218 /**
219 * Event Viewer's constructor hook
220 *
221 * This constructor is given as a parameter to the menuitem and toolbar button
222 * registration. It creates the list.
223 * @param tab A pointer to the parent tab.
224 * @return The widget created.
225 */
226 GtkWidget *
227 h_guicontrolflow(Tab *tab)
228 {
229 g_info("h_guicontrolflow, %p", tab);
230 ControlFlowData *control_flow_data = guicontrolflow() ;
231
232 control_flow_data->tab = tab;
233
234 //g_debug("time width2 : %u",time_window->time_width);
235 // Unreg done in the GuiControlFlow_Destructor
236 lttvwindow_register_traceset_notify(tab,
237 traceset_notify,
238 control_flow_data);
239
240 lttvwindow_register_time_window_notify(tab,
241 update_time_window_hook,
242 control_flow_data);
243 lttvwindow_register_current_time_notify(tab,
244 update_current_time_hook,
245 control_flow_data);
246 lttvwindow_register_redraw_notify(tab,
247 redraw_notify,
248 control_flow_data);
249 lttvwindow_register_continue_notify(tab,
250 continue_notify,
251 control_flow_data);
252 request_background_data(control_flow_data);
253
254
255 return guicontrolflow_get_widget(control_flow_data) ;
256
257 }
258
259 int event_selected_hook(void *hook_data, void *call_data)
260 {
261 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
262 guint *event_number = (guint*) call_data;
263
264 g_debug("DEBUG : event selected by main window : %u", *event_number);
265
266 }
267
268
269 static __inline PropertiesLine prepare_status_line(LttvProcessState *process)
270 {
271 PropertiesLine prop_line;
272 prop_line.line_width = 2;
273 prop_line.style = GDK_LINE_SOLID;
274 prop_line.y = MIDDLE;
275 //GdkColormap *colormap = gdk_colormap_get_system();
276
277 g_debug("prepare_status_line for state : %s", g_quark_to_string(process->state->s));
278
279 /* color of line : status of the process */
280 if(process->state->s == LTTV_STATE_UNNAMED)
281 prop_line.color = drawing_colors[COL_WHITE];
282 else if(process->state->s == LTTV_STATE_WAIT_FORK)
283 prop_line.color = drawing_colors[COL_WAIT_FORK];
284 else if(process->state->s == LTTV_STATE_WAIT_CPU)
285 prop_line.color = drawing_colors[COL_WAIT_CPU];
286 else if(process->state->s == LTTV_STATE_ZOMBIE)
287 prop_line.color = drawing_colors[COL_ZOMBIE];
288 else if(process->state->s == LTTV_STATE_WAIT)
289 prop_line.color = drawing_colors[COL_WAIT];
290 else if(process->state->s == LTTV_STATE_RUN)
291 prop_line.color = drawing_colors[COL_RUN];
292 else
293 prop_line.color = drawing_colors[COL_WHITE];
294
295 //gdk_colormap_alloc_color(colormap,
296 // prop_line.color,
297 // FALSE,
298 // TRUE);
299
300 return prop_line;
301
302 }
303
304
305
306 /* before_schedchange_hook
307 *
308 * This function basically draw lines and icons. Two types of lines are drawn :
309 * one small (3 pixels?) representing the state of the process and the second
310 * type is thicker (10 pixels?) representing on which CPU a process is running
311 * (and this only in running state).
312 *
313 * Extremums of the lines :
314 * x_min : time of the last event context for this process kept in memory.
315 * x_max : time of the current event.
316 * y : middle of the process in the process list. The process is found in the
317 * list, therefore is it's position in pixels.
318 *
319 * The choice of lines'color is defined by the context of the last event for this
320 * process.
321 */
322
323
324 int before_schedchange_hook(void *hook_data, void *call_data)
325 {
326 EventsRequest *events_request = (EventsRequest*)hook_data;
327 ControlFlowData *control_flow_data = events_request->viewer_data;
328 Drawing_t *drawing = control_flow_data->drawing;
329
330 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
331
332 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
333 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
334
335 LttEvent *e;
336 e = tfc->e;
337
338 LttTime evtime = ltt_event_time(e);
339 TimeWindow time_window =
340 lttvwindow_get_time_window(control_flow_data->tab);
341
342 LttTime end_time = ltt_time_add(time_window.start_time,
343 time_window.time_width);
344
345 if(ltt_time_compare(evtime, time_window.start_time) == -1
346 || ltt_time_compare(evtime, end_time) == 1)
347 return;
348
349 guint width = drawing->width;
350
351 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0) {
352
353 /* we are in a schedchange, before the state update. We must draw the
354 * items corresponding to the state before it changes : now is the right
355 * time to do it.
356 */
357
358 guint pid_out;
359 guint pid_in;
360 {
361 LttField *f = ltt_event_field(e);
362 LttField *element;
363 element = ltt_field_member(f,0);
364 pid_out = ltt_event_get_long_unsigned(e,element);
365 element = ltt_field_member(f,1);
366 pid_in = ltt_event_get_long_unsigned(e,element);
367 g_debug("out : %u in : %u", pid_out, pid_in);
368 }
369
370 {
371 /* For the pid_out */
372 /* First, check if the current process is in the state computation
373 * process list. If it is there, that means we must add it right now and
374 * draw items from the beginning of the read for it. If it is not
375 * present, it's a new process and it was not present : it will
376 * be added after the state update. */
377 LttvProcessState *process;
378 process = lttv_state_find_process(tfs, pid_out);
379
380 if(process != NULL) {
381 /* Well, the process_out existed : we must get it in the process hash
382 * or add it, and draw its items.
383 */
384 /* Add process to process list (if not present) */
385 guint y = 0, height = 0, pl_height = 0;
386 HashedProcessData *hashed_process_data = NULL;
387 ProcessList *process_list =
388 guicontrolflow_get_process_list(control_flow_data);
389 LttTime birth = process->creation_time;
390 const gchar *name = g_quark_to_string(process->name);
391
392 if(processlist_get_process_pixels(process_list,
393 pid_out,
394 &birth,
395 tfc->t_context->index,
396 &y,
397 &height,
398 &hashed_process_data) == 1)
399 {
400 g_assert(pid_out == 0 || pid_out != process->ppid);
401 /* Process not present */
402 processlist_add(process_list,
403 pid_out,
404 process->ppid,
405 &birth,
406 tfc->t_context->index,
407 name,
408 &pl_height,
409 &hashed_process_data);
410 processlist_get_process_pixels(process_list,
411 pid_out,
412 &birth,
413 tfc->t_context->index,
414 &y,
415 &height,
416 &hashed_process_data);
417 drawing_insert_square( drawing, y, height);
418 }
419
420 /* Now, the process is in the state hash and our own process hash.
421 * We definitely can draw the items related to the ending state.
422 */
423
424 /* Check if the x position is unset. In can have been left unset by
425 * a draw closure from a after chunk hook. This should never happen,
426 * because it must be set by before chunk hook to the damage_begin
427 * value.
428 */
429 g_assert(hashed_process_data->x != -1);
430 {
431 guint x;
432 DrawContext draw_context;
433
434 convert_time_to_pixels(
435 time_window.start_time,
436 end_time,
437 evtime,
438 width,
439 &x);
440
441 /* Now create the drawing context that will be used to draw
442 * items related to the last state. */
443 draw_context.drawable = drawing->pixmap;
444 draw_context.gc = drawing->gc;
445 draw_context.pango_layout = drawing->pango_layout;
446 draw_context.drawinfo.start.x = hashed_process_data->x;
447 draw_context.drawinfo.end.x = x;
448
449 draw_context.drawinfo.y.over = y;
450 draw_context.drawinfo.y.middle = y+(height/4);
451 draw_context.drawinfo.y.under = y+(height/2)+2;
452
453 draw_context.drawinfo.start.offset.over = 0;
454 draw_context.drawinfo.start.offset.middle = 0;
455 draw_context.drawinfo.start.offset.under = 0;
456 draw_context.drawinfo.end.offset.over = 0;
457 draw_context.drawinfo.end.offset.middle = 0;
458 draw_context.drawinfo.end.offset.under = 0;
459
460 {
461 /* Draw the line */
462 PropertiesLine prop_line = prepare_status_line(process);
463 draw_line((void*)&prop_line, (void*)&draw_context);
464
465 }
466 /* become the last x position */
467 hashed_process_data->x = x;
468 }
469 }
470 }
471
472 {
473 /* For the pid_in */
474 /* First, check if the current process is in the state computation
475 * process list. If it is there, that means we must add it right now and
476 * draw items from the beginning of the read for it. If it is not
477 * present, it's a new process and it was not present : it will
478 * be added after the state update. */
479 LttvProcessState *process;
480 process = lttv_state_find_process(tfs, pid_in);
481
482 if(process != NULL) {
483 /* Well, the process_out existed : we must get it in the process hash
484 * or add it, and draw its items.
485 */
486 /* Add process to process list (if not present) */
487 guint y = 0, height = 0, pl_height = 0;
488 HashedProcessData *hashed_process_data = NULL;
489 ProcessList *process_list =
490 guicontrolflow_get_process_list(control_flow_data);
491 LttTime birth = process->creation_time;
492 const gchar *name = g_quark_to_string(process->name);
493
494 if(processlist_get_process_pixels(process_list,
495 pid_in,
496 &birth,
497 tfc->t_context->index,
498 &y,
499 &height,
500 &hashed_process_data) == 1)
501 {
502 g_assert(pid_in == 0 || pid_in != process->ppid);
503 /* Process not present */
504 processlist_add(process_list,
505 pid_in,
506 process->ppid,
507 &birth,
508 tfc->t_context->index,
509 name,
510 &pl_height,
511 &hashed_process_data);
512 processlist_get_process_pixels(process_list,
513 pid_in,
514 &birth,
515 tfc->t_context->index,
516 &y,
517 &height,
518 &hashed_process_data);
519 drawing_insert_square( drawing, y, height);
520 }
521
522 /* Now, the process is in the state hash and our own process hash.
523 * We definitely can draw the items related to the ending state.
524 */
525
526 /* Check if the x position is unset. In can have been left unset by
527 * a draw closure from a after chunk hook. This should never happen,
528 * because it must be set by before chunk hook to the damage_begin
529 * value.
530 */
531 g_assert(hashed_process_data->x != -1);
532 {
533 guint x;
534 DrawContext draw_context;
535
536 convert_time_to_pixels(
537 time_window.start_time,
538 end_time,
539 evtime,
540 width,
541 &x);
542
543 /* Now create the drawing context that will be used to draw
544 * items related to the last state. */
545 draw_context.drawable = drawing->pixmap;
546 draw_context.gc = drawing->gc;
547 draw_context.pango_layout = drawing->pango_layout;
548 draw_context.drawinfo.start.x = hashed_process_data->x;
549 draw_context.drawinfo.end.x = x;
550
551 draw_context.drawinfo.y.over = y;
552 draw_context.drawinfo.y.middle = y+(height/4);
553 draw_context.drawinfo.y.under = y+(height/2)+2;
554
555 draw_context.drawinfo.start.offset.over = 0;
556 draw_context.drawinfo.start.offset.middle = 0;
557 draw_context.drawinfo.start.offset.under = 0;
558 draw_context.drawinfo.end.offset.over = 0;
559 draw_context.drawinfo.end.offset.middle = 0;
560 draw_context.drawinfo.end.offset.under = 0;
561
562 {
563 /* Draw the line */
564 PropertiesLine prop_line = prepare_status_line(process);
565 draw_line((void*)&prop_line, (void*)&draw_context);
566 }
567
568
569 /* become the last x position */
570 hashed_process_data->x = x;
571 }
572 }
573 }
574 } else if(strcmp(
575 ltt_eventtype_name(ltt_event_eventtype(e)),"process") == 0) {
576 /* We are in a fork or exit event */
577
578
579 }
580
581
582 return 0;
583
584
585 #if 0
586 EventsRequest *events_request = (EventsRequest*)hook_data;
587 ControlFlowData *control_flow_data =
588 (ControlFlowData*)events_request->viewer_data;
589 Tab *tab = control_flow_data->tab;
590
591 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
592
593 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
594 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
595
596 LttEvent *e;
597 e = tfc->e;
598
599 LttTime evtime = ltt_event_time(e);
600 TimeWindow time_window =
601 lttvwindow_get_time_window(tab);
602
603 LttTime end_time = ltt_time_add(time_window.start_time,
604 time_window.time_width);
605 //if(time < time_beg || time > time_end) return;
606 if(ltt_time_compare(evtime, time_window.start_time) == -1
607 || ltt_time_compare(evtime, end_time) == 1)
608 return;
609
610 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
611 {
612 g_debug("schedchange!");
613
614 /* Add process to process list (if not present) and get drawing "y" from
615 * process position */
616 guint pid_out, pid_in;
617 LttvProcessState *process_out, *process_in;
618 LttTime birth;
619 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
620
621 ProcessList *process_list =
622 guicontrolflow_get_process_list(control_flow_data);
623
624
625 LttField *f = ltt_event_field(e);
626 LttField *element;
627 element = ltt_field_member(f,0);
628 pid_out = ltt_event_get_long_unsigned(e,element);
629 element = ltt_field_member(f,1);
630 pid_in = ltt_event_get_long_unsigned(e,element);
631 g_debug("out : %u in : %u", pid_out, pid_in);
632
633
634 /* Find process pid_out in the list... */
635 process_out = lttv_state_find_process(tfs, pid_out);
636 if(process_out == NULL) return 0;
637 g_debug("out : %s",g_quark_to_string(process_out->state->s));
638
639 birth = process_out->creation_time;
640 const gchar *name = g_quark_to_string(process_out->name);
641 HashedProcessData *hashed_process_data_out = NULL;
642
643 if(processlist_get_process_pixels(process_list,
644 pid_out,
645 &birth,
646 tfc->t_context->index,
647 &y_out,
648 &height,
649 &hashed_process_data_out) == 1)
650 {
651 /* Process not present */
652 processlist_add(process_list,
653 pid_out,
654 &birth,
655 tfc->t_context->index,
656 name,
657 &pl_height,
658 &hashed_process_data_out);
659 g_assert(processlist_get_process_pixels(process_list,
660 pid_out,
661 &birth,
662 tfc->t_context->index,
663 &y_out,
664 &height,
665 &hashed_process_data_out)==0);
666 drawing_insert_square( control_flow_data->drawing, y_out, height);
667 }
668 //g_free(name);
669
670 /* Find process pid_in in the list... */
671 process_in = lttv_state_find_process(tfs, pid_in);
672 if(process_in == NULL) return 0;
673 g_debug("in : %s",g_quark_to_string(process_in->state->s));
674
675 birth = process_in->creation_time;
676 name = g_quark_to_string(process_in->name);
677 HashedProcessData *hashed_process_data_in = NULL;
678
679 if(processlist_get_process_pixels(process_list,
680 pid_in,
681 &birth,
682 tfc->t_context->index,
683 &y_in,
684 &height,
685 &hashed_process_data_in) == 1)
686 {
687 /* Process not present */
688 processlist_add(process_list,
689 pid_in,
690 &birth,
691 tfc->t_context->index,
692 name,
693 &pl_height,
694 &hashed_process_data_in);
695 processlist_get_process_pixels(process_list,
696 pid_in,
697 &birth,
698 tfc->t_context->index,
699 &y_in,
700 &height,
701 &hashed_process_data_in);
702
703 drawing_insert_square( control_flow_data->drawing, y_in, height);
704 }
705 //g_free(name);
706
707
708 /* Find pixels corresponding to time of the event. If the time does
709 * not fit in the window, show a warning, not supposed to happend. */
710 guint x = 0;
711 guint width = control_flow_data->drawing->width;
712
713 LttTime time = ltt_event_time(e);
714
715 LttTime window_end = ltt_time_add(time_window.time_width,
716 time_window.start_time);
717
718
719 convert_time_to_pixels(
720 time_window.start_time,
721 window_end,
722 time,
723 width,
724 &x);
725 //assert(x <= width);
726 //
727 /* draw what represents the event for outgoing process. */
728
729 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
730 draw_context_out->current->modify_over->x = x;
731 draw_context_out->current->modify_under->x = x;
732 draw_context_out->current->modify_over->y = y_out;
733 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
734 draw_context_out->drawable = control_flow_data->drawing->pixmap;
735 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
736 GtkWidget *widget = control_flow_data->drawing->drawing_area;
737 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
738 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
739 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
740 //draw_context_out->gc = widget->style->black_gc;
741
742 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
743 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
744
745 /* Draw the line/background of the out process */
746 if(draw_context_out->previous->middle->x == -1)
747 {
748 draw_context_out->previous->over->x =
749 control_flow_data->drawing->damage_begin;
750 draw_context_out->previous->middle->x =
751 control_flow_data->drawing->damage_begin;
752 draw_context_out->previous->under->x =
753 control_flow_data->drawing->damage_begin;
754
755 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
756 }
757
758 draw_context_out->current->middle->x = x;
759 draw_context_out->current->over->x = x;
760 draw_context_out->current->under->x = x;
761 draw_context_out->current->middle->y = y_out + height/2;
762 draw_context_out->current->over->y = y_out;
763 draw_context_out->current->under->y = y_out + height;
764 draw_context_out->previous->middle->y = y_out + height/2;
765 draw_context_out->previous->over->y = y_out;
766 draw_context_out->previous->under->y = y_out + height;
767
768 draw_context_out->drawable = control_flow_data->drawing->pixmap;
769 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
770
771 if(process_out->state->s == LTTV_STATE_RUN)
772 {
773 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
774 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
775 draw_context_out->gc = control_flow_data->drawing->gc;
776
777 PropertiesBG prop_bg;
778 prop_bg.color = g_new(GdkColor,1);
779
780 switch(tfc->index) {
781 case 0:
782 prop_bg.color->red = 0x1515;
783 prop_bg.color->green = 0x1515;
784 prop_bg.color->blue = 0x8c8c;
785 break;
786 case 1:
787 prop_bg.color->red = 0x4e4e;
788 prop_bg.color->green = 0xa9a9;
789 prop_bg.color->blue = 0xa4a4;
790 break;
791 case 2:
792 prop_bg.color->red = 0x7a7a;
793 prop_bg.color->green = 0x4a4a;
794 prop_bg.color->blue = 0x8b8b;
795 break;
796 case 3:
797 prop_bg.color->red = 0x8080;
798 prop_bg.color->green = 0x7777;
799 prop_bg.color->blue = 0x4747;
800 break;
801 default:
802 prop_bg.color->red = 0xe7e7;
803 prop_bg.color->green = 0xe7e7;
804 prop_bg.color->blue = 0xe7e7;
805 }
806
807 g_debug("calling from draw_event");
808 draw_bg((void*)&prop_bg, (void*)draw_context_out);
809 g_free(prop_bg.color);
810 //gdk_gc_unref(draw_context_out->gc);
811 }
812
813 draw_context_out->gc = widget->style->black_gc;
814
815 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
816 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
817 PropertiesText prop_text_out;
818 prop_text_out.foreground = &colorfg_out;
819 prop_text_out.background = &colorbg_out;
820 prop_text_out.size = 6;
821 prop_text_out.position = OVER;
822
823 /* color of text : status of the process */
824 if(process_out->state->s == LTTV_STATE_UNNAMED)
825 {
826 prop_text_out.foreground->red = 0xffff;
827 prop_text_out.foreground->green = 0xffff;
828 prop_text_out.foreground->blue = 0xffff;
829 }
830 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
831 {
832 prop_text_out.foreground->red = 0x0fff;
833 prop_text_out.foreground->green = 0xffff;
834 prop_text_out.foreground->blue = 0xfff0;
835 }
836 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
837 {
838 prop_text_out.foreground->red = 0xffff;
839 prop_text_out.foreground->green = 0xffff;
840 prop_text_out.foreground->blue = 0x0000;
841 }
842 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
843 {
844 prop_text_out.foreground->red = 0xffff;
845 prop_text_out.foreground->green = 0x0000;
846 prop_text_out.foreground->blue = 0xffff;
847 }
848 else if(process_out->state->s == LTTV_STATE_WAIT)
849 {
850 prop_text_out.foreground->red = 0xffff;
851 prop_text_out.foreground->green = 0x0000;
852 prop_text_out.foreground->blue = 0x0000;
853 }
854 else if(process_out->state->s == LTTV_STATE_RUN)
855 {
856 prop_text_out.foreground->red = 0x0000;
857 prop_text_out.foreground->green = 0xffff;
858 prop_text_out.foreground->blue = 0x0000;
859 }
860 else
861 {
862 prop_text_out.foreground->red = 0xffff;
863 prop_text_out.foreground->green = 0xffff;
864 prop_text_out.foreground->blue = 0xffff;
865 }
866
867
868 /* Print status of the process : U, WF, WC, E, W, R */
869 if(process_out->state->s == LTTV_STATE_UNNAMED)
870 prop_text_out.text = "U->";
871 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
872 prop_text_out.text = "WF->";
873 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
874 prop_text_out.text = "WC->";
875 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
876 prop_text_out.text = "E->";
877 else if(process_out->state->s == LTTV_STATE_WAIT)
878 prop_text_out.text = "W->";
879 else if(process_out->state->s == LTTV_STATE_RUN)
880 prop_text_out.text = "R->";
881 else
882 prop_text_out.text = "U";
883
884 draw_text((void*)&prop_text_out, (void*)draw_context_out);
885 //gdk_gc_unref(draw_context_out->gc);
886
887 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
888 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
889 draw_context_out->gc = control_flow_data->drawing->gc;
890
891 PropertiesLine prop_line_out;
892 prop_line_out.color = g_new(GdkColor,1);
893 prop_line_out.line_width = 2;
894 prop_line_out.style = GDK_LINE_SOLID;
895 prop_line_out.position = MIDDLE;
896
897 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
898
899 /* color of line : status of the process */
900 if(process_out->state->s == LTTV_STATE_UNNAMED)
901 {
902 prop_line_out.color->red = 0xffff;
903 prop_line_out.color->green = 0xffff;
904 prop_line_out.color->blue = 0xffff;
905 }
906 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
907 {
908 prop_line_out.color->red = 0x0fff;
909 prop_line_out.color->green = 0xffff;
910 prop_line_out.color->blue = 0xfff0;
911 }
912 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
913 {
914 prop_line_out.color->red = 0xffff;
915 prop_line_out.color->green = 0xffff;
916 prop_line_out.color->blue = 0x0000;
917 }
918 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
919 {
920 prop_line_out.color->red = 0xffff;
921 prop_line_out.color->green = 0x0000;
922 prop_line_out.color->blue = 0xffff;
923 }
924 else if(process_out->state->s == LTTV_STATE_WAIT)
925 {
926 prop_line_out.color->red = 0xffff;
927 prop_line_out.color->green = 0x0000;
928 prop_line_out.color->blue = 0x0000;
929 }
930 else if(process_out->state->s == LTTV_STATE_RUN)
931 {
932 prop_line_out.color->red = 0x0000;
933 prop_line_out.color->green = 0xffff;
934 prop_line_out.color->blue = 0x0000;
935 }
936 else
937 {
938 prop_line_out.color->red = 0xffff;
939 prop_line_out.color->green = 0xffff;
940 prop_line_out.color->blue = 0xffff;
941 }
942
943 draw_line((void*)&prop_line_out, (void*)draw_context_out);
944 g_free(prop_line_out.color);
945 //gdk_gc_unref(draw_context_out->gc);
946 /* Note : finishing line will have to be added when trace read over. */
947
948 /* Finally, update the drawing context of the pid_in. */
949
950 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
951 draw_context_in->current->modify_over->x = x;
952 draw_context_in->current->modify_under->x = x;
953 draw_context_in->current->modify_over->y = y_in;
954 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
955 draw_context_in->drawable = control_flow_data->drawing->pixmap;
956 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
957 widget = control_flow_data->drawing->drawing_area;
958 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
959 //draw_context_in->gc = widget->style->black_gc;
960 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
961 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
962
963 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
964 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
965
966 /* Draw the line/bg of the in process */
967 if(draw_context_in->previous->middle->x == -1)
968 {
969 draw_context_in->previous->over->x =
970 control_flow_data->drawing->damage_begin;
971 draw_context_in->previous->middle->x =
972 control_flow_data->drawing->damage_begin;
973 draw_context_in->previous->under->x =
974 control_flow_data->drawing->damage_begin;
975
976 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
977
978 }
979
980 draw_context_in->current->middle->x = x;
981 draw_context_in->current->over->x = x;
982 draw_context_in->current->under->x = x;
983 draw_context_in->current->middle->y = y_in + height/2;
984 draw_context_in->current->over->y = y_in;
985 draw_context_in->current->under->y = y_in + height;
986 draw_context_in->previous->middle->y = y_in + height/2;
987 draw_context_in->previous->over->y = y_in;
988 draw_context_in->previous->under->y = y_in + height;
989
990 draw_context_in->drawable = control_flow_data->drawing->pixmap;
991 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
992
993
994 if(process_in->state->s == LTTV_STATE_RUN)
995 {
996 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
997 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
998 draw_context_in->gc = control_flow_data->drawing->gc;
999
1000 PropertiesBG prop_bg;
1001 prop_bg.color = g_new(GdkColor,1);
1002
1003 switch(tfc->index) {
1004 case 0:
1005 prop_bg.color->red = 0x1515;
1006 prop_bg.color->green = 0x1515;
1007 prop_bg.color->blue = 0x8c8c;
1008 break;
1009 case 1:
1010 prop_bg.color->red = 0x4e4e;
1011 prop_bg.color->green = 0xa9a9;
1012 prop_bg.color->blue = 0xa4a4;
1013 break;
1014 case 2:
1015 prop_bg.color->red = 0x7a7a;
1016 prop_bg.color->green = 0x4a4a;
1017 prop_bg.color->blue = 0x8b8b;
1018 break;
1019 case 3:
1020 prop_bg.color->red = 0x8080;
1021 prop_bg.color->green = 0x7777;
1022 prop_bg.color->blue = 0x4747;
1023 break;
1024 default:
1025 prop_bg.color->red = 0xe7e7;
1026 prop_bg.color->green = 0xe7e7;
1027 prop_bg.color->blue = 0xe7e7;
1028 }
1029
1030
1031 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1032 g_free(prop_bg.color);
1033 //gdk_gc_unref(draw_context_in->gc);
1034 }
1035
1036 draw_context_in->gc = widget->style->black_gc;
1037
1038 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1039 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1040 PropertiesText prop_text_in;
1041 prop_text_in.foreground = &colorfg_in;
1042 prop_text_in.background = &colorbg_in;
1043 prop_text_in.size = 6;
1044 prop_text_in.position = OVER;
1045
1046 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
1047 /* foreground of text : status of the process */
1048 if(process_in->state->s == LTTV_STATE_UNNAMED)
1049 {
1050 prop_text_in.foreground->red = 0xffff;
1051 prop_text_in.foreground->green = 0xffff;
1052 prop_text_in.foreground->blue = 0xffff;
1053 }
1054 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1055 {
1056 prop_text_in.foreground->red = 0x0fff;
1057 prop_text_in.foreground->green = 0xffff;
1058 prop_text_in.foreground->blue = 0xfff0;
1059 }
1060 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1061 {
1062 prop_text_in.foreground->red = 0xffff;
1063 prop_text_in.foreground->green = 0xffff;
1064 prop_text_in.foreground->blue = 0x0000;
1065 }
1066 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1067 {
1068 prop_text_in.foreground->red = 0xffff;
1069 prop_text_in.foreground->green = 0x0000;
1070 prop_text_in.foreground->blue = 0xffff;
1071 }
1072 else if(process_in->state->s == LTTV_STATE_WAIT)
1073 {
1074 prop_text_in.foreground->red = 0xffff;
1075 prop_text_in.foreground->green = 0x0000;
1076 prop_text_in.foreground->blue = 0x0000;
1077 }
1078 else if(process_in->state->s == LTTV_STATE_RUN)
1079 {
1080 prop_text_in.foreground->red = 0x0000;
1081 prop_text_in.foreground->green = 0xffff;
1082 prop_text_in.foreground->blue = 0x0000;
1083 }
1084 else
1085 {
1086 prop_text_in.foreground->red = 0xffff;
1087 prop_text_in.foreground->green = 0xffff;
1088 prop_text_in.foreground->blue = 0xffff;
1089 }
1090
1091
1092
1093 /* Print status of the process : U, WF, WC, E, W, R */
1094 if(process_in->state->s == LTTV_STATE_UNNAMED)
1095 prop_text_in.text = "U->";
1096 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1097 prop_text_in.text = "WF->";
1098 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1099 prop_text_in.text = "WC->";
1100 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1101 prop_text_in.text = "E->";
1102 else if(process_in->state->s == LTTV_STATE_WAIT)
1103 prop_text_in.text = "W->";
1104 else if(process_in->state->s == LTTV_STATE_RUN)
1105 prop_text_in.text = "R->";
1106 else
1107 prop_text_in.text = "U";
1108
1109 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1110 //gdk_gc_unref(draw_context_in->gc);
1111
1112 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1113 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1114 draw_context_in->gc = control_flow_data->drawing->gc;
1115
1116 PropertiesLine prop_line_in;
1117 prop_line_in.color = g_new(GdkColor,1);
1118 prop_line_in.line_width = 2;
1119 prop_line_in.style = GDK_LINE_SOLID;
1120 prop_line_in.position = MIDDLE;
1121
1122 /* color of line : status of the process */
1123 if(process_in->state->s == LTTV_STATE_UNNAMED)
1124 {
1125 prop_line_in.color->red = 0xffff;
1126 prop_line_in.color->green = 0xffff;
1127 prop_line_in.color->blue = 0xffff;
1128 }
1129 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1130 {
1131 prop_line_in.color->red = 0x0fff;
1132 prop_line_in.color->green = 0xffff;
1133 prop_line_in.color->blue = 0xfff0;
1134 }
1135 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1136 {
1137 prop_line_in.color->red = 0xffff;
1138 prop_line_in.color->green = 0xffff;
1139 prop_line_in.color->blue = 0x0000;
1140 }
1141 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1142 {
1143 prop_line_in.color->red = 0xffff;
1144 prop_line_in.color->green = 0x0000;
1145 prop_line_in.color->blue = 0xffff;
1146 }
1147 else if(process_in->state->s == LTTV_STATE_WAIT)
1148 {
1149 prop_line_in.color->red = 0xffff;
1150 prop_line_in.color->green = 0x0000;
1151 prop_line_in.color->blue = 0x0000;
1152 }
1153 else if(process_in->state->s == LTTV_STATE_RUN)
1154 {
1155 prop_line_in.color->red = 0x0000;
1156 prop_line_in.color->green = 0xffff;
1157 prop_line_in.color->blue = 0x0000;
1158 }
1159 else
1160 {
1161 prop_line_in.color->red = 0xffff;
1162 prop_line_in.color->green = 0xffff;
1163 prop_line_in.color->blue = 0xffff;
1164 }
1165
1166 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1167 g_free(prop_line_in.color);
1168 //gdk_gc_unref(draw_context_in->gc);
1169 }
1170
1171 return 0;
1172 #endif //0
1173
1174
1175
1176 /* Text dump */
1177 #ifdef DONTSHOW
1178 GString *string = g_string_new("");;
1179 gboolean field_names = TRUE, state = TRUE;
1180
1181 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1182 g_string_append_printf(string,"\n");
1183
1184 if(state) {
1185 g_string_append_printf(string, " %s",
1186 g_quark_to_string(tfs->process->state->s));
1187 }
1188
1189 g_info("%s",string->str);
1190
1191 g_string_free(string, TRUE);
1192
1193 /* End of text dump */
1194 #endif //DONTSHOW
1195
1196 }
1197
1198 /* after_schedchange_hook
1199 *
1200 * The draw after hook is called by the reading API to have a
1201 * particular event drawn on the screen.
1202 * @param hook_data ControlFlowData structure of the viewer.
1203 * @param call_data Event context.
1204 *
1205 * This function adds items to be drawn in a queue for each process.
1206 *
1207 */
1208 int after_schedchange_hook(void *hook_data, void *call_data)
1209 {
1210 EventsRequest *events_request = (EventsRequest*)hook_data;
1211 ControlFlowData *control_flow_data = events_request->viewer_data;
1212
1213 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1214
1215 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1216 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1217
1218 LttEvent *e;
1219 e = tfc->e;
1220
1221 LttTime evtime = ltt_event_time(e);
1222 TimeWindow time_window =
1223 lttvwindow_get_time_window(control_flow_data->tab);
1224
1225 LttTime end_time = ltt_time_add(time_window.start_time,
1226 time_window.time_width);
1227
1228 if(ltt_time_compare(evtime, time_window.start_time) == -1
1229 || ltt_time_compare(evtime, end_time) == 1)
1230 return;
1231
1232 guint width = control_flow_data->drawing->width;
1233
1234 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0) {
1235
1236 g_debug("schedchange!");
1237
1238 {
1239 /* Add process to process list (if not present) */
1240 LttvProcessState *process_out, *process_in;
1241 LttTime birth;
1242 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1243 HashedProcessData *hashed_process_data_in = NULL;
1244
1245 ProcessList *process_list =
1246 guicontrolflow_get_process_list(control_flow_data);
1247
1248 guint pid_in;
1249 {
1250 guint pid_out;
1251 LttField *f = ltt_event_field(e);
1252 LttField *element;
1253 element = ltt_field_member(f,0);
1254 pid_out = ltt_event_get_long_unsigned(e,element);
1255 element = ltt_field_member(f,1);
1256 pid_in = ltt_event_get_long_unsigned(e,element);
1257 g_debug("out : %u in : %u", pid_out, pid_in);
1258 }
1259
1260
1261 /* Find process pid_in in the list... */
1262 process_in = lttv_state_find_process(tfs, pid_in);
1263 /* It should exist, because we are after the state update. */
1264 g_assert(process_in != NULL);
1265
1266 birth = process_in->creation_time;
1267 const gchar *name = g_quark_to_string(process_in->name);
1268
1269 if(processlist_get_process_pixels(process_list,
1270 pid_in,
1271 &birth,
1272 tfc->t_context->index,
1273 &y_in,
1274 &height,
1275 &hashed_process_data_in) == 1)
1276 {
1277 g_assert(pid_in == 0 || pid_in != process_in->ppid);
1278 /* Process not present */
1279 processlist_add(process_list,
1280 pid_in,
1281 process_in->ppid,
1282 &birth,
1283 tfc->t_context->index,
1284 name,
1285 &pl_height,
1286 &hashed_process_data_in);
1287 processlist_get_process_pixels(process_list,
1288 pid_in,
1289 &birth,
1290 tfc->t_context->index,
1291 &y_in,
1292 &height,
1293 &hashed_process_data_in);
1294 drawing_insert_square( control_flow_data->drawing, y_in, height);
1295 }
1296
1297 convert_time_to_pixels(
1298 time_window.start_time,
1299 end_time,
1300 evtime,
1301 width,
1302 &hashed_process_data_in->x);
1303 }
1304 }
1305 return 0;
1306
1307
1308
1309 #if 0
1310 EventsRequest *events_request = (EventsRequest*)hook_data;
1311 ControlFlowData *control_flow_data = events_request->viewer_data;
1312
1313 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1314
1315 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1316 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1317
1318
1319 LttEvent *e;
1320 e = tfc->e;
1321
1322 LttTime evtime = ltt_event_time(e);
1323 TimeWindow time_window =
1324 lttvwindow_get_time_window(control_flow_data->tab);
1325
1326 LttTime end_time = ltt_time_add(time_window.start_time,
1327 time_window.time_width);
1328 //if(time < time_beg || time > time_end) return;
1329 if(ltt_time_compare(evtime, time_window.start_time) == -1
1330 || ltt_time_compare(evtime, end_time) == 1)
1331 return;
1332
1333
1334 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1335 {
1336 g_debug("schedchange!");
1337
1338 /* Add process to process list (if not present) and get drawing "y" from
1339 * process position */
1340 guint pid_out, pid_in;
1341 LttvProcessState *process_out, *process_in;
1342 LttTime birth;
1343 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1344
1345 ProcessList *process_list =
1346 guicontrolflow_get_process_list(control_flow_data);
1347
1348
1349 LttField *f = ltt_event_field(e);
1350 LttField *element;
1351 element = ltt_field_member(f,0);
1352 pid_out = ltt_event_get_long_unsigned(e,element);
1353 element = ltt_field_member(f,1);
1354 pid_in = ltt_event_get_long_unsigned(e,element);
1355 //g_debug("out : %u in : %u", pid_out, pid_in);
1356
1357
1358 /* Find process pid_out in the list... */
1359 process_out = lttv_state_find_process(tfs, pid_out);
1360 if(process_out == NULL) return 0;
1361 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1362
1363 birth = process_out->creation_time;
1364 gchar *name = strdup(g_quark_to_string(process_out->name));
1365 HashedProcessData *hashed_process_data_out = NULL;
1366
1367 if(processlist_get_process_pixels(process_list,
1368 pid_out,
1369 &birth,
1370 tfc->t_context->index,
1371 &y_out,
1372 &height,
1373 &hashed_process_data_out) == 1)
1374 {
1375 /* Process not present */
1376 processlist_add(process_list,
1377 pid_out,
1378 &birth,
1379 tfc->t_context->index,
1380 name,
1381 &pl_height,
1382 &hashed_process_data_out);
1383 processlist_get_process_pixels(process_list,
1384 pid_out,
1385 &birth,
1386 tfc->t_context->index,
1387 &y_out,
1388 &height,
1389 &hashed_process_data_out);
1390 drawing_insert_square( control_flow_data->drawing, y_out, height);
1391 }
1392
1393 g_free(name);
1394
1395 /* Find process pid_in in the list... */
1396 process_in = lttv_state_find_process(tfs, pid_in);
1397 if(process_in == NULL) return 0;
1398 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1399
1400 birth = process_in->creation_time;
1401 name = strdup(g_quark_to_string(process_in->name));
1402 HashedProcessData *hashed_process_data_in = NULL;
1403
1404 if(processlist_get_process_pixels(process_list,
1405 pid_in,
1406 &birth,
1407 tfc->t_context->index,
1408 &y_in,
1409 &height,
1410 &hashed_process_data_in) == 1)
1411 {
1412 /* Process not present */
1413 processlist_add(process_list,
1414 pid_in,
1415 &birth,
1416 tfc->t_context->index,
1417 name,
1418 &pl_height,
1419 &hashed_process_data_in);
1420 processlist_get_process_pixels(process_list,
1421 pid_in,
1422 &birth,
1423 tfc->t_context->index,
1424 &y_in,
1425 &height,
1426 &hashed_process_data_in);
1427
1428 drawing_insert_square( control_flow_data->drawing, y_in, height);
1429 }
1430 g_free(name);
1431
1432
1433 /* Find pixels corresponding to time of the event. If the time does
1434 * not fit in the window, show a warning, not supposed to happend. */
1435 //guint x = 0;
1436 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1437
1438 //LttTime time = ltt_event_time(e);
1439
1440 //LttTime window_end = ltt_time_add(time_window->time_width,
1441 // time_window->start_time);
1442
1443
1444 //convert_time_to_pixels(
1445 // time_window->start_time,
1446 // window_end,
1447 // time,
1448 // width,
1449 // &x);
1450
1451 //assert(x <= width);
1452
1453 /* draw what represents the event for outgoing process. */
1454
1455 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
1456 //draw_context_out->current->modify_over->x = x;
1457 draw_context_out->current->modify_over->y = y_out;
1458 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
1459 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1460 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1461 GtkWidget *widget = control_flow_data->drawing->drawing_area;
1462 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1463
1464 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1465 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1466
1467 /*if(process_out->state->s == LTTV_STATE_RUN)
1468 {
1469 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1470 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1471 PropertiesBG prop_bg;
1472 prop_bg.color = g_new(GdkColor,1);
1473
1474 prop_bg.color->red = 0xffff;
1475 prop_bg.color->green = 0xffff;
1476 prop_bg.color->blue = 0xffff;
1477
1478 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1479 g_free(prop_bg.color);
1480 gdk_gc_unref(draw_context_out->gc);
1481 }*/
1482
1483 draw_context_out->gc = widget->style->black_gc;
1484
1485 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
1486 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
1487 PropertiesText prop_text_out;
1488 prop_text_out.foreground = &colorfg_out;
1489 prop_text_out.background = &colorbg_out;
1490 prop_text_out.size = 6;
1491 prop_text_out.position = OVER;
1492
1493 /* color of text : status of the process */
1494 if(process_out->state->s == LTTV_STATE_UNNAMED)
1495 {
1496 prop_text_out.foreground->red = 0xffff;
1497 prop_text_out.foreground->green = 0xffff;
1498 prop_text_out.foreground->blue = 0xffff;
1499 }
1500 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1501 {
1502 prop_text_out.foreground->red = 0x0fff;
1503 prop_text_out.foreground->green = 0xffff;
1504 prop_text_out.foreground->blue = 0xfff0;
1505 }
1506 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1507 {
1508 prop_text_out.foreground->red = 0xffff;
1509 prop_text_out.foreground->green = 0xffff;
1510 prop_text_out.foreground->blue = 0x0000;
1511 }
1512 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1513 {
1514 prop_text_out.foreground->red = 0xffff;
1515 prop_text_out.foreground->green = 0x0000;
1516 prop_text_out.foreground->blue = 0xffff;
1517 }
1518 else if(process_out->state->s == LTTV_STATE_WAIT)
1519 {
1520 prop_text_out.foreground->red = 0xffff;
1521 prop_text_out.foreground->green = 0x0000;
1522 prop_text_out.foreground->blue = 0x0000;
1523 }
1524 else if(process_out->state->s == LTTV_STATE_RUN)
1525 {
1526 prop_text_out.foreground->red = 0x0000;
1527 prop_text_out.foreground->green = 0xffff;
1528 prop_text_out.foreground->blue = 0x0000;
1529 }
1530 else
1531 {
1532 prop_text_out.foreground->red = 0xffff;
1533 prop_text_out.foreground->green = 0xffff;
1534 prop_text_out.foreground->blue = 0xffff;
1535 }
1536
1537 /* Print status of the process : U, WF, WC, E, W, R */
1538 if(process_out->state->s == LTTV_STATE_UNNAMED)
1539 prop_text_out.text = "U";
1540 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1541 prop_text_out.text = "WF";
1542 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1543 prop_text_out.text = "WC";
1544 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
1545 prop_text_out.text = "E";
1546 else if(process_out->state->s == LTTV_STATE_WAIT)
1547 prop_text_out.text = "W";
1548 else if(process_out->state->s == LTTV_STATE_RUN)
1549 prop_text_out.text = "R";
1550 else
1551 prop_text_out.text = "U";
1552
1553 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1554
1555 //gdk_gc_unref(draw_context_out->gc);
1556
1557 draw_context_out->current->middle->y = y_out+height/2;
1558 draw_context_out->current->over->y = y_out;
1559 draw_context_out->current->under->y = y_out+height;
1560 draw_context_out->current->status = process_out->state->s;
1561
1562 /* for pid_out : remove previous, Prev = current, new current (default) */
1563 g_free(draw_context_out->previous->modify_under);
1564 g_free(draw_context_out->previous->modify_middle);
1565 g_free(draw_context_out->previous->modify_over);
1566 g_free(draw_context_out->previous->under);
1567 g_free(draw_context_out->previous->middle);
1568 g_free(draw_context_out->previous->over);
1569 g_free(draw_context_out->previous);
1570
1571 draw_context_out->previous = draw_context_out->current;
1572
1573 draw_context_out->current = g_new(DrawInfo,1);
1574 draw_context_out->current->over = g_new(ItemInfo,1);
1575 draw_context_out->current->over->x = -1;
1576 draw_context_out->current->over->y = -1;
1577 draw_context_out->current->middle = g_new(ItemInfo,1);
1578 draw_context_out->current->middle->x = -1;
1579 draw_context_out->current->middle->y = -1;
1580 draw_context_out->current->under = g_new(ItemInfo,1);
1581 draw_context_out->current->under->x = -1;
1582 draw_context_out->current->under->y = -1;
1583 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1584 draw_context_out->current->modify_over->x = -1;
1585 draw_context_out->current->modify_over->y = -1;
1586 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1587 draw_context_out->current->modify_middle->x = -1;
1588 draw_context_out->current->modify_middle->y = -1;
1589 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1590 draw_context_out->current->modify_under->x = -1;
1591 draw_context_out->current->modify_under->y = -1;
1592 draw_context_out->current->status = LTTV_STATE_UNNAMED;
1593
1594 /* Finally, update the drawing context of the pid_in. */
1595
1596 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1597 //draw_context_in->current->modify_over->x = x;
1598 draw_context_in->current->modify_over->y = y_in;
1599 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1600 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1601 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1602 widget = control_flow_data->drawing->drawing_area;
1603 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1604
1605 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1606 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1607
1608 /*if(process_in->state->s == LTTV_STATE_RUN)
1609 {
1610 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1611 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1612 PropertiesBG prop_bg;
1613 prop_bg.color = g_new(GdkColor,1);
1614
1615 prop_bg.color->red = 0xffff;
1616 prop_bg.color->green = 0xffff;
1617 prop_bg.color->blue = 0xffff;
1618
1619 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1620 g_free(prop_bg.color);
1621 gdk_gc_unref(draw_context_in->gc);
1622 }*/
1623
1624 draw_context_in->gc = widget->style->black_gc;
1625
1626 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1627 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1628 PropertiesText prop_text_in;
1629 prop_text_in.foreground = &colorfg_in;
1630 prop_text_in.background = &colorbg_in;
1631 prop_text_in.size = 6;
1632 prop_text_in.position = OVER;
1633
1634 /* foreground of text : status of the process */
1635 if(process_in->state->s == LTTV_STATE_UNNAMED)
1636 {
1637 prop_text_in.foreground->red = 0xffff;
1638 prop_text_in.foreground->green = 0xffff;
1639 prop_text_in.foreground->blue = 0xffff;
1640 }
1641 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1642 {
1643 prop_text_in.foreground->red = 0x0fff;
1644 prop_text_in.foreground->green = 0xffff;
1645 prop_text_in.foreground->blue = 0xfff0;
1646 }
1647 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1648 {
1649 prop_text_in.foreground->red = 0xffff;
1650 prop_text_in.foreground->green = 0xffff;
1651 prop_text_in.foreground->blue = 0x0000;
1652 }
1653 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1654 {
1655 prop_text_in.foreground->red = 0xffff;
1656 prop_text_in.foreground->green = 0x0000;
1657 prop_text_in.foreground->blue = 0xffff;
1658 }
1659 else if(process_in->state->s == LTTV_STATE_WAIT)
1660 {
1661 prop_text_in.foreground->red = 0xffff;
1662 prop_text_in.foreground->green = 0x0000;
1663 prop_text_in.foreground->blue = 0x0000;
1664 }
1665 else if(process_in->state->s == LTTV_STATE_RUN)
1666 {
1667 prop_text_in.foreground->red = 0x0000;
1668 prop_text_in.foreground->green = 0xffff;
1669 prop_text_in.foreground->blue = 0x0000;
1670 }
1671 else
1672 {
1673 prop_text_in.foreground->red = 0xffff;
1674 prop_text_in.foreground->green = 0xffff;
1675 prop_text_in.foreground->blue = 0xffff;
1676 }
1677
1678
1679 /* Print status of the process : U, WF, WC, E, W, R */
1680 if(process_in->state->s == LTTV_STATE_UNNAMED)
1681 prop_text_in.text = "U";
1682 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1683 prop_text_in.text = "WF";
1684 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1685 prop_text_in.text = "WC";
1686 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
1687 prop_text_in.text = "E";
1688 else if(process_in->state->s == LTTV_STATE_WAIT)
1689 prop_text_in.text = "W";
1690 else if(process_in->state->s == LTTV_STATE_RUN)
1691 prop_text_in.text = "R";
1692 else
1693 prop_text_in.text = "U";
1694
1695 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1696
1697
1698 if(process_in->state->s == LTTV_STATE_RUN)
1699 {
1700 gchar tmp[255];
1701 prop_text_in.foreground = &colorfg_in;
1702 prop_text_in.background = &colorbg_in;
1703 prop_text_in.foreground->red = 0xffff;
1704 prop_text_in.foreground->green = 0xffff;
1705 prop_text_in.foreground->blue = 0xffff;
1706 prop_text_in.size = 6;
1707 prop_text_in.position = UNDER;
1708
1709 prop_text_in.text = g_new(gchar, 260);
1710 strcpy(prop_text_in.text, "CPU ");
1711 snprintf(tmp, 255, "%u", tfc->index);
1712 strcat(prop_text_in.text, tmp);
1713
1714 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1715 g_free(prop_text_in.text);
1716 }
1717
1718
1719 draw_context_in->current->middle->y = y_in+height/2;
1720 draw_context_in->current->over->y = y_in;
1721 draw_context_in->current->under->y = y_in+height;
1722 draw_context_in->current->status = process_in->state->s;
1723
1724 /* for pid_in : remove previous, Prev = current, new current (default) */
1725 g_free(draw_context_in->previous->modify_under);
1726 g_free(draw_context_in->previous->modify_middle);
1727 g_free(draw_context_in->previous->modify_over);
1728 g_free(draw_context_in->previous->under);
1729 g_free(draw_context_in->previous->middle);
1730 g_free(draw_context_in->previous->over);
1731 g_free(draw_context_in->previous);
1732
1733 draw_context_in->previous = draw_context_in->current;
1734
1735 draw_context_in->current = g_new(DrawInfo,1);
1736 draw_context_in->current->over = g_new(ItemInfo,1);
1737 draw_context_in->current->over->x = -1;
1738 draw_context_in->current->over->y = -1;
1739 draw_context_in->current->middle = g_new(ItemInfo,1);
1740 draw_context_in->current->middle->x = -1;
1741 draw_context_in->current->middle->y = -1;
1742 draw_context_in->current->under = g_new(ItemInfo,1);
1743 draw_context_in->current->under->x = -1;
1744 draw_context_in->current->under->y = -1;
1745 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1746 draw_context_in->current->modify_over->x = -1;
1747 draw_context_in->current->modify_over->y = -1;
1748 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1749 draw_context_in->current->modify_middle->x = -1;
1750 draw_context_in->current->modify_middle->y = -1;
1751 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1752 draw_context_in->current->modify_under->x = -1;
1753 draw_context_in->current->modify_under->y = -1;
1754 draw_context_in->current->status = LTTV_STATE_UNNAMED;
1755
1756 }
1757
1758 return 0;
1759 #endif //0
1760 }
1761
1762 /* after_fork_hook
1763 *
1764 * Create the processlist entry for the child process. Put the last
1765 * position in x at the current time value.
1766 *
1767 * @param hook_data ControlFlowData structure of the viewer.
1768 * @param call_data Event context.
1769 *
1770 * This function adds items to be drawn in a queue for each process.
1771 *
1772 */
1773 int after_fork_hook(void *hook_data, void *call_data)
1774 {
1775 EventsRequest *events_request = (EventsRequest*)hook_data;
1776 ControlFlowData *control_flow_data = events_request->viewer_data;
1777
1778 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1779
1780 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1781 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1782
1783 LttEvent *e;
1784 e = tfc->e;
1785
1786 LttTime evtime = ltt_event_time(e);
1787 TimeWindow time_window =
1788 lttvwindow_get_time_window(control_flow_data->tab);
1789
1790 LttTime end_time = ltt_time_add(time_window.start_time,
1791 time_window.time_width);
1792
1793 if(ltt_time_compare(evtime, time_window.start_time) == -1
1794 || ltt_time_compare(evtime, end_time) == 1)
1795 return;
1796
1797 guint width = control_flow_data->drawing->width;
1798
1799 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"process") == 0) {
1800
1801 guint sub_id;
1802 guint child_pid;
1803 {
1804 LttField *f = ltt_event_field(e);
1805 LttField *element;
1806 element = ltt_field_member(f,0);
1807 sub_id = ltt_event_get_long_unsigned(e,element);
1808 element = ltt_field_member(f,1);
1809 child_pid = ltt_event_get_long_unsigned(e,element);
1810 }
1811
1812 if(sub_id == 2) { /* fork */
1813
1814 /* Add process to process list (if not present) */
1815 LttvProcessState *process_child;
1816 LttTime birth;
1817 guint y_child = 0, height = 0, pl_height = 0;
1818 HashedProcessData *hashed_process_data_child = NULL;
1819
1820 ProcessList *process_list =
1821 guicontrolflow_get_process_list(control_flow_data);
1822
1823
1824 /* Find child in the list... */
1825 process_child = lttv_state_find_process(tfs, child_pid);
1826 /* It should exist, because we are after the state update. */
1827 g_assert(process_child != NULL);
1828
1829 birth = process_child->creation_time;
1830 const gchar *name = g_quark_to_string(process_child->name);
1831
1832 if(processlist_get_process_pixels(process_list,
1833 child_pid,
1834 &birth,
1835 tfc->t_context->index,
1836 &y_child,
1837 &height,
1838 &hashed_process_data_child) == 1)
1839 {
1840 g_assert(child_pid == 0 || child_pid != process_child->ppid);
1841 /* Process not present */
1842 processlist_add(process_list,
1843 child_pid,
1844 process_child->ppid,
1845 &birth,
1846 tfc->t_context->index,
1847 name,
1848 &pl_height,
1849 &hashed_process_data_child);
1850 processlist_get_process_pixels(process_list,
1851 child_pid,
1852 &birth,
1853 tfc->t_context->index,
1854 &y_child,
1855 &height,
1856 &hashed_process_data_child);
1857 drawing_insert_square( control_flow_data->drawing, y_child, height);
1858 }
1859
1860 convert_time_to_pixels(
1861 time_window.start_time,
1862 end_time,
1863 evtime,
1864 width,
1865 &hashed_process_data_child->x);
1866 }
1867 }
1868 return 0;
1869
1870 }
1871
1872
1873 gint update_time_window_hook(void *hook_data, void *call_data)
1874 {
1875 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1876 Drawing_t *drawing = control_flow_data->drawing;
1877
1878 const TimeWindowNotifyData *time_window_nofify_data =
1879 ((const TimeWindowNotifyData *)call_data);
1880
1881 TimeWindow *old_time_window =
1882 time_window_nofify_data->old_time_window;
1883 TimeWindow *new_time_window =
1884 time_window_nofify_data->new_time_window;
1885
1886 /* Update the ruler */
1887 drawing_update_ruler(control_flow_data->drawing,
1888 new_time_window);
1889
1890
1891 /* Two cases : zoom in/out or scrolling */
1892
1893 /* In order to make sure we can reuse the old drawing, the scale must
1894 * be the same and the new time interval being partly located in the
1895 * currently shown time interval. (reuse is only for scrolling)
1896 */
1897
1898 g_info("Old time window HOOK : %u, %u to %u, %u",
1899 old_time_window->start_time.tv_sec,
1900 old_time_window->start_time.tv_nsec,
1901 old_time_window->time_width.tv_sec,
1902 old_time_window->time_width.tv_nsec);
1903
1904 g_info("New time window HOOK : %u, %u to %u, %u",
1905 new_time_window->start_time.tv_sec,
1906 new_time_window->start_time.tv_nsec,
1907 new_time_window->time_width.tv_sec,
1908 new_time_window->time_width.tv_nsec);
1909
1910 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1911 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1912 {
1913 /* Same scale (scrolling) */
1914 g_info("scrolling");
1915 LttTime *ns = &new_time_window->start_time;
1916 LttTime *os = &old_time_window->start_time;
1917 LttTime old_end = ltt_time_add(old_time_window->start_time,
1918 old_time_window->time_width);
1919 LttTime new_end = ltt_time_add(new_time_window->start_time,
1920 new_time_window->time_width);
1921 //if(ns<os+w<ns+w)
1922 //if(ns<os+w && os+w<ns+w)
1923 //if(ns<old_end && os<ns)
1924 if(ltt_time_compare(*ns, old_end) == -1
1925 && ltt_time_compare(*os, *ns) == -1)
1926 {
1927 g_info("scrolling near right");
1928 /* Scroll right, keep right part of the screen */
1929 guint x = 0;
1930 guint width = control_flow_data->drawing->width;
1931 convert_time_to_pixels(
1932 *os,
1933 old_end,
1934 *ns,
1935 width,
1936 &x);
1937
1938 /* Copy old data to new location */
1939 gdk_draw_drawable (control_flow_data->drawing->pixmap,
1940 control_flow_data->drawing->drawing_area->style->black_gc,
1941 control_flow_data->drawing->pixmap,
1942 x, 0,
1943 0, 0,
1944 control_flow_data->drawing->width-x+SAFETY, -1);
1945
1946 if(drawing->damage_begin == drawing->damage_end)
1947 drawing->damage_begin = control_flow_data->drawing->width-x;
1948 else
1949 drawing->damage_begin = 0;
1950
1951 drawing->damage_end = control_flow_data->drawing->width;
1952
1953 /* Clear the data request background, but not SAFETY */
1954 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
1955 //control_flow_data->drawing->drawing_area->style->black_gc,
1956 control_flow_data->drawing->drawing_area->style->black_gc,
1957 TRUE,
1958 drawing->damage_begin+SAFETY, 0,
1959 drawing->damage_end - drawing->damage_begin, // do not overlap
1960 control_flow_data->drawing->height);
1961
1962 gtk_widget_queue_draw_area (drawing->drawing_area,
1963 0,0,
1964 control_flow_data->drawing->width,
1965 control_flow_data->drawing->height);
1966
1967 /* Get new data for the rest. */
1968 drawing_data_request(control_flow_data->drawing,
1969 &control_flow_data->drawing->pixmap,
1970 drawing->damage_begin, 0,
1971 drawing->damage_end - drawing->damage_begin,
1972 control_flow_data->drawing->height);
1973 } else {
1974 //if(ns<os<ns+w)
1975 //if(ns<os && os<ns+w)
1976 //if(ns<os && os<new_end)
1977 if(ltt_time_compare(*ns,*os) == -1
1978 && ltt_time_compare(*os,new_end) == -1)
1979 {
1980 g_info("scrolling near left");
1981 /* Scroll left, keep left part of the screen */
1982 guint x = 0;
1983 guint width = control_flow_data->drawing->width;
1984 convert_time_to_pixels(
1985 *ns,
1986 new_end,
1987 *os,
1988 width,
1989 &x);
1990
1991
1992 /* Copy old data to new location */
1993 gdk_draw_drawable (control_flow_data->drawing->pixmap,
1994 control_flow_data->drawing->drawing_area->style->black_gc,
1995 control_flow_data->drawing->pixmap,
1996 0, 0,
1997 x, 0,
1998 -1, -1);
1999
2000 if(drawing->damage_begin == drawing->damage_end)
2001 drawing->damage_end = x;
2002 else
2003 drawing->damage_end =
2004 control_flow_data->drawing->width;
2005
2006 drawing->damage_begin = 0;
2007
2008 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2009 control_flow_data->drawing->drawing_area->style->black_gc,
2010 TRUE,
2011 drawing->damage_begin, 0,
2012 drawing->damage_end - drawing->damage_begin, // do not overlap
2013 control_flow_data->drawing->height);
2014
2015 gtk_widget_queue_draw_area (drawing->drawing_area,
2016 0,0,
2017 control_flow_data->drawing->width,
2018 control_flow_data->drawing->height);
2019
2020
2021 /* Get new data for the rest. */
2022 drawing_data_request(control_flow_data->drawing,
2023 &control_flow_data->drawing->pixmap,
2024 drawing->damage_begin, 0,
2025 drawing->damage_end - drawing->damage_begin,
2026 control_flow_data->drawing->height);
2027
2028 } else {
2029 if(ltt_time_compare(*ns,*os) == 0)
2030 {
2031 g_info("not scrolling");
2032 } else {
2033 g_info("scrolling far");
2034 /* Cannot reuse any part of the screen : far jump */
2035
2036
2037 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2038 control_flow_data->drawing->drawing_area->style->black_gc,
2039 TRUE,
2040 0, 0,
2041 control_flow_data->drawing->width+SAFETY, // do not overlap
2042 control_flow_data->drawing->height);
2043
2044 gtk_widget_queue_draw_area (drawing->drawing_area,
2045 0,0,
2046 control_flow_data->drawing->width,
2047 control_flow_data->drawing->height);
2048
2049 drawing->damage_begin = 0;
2050 drawing->damage_end = control_flow_data->drawing->width;
2051
2052 drawing_data_request(control_flow_data->drawing,
2053 &control_flow_data->drawing->pixmap,
2054 0, 0,
2055 control_flow_data->drawing->width,
2056 control_flow_data->drawing->height);
2057
2058 }
2059 }
2060 }
2061 } else {
2062 /* Different scale (zoom) */
2063 g_info("zoom");
2064
2065 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2066 control_flow_data->drawing->drawing_area->style->black_gc,
2067 TRUE,
2068 0, 0,
2069 control_flow_data->drawing->width+SAFETY, // do not overlap
2070 control_flow_data->drawing->height);
2071
2072 gtk_widget_queue_draw_area (drawing->drawing_area,
2073 0,0,
2074 control_flow_data->drawing->width,
2075 control_flow_data->drawing->height);
2076
2077 drawing->damage_begin = 0;
2078 drawing->damage_end = control_flow_data->drawing->width;
2079
2080 drawing_data_request(control_flow_data->drawing,
2081 &control_flow_data->drawing->pixmap,
2082 0, 0,
2083 control_flow_data->drawing->width,
2084 control_flow_data->drawing->height);
2085 }
2086
2087
2088
2089 return 0;
2090 }
2091
2092 gint traceset_notify(void *hook_data, void *call_data)
2093 {
2094 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2095 Drawing_t *drawing = control_flow_data->drawing;
2096 GtkWidget *widget = drawing->drawing_area;
2097
2098
2099 drawing_clear(control_flow_data->drawing);
2100 processlist_clear(control_flow_data->process_list);
2101 redraw_notify(control_flow_data, NULL);
2102
2103 request_background_data(control_flow_data);
2104 #if 0
2105 drawing->damage_begin = 0;
2106 drawing->damage_end = drawing->width;
2107 if(drawing->damage_begin < drawing->damage_end)
2108 {
2109 drawing_data_request(drawing,
2110 &drawing->pixmap,
2111 drawing->damage_begin,
2112 0,
2113 drawing->damage_end-drawing->damage_begin,
2114 drawing->height);
2115 }
2116
2117 gtk_widget_queue_draw_area(drawing->drawing_area,
2118 0,0,
2119 drawing->width,
2120 drawing->height);
2121 #endif //0
2122
2123 return FALSE;
2124 }
2125
2126 gint redraw_notify(void *hook_data, void *call_data)
2127 {
2128 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2129 Drawing_t *drawing = control_flow_data->drawing;
2130 GtkWidget *widget = drawing->drawing_area;
2131
2132 drawing->damage_begin = 0;
2133 drawing->damage_end = drawing->width;
2134
2135
2136 // Clear the image
2137 gdk_draw_rectangle (drawing->pixmap,
2138 widget->style->black_gc,
2139 TRUE,
2140 0, 0,
2141 drawing->width+SAFETY,
2142 drawing->height);
2143
2144
2145 if(drawing->damage_begin < drawing->damage_end)
2146 {
2147 drawing_data_request(drawing,
2148 &drawing->pixmap,
2149 drawing->damage_begin,
2150 0,
2151 drawing->damage_end-drawing->damage_begin,
2152 drawing->height);
2153 }
2154
2155 gtk_widget_queue_draw_area(drawing->drawing_area,
2156 0,0,
2157 drawing->width,
2158 drawing->height);
2159
2160 return FALSE;
2161
2162 }
2163
2164
2165 gint continue_notify(void *hook_data, void *call_data)
2166 {
2167 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2168 Drawing_t *drawing = control_flow_data->drawing;
2169 GtkWidget *widget = drawing->drawing_area;
2170
2171 //g_assert(widget->allocation.width == drawing->damage_end);
2172
2173 if(drawing->damage_begin < drawing->damage_end)
2174 {
2175 drawing_data_request(drawing,
2176 &drawing->pixmap,
2177 drawing->damage_begin,
2178 0,
2179 drawing->damage_end-drawing->damage_begin,
2180 drawing->height);
2181 }
2182
2183 return FALSE;
2184 }
2185
2186
2187 gint update_current_time_hook(void *hook_data, void *call_data)
2188 {
2189 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
2190 Drawing_t *drawing = control_flow_data->drawing;
2191
2192 LttTime current_time = *((LttTime*)call_data);
2193
2194 TimeWindow time_window =
2195 lttvwindow_get_time_window(control_flow_data->tab);
2196
2197 LttTime time_begin = time_window.start_time;
2198 LttTime width = time_window.time_width;
2199 LttTime half_width = ltt_time_div(width,2.0);
2200 LttTime time_end = ltt_time_add(time_begin, width);
2201
2202 LttvTracesetContext * tsc =
2203 lttvwindow_get_traceset_context(control_flow_data->tab);
2204
2205 LttTime trace_start = tsc->time_span.start_time;
2206 LttTime trace_end = tsc->time_span.end_time;
2207
2208 g_info("New current time HOOK : %u, %u", current_time.tv_sec,
2209 current_time.tv_nsec);
2210
2211
2212
2213 /* If current time is inside time interval, just move the highlight
2214 * bar */
2215
2216 /* Else, we have to change the time interval. We have to tell it
2217 * to the main window. */
2218 /* The time interval change will take care of placing the current
2219 * time at the center of the visible area, or nearest possible if we are
2220 * at one end of the trace. */
2221
2222
2223 if(ltt_time_compare(current_time, time_begin) == -1)
2224 {
2225 TimeWindow new_time_window;
2226
2227 if(ltt_time_compare(current_time,
2228 ltt_time_add(trace_start,half_width)) == -1)
2229 time_begin = trace_start;
2230 else
2231 time_begin = ltt_time_sub(current_time,half_width);
2232
2233 new_time_window.start_time = time_begin;
2234 new_time_window.time_width = width;
2235
2236 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
2237 }
2238 else if(ltt_time_compare(current_time, time_end) == 1)
2239 {
2240 TimeWindow new_time_window;
2241
2242 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) == 1)
2243 time_begin = ltt_time_sub(trace_end,width);
2244 else
2245 time_begin = ltt_time_sub(current_time,half_width);
2246
2247 new_time_window.start_time = time_begin;
2248 new_time_window.time_width = width;
2249
2250 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
2251
2252 }
2253 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2254 gtk_widget_queue_draw_area(drawing->drawing_area,
2255 0,0,
2256 drawing->width,
2257 drawing->height);
2258
2259 return 0;
2260 }
2261
2262 typedef struct _ClosureData {
2263 EventsRequest *events_request;
2264 LttvTracesetState *tss;
2265 LttTime end_time;
2266 } ClosureData;
2267
2268
2269 void draw_closure(gpointer key, gpointer value, gpointer user_data)
2270 {
2271 ProcessInfo *process_info = (ProcessInfo*)key;
2272 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
2273 ClosureData *closure_data = (ClosureData*)user_data;
2274
2275 EventsRequest *events_request = closure_data->events_request;
2276 ControlFlowData *control_flow_data = events_request->viewer_data;
2277 Drawing_t *drawing = control_flow_data->drawing;
2278
2279 LttvTracesetState *tss = closure_data->tss;
2280 LttvTracesetContext *tsc = (LttvTracesetContext*)closure_data->tss;
2281
2282 LttTime evtime = closure_data->end_time;
2283 TimeWindow time_window =
2284 lttvwindow_get_time_window(control_flow_data->tab);
2285
2286 LttTime end_time = ltt_time_add(time_window.start_time,
2287 time_window.time_width);
2288
2289 if(ltt_time_compare(evtime, time_window.start_time) == -1
2290 || ltt_time_compare(evtime, end_time) == 1)
2291 return;
2292
2293 guint width = drawing->width;
2294
2295 {
2296 /* For the process */
2297 /* First, check if the current process is in the state computation
2298 * process list. If it is there, that means we must add it right now and
2299 * draw items from the beginning of the read for it. If it is not
2300 * present, it's a new process and it was not present : it will
2301 * be added after the state update. */
2302 g_assert(lttv_traceset_number(tsc->ts) > 0);
2303
2304 /* tracefiles[0] is ok here, because we draw for every PID, and
2305 * assume CPU 0 for PID 0 //FIXME */
2306 LttvTracefileState *tfs =
2307 (LttvTracefileState*)tsc->traces[process_info->trace_num]->tracefiles[0];
2308
2309 LttvProcessState *process;
2310 process = lttv_state_find_process(tfs,
2311 process_info->pid);
2312
2313 if(process != NULL) {
2314
2315 /* Only draw for processes that are currently in the trace states */
2316
2317 guint y = 0, height = 0, pl_height = 0;
2318 ProcessList *process_list =
2319 guicontrolflow_get_process_list(control_flow_data);
2320 LttTime birth = process_info->birth;
2321
2322 /* Should be alike when background info is ready */
2323 if(control_flow_data->background_info_waiting==0)
2324 g_assert(ltt_time_compare(process->creation_time,
2325 process_info->birth) == 0);
2326 const gchar *name = g_quark_to_string(process->name);
2327
2328 /* process HAS to be present */
2329 g_assert(processlist_get_process_pixels(process_list,
2330 process_info->pid,
2331 &birth,
2332 process_info->trace_num,
2333 &y,
2334 &height,
2335 &hashed_process_data) != 1);
2336
2337 /* Now, the process is in the state hash and our own process hash.
2338 * We definitely can draw the items related to the ending state.
2339 */
2340
2341 /* Check if the x position is unset. In can have been left unset by
2342 * a draw closure from a after chunk hook. This should never happen,
2343 * because it must be set by before chunk hook to the damage_begin
2344 * value.
2345 */
2346 g_assert(hashed_process_data->x != -1);
2347 {
2348 guint x;
2349 DrawContext draw_context;
2350
2351 convert_time_to_pixels(
2352 time_window.start_time,
2353 end_time,
2354 evtime,
2355 width,
2356 &x);
2357
2358 /* Now create the drawing context that will be used to draw
2359 * items related to the last state. */
2360 draw_context.drawable = drawing->pixmap;
2361 draw_context.gc = drawing->gc;
2362 draw_context.pango_layout = drawing->pango_layout;
2363 draw_context.drawinfo.start.x = hashed_process_data->x;
2364 draw_context.drawinfo.end.x = x;
2365
2366 draw_context.drawinfo.y.over = y;
2367 draw_context.drawinfo.y.middle = y+(height/4);
2368 draw_context.drawinfo.y.under = y+(height/2)+2;
2369
2370 draw_context.drawinfo.start.offset.over = 0;
2371 draw_context.drawinfo.start.offset.middle = 0;
2372 draw_context.drawinfo.start.offset.under = 0;
2373 draw_context.drawinfo.end.offset.over = 0;
2374 draw_context.drawinfo.end.offset.middle = 0;
2375 draw_context.drawinfo.end.offset.under = 0;
2376
2377 {
2378 /* Draw the line */
2379 PropertiesLine prop_line = prepare_status_line(process);
2380 draw_line((void*)&prop_line, (void*)&draw_context);
2381
2382 }
2383
2384 /* special case LTTV_STATE_WAIT : CPU is unknown. */
2385
2386 /* become the last x position */
2387 hashed_process_data->x = x;
2388 }
2389 }
2390 }
2391 return;
2392 }
2393
2394 int before_chunk(void *hook_data, void *call_data)
2395 {
2396 EventsRequest *events_request = (EventsRequest*)hook_data;
2397 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2398
2399 drawing_chunk_begin(events_request, tss);
2400
2401 return 0;
2402 }
2403
2404 int before_request(void *hook_data, void *call_data)
2405 {
2406 EventsRequest *events_request = (EventsRequest*)hook_data;
2407 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2408
2409 drawing_data_request_begin(events_request, tss);
2410
2411 return 0;
2412 }
2413
2414
2415 /*
2416 * after request is necessary in addition of after chunk in order to draw
2417 * lines until the end of the screen. after chunk just draws lines until
2418 * the last event.
2419 *
2420 * for each process
2421 * draw closing line
2422 * expose
2423 */
2424 int after_request(void *hook_data, void *call_data)
2425 {
2426 EventsRequest *events_request = (EventsRequest*)hook_data;
2427 ControlFlowData *control_flow_data = events_request->viewer_data;
2428 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2429 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
2430
2431 ProcessList *process_list =
2432 guicontrolflow_get_process_list(control_flow_data);
2433 LttTime end_time = events_request->end_time;
2434
2435 ClosureData closure_data;
2436 closure_data.events_request = (EventsRequest*)hook_data;
2437 closure_data.tss = tss;
2438 closure_data.end_time = end_time;
2439
2440 /* Draw last items */
2441 g_hash_table_foreach(process_list->process_hash, draw_closure,
2442 (void*)&closure_data);
2443
2444 /* Request expose */
2445 drawing_request_expose(events_request, tss, end_time);
2446 return 0;
2447 }
2448
2449 /*
2450 * for each process
2451 * draw closing line
2452 * expose
2453 */
2454 int after_chunk(void *hook_data, void *call_data)
2455 {
2456 EventsRequest *events_request = (EventsRequest*)hook_data;
2457 ControlFlowData *control_flow_data = events_request->viewer_data;
2458 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2459 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
2460 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2461 LttTime end_time;
2462
2463 ProcessList *process_list =
2464 guicontrolflow_get_process_list(control_flow_data);
2465
2466 if(tfc != NULL)
2467 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
2468 else /* end of traceset, or position now out of request : end */
2469 end_time = events_request->end_time;
2470
2471 ClosureData closure_data;
2472 closure_data.events_request = (EventsRequest*)hook_data;
2473 closure_data.tss = tss;
2474 closure_data.end_time = end_time;
2475
2476 /* Draw last items */
2477 g_hash_table_foreach(process_list->process_hash, draw_closure,
2478 (void*)&closure_data);
2479
2480 /* Request expose */
2481 drawing_request_expose(events_request, tss, end_time);
2482
2483 return 0;
2484 }
2485
This page took 0.081452 seconds and 4 git commands to generate.