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