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