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