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