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