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