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