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