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