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